Merge from Chromium at DEPS revision r216972

This commit was generated by merge_to_master.py.

Change-Id: I01cb28d94e3fcf99e3624d75cafa50d929787ddd
diff --git a/.DEPS.git b/.DEPS.git
index acce559..a1071d8 100644
--- a/.DEPS.git
+++ b/.DEPS.git
@@ -11,7 +11,7 @@
     'git_url':
          'https://chromium.googlesource.com',
     'webkit_rev':
-         '@88c9a95505973e4bc340d847a42caaae3e709774'
+         '@2384839ebef90ff82cbfc837374243a8b7985dc0'
 }
 
 deps = {
@@ -25,10 +25,10 @@
         Var('git_url') + '/chromium/frame_rate/content.git@c10272c88463efeef6bb19c9ec07c42bc8fe22b9',
     'src/chrome/test/data/perf/third_party/octane':
         Var('git_url') + '/external/octane-benchmark.git@9ac27bfd9e0bc73663db0c0551440215d8b20d09',
-    'src/googleurl':
-        Var('git_url') + '/external/google-url.git@ca8c31644137b3b46021ee37973c8749aae5c3bf',
+    'src/media/cdm/ppapi/api':
+        Var('git_url') + '/chromium/cdm.git@c2b192a02546916d28233cfd8b7717ffcdcc8347',
     'src/native_client':
-        Var('git_url') + '/native_client/src/native_client.git@f87ee6e69c38cec1acdabf4d2d608ea8f0510253',
+        Var('git_url') + '/native_client/src/native_client.git@3a9cf2a60e4c3f54564de368d540c556efaa9289',
     'src/sdch/open-vcdiff':
         Var('git_url') + '/external/open-vcdiff.git@438f2a5be6d809bc21611a94cd37bfc8c28ceb33',
     'src/testing/gmock':
@@ -64,7 +64,7 @@
     '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/stable/talk.git@c237f0ad875cde990bf9d89f41424b18809cc345',
+        Var('git_url') + '/external/webrtc/stable/talk.git@7bf94f9c4ab08aa82f78018d8ba363b5b60b05ed',
     'src/third_party/libjpeg_turbo':
         Var('git_url') + '/chromium/deps/libjpeg_turbo.git@82ce8a6d4ebe12a177c0c3597192f2b4f09e81c3',
     'src/third_party/libphonenumber/src/phonenumbers':
@@ -98,11 +98,11 @@
     'src/third_party/sfntly/cpp/src':
         Var('git_url') + '/external/sfntly/cpp/src.git@cfb2f1743f0169ad8d01035458617bce97107539',
     'src/third_party/skia/gyp':
-        Var('git_url') + '/external/skia/gyp.git@dccf47acbdb65e21ed989fa3f45e638caffa6ce6',
+        Var('git_url') + '/external/skia/gyp.git@5afe400f473c747e2e5acb50b249fad1b8f2b0fc',
     'src/third_party/skia/include':
-        Var('git_url') + '/external/skia/include.git@970ef2af6ab2e1d6554207e3f66cce934cd091d5',
+        Var('git_url') + '/external/skia/include.git@9b8ab717a6bf3fdc5eaa0ef5845c8daa14e3604b',
     'src/third_party/skia/src':
-        Var('git_url') + '/external/skia/src.git@d2da8bcbed4791ae93c3070c50e89865b6398e10',
+        Var('git_url') + '/external/skia/src.git@06e8b2aa9249ff96559f7c08adffa83f4e855258',
     'src/third_party/smhasher/src':
         Var('git_url') + '/external/smhasher.git@6f63a4882e6b2cf87e8eec1a3ef8644e0d963283',
     'src/third_party/snappy/src':
@@ -112,7 +112,7 @@
     'src/third_party/swig/Lib':
         Var('git_url') + '/chromium/deps/swig/Lib.git@549f0b084ad9c40ef42d111303d831eb8d91252e',
     'src/third_party/trace-viewer':
-        Var('git_url') + '/external/trace-viewer.git@a6a836af25bb1a05cb9b03e2a955a9c0c93254bc',
+        Var('git_url') + '/external/trace-viewer.git@105f1a5f16ef9ca378f8caf006cc7da2d09da57f',
     'src/third_party/usrsctp/usrsctplib':
         Var('git_url') + '/external/usrsctplib.git@9fde21ced28f3314e75a2d90e5dcc7867e2a6b75',
     'src/third_party/webdriver/pylib':
@@ -122,7 +122,7 @@
     'src/third_party/webpagereplay':
         Var('git_url') + '/external/web-page-replay.git@ca269709e412d06b7b9f649dd47fb91f38f73852',
     'src/third_party/webrtc':
-        Var('git_url') + '/external/webrtc/stable/webrtc.git@dc26d5440b80f042dfc516116b2e15ce618a405d',
+        Var('git_url') + '/external/webrtc/stable/webrtc.git@2b8e89ebe8233d5faca71c5df3fc0259ca7fa784',
     'src/third_party/yasm/source/patched-yasm':
         Var('git_url') + '/chromium/deps/yasm/patched-yasm.git@c960eb11ccda80b10ed50be39df4f0663b371d1d',
     'src/tools/deps2git':
@@ -136,16 +136,14 @@
     'src/tools/swarm_client':
         Var('git_url') + '/chromium/tools/swarm_client.git@86681e9a54c88972dba217b4f1007222dd8936a4',
     'src/v8':
-        Var('git_url') + '/external/v8.git@54d8a9855f2c6a6c3c33b5b66cbfbbac2cbcaa00',
-    'src/webkit/renderer/media/crypto/ppapi/cdm':
-        Var('git_url') + '/chromium/cdm.git@c2b192a02546916d28233cfd8b7717ffcdcc8347',
+        Var('git_url') + '/external/v8.git@89acc0bef1acf051e807b057dbcbcd478a8ad301',
 }
 
 deps_os = {
     'android':
     {
         'src/third_party/android_tools':
-            Var('git_url') + '/android_tools.git@eda719cf5bf102f38b17fe4f583fbc5fde581be6',
+            Var('git_url') + '/android_tools.git@881586ca84f2fb8e82faa9c8d645416d175d0f01',
         'src/third_party/aosp':
             Var('git_url') + '/chromium/deps/aosp.git@bbafe5155dff86bbba1e92b42a073ffcfcfbf28c',
         'src/third_party/apache-mime4j':
@@ -357,15 +355,13 @@
     '+testing',
     '+third_party/icu/source/common/unicode',
     '+third_party/icu/source/i18n/unicode',
-    '+url',
-    '!googleurl'
+    '+url'
 ]
 
 skip_child_includes = [
     'breakpad',
     'chrome_frame',
     'delegate_execute',
-    'googleurl',
     'metro_driver',
     'native_client_sdk',
     'o3d',
diff --git a/DEPS b/DEPS
index 7798439..01ca9de 100644
--- a/DEPS
+++ b/DEPS
@@ -8,12 +8,12 @@
   "sourceforge_url": "http://svn.code.sf.net/p/%(repo)s/code",
   "webkit_trunk": "http://src.chromium.org/blink/trunk",
   "nacl_trunk": "http://src.chromium.org/native_client/trunk",
-  "webkit_revision": "155688",
+  "webkit_revision": "155921",
   "chromium_git": "https://chromium.googlesource.com",
   "chromiumos_git": "https://chromium.googlesource.com/chromiumos",
   "skia_git": "https://skia.googlesource.com",
   "swig_revision": "69281",
-  "nacl_revision": "11930",
+  "nacl_revision": "11988",
   # After changing nacl_revision, run 'glient sync' and check native_client/DEPS
   # to update other nacl_*_revision's.
   "nacl_tools_revision": "11437",  # native_client/DEPS: tools_rev
@@ -29,16 +29,16 @@
   "ffmpeg_hash": "894e6f715645528e815aee2dad45b59704238dcd",
 
   "sfntly_revision": "134",
-  "skia_revision": "10602",
-  "skia_hash": "6d04e64f56b658635eeb46fcdb02188ce54f1567",
+  "skia_revision": "10648",
+  "skia_hash": "a5b11fcd59d769450ac85a3b1e88d2e6eaca865e",
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling Skia
   # and V8 without interference from each other.
-  "v8_revision": "16104",
+  "v8_revision": "16142",
   # 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": "4490",
+  "webrtc_revision": "4520",
   "jsoncpp_revision": "248",
   "nss_revision": "209026",
   # Three lines of non-changing comments so that
@@ -55,9 +55,6 @@
   "src/breakpad/src":
     (Var("googlecode_url") % "google-breakpad") + "/trunk/src@1199",
 
-  "src/googleurl":
-    (Var("googlecode_url") % "google-url") + "/trunk@185",
-
   "src/sdch/open-vcdiff":
     (Var("googlecode_url") % "open-vcdiff") + "/trunk@42",
 
@@ -72,7 +69,7 @@
     "/external/angle.git@b93f84acdecd3eebf316750d8024b8b592c9012b",
 
   "src/third_party/trace-viewer":
-    (Var("googlecode_url") % "trace-viewer") + "/trunk@816",
+    (Var("googlecode_url") % "trace-viewer") + "/trunk@847",
 
   "src/third_party/WebKit":
     Var("webkit_trunk") + "@" + Var("webkit_revision"),
@@ -247,7 +244,7 @@
   "src/third_party/accessibility-developer-tools":
     Var("chromium_git") + "/external/accessibility-developer-tools.git@2e3c9c8e49277a0ca1eeba510271eb03f9486d8f",
 
-  "src/webkit/renderer/media/crypto/ppapi/cdm":
+  "src/media/cdm/ppapi/api":
     "/trunk/deps/cdm@181763",
 
   "src/third_party/mesa/src":
@@ -456,7 +453,7 @@
   "android": {
     "src/third_party/android_tools":
       Var("chromium_git") + "/android_tools.git" +
-      "@eda719cf5bf102f38b17fe4f583fbc5fde581be6",
+      "@881586ca84f2fb8e82faa9c8d645416d175d0f01",
 
     "src/third_party/aosp":
       "/trunk/deps/third_party/aosp@148330",
@@ -513,8 +510,6 @@
   "+third_party/icu/source/common/unicode",
   "+third_party/icu/source/i18n/unicode",
   "+url",
-  # TODO(tfarina): Temporary, until we finish the migration to url. Remove this!
-  "!googleurl",
 ]
 
 
@@ -523,7 +518,6 @@
   "breakpad",
   "chrome_frame",
   "delegate_execute",
-  "googleurl",
   "metro_driver",
   "native_client_sdk",
   "o3d",
diff --git a/GypAndroid.darwin-arm.mk b/GypAndroid.darwin-arm.mk
index d4f87d0..85b5b60 100644
--- a/GypAndroid.darwin-arm.mk
+++ b/GypAndroid.darwin-arm.mk
@@ -85,8 +85,6 @@
 include $(LOCAL_PATH)/net/net_jni_headers.target.darwin-arm.mk
 include $(LOCAL_PATH)/net/net_resources.target.darwin-arm.mk
 include $(LOCAL_PATH)/net/private_key_types_java.target.darwin-arm.mk
-include $(LOCAL_PATH)/ppapi/ppapi_c.target.darwin-arm.mk
-include $(LOCAL_PATH)/ppapi/ppapi_shared.target.darwin-arm.mk
 include $(LOCAL_PATH)/printing/printing.target.darwin-arm.mk
 include $(LOCAL_PATH)/sandbox/sandbox.target.darwin-arm.mk
 include $(LOCAL_PATH)/sandbox/sandbox_services.target.darwin-arm.mk
@@ -150,6 +148,7 @@
 include $(LOCAL_PATH)/third_party/WebKit/Source/wtf/wtf_config.target.darwin-arm.mk
 include $(LOCAL_PATH)/third_party/WebKit/public/blink.target.darwin-arm.mk
 include $(LOCAL_PATH)/third_party/WebKit/public/blink_minimal.target.darwin-arm.mk
+include $(LOCAL_PATH)/third_party/WebKit/public/blink_skia_config.target.darwin-arm.mk
 include $(LOCAL_PATH)/third_party/angle_dx11/src/preprocessor.target.darwin-arm.mk
 include $(LOCAL_PATH)/third_party/angle_dx11/src/translator_common.target.darwin-arm.mk
 include $(LOCAL_PATH)/third_party/angle_dx11/src/translator_glsl.target.darwin-arm.mk
@@ -226,14 +225,12 @@
 include $(LOCAL_PATH)/webkit/common/user_agent/user_agent.target.darwin-arm.mk
 include $(LOCAL_PATH)/webkit/common/user_agent/webkit_version.target.darwin-arm.mk
 include $(LOCAL_PATH)/webkit/common/webkit_common.target.darwin-arm.mk
-include $(LOCAL_PATH)/webkit/plugins/plugins_common.target.darwin-arm.mk
 include $(LOCAL_PATH)/webkit/renderer/compositor_bindings/webkit_compositor_bindings.target.darwin-arm.mk
 include $(LOCAL_PATH)/webkit/renderer/compositor_bindings/webkit_compositor_support.target.darwin-arm.mk
 include $(LOCAL_PATH)/webkit/renderer/webkit_renderer.target.darwin-arm.mk
 include $(LOCAL_PATH)/webkit/support/glue.target.darwin-arm.mk
 include $(LOCAL_PATH)/webkit/support/glue_child.target.darwin-arm.mk
 include $(LOCAL_PATH)/webkit/support/overscroller_jni_headers.target.darwin-arm.mk
-include $(LOCAL_PATH)/webkit/support/plugins.target.darwin-arm.mk
 include $(LOCAL_PATH)/webkit/webkit_resources.target.darwin-arm.mk
 include $(LOCAL_PATH)/webkit/webkit_storage_browser.target.darwin-arm.mk
 include $(LOCAL_PATH)/webkit/webkit_storage_common.target.darwin-arm.mk
diff --git a/GypAndroid.darwin-mips.mk b/GypAndroid.darwin-mips.mk
index d870e25..5dc9a15 100644
--- a/GypAndroid.darwin-mips.mk
+++ b/GypAndroid.darwin-mips.mk
@@ -85,8 +85,6 @@
 include $(LOCAL_PATH)/net/net_jni_headers.target.darwin-mips.mk
 include $(LOCAL_PATH)/net/net_resources.target.darwin-mips.mk
 include $(LOCAL_PATH)/net/private_key_types_java.target.darwin-mips.mk
-include $(LOCAL_PATH)/ppapi/ppapi_c.target.darwin-mips.mk
-include $(LOCAL_PATH)/ppapi/ppapi_shared.target.darwin-mips.mk
 include $(LOCAL_PATH)/printing/printing.target.darwin-mips.mk
 include $(LOCAL_PATH)/sandbox/sandbox.target.darwin-mips.mk
 include $(LOCAL_PATH)/sandbox/sandbox_services.target.darwin-mips.mk
@@ -146,6 +144,7 @@
 include $(LOCAL_PATH)/third_party/WebKit/Source/wtf/wtf_config.target.darwin-mips.mk
 include $(LOCAL_PATH)/third_party/WebKit/public/blink.target.darwin-mips.mk
 include $(LOCAL_PATH)/third_party/WebKit/public/blink_minimal.target.darwin-mips.mk
+include $(LOCAL_PATH)/third_party/WebKit/public/blink_skia_config.target.darwin-mips.mk
 include $(LOCAL_PATH)/third_party/angle_dx11/src/preprocessor.target.darwin-mips.mk
 include $(LOCAL_PATH)/third_party/angle_dx11/src/translator_common.target.darwin-mips.mk
 include $(LOCAL_PATH)/third_party/angle_dx11/src/translator_glsl.target.darwin-mips.mk
@@ -222,14 +221,12 @@
 include $(LOCAL_PATH)/webkit/common/user_agent/user_agent.target.darwin-mips.mk
 include $(LOCAL_PATH)/webkit/common/user_agent/webkit_version.target.darwin-mips.mk
 include $(LOCAL_PATH)/webkit/common/webkit_common.target.darwin-mips.mk
-include $(LOCAL_PATH)/webkit/plugins/plugins_common.target.darwin-mips.mk
 include $(LOCAL_PATH)/webkit/renderer/compositor_bindings/webkit_compositor_bindings.target.darwin-mips.mk
 include $(LOCAL_PATH)/webkit/renderer/compositor_bindings/webkit_compositor_support.target.darwin-mips.mk
 include $(LOCAL_PATH)/webkit/renderer/webkit_renderer.target.darwin-mips.mk
 include $(LOCAL_PATH)/webkit/support/glue.target.darwin-mips.mk
 include $(LOCAL_PATH)/webkit/support/glue_child.target.darwin-mips.mk
 include $(LOCAL_PATH)/webkit/support/overscroller_jni_headers.target.darwin-mips.mk
-include $(LOCAL_PATH)/webkit/support/plugins.target.darwin-mips.mk
 include $(LOCAL_PATH)/webkit/webkit_resources.target.darwin-mips.mk
 include $(LOCAL_PATH)/webkit/webkit_storage_browser.target.darwin-mips.mk
 include $(LOCAL_PATH)/webkit/webkit_storage_common.target.darwin-mips.mk
diff --git a/GypAndroid.darwin-x86.mk b/GypAndroid.darwin-x86.mk
index 6ee10d3..f9ea4ce 100644
--- a/GypAndroid.darwin-x86.mk
+++ b/GypAndroid.darwin-x86.mk
@@ -90,8 +90,6 @@
 include $(LOCAL_PATH)/net/net_jni_headers.target.darwin-x86.mk
 include $(LOCAL_PATH)/net/net_resources.target.darwin-x86.mk
 include $(LOCAL_PATH)/net/private_key_types_java.target.darwin-x86.mk
-include $(LOCAL_PATH)/ppapi/ppapi_c.target.darwin-x86.mk
-include $(LOCAL_PATH)/ppapi/ppapi_shared.target.darwin-x86.mk
 include $(LOCAL_PATH)/printing/printing.target.darwin-x86.mk
 include $(LOCAL_PATH)/sandbox/sandbox.target.darwin-x86.mk
 include $(LOCAL_PATH)/sandbox/sandbox_services.target.darwin-x86.mk
@@ -154,6 +152,7 @@
 include $(LOCAL_PATH)/third_party/WebKit/Source/wtf/wtf_config.target.darwin-x86.mk
 include $(LOCAL_PATH)/third_party/WebKit/public/blink.target.darwin-x86.mk
 include $(LOCAL_PATH)/third_party/WebKit/public/blink_minimal.target.darwin-x86.mk
+include $(LOCAL_PATH)/third_party/WebKit/public/blink_skia_config.target.darwin-x86.mk
 include $(LOCAL_PATH)/third_party/angle_dx11/src/preprocessor.target.darwin-x86.mk
 include $(LOCAL_PATH)/third_party/angle_dx11/src/translator_common.target.darwin-x86.mk
 include $(LOCAL_PATH)/third_party/angle_dx11/src/translator_glsl.target.darwin-x86.mk
@@ -240,14 +239,12 @@
 include $(LOCAL_PATH)/webkit/common/user_agent/user_agent.target.darwin-x86.mk
 include $(LOCAL_PATH)/webkit/common/user_agent/webkit_version.target.darwin-x86.mk
 include $(LOCAL_PATH)/webkit/common/webkit_common.target.darwin-x86.mk
-include $(LOCAL_PATH)/webkit/plugins/plugins_common.target.darwin-x86.mk
 include $(LOCAL_PATH)/webkit/renderer/compositor_bindings/webkit_compositor_bindings.target.darwin-x86.mk
 include $(LOCAL_PATH)/webkit/renderer/compositor_bindings/webkit_compositor_support.target.darwin-x86.mk
 include $(LOCAL_PATH)/webkit/renderer/webkit_renderer.target.darwin-x86.mk
 include $(LOCAL_PATH)/webkit/support/glue.target.darwin-x86.mk
 include $(LOCAL_PATH)/webkit/support/glue_child.target.darwin-x86.mk
 include $(LOCAL_PATH)/webkit/support/overscroller_jni_headers.target.darwin-x86.mk
-include $(LOCAL_PATH)/webkit/support/plugins.target.darwin-x86.mk
 include $(LOCAL_PATH)/webkit/webkit_resources.target.darwin-x86.mk
 include $(LOCAL_PATH)/webkit/webkit_storage_browser.target.darwin-x86.mk
 include $(LOCAL_PATH)/webkit/webkit_storage_common.target.darwin-x86.mk
diff --git a/GypAndroid.linux-arm.mk b/GypAndroid.linux-arm.mk
index 0a2979b..673934c 100644
--- a/GypAndroid.linux-arm.mk
+++ b/GypAndroid.linux-arm.mk
@@ -85,8 +85,6 @@
 include $(LOCAL_PATH)/net/net_jni_headers.target.linux-arm.mk
 include $(LOCAL_PATH)/net/net_resources.target.linux-arm.mk
 include $(LOCAL_PATH)/net/private_key_types_java.target.linux-arm.mk
-include $(LOCAL_PATH)/ppapi/ppapi_c.target.linux-arm.mk
-include $(LOCAL_PATH)/ppapi/ppapi_shared.target.linux-arm.mk
 include $(LOCAL_PATH)/printing/printing.target.linux-arm.mk
 include $(LOCAL_PATH)/sandbox/sandbox.target.linux-arm.mk
 include $(LOCAL_PATH)/sandbox/sandbox_services.target.linux-arm.mk
@@ -150,6 +148,7 @@
 include $(LOCAL_PATH)/third_party/WebKit/Source/wtf/wtf_config.target.linux-arm.mk
 include $(LOCAL_PATH)/third_party/WebKit/public/blink.target.linux-arm.mk
 include $(LOCAL_PATH)/third_party/WebKit/public/blink_minimal.target.linux-arm.mk
+include $(LOCAL_PATH)/third_party/WebKit/public/blink_skia_config.target.linux-arm.mk
 include $(LOCAL_PATH)/third_party/angle_dx11/src/preprocessor.target.linux-arm.mk
 include $(LOCAL_PATH)/third_party/angle_dx11/src/translator_common.target.linux-arm.mk
 include $(LOCAL_PATH)/third_party/angle_dx11/src/translator_glsl.target.linux-arm.mk
@@ -226,14 +225,12 @@
 include $(LOCAL_PATH)/webkit/common/user_agent/user_agent.target.linux-arm.mk
 include $(LOCAL_PATH)/webkit/common/user_agent/webkit_version.target.linux-arm.mk
 include $(LOCAL_PATH)/webkit/common/webkit_common.target.linux-arm.mk
-include $(LOCAL_PATH)/webkit/plugins/plugins_common.target.linux-arm.mk
 include $(LOCAL_PATH)/webkit/renderer/compositor_bindings/webkit_compositor_bindings.target.linux-arm.mk
 include $(LOCAL_PATH)/webkit/renderer/compositor_bindings/webkit_compositor_support.target.linux-arm.mk
 include $(LOCAL_PATH)/webkit/renderer/webkit_renderer.target.linux-arm.mk
 include $(LOCAL_PATH)/webkit/support/glue.target.linux-arm.mk
 include $(LOCAL_PATH)/webkit/support/glue_child.target.linux-arm.mk
 include $(LOCAL_PATH)/webkit/support/overscroller_jni_headers.target.linux-arm.mk
-include $(LOCAL_PATH)/webkit/support/plugins.target.linux-arm.mk
 include $(LOCAL_PATH)/webkit/webkit_resources.target.linux-arm.mk
 include $(LOCAL_PATH)/webkit/webkit_storage_browser.target.linux-arm.mk
 include $(LOCAL_PATH)/webkit/webkit_storage_common.target.linux-arm.mk
diff --git a/GypAndroid.linux-mips.mk b/GypAndroid.linux-mips.mk
index 07ae768..d3e160f 100644
--- a/GypAndroid.linux-mips.mk
+++ b/GypAndroid.linux-mips.mk
@@ -85,8 +85,6 @@
 include $(LOCAL_PATH)/net/net_jni_headers.target.linux-mips.mk
 include $(LOCAL_PATH)/net/net_resources.target.linux-mips.mk
 include $(LOCAL_PATH)/net/private_key_types_java.target.linux-mips.mk
-include $(LOCAL_PATH)/ppapi/ppapi_c.target.linux-mips.mk
-include $(LOCAL_PATH)/ppapi/ppapi_shared.target.linux-mips.mk
 include $(LOCAL_PATH)/printing/printing.target.linux-mips.mk
 include $(LOCAL_PATH)/sandbox/sandbox.target.linux-mips.mk
 include $(LOCAL_PATH)/sandbox/sandbox_services.target.linux-mips.mk
@@ -146,6 +144,7 @@
 include $(LOCAL_PATH)/third_party/WebKit/Source/wtf/wtf_config.target.linux-mips.mk
 include $(LOCAL_PATH)/third_party/WebKit/public/blink.target.linux-mips.mk
 include $(LOCAL_PATH)/third_party/WebKit/public/blink_minimal.target.linux-mips.mk
+include $(LOCAL_PATH)/third_party/WebKit/public/blink_skia_config.target.linux-mips.mk
 include $(LOCAL_PATH)/third_party/angle_dx11/src/preprocessor.target.linux-mips.mk
 include $(LOCAL_PATH)/third_party/angle_dx11/src/translator_common.target.linux-mips.mk
 include $(LOCAL_PATH)/third_party/angle_dx11/src/translator_glsl.target.linux-mips.mk
@@ -222,14 +221,12 @@
 include $(LOCAL_PATH)/webkit/common/user_agent/user_agent.target.linux-mips.mk
 include $(LOCAL_PATH)/webkit/common/user_agent/webkit_version.target.linux-mips.mk
 include $(LOCAL_PATH)/webkit/common/webkit_common.target.linux-mips.mk
-include $(LOCAL_PATH)/webkit/plugins/plugins_common.target.linux-mips.mk
 include $(LOCAL_PATH)/webkit/renderer/compositor_bindings/webkit_compositor_bindings.target.linux-mips.mk
 include $(LOCAL_PATH)/webkit/renderer/compositor_bindings/webkit_compositor_support.target.linux-mips.mk
 include $(LOCAL_PATH)/webkit/renderer/webkit_renderer.target.linux-mips.mk
 include $(LOCAL_PATH)/webkit/support/glue.target.linux-mips.mk
 include $(LOCAL_PATH)/webkit/support/glue_child.target.linux-mips.mk
 include $(LOCAL_PATH)/webkit/support/overscroller_jni_headers.target.linux-mips.mk
-include $(LOCAL_PATH)/webkit/support/plugins.target.linux-mips.mk
 include $(LOCAL_PATH)/webkit/webkit_resources.target.linux-mips.mk
 include $(LOCAL_PATH)/webkit/webkit_storage_browser.target.linux-mips.mk
 include $(LOCAL_PATH)/webkit/webkit_storage_common.target.linux-mips.mk
diff --git a/GypAndroid.linux-x86.mk b/GypAndroid.linux-x86.mk
index 5ca8972..06bb9bf 100644
--- a/GypAndroid.linux-x86.mk
+++ b/GypAndroid.linux-x86.mk
@@ -90,8 +90,6 @@
 include $(LOCAL_PATH)/net/net_jni_headers.target.linux-x86.mk
 include $(LOCAL_PATH)/net/net_resources.target.linux-x86.mk
 include $(LOCAL_PATH)/net/private_key_types_java.target.linux-x86.mk
-include $(LOCAL_PATH)/ppapi/ppapi_c.target.linux-x86.mk
-include $(LOCAL_PATH)/ppapi/ppapi_shared.target.linux-x86.mk
 include $(LOCAL_PATH)/printing/printing.target.linux-x86.mk
 include $(LOCAL_PATH)/sandbox/sandbox.target.linux-x86.mk
 include $(LOCAL_PATH)/sandbox/sandbox_services.target.linux-x86.mk
@@ -154,6 +152,7 @@
 include $(LOCAL_PATH)/third_party/WebKit/Source/wtf/wtf_config.target.linux-x86.mk
 include $(LOCAL_PATH)/third_party/WebKit/public/blink.target.linux-x86.mk
 include $(LOCAL_PATH)/third_party/WebKit/public/blink_minimal.target.linux-x86.mk
+include $(LOCAL_PATH)/third_party/WebKit/public/blink_skia_config.target.linux-x86.mk
 include $(LOCAL_PATH)/third_party/angle_dx11/src/preprocessor.target.linux-x86.mk
 include $(LOCAL_PATH)/third_party/angle_dx11/src/translator_common.target.linux-x86.mk
 include $(LOCAL_PATH)/third_party/angle_dx11/src/translator_glsl.target.linux-x86.mk
@@ -240,14 +239,12 @@
 include $(LOCAL_PATH)/webkit/common/user_agent/user_agent.target.linux-x86.mk
 include $(LOCAL_PATH)/webkit/common/user_agent/webkit_version.target.linux-x86.mk
 include $(LOCAL_PATH)/webkit/common/webkit_common.target.linux-x86.mk
-include $(LOCAL_PATH)/webkit/plugins/plugins_common.target.linux-x86.mk
 include $(LOCAL_PATH)/webkit/renderer/compositor_bindings/webkit_compositor_bindings.target.linux-x86.mk
 include $(LOCAL_PATH)/webkit/renderer/compositor_bindings/webkit_compositor_support.target.linux-x86.mk
 include $(LOCAL_PATH)/webkit/renderer/webkit_renderer.target.linux-x86.mk
 include $(LOCAL_PATH)/webkit/support/glue.target.linux-x86.mk
 include $(LOCAL_PATH)/webkit/support/glue_child.target.linux-x86.mk
 include $(LOCAL_PATH)/webkit/support/overscroller_jni_headers.target.linux-x86.mk
-include $(LOCAL_PATH)/webkit/support/plugins.target.linux-x86.mk
 include $(LOCAL_PATH)/webkit/webkit_resources.target.linux-x86.mk
 include $(LOCAL_PATH)/webkit/webkit_storage_browser.target.linux-x86.mk
 include $(LOCAL_PATH)/webkit/webkit_storage_common.target.linux-x86.mk
diff --git a/NOTICE b/NOTICE
index 2d19b86..3e42dcf 100644
--- a/NOTICE
+++ b/NOTICE
@@ -522,72 +522,6 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
-Copyright 2007, 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.
-
--------------------------------------------------------------------------------
-
-The file url_parse.cc is based on nsURLParsers.cc from Mozilla. This file is
-licensed separately as follows:
-
-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 mozilla.org code.
-
-The Initial Developer of the Original Code is
-Netscape Communications Corporation.
-Portions created by the Initial Developer are Copyright (C) 1998
-the Initial Developer. All Rights Reserved.
-
-Contributor(s):
-  Darin Fisher (original author)
-
-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.
-
 Copyright 2011, The Chromium Authors
 All rights reserved.
 
@@ -7997,6 +7931,138 @@
 
 */
 
+Copyright 2007, 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.
+
+-------------------------------------------------------------------------------
+
+The file url_parse.cc is based on nsURLParsers.cc from Mozilla. This file is
+licensed separately as follows:
+
+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 mozilla.org code.
+
+The Initial Developer of the Original Code is
+Netscape Communications Corporation.
+Portions created by the Initial Developer are Copyright (C) 1998
+the Initial Developer. All Rights Reserved.
+
+Contributor(s):
+  Darin Fisher (original author)
+
+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.
+
+Copyright 2007, 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.
+
+-------------------------------------------------------------------------------
+
+The file url_parse.cc is based on nsURLParsers.cc from Mozilla. This file is
+licensed separately as follows:
+
+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 mozilla.org code.
+
+The Initial Developer of the Original Code is
+Netscape Communications Corporation.
+Portions created by the Initial Developer are Copyright (C) 1998
+the Initial Developer. All Rights Reserved.
+
+Contributor(s):
+  Darin Fisher (original author)
+
+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.
+
 This license applies to all parts of V8 that are not externally
 maintained libraries.  The externally maintained libraries used by V8
 are:
diff --git a/WATCHLISTS b/WATCHLISTS
index 995f53c..b9c1b36 100644
--- a/WATCHLISTS
+++ b/WATCHLISTS
@@ -262,6 +262,14 @@
     'fullscreen_controller': {
       'filepath': 'fullscreen_controller',
     },
+    'geolocation': {
+      'filepath': 'chrome/browser/geolocation/|'\
+                  'content/browser/geolocation|'\
+                  'content/public/common/geoposition.*|'\
+                  'content/public/browser/geolocation.*|'\
+                  'content/renderer/geolocation.*|'\
+                  'content/shell/geolocation/',
+    },
     'gfx_image': {
       'filepath': 'ui/gfx/image/',
     },
@@ -676,6 +684,7 @@
     'filebrowse': ['rginda+watch@chromium.org'],
     'ftp': ['phajdan.jr@chromium.org'],
     'fullscreen_controller': ['scheib+watch@chromium.org'],
+    'geolocation': ['mvanouwerkerk@chromium.org'],
     'gfx_geometry': ['cc-bugs@chromium.org'],
     'gfx_image': ['rsesek+watch@chromium.org'],
     'gpu': ['apatrick@chromium.org'],
diff --git a/android_webview/android_webview.gyp b/android_webview/android_webview.gyp
index 237712a..1653997 100644
--- a/android_webview/android_webview.gyp
+++ b/android_webview/android_webview.gyp
@@ -85,6 +85,7 @@
         '../gpu/gpu.gyp:command_buffer_service',
         '../gpu/gpu.gyp:gles2_implementation',
         '../ui/gl/gl.gyp:gl',
+        '../ui/ui.gyp:shell_dialogs',
         '../webkit/common/gpu/webkit_gpu.gyp:webkit_gpu',
         'android_webview_pak',
       ],
diff --git a/android_webview/android_webview_common.target.darwin-arm.mk b/android_webview/android_webview_common.target.darwin-arm.mk
index 5e3624e..b07ae11 100644
--- a/android_webview/android_webview_common.target.darwin-arm.mk
+++ b/android_webview/android_webview_common.target.darwin-arm.mk
@@ -124,6 +124,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
@@ -233,6 +234,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
diff --git a/android_webview/android_webview_common.target.darwin-mips.mk b/android_webview/android_webview_common.target.darwin-mips.mk
index c775bc5..0f138a1 100644
--- a/android_webview/android_webview_common.target.darwin-mips.mk
+++ b/android_webview/android_webview_common.target.darwin-mips.mk
@@ -123,6 +123,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
@@ -231,6 +232,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
diff --git a/android_webview/android_webview_common.target.darwin-x86.mk b/android_webview/android_webview_common.target.darwin-x86.mk
index 0044f93..7ee937e 100644
--- a/android_webview/android_webview_common.target.darwin-x86.mk
+++ b/android_webview/android_webview_common.target.darwin-x86.mk
@@ -126,6 +126,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
@@ -238,6 +239,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
diff --git a/android_webview/android_webview_common.target.linux-arm.mk b/android_webview/android_webview_common.target.linux-arm.mk
index 5e3624e..b07ae11 100644
--- a/android_webview/android_webview_common.target.linux-arm.mk
+++ b/android_webview/android_webview_common.target.linux-arm.mk
@@ -124,6 +124,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
@@ -233,6 +234,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
diff --git a/android_webview/android_webview_common.target.linux-mips.mk b/android_webview/android_webview_common.target.linux-mips.mk
index c775bc5..0f138a1 100644
--- a/android_webview/android_webview_common.target.linux-mips.mk
+++ b/android_webview/android_webview_common.target.linux-mips.mk
@@ -123,6 +123,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
@@ -231,6 +232,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
diff --git a/android_webview/android_webview_common.target.linux-x86.mk b/android_webview/android_webview_common.target.linux-x86.mk
index 0044f93..7ee937e 100644
--- a/android_webview/android_webview_common.target.linux-x86.mk
+++ b/android_webview/android_webview_common.target.linux-x86.mk
@@ -126,6 +126,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
@@ -238,6 +239,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
diff --git a/android_webview/browser/browser_view_renderer.h b/android_webview/browser/browser_view_renderer.h
index 9e02959..78beb17 100644
--- a/android_webview/browser/browser_view_renderer.h
+++ b/android_webview/browser/browser_view_renderer.h
@@ -6,10 +6,12 @@
 #define ANDROID_WEBVIEW_BROWSER_BROWSER_VIEW_RENDERER_H_
 
 #include "base/android/scoped_java_ref.h"
+#include "skia/ext/refptr.h"
 #include "ui/gfx/point.h"
 #include "ui/gfx/rect.h"
 #include "ui/gfx/vector2d_f.h"
 
+class SkPicture;
 struct AwDrawGLInfo;
 struct AwDrawSWFunctionTable;
 
@@ -84,7 +86,6 @@
   // Global hookup methods.
   static void SetAwDrawSWFunctionTable(AwDrawSWFunctionTable* table);
   static AwDrawSWFunctionTable* GetAwDrawSWFunctionTable();
-  static bool IsSkiaVersionCompatible();
 
   // Rendering methods.
 
@@ -108,9 +109,7 @@
   virtual void SetGlobalVisibleRect(const gfx::Rect& visible_rect) = 0;
 
   // CapturePicture API methods.
-  virtual base::android::ScopedJavaLocalRef<jobject> CapturePicture(
-      int width,
-      int height) = 0;
+  virtual skia::RefPtr<SkPicture> CapturePicture(int width, int height) = 0;
   virtual void EnableOnNewPicture(bool enabled) = 0;
 
   // View update notifications.
diff --git a/android_webview/browser/in_process_view_renderer.cc b/android_webview/browser/in_process_view_renderer.cc
index 3e25680..39614d3 100644
--- a/android_webview/browser/in_process_view_renderer.cc
+++ b/android_webview/browser/in_process_view_renderer.cc
@@ -22,7 +22,6 @@
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/web_contents.h"
 #include "gpu/command_buffer/service/in_process_command_buffer.h"
-#include "skia/ext/refptr.h"
 #include "third_party/skia/include/core/SkBitmap.h"
 #include "third_party/skia/include/core/SkCanvas.h"
 #include "third_party/skia/include/core/SkDevice.h"
@@ -64,13 +63,11 @@
   InProcessViewRenderer* instance_;
 };
 
-typedef base::Callback<bool(SkCanvas*)> RenderMethod;
-
 bool RasterizeIntoBitmap(JNIEnv* env,
                          const JavaRef<jobject>& jbitmap,
                          int scroll_x,
                          int scroll_y,
-                         const RenderMethod& renderer) {
+                         const InProcessViewRenderer::RenderMethod& renderer) {
   DCHECK(jbitmap.obj());
 
   AndroidBitmapInfo bitmap_info;
@@ -113,6 +110,26 @@
   return true;
 }
 
+class ScopedPixelAccess {
+ public:
+  ScopedPixelAccess(JNIEnv* env, jobject java_canvas) {
+    AwDrawSWFunctionTable* sw_functions =
+        BrowserViewRenderer::GetAwDrawSWFunctionTable();
+    pixels_ = sw_functions ?
+      sw_functions->access_pixels(env, java_canvas) : NULL;
+  }
+  ~ScopedPixelAccess() {
+    if (pixels_)
+      BrowserViewRenderer::GetAwDrawSWFunctionTable()->release_pixels(pixels_);
+  }
+  AwPixelInfo* pixels() { return pixels_; }
+
+ private:
+  AwPixelInfo* pixels_;
+
+  DISALLOW_IMPLICIT_CONSTRUCTORS(ScopedPixelAccess);
+};
+
 bool HardwareEnabled() {
   static bool g_hw_enabled = !CommandLine::ForCurrentProcess()->HasSwitch(
       switches::kDisableWebViewGLMode);
@@ -123,13 +140,6 @@
 // Allows preventing extra copies of data when rendering.
 AwDrawSWFunctionTable* g_sw_draw_functions = NULL;
 
-// Tells if the Skia library versions in Android and Chromium are compatible.
-// If they are then it's possible to pass Skia objects like SkPictures to the
-// Android glue layer via the SW rendering functions.
-// If they are not, then additional copies and rasterizations are required
-// as a fallback mechanism, which will have an important performance impact.
-bool g_is_skia_version_compatible = false;
-
 const int64 kFallbackTickTimeoutInMilliseconds = 20;
 
 class ScopedAllowGL {
@@ -180,11 +190,6 @@
 void BrowserViewRenderer::SetAwDrawSWFunctionTable(
     AwDrawSWFunctionTable* table) {
   g_sw_draw_functions = table;
-  g_is_skia_version_compatible =
-      g_sw_draw_functions->is_skia_version_compatible(&SkGraphics::GetVersion);
-  LOG_IF(WARNING, !g_is_skia_version_compatible)
-      << "Skia versions are not compatible, rendering performance will suffer.";
-
   gpu::InProcessCommandBuffer::SetScheduleCallback(
       base::Bind(&ScheduleGpuWork));
 }
@@ -194,12 +199,6 @@
   return g_sw_draw_functions;
 }
 
-// static
-bool BrowserViewRenderer::IsSkiaVersionCompatible() {
-  DCHECK(g_sw_draw_functions);
-  return g_is_skia_version_compatible;
-}
-
 InProcessViewRenderer::InProcessViewRenderer(
     BrowserViewRenderer::Client* client,
     JavaHelper* java_helper,
@@ -213,6 +212,7 @@
       page_scale_factor_(1.0),
       on_new_picture_enable_(false),
       compositor_needs_continuous_invalidate_(false),
+      need_fast_invalidate_(false),
       block_invalidates_(false),
       width_(0),
       height_(0),
@@ -305,7 +305,6 @@
 
 void InProcessViewRenderer::DrawGL(AwDrawGLInfo* draw_info) {
   TRACE_EVENT0("android_webview", "InProcessViewRenderer::DrawGL");
-  DCHECK(visible_);
 
   manager_key_ = g_view_renderer_manager.Get().DidDrawGL(manager_key_, this);
 
@@ -330,8 +329,19 @@
     }
   }
 
-  if (draw_info->mode == AwDrawGLInfo::kModeProcess)
+  if (draw_info->mode == AwDrawGLInfo::kModeProcess) {
+    TRACE_EVENT_INSTANT0(
+        "android_webview", "EarlyOut_ModeProcess", TRACE_EVENT_SCOPE_THREAD);
     return;
+  }
+
+  UpdateCachedGlobalVisibleRect();
+  if (cached_global_visible_rect_.IsEmpty()) {
+    TRACE_EVENT_INSTANT0("android_webview",
+                         "EarlyOut_EmptyVisibleRect",
+                         TRACE_EVENT_SCOPE_THREAD);
+    return;
+  }
 
   // DrawGL may be called without OnDraw, so cancel |fallback_tick_| here as
   // well just to be safe.
@@ -361,6 +371,15 @@
                       draw_info->clip_top,
                       draw_info->clip_right - draw_info->clip_left,
                       draw_info->clip_bottom - draw_info->clip_top);
+
+  // Assume we always draw the full visible rect if we are drawing into a layer.
+  bool drew_full_visible_rect = true;
+
+  if (!draw_info->is_layer) {
+    clip_rect.Intersect(cached_global_visible_rect_);
+    drew_full_visible_rect = clip_rect.Contains(cached_global_visible_rect_);
+  }
+
   block_invalidates_ = true;
   // TODO(joth): Check return value.
   compositor_->DemandDrawHw(gfx::Size(draw_info->width, draw_info->height),
@@ -370,8 +389,6 @@
   block_invalidates_ = false;
   gl_surface_->ResetBackingFrameBufferObject();
 
-  UpdateCachedGlobalVisibleRect();
-  bool drew_full_visible_rect = clip_rect.Contains(cached_global_visible_rect_);
   EnsureContinuousInvalidation(draw_info, !drew_full_visible_rect);
 }
 
@@ -382,7 +399,6 @@
 
 bool InProcessViewRenderer::DrawSWInternal(jobject java_canvas,
                                            const gfx::Rect& clip) {
-  TRACE_EVENT0("android_webview", "InProcessViewRenderer::DrawSW");
   fallback_tick_.Cancel();
 
   if (clip.IsEmpty()) {
@@ -397,17 +413,57 @@
     return false;
   }
 
-  JNIEnv* env = AttachCurrentThread();
+  return RenderViaAuxilaryBitmapIfNeeded(
+      java_canvas,
+      java_helper_,
+      scroll_at_start_of_frame_,
+      clip,
+      base::Bind(&InProcessViewRenderer::CompositeSW,
+                 base::Unretained(this)),
+      web_contents_);
+}
 
-  AwDrawSWFunctionTable* sw_functions = GetAwDrawSWFunctionTable();
-  AwPixelInfo* pixels = sw_functions ?
-      sw_functions->access_pixels(env, java_canvas) : NULL;
-  // Render into an auxiliary bitmap if pixel info is not available.
-  ScopedJavaLocalRef<jobject> jcanvas(env, java_canvas);
-  if (pixels == NULL) {
+// static
+bool InProcessViewRenderer::RenderViaAuxilaryBitmapIfNeeded(
+      jobject java_canvas,
+      BrowserViewRenderer::JavaHelper* java_helper,
+      const gfx::Vector2d& scroll_correction,
+      const gfx::Rect& clip,
+      InProcessViewRenderer::RenderMethod render_source,
+      void* owner_key) {
+  TRACE_EVENT0("android_webview",
+               "InProcessViewRenderer::RenderViaAuxilaryBitmapIfNeeded");
+
+  JNIEnv* env = AttachCurrentThread();
+  ScopedPixelAccess auto_release_pixels(env, java_canvas);
+  AwPixelInfo* pixels = auto_release_pixels.pixels();
+  SkMatrix matrix;
+  SkBitmap::Config config(SkBitmap::kNo_Config);
+  if (pixels) {
+    switch (pixels->config) {
+      case AwConfig_ARGB_8888:
+        config = SkBitmap::kARGB_8888_Config;
+        break;
+      case AwConfig_RGB_565:
+        config = SkBitmap::kRGB_565_Config;
+        break;
+    }
+
+    for (int i = 0; i < 9; i++) {
+      matrix.set(i, pixels->matrix[i]);
+    }
+    // Workaround for http://crbug.com/271096: SW draw only supports
+    // translate & scale transforms.
+    if (matrix.getType() & ~(SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask))
+      config = SkBitmap::kNo_Config;
+  }
+
+  if (config == SkBitmap::kNo_Config) {
+    // Render into an auxiliary bitmap if pixel info is not available.
+    ScopedJavaLocalRef<jobject> jcanvas(env, java_canvas);
     TRACE_EVENT0("android_webview", "RenderToAuxBitmap");
-    ScopedJavaLocalRef<jobject> jbitmap(java_helper_->CreateBitmap(
-        env, clip.width(), clip.height(), jcanvas, web_contents_));
+    ScopedJavaLocalRef<jobject> jbitmap(java_helper->CreateBitmap(
+        env, clip.width(), clip.height(), jcanvas, owner_key));
     if (!jbitmap.obj()) {
       TRACE_EVENT_INSTANT0("android_webview",
                            "EarlyOut_BitmapAllocFail",
@@ -416,68 +472,57 @@
     }
 
     if (!RasterizeIntoBitmap(env, jbitmap,
-                             clip.x() - scroll_at_start_of_frame_.x(),
-                             clip.y() - scroll_at_start_of_frame_.y(),
-                             base::Bind(&InProcessViewRenderer::CompositeSW,
-                                        base::Unretained(this)))) {
+                             clip.x() - scroll_correction.x(),
+                             clip.y() - scroll_correction.y(),
+                             render_source)) {
       TRACE_EVENT_INSTANT0("android_webview",
                            "EarlyOut_RasterizeFail",
                            TRACE_EVENT_SCOPE_THREAD);
       return false;
     }
 
-    java_helper_->DrawBitmapIntoCanvas(env, jbitmap, jcanvas,
-                                       clip.x(), clip.y());
+    java_helper->DrawBitmapIntoCanvas(env, jbitmap, jcanvas,
+                                      clip.x(), clip.y());
     return true;
   }
 
   // Draw in a SkCanvas built over the pixel information.
-  bool succeeded = false;
-  {
-    SkBitmap bitmap;
-    bitmap.setConfig(static_cast<SkBitmap::Config>(pixels->config),
-                     pixels->width,
-                     pixels->height,
-                     pixels->row_bytes);
-    bitmap.setPixels(pixels->pixels);
-    SkDevice device(bitmap);
-    SkCanvas canvas(&device);
-    SkMatrix matrix;
-    for (int i = 0; i < 9; i++)
-      matrix.set(i, pixels->matrix[i]);
-    canvas.setMatrix(matrix);
+  SkBitmap bitmap;
+  bitmap.setConfig(config,
+                   pixels->width,
+                   pixels->height,
+                   pixels->row_bytes);
+  bitmap.setPixels(pixels->pixels);
+  SkDevice device(bitmap);
+  SkCanvas canvas(&device);
+  canvas.setMatrix(matrix);
 
-    if (pixels->clip_region_size) {
-      SkRegion clip_region;
-      size_t bytes_read = clip_region.readFromMemory(pixels->clip_region);
-      DCHECK_EQ(pixels->clip_region_size, bytes_read);
-      canvas.setClipRegion(clip_region);
-    } else {
-      canvas.clipRect(gfx::RectToSkRect(clip));
+  if (pixels->clip_rect_count) {
+    SkRegion clip;
+    for (int i = 0; i < pixels->clip_rect_count; ++i) {
+      clip.op(SkIRect::MakeXYWH(pixels->clip_rects[i + 0],
+                                pixels->clip_rects[i + 1],
+                                pixels->clip_rects[i + 2],
+                                pixels->clip_rects[i + 3]),
+              SkRegion::kUnion_Op);
     }
-    canvas.translate(scroll_at_start_of_frame_.x(),
-                     scroll_at_start_of_frame_.y());
-
-    succeeded = CompositeSW(&canvas);
+    canvas.setClipRegion(clip);
   }
 
-  sw_functions->release_pixels(pixels);
-  return succeeded;
+  canvas.translate(scroll_correction.x(),
+                   scroll_correction.y());
+
+  return render_source.Run(&canvas);
 }
 
-base::android::ScopedJavaLocalRef<jobject>
-InProcessViewRenderer::CapturePicture(int width, int height) {
-  if (!compositor_ || !GetAwDrawSWFunctionTable()) {
-    TRACE_EVENT_INSTANT0(
-        "android_webview", "EarlyOut_CapturePicture", TRACE_EVENT_SCOPE_THREAD);
-    return ScopedJavaLocalRef<jobject>();
-  }
+skia::RefPtr<SkPicture> InProcessViewRenderer::CapturePicture(int width,
+                                                              int height) {
+  TRACE_EVENT0("android_webview", "InProcessViewRenderer::CapturePicture");
 
   // Return empty Picture objects for empty SkPictures.
-  JNIEnv* env = AttachCurrentThread();
+  skia::RefPtr<SkPicture> picture = skia::AdoptRef(new SkPicture);
   if (width <= 0 || height <= 0) {
-    return java_helper_->RecordBitmapIntoPicture(env,
-                                                 ScopedJavaLocalRef<jobject>());
+    return picture;
   }
 
   // Reset scroll back to the origin, will go back to the old
@@ -485,36 +530,11 @@
   base::AutoReset<gfx::Vector2dF> scroll_reset(&scroll_offset_css_,
                                                gfx::Vector2d());
 
-  skia::RefPtr<SkPicture> picture = skia::AdoptRef(new SkPicture);
   SkCanvas* rec_canvas = picture->beginRecording(width, height, 0);
-  if (!CompositeSW(rec_canvas))
-    return ScopedJavaLocalRef<jobject>();
+  if (compositor_)
+    CompositeSW(rec_canvas);
   picture->endRecording();
-
-  if (IsSkiaVersionCompatible()) {
-    // Add a reference that the create_picture() will take ownership of.
-    picture->ref();
-    return ScopedJavaLocalRef<jobject>(env,
-        GetAwDrawSWFunctionTable()->create_picture(env, picture.get()));
-  }
-
-  // If Skia versions are not compatible, workaround it by rasterizing the
-  // picture into a bitmap and drawing it into a new Java picture. Pass null
-  // for |canvas| as we don't have java canvas at this point (and it would be
-  // software anyway).
-  ScopedJavaLocalRef<jobject> jbitmap(java_helper_->CreateBitmap(
-      env, picture->width(), picture->height(), ScopedJavaLocalRef<jobject>(),
-      NULL));
-  if (!jbitmap.obj())
-    return ScopedJavaLocalRef<jobject>();
-
-  if (!RasterizeIntoBitmap(env, jbitmap, 0, 0,
-      base::Bind(&RenderPictureToCanvas,
-                 base::Unretained(picture.get())))) {
-    return ScopedJavaLocalRef<jobject>();
-  }
-
-  return java_helper_->RecordBitmapIntoPicture(env, jbitmap);
+  return picture;
 }
 
 void InProcessViewRenderer::EnableOnNewPicture(bool enabled) {
@@ -620,6 +640,7 @@
                        "invalidate",
                        invalidate);
   compositor_needs_continuous_invalidate_ = invalidate;
+  need_fast_invalidate_ = compositor_needs_continuous_invalidate_;
   EnsureContinuousInvalidation(NULL, false);
 }
 
@@ -726,11 +747,17 @@
     // ticked. This can happen if this is reached because
     // invalidate_ignore_compositor is true.
     if (compositor_needs_continuous_invalidate_) {
+      int64 delay_in_ms = kFallbackTickTimeoutInMilliseconds;
+      if (need_fast_invalidate_) {
+        TRACE_EVENT_INSTANT0(
+            "android_webview", "FastFallbackTick", TRACE_EVENT_SCOPE_THREAD);
+        delay_in_ms = 0;
+        need_fast_invalidate_ = false;
+      }
       base::MessageLoop::current()->PostDelayedTask(
           FROM_HERE,
           fallback_tick_.callback(),
-          base::TimeDelta::FromMilliseconds(
-              kFallbackTickTimeoutInMilliseconds));
+          base::TimeDelta::FromMilliseconds(delay_in_ms));
     }
   }
 }
diff --git a/android_webview/browser/in_process_view_renderer.h b/android_webview/browser/in_process_view_renderer.h
index 8bb2c60..e86796f 100644
--- a/android_webview/browser/in_process_view_renderer.h
+++ b/android_webview/browser/in_process_view_renderer.h
@@ -38,6 +38,16 @@
   static InProcessViewRenderer* FromWebContents(
       content::WebContents* contents);
 
+  // TODO(joth): consider extracting this to its own utility class.
+  typedef base::Callback<bool(SkCanvas*)> RenderMethod;
+  static bool RenderViaAuxilaryBitmapIfNeeded(
+      jobject java_canvas,
+      JavaHelper* java_helper,
+      const gfx::Vector2d& scroll_correction,
+      const gfx::Rect& clip,
+      RenderMethod render_source,
+      void* owner_key);
+
   // BrowserViewRenderer overrides
   virtual bool OnDraw(jobject java_canvas,
                       bool is_hardware_canvas,
@@ -45,9 +55,8 @@
                       const gfx::Rect& clip) OVERRIDE;
   virtual void DrawGL(AwDrawGLInfo* draw_info) OVERRIDE;
   virtual void SetGlobalVisibleRect(const gfx::Rect& visible_rect) OVERRIDE;
-  virtual base::android::ScopedJavaLocalRef<jobject> CapturePicture(
-      int width,
-      int height) OVERRIDE;
+  virtual skia::RefPtr<SkPicture> CapturePicture(int width,
+                                                 int height) OVERRIDE;
   virtual void EnableOnNewPicture(bool enabled) OVERRIDE;
   virtual void OnVisibilityChanged(bool visible) OVERRIDE;
   virtual void OnSizeChanged(int width, int height) OVERRIDE;
@@ -117,6 +126,13 @@
   // states.
   bool compositor_needs_continuous_invalidate_;
 
+  // If this is true, then the fallback tick is posted with zero delay. This
+  // is to reduce the time in cases when blink main thread is blocked waiting.
+  // This is set when |compositor_needs_continuous_invalidate_| is set.
+  // Eventually, this should correspond to BeginFrame when BeginFrame and
+  // BeginFrameDeadline are separate functions.
+  bool need_fast_invalidate_;
+
   // Used to block additional invalidates while one is already pending or before
   // compositor draw which may switch continuous_invalidate on and off in the
   // process.
diff --git a/android_webview/buildbot/deps_whitelist.py b/android_webview/buildbot/deps_whitelist.py
index 69c87be..105646f 100755
--- a/android_webview/buildbot/deps_whitelist.py
+++ b/android_webview/buildbot/deps_whitelist.py
@@ -32,7 +32,6 @@
 
     # Dependencies that need to be merged into the Android tree.
     self._snapshot_into_android_dependencies = [
-      'googleurl',
       'sdch/open-vcdiff',
       'testing/gtest',
       'third_party/WebKit',
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 099a6e9..493e75b 100644
--- a/android_webview/java/src/org/chromium/android_webview/AwContents.java
+++ b/android_webview/java/src/org/chromium/android_webview/AwContents.java
@@ -11,6 +11,7 @@
 import android.graphics.Color;
 import android.graphics.Picture;
 import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
 import android.net.http.SslCertificate;
 import android.os.AsyncTask;
 import android.os.Build;
@@ -124,6 +125,11 @@
         void setMeasuredDimension(int measuredWidth, int measuredHeight);
 
         /**
+         * @see View#getScrollBarStyle()
+         */
+        int super_getScrollBarStyle();
+
+        /**
          * Requests a callback on the native DrawGL method (see getAwDrawGLFunction)
          * if called from within onDraw, |canvas| will be non-null and hardware accelerated.
          * otherwise, |canvas| will be null, and the container view itself will be hardware
@@ -500,6 +506,7 @@
                 new OverScroller(mContainerView.getContext()));
 
         setOverScrollMode(mContainerView.getOverScrollMode());
+        setScrollBarStyle(mInternalAccessAdapter.super_getScrollBarStyle());
 
         setNewAwContents(nativeInit(browserContext));
     }
@@ -664,7 +671,10 @@
 
     @CalledByNative
     private void updateGlobalVisibleRect() {
-        mContainerView.getGlobalVisibleRect(sLocalGlobalVisibleRect);
+        if (!mContainerView.getGlobalVisibleRect(sLocalGlobalVisibleRect)) {
+            sLocalGlobalVisibleRect.setEmpty();
+        }
+
         nativeSetGlobalVisibleRect(mNativeAwContents, sLocalGlobalVisibleRect.left,
                 sLocalGlobalVisibleRect.top, sLocalGlobalVisibleRect.right,
                 sLocalGlobalVisibleRect.bottom);
@@ -714,9 +724,9 @@
     }
 
     public Picture capturePicture() {
-        return nativeCapturePicture(mNativeAwContents,
-                mScrollOffsetManager.computeHorizontalScrollRange(),
-                mScrollOffsetManager.computeVerticalScrollRange());
+        return new AwPicture(nativeCapturePicture(mNativeAwContents,
+                    mScrollOffsetManager.computeHorizontalScrollRange(),
+                    mScrollOffsetManager.computeVerticalScrollRange()));
     }
 
     /**
@@ -889,6 +899,54 @@
         }
     }
 
+    // TODO(mkosiba): In WebViewClassic these appear in some of the scroll extent calculation
+    // methods but toggling them has no visiual effect on the content (in other words the scrolling
+    // code behaves as if the scrollbar-related padding is in place but the onDraw code doesn't
+    // take that into consideration).
+    // http://crbug.com/269032
+    private boolean mOverlayHorizontalScrollbar = true;
+    private boolean mOverlayVerticalScrollbar = false;
+
+    /**
+     * @see View#setScrollBarStyle(int)
+     */
+    public void setScrollBarStyle(int style) {
+        if (style == View.SCROLLBARS_INSIDE_OVERLAY
+                || style == View.SCROLLBARS_OUTSIDE_OVERLAY) {
+            mOverlayHorizontalScrollbar = mOverlayVerticalScrollbar = true;
+        } else {
+            mOverlayHorizontalScrollbar = mOverlayVerticalScrollbar = false;
+        }
+    }
+
+    /**
+     * @see View#setHorizontalScrollbarOverlay(boolean)
+     */
+    public void setHorizontalScrollbarOverlay(boolean overlay) {
+        mOverlayHorizontalScrollbar = overlay;
+    }
+
+    /**
+     * @see View#setVerticalScrollbarOverlay(boolean)
+     */
+    public void setVerticalScrollbarOverlay(boolean overlay) {
+        mOverlayVerticalScrollbar = overlay;
+    }
+
+    /**
+     * @see View#overlayHorizontalScrollbar()
+     */
+    public boolean overlayHorizontalScrollbar() {
+        return mOverlayVerticalScrollbar;
+    }
+
+    /**
+     * @see View#overlayVerticalScrollbar()
+     */
+    public boolean overlayVerticalScrollbar() {
+        return mOverlayVerticalScrollbar;
+    }
+
     /**
      * Called by the embedder when the scroll offset of the containing view has changed.
      * @see View#onScrollChanged(int,int)
@@ -1811,7 +1869,7 @@
     private native void nativeSetBackgroundColor(int nativeAwContents, int color);
 
     private native int nativeGetAwDrawGLViewContext(int nativeAwContents);
-    private native Picture nativeCapturePicture(int nativeAwContents, int width, int height);
+    private native int nativeCapturePicture(int nativeAwContents, int width, int height);
     private native void nativeEnableOnNewPicture(int nativeAwContents, boolean enabled);
 
     private native void nativeInvokeGeolocationCallback(
diff --git a/android_webview/java/src/org/chromium/android_webview/AwContentsClient.java b/android_webview/java/src/org/chromium/android_webview/AwContentsClient.java
index f1c7f45..3f2245c 100644
--- a/android_webview/java/src/org/chromium/android_webview/AwContentsClient.java
+++ b/android_webview/java/src/org/chromium/android_webview/AwContentsClient.java
@@ -199,6 +199,14 @@
     //             WebView specific methods that map directly to WebViewClient / WebChromeClient
     //--------------------------------------------------------------------------------------------
 
+    public static class FileChooserParams {
+        public int mode;
+        public String acceptTypes;
+        public String title;
+        public String defaultFilename;
+        public boolean capture;
+    }
+
     public abstract void getVisitedHistory(ValueCallback<String[]> callback);
 
     public abstract void doUpdateVisitedHistory(String url, boolean isReload);
@@ -229,6 +237,10 @@
     public abstract void onDownloadStart(String url, String userAgent, String contentDisposition,
             String mimeType, long contentLength);
 
+    // TODO(joth): Make abstract once this has rolled in downstream.
+    public /*abstract*/ void showFileChooser(ValueCallback<String[]> uploadFilePathsCallback,
+            FileChooserParams fileChooserParams) { }
+
     public abstract void onGeolocationPermissionsShowPrompt(String origin,
             GeolocationPermissions.Callback callback);
 
diff --git a/android_webview/java/src/org/chromium/android_webview/AwPicture.java b/android_webview/java/src/org/chromium/android_webview/AwPicture.java
new file mode 100644
index 0000000..30ec57b
--- /dev/null
+++ b/android_webview/java/src/org/chromium/android_webview/AwPicture.java
@@ -0,0 +1,95 @@
+// 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.
+
+package org.chromium.android_webview;
+
+import android.graphics.Canvas;
+import android.graphics.Picture;
+import android.graphics.Rect;
+
+import org.chromium.base.CalledByNative;
+import org.chromium.base.JNINamespace;
+import org.chromium.content.common.CleanupReference;
+
+import java.io.OutputStream;
+
+// A simple wrapper around a SkPicture, that allows final rendering to be performed using the
+// chromium skia library.
+@JNINamespace("android_webview")
+class AwPicture extends Picture {
+
+    private int mNativeAwPicture;
+
+    // There is no explicit destroy method on Picture base-class, so cleanup is always
+    // handled via the CleanupReference.
+    private static final class DestroyRunnable implements Runnable {
+        private int mNativeAwPicture;
+        private DestroyRunnable(int nativeAwPicture) {
+            mNativeAwPicture = nativeAwPicture;
+        }
+        @Override
+        public void run() {
+            nativeDestroy(mNativeAwPicture);
+        }
+    }
+
+    private CleanupReference mCleanupReference;
+
+    /**
+     * @param nativeAwPicture is an instance of the AwPicture native class. Ownership is
+     *                        taken by this java instance.
+     */
+    AwPicture(int nativeAwPicture) {
+        mNativeAwPicture = nativeAwPicture;
+        mCleanupReference = new CleanupReference(this, new DestroyRunnable(nativeAwPicture));
+    }
+
+    @Override
+    public Canvas beginRecording(int width, int height) {
+        unsupportedOperation();
+        return null;
+    }
+
+    @Override
+    public void endRecording() {
+        // Intentional no-op. The native picture ended recording prior to java c'tor call.
+    }
+
+    @Override
+    public int getWidth() {
+        return nativeGetWidth(mNativeAwPicture);
+    }
+
+    @Override
+    public int getHeight() {
+        return nativeGetHeight(mNativeAwPicture);
+    }
+
+    // Effectively a local variable of draw(), but held as a member to avoid GC churn.
+    private Rect mClipBoundsTemporary = new Rect();
+
+    @Override
+    public void draw(Canvas canvas) {
+        canvas.getClipBounds(mClipBoundsTemporary);
+        nativeDraw(mNativeAwPicture, canvas,
+                mClipBoundsTemporary.left, mClipBoundsTemporary.top,
+                mClipBoundsTemporary.right, mClipBoundsTemporary.bottom);
+    }
+
+    @Override
+    public void writeToStream(OutputStream stream) {
+        unsupportedOperation();
+    }
+
+    private void unsupportedOperation() {
+        throw new IllegalStateException("Unsupported in AwPicture");
+    }
+
+    private static native void nativeDestroy(int nativeAwPicture);
+    private native int nativeGetWidth(int nativeAwPicture);
+    private native int nativeGetHeight(int nativeAwPicture);
+    private native void nativeDraw(int nativeAwPicture, Canvas canvas,
+            int left, int top, int right, int bottom);
+}
+
diff --git a/android_webview/java/src/org/chromium/android_webview/AwWebContentsDelegate.java b/android_webview/java/src/org/chromium/android_webview/AwWebContentsDelegate.java
index 23f48eb..d26fd9a 100644
--- a/android_webview/java/src/org/chromium/android_webview/AwWebContentsDelegate.java
+++ b/android_webview/java/src/org/chromium/android_webview/AwWebContentsDelegate.java
@@ -4,6 +4,8 @@
 
 package org.chromium.android_webview;
 
+import com.google.common.annotations.VisibleForTesting;
+
 import org.chromium.base.CalledByNative;
 import org.chromium.base.JNINamespace;
 import org.chromium.components.web_contents_delegate_android.WebContentsDelegateAndroid;
@@ -14,8 +16,14 @@
  * It should contain abstract WebContentsDelegate methods to be implemented by the embedder.
  * These methods belong to WebView but are not shared with the Chromium Android port.
  */
+@VisibleForTesting
 @JNINamespace("android_webview")
 public abstract class AwWebContentsDelegate extends WebContentsDelegateAndroid {
+    // Callback filesSelectedInChooser() when done.
+    @CalledByNative
+    public abstract void runFileChooser(int processId, int renderId, int mode_flags,
+            String acceptTypes, String title, String defaultFilename,  boolean capture);
+
     @CalledByNative
     public abstract boolean addNewContents(boolean isDialog, boolean isUserGesture);
 
@@ -33,4 +41,8 @@
     @CalledByNative
     public void updatePreferredSize(int widthCss, int heightCss) {
     }
+
+    // Call in response to a prior runFileChooser call.
+    protected static native void nativeFilesSelectedInChooser(int processId, int renderId,
+            int mode_flags, String[] filePath);
 }
diff --git a/android_webview/java/src/org/chromium/android_webview/AwWebContentsDelegateAdapter.java b/android_webview/java/src/org/chromium/android_webview/AwWebContentsDelegateAdapter.java
index f5eefe8..260ea96 100644
--- a/android_webview/java/src/org/chromium/android_webview/AwWebContentsDelegateAdapter.java
+++ b/android_webview/java/src/org/chromium/android_webview/AwWebContentsDelegateAdapter.java
@@ -11,6 +11,7 @@
 import android.util.Log;
 import android.view.KeyEvent;
 import android.webkit.ConsoleMessage;
+import android.webkit.ValueCallback;
 
 import org.chromium.content.browser.ContentViewCore;
 
@@ -86,14 +87,15 @@
 
     @Override
     public void openNewTab(String url, String extraHeaders, byte[] postData, int disposition) {
-        // TODO: implement
+        // This is only called in chrome layers.
+        assert false;
     }
 
     @Override
     public boolean addNewContents(int nativeSourceWebContents, int nativeWebContents,
             int disposition, Rect initialPosition, boolean userGesture) {
-        // TODO: implement
-        return false;
+        // This is overridden native side; see the other addNewContents overload.
+        throw new RuntimeException("Impossible");
     }
 
     @Override
@@ -136,6 +138,29 @@
     }
 
     @Override
+    public void runFileChooser(final int processId, final int renderId, final int mode_flags,
+            String acceptTypes, String title, String defaultFilename, boolean capture) {
+        AwContentsClient.FileChooserParams params = new AwContentsClient.FileChooserParams();
+        params.mode = mode_flags;
+        params.acceptTypes = acceptTypes;
+        params.title = title;
+        params.defaultFilename = defaultFilename;
+        params.capture = capture;
+
+        mContentsClient.showFileChooser(new ValueCallback<String[]>() {
+            boolean completed = false;
+            @Override
+            public void onReceiveValue(String[] results) {
+                if (completed) {
+                    throw new IllegalStateException("Duplicate showFileChooser result");
+                }
+                completed = true;
+                nativeFilesSelectedInChooser(processId, renderId, mode_flags, results);
+            }
+        }, params);
+    }
+
+    @Override
     public boolean addNewContents(boolean isDialog, boolean isUserGesture) {
         return mContentsClient.onCreateWindow(isDialog, isUserGesture);
     }
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/AwTargetDensityDpiTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/AwTargetDensityDpiTest.java
index 92dfb61..1a10196 100644
--- a/android_webview/javatests/src/org/chromium/android_webview/test/AwTargetDensityDpiTest.java
+++ b/android_webview/javatests/src/org/chromium/android_webview/test/AwTargetDensityDpiTest.java
@@ -38,8 +38,9 @@
         int actualWidth = Integer.parseInt(getTitleOnUiThread(awContents));
         assertEquals((float)deviceInfo.getDisplayWidth(), (float)actualWidth, 10f);
 
-        float displayWidth = (float)(deviceInfo.getDisplayWidth() / deviceInfo.getDIPScale());
-        float deviceDpi = (float)(120f * deviceInfo.getDIPScale());
+        float displayWidth = (float)(deviceInfo.getDisplayWidth());
+        float deviceDpi = (float)(160f * deviceInfo.getDIPScale());
+
         loadDataSync(awContents, onPageFinishedHelper, pageHighDpi, "text/html", false);
         actualWidth = Integer.parseInt(getTitleOnUiThread(awContents));
         assertEquals(displayWidth * (240f / deviceDpi), (float)actualWidth, 10f);
diff --git a/android_webview/libwebviewchromium.target.darwin-arm.mk b/android_webview/libwebviewchromium.target.darwin-arm.mk
index a634af8..fe7c5a0 100644
--- a/android_webview/libwebviewchromium.target.darwin-arm.mk
+++ b/android_webview/libwebviewchromium.target.darwin-arm.mk
@@ -38,6 +38,7 @@
 	$(call intermediates-dir-for,STATIC_LIBRARIES,skia_skia_opts_gyp)/skia_skia_opts_gyp.a \
 	$(call intermediates-dir-for,STATIC_LIBRARIES,skia_skia_opts_neon_gyp)/skia_skia_opts_neon_gyp.a \
 	$(call intermediates-dir-for,STATIC_LIBRARIES,third_party_zlib_zlib_gyp)/third_party_zlib_zlib_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,skia_skia_chrome_gyp)/skia_skia_chrome_gyp.a \
@@ -151,18 +152,10 @@
 	$(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,STATIC_LIBRARIES,webkit_support_glue_gyp)/webkit_support_glue_gyp.a \
 	$(call intermediates-dir-for,STATIC_LIBRARIES,printing_printing_gyp)/printing_printing_gyp.a \
-	$(call intermediates-dir-for,STATIC_LIBRARIES,webkit_plugins_plugins_common_gyp)/webkit_plugins_plugins_common_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,webkit_renderer_compositor_bindings_webkit_compositor_bindings_gyp)/webkit_renderer_compositor_bindings_webkit_compositor_bindings_gyp.a \
 	$(call intermediates-dir-for,STATIC_LIBRARIES,webkit_common_gpu_webkit_gpu_gyp)/webkit_common_gpu_webkit_gpu_gyp.a \
 	$(call intermediates-dir-for,GYP,webkit_webkit_strings_gyp)/webkit_strings.stamp \
-	$(call intermediates-dir-for,STATIC_LIBRARIES,webkit_support_plugins_gyp)/webkit_support_plugins_gyp.a \
-	$(call intermediates-dir-for,GYP,ppapi_ppapi_c_gyp)/ppapi_c.stamp \
-	$(call intermediates-dir-for,STATIC_LIBRARIES,ppapi_ppapi_shared_gyp)/ppapi_ppapi_shared_gyp.a \
-	$(call intermediates-dir-for,STATIC_LIBRARIES,ui_surface_surface_gyp)/ui_surface_surface_gyp.a \
-	$(call intermediates-dir-for,STATIC_LIBRARIES,webkit_support_glue_child_gyp)/webkit_support_glue_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_support_overscroller_jni_headers_gyp)/overscroller_jni_headers.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_common_aidl_gyp)/common_aidl.stamp \
@@ -179,6 +172,9 @@
 	$(call intermediates-dir-for,STATIC_LIBRARIES,ui_snapshot_snapshot_gyp)/ui_snapshot_snapshot_gyp.a \
 	$(call intermediates-dir-for,STATIC_LIBRARIES,content_content_gpu_gyp)/content_content_gpu_gyp.a \
 	$(call intermediates-dir-for,STATIC_LIBRARIES,content_content_child_gyp)/content_content_child_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,webkit_support_glue_child_gyp)/webkit_support_glue_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_support_overscroller_jni_headers_gyp)/overscroller_jni_headers.stamp \
 	$(call intermediates-dir-for,STATIC_LIBRARIES,content_content_utility_gyp)/content_content_utility_gyp.a \
 	$(call intermediates-dir-for,GYP,content_browser_devtools_devtools_resources_gyp)/devtools_resources.stamp \
 	$(call intermediates-dir-for,GYP,third_party_WebKit_Source_devtools_generate_devtools_grd_gyp)/generate_devtools_grd.stamp \
@@ -198,6 +194,7 @@
 	$(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_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,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 \
@@ -548,15 +545,9 @@
 	third_party_WebKit_Source_modules_modules_gyp \
 	webkit_support_glue_gyp \
 	printing_printing_gyp \
-	webkit_plugins_plugins_common_gyp \
 	webkit_renderer_compositor_bindings_webkit_compositor_support_gyp \
 	webkit_renderer_compositor_bindings_webkit_compositor_bindings_gyp \
 	webkit_common_gpu_webkit_gpu_gyp \
-	webkit_support_plugins_gyp \
-	ppapi_ppapi_shared_gyp \
-	ui_surface_surface_gyp \
-	webkit_support_glue_child_gyp \
-	ui_native_theme_native_theme_gyp \
 	components_encryptor_gyp \
 	components_user_prefs_gyp \
 	base_base_prefs_gyp \
@@ -568,8 +559,11 @@
 	ui_snapshot_snapshot_gyp \
 	content_content_gpu_gyp \
 	content_content_child_gyp \
+	webkit_support_glue_child_gyp \
+	ui_native_theme_native_theme_gyp \
 	content_content_utility_gyp \
 	net_http_server_gyp \
+	ui_surface_surface_gyp \
 	sandbox_sandbox_services_gyp \
 	sandbox_seccomp_bpf_gyp \
 	components_webdata_common_gyp \
diff --git a/android_webview/libwebviewchromium.target.darwin-mips.mk b/android_webview/libwebviewchromium.target.darwin-mips.mk
index a8686e5..f153051 100644
--- a/android_webview/libwebviewchromium.target.darwin-mips.mk
+++ b/android_webview/libwebviewchromium.target.darwin-mips.mk
@@ -37,6 +37,7 @@
 	$(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,third_party_zlib_zlib_gyp)/third_party_zlib_zlib_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,skia_skia_chrome_gyp)/skia_skia_chrome_gyp.a \
@@ -149,18 +150,10 @@
 	$(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,STATIC_LIBRARIES,webkit_support_glue_gyp)/webkit_support_glue_gyp.a \
 	$(call intermediates-dir-for,STATIC_LIBRARIES,printing_printing_gyp)/printing_printing_gyp.a \
-	$(call intermediates-dir-for,STATIC_LIBRARIES,webkit_plugins_plugins_common_gyp)/webkit_plugins_plugins_common_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,webkit_renderer_compositor_bindings_webkit_compositor_bindings_gyp)/webkit_renderer_compositor_bindings_webkit_compositor_bindings_gyp.a \
 	$(call intermediates-dir-for,STATIC_LIBRARIES,webkit_common_gpu_webkit_gpu_gyp)/webkit_common_gpu_webkit_gpu_gyp.a \
 	$(call intermediates-dir-for,GYP,webkit_webkit_strings_gyp)/webkit_strings.stamp \
-	$(call intermediates-dir-for,STATIC_LIBRARIES,webkit_support_plugins_gyp)/webkit_support_plugins_gyp.a \
-	$(call intermediates-dir-for,GYP,ppapi_ppapi_c_gyp)/ppapi_c.stamp \
-	$(call intermediates-dir-for,STATIC_LIBRARIES,ppapi_ppapi_shared_gyp)/ppapi_ppapi_shared_gyp.a \
-	$(call intermediates-dir-for,STATIC_LIBRARIES,ui_surface_surface_gyp)/ui_surface_surface_gyp.a \
-	$(call intermediates-dir-for,STATIC_LIBRARIES,webkit_support_glue_child_gyp)/webkit_support_glue_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_support_overscroller_jni_headers_gyp)/overscroller_jni_headers.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_common_aidl_gyp)/common_aidl.stamp \
@@ -177,6 +170,9 @@
 	$(call intermediates-dir-for,STATIC_LIBRARIES,ui_snapshot_snapshot_gyp)/ui_snapshot_snapshot_gyp.a \
 	$(call intermediates-dir-for,STATIC_LIBRARIES,content_content_gpu_gyp)/content_content_gpu_gyp.a \
 	$(call intermediates-dir-for,STATIC_LIBRARIES,content_content_child_gyp)/content_content_child_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,webkit_support_glue_child_gyp)/webkit_support_glue_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_support_overscroller_jni_headers_gyp)/overscroller_jni_headers.stamp \
 	$(call intermediates-dir-for,STATIC_LIBRARIES,content_content_utility_gyp)/content_content_utility_gyp.a \
 	$(call intermediates-dir-for,GYP,content_browser_devtools_devtools_resources_gyp)/devtools_resources.stamp \
 	$(call intermediates-dir-for,GYP,third_party_WebKit_Source_devtools_generate_devtools_grd_gyp)/generate_devtools_grd.stamp \
@@ -196,6 +192,7 @@
 	$(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_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,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,components_webdata_common_gyp)/components_webdata_common_gyp.a \
@@ -535,15 +532,9 @@
 	third_party_WebKit_Source_modules_modules_gyp \
 	webkit_support_glue_gyp \
 	printing_printing_gyp \
-	webkit_plugins_plugins_common_gyp \
 	webkit_renderer_compositor_bindings_webkit_compositor_support_gyp \
 	webkit_renderer_compositor_bindings_webkit_compositor_bindings_gyp \
 	webkit_common_gpu_webkit_gpu_gyp \
-	webkit_support_plugins_gyp \
-	ppapi_ppapi_shared_gyp \
-	ui_surface_surface_gyp \
-	webkit_support_glue_child_gyp \
-	ui_native_theme_native_theme_gyp \
 	components_encryptor_gyp \
 	components_user_prefs_gyp \
 	base_base_prefs_gyp \
@@ -555,8 +546,11 @@
 	ui_snapshot_snapshot_gyp \
 	content_content_gpu_gyp \
 	content_content_child_gyp \
+	webkit_support_glue_child_gyp \
+	ui_native_theme_native_theme_gyp \
 	content_content_utility_gyp \
 	net_http_server_gyp \
+	ui_surface_surface_gyp \
 	sandbox_sandbox_services_gyp \
 	components_webdata_common_gyp \
 	third_party_libjingle_libjingle_gyp \
diff --git a/android_webview/libwebviewchromium.target.darwin-x86.mk b/android_webview/libwebviewchromium.target.darwin-x86.mk
index b2cbb0e..5bc5e16 100644
--- a/android_webview/libwebviewchromium.target.darwin-x86.mk
+++ b/android_webview/libwebviewchromium.target.darwin-x86.mk
@@ -38,6 +38,7 @@
 	$(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,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,skia_skia_chrome_gyp)/skia_skia_chrome_gyp.a \
@@ -155,18 +156,10 @@
 	$(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,STATIC_LIBRARIES,webkit_support_glue_gyp)/webkit_support_glue_gyp.a \
 	$(call intermediates-dir-for,STATIC_LIBRARIES,printing_printing_gyp)/printing_printing_gyp.a \
-	$(call intermediates-dir-for,STATIC_LIBRARIES,webkit_plugins_plugins_common_gyp)/webkit_plugins_plugins_common_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,webkit_renderer_compositor_bindings_webkit_compositor_bindings_gyp)/webkit_renderer_compositor_bindings_webkit_compositor_bindings_gyp.a \
 	$(call intermediates-dir-for,STATIC_LIBRARIES,webkit_common_gpu_webkit_gpu_gyp)/webkit_common_gpu_webkit_gpu_gyp.a \
 	$(call intermediates-dir-for,GYP,webkit_webkit_strings_gyp)/webkit_strings.stamp \
-	$(call intermediates-dir-for,STATIC_LIBRARIES,webkit_support_plugins_gyp)/webkit_support_plugins_gyp.a \
-	$(call intermediates-dir-for,GYP,ppapi_ppapi_c_gyp)/ppapi_c.stamp \
-	$(call intermediates-dir-for,STATIC_LIBRARIES,ppapi_ppapi_shared_gyp)/ppapi_ppapi_shared_gyp.a \
-	$(call intermediates-dir-for,STATIC_LIBRARIES,ui_surface_surface_gyp)/ui_surface_surface_gyp.a \
-	$(call intermediates-dir-for,STATIC_LIBRARIES,webkit_support_glue_child_gyp)/webkit_support_glue_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_support_overscroller_jni_headers_gyp)/overscroller_jni_headers.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_common_aidl_gyp)/common_aidl.stamp \
@@ -183,6 +176,9 @@
 	$(call intermediates-dir-for,STATIC_LIBRARIES,ui_snapshot_snapshot_gyp)/ui_snapshot_snapshot_gyp.a \
 	$(call intermediates-dir-for,STATIC_LIBRARIES,content_content_gpu_gyp)/content_content_gpu_gyp.a \
 	$(call intermediates-dir-for,STATIC_LIBRARIES,content_content_child_gyp)/content_content_child_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,webkit_support_glue_child_gyp)/webkit_support_glue_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_support_overscroller_jni_headers_gyp)/overscroller_jni_headers.stamp \
 	$(call intermediates-dir-for,STATIC_LIBRARIES,content_content_utility_gyp)/content_content_utility_gyp.a \
 	$(call intermediates-dir-for,GYP,content_browser_devtools_devtools_resources_gyp)/devtools_resources.stamp \
 	$(call intermediates-dir-for,GYP,third_party_WebKit_Source_devtools_generate_devtools_grd_gyp)/generate_devtools_grd.stamp \
@@ -202,6 +198,7 @@
 	$(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_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,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 \
@@ -555,15 +552,9 @@
 	third_party_WebKit_Source_modules_modules_gyp \
 	webkit_support_glue_gyp \
 	printing_printing_gyp \
-	webkit_plugins_plugins_common_gyp \
 	webkit_renderer_compositor_bindings_webkit_compositor_support_gyp \
 	webkit_renderer_compositor_bindings_webkit_compositor_bindings_gyp \
 	webkit_common_gpu_webkit_gpu_gyp \
-	webkit_support_plugins_gyp \
-	ppapi_ppapi_shared_gyp \
-	ui_surface_surface_gyp \
-	webkit_support_glue_child_gyp \
-	ui_native_theme_native_theme_gyp \
 	components_encryptor_gyp \
 	components_user_prefs_gyp \
 	base_base_prefs_gyp \
@@ -575,8 +566,11 @@
 	ui_snapshot_snapshot_gyp \
 	content_content_gpu_gyp \
 	content_content_child_gyp \
+	webkit_support_glue_child_gyp \
+	ui_native_theme_native_theme_gyp \
 	content_content_utility_gyp \
 	net_http_server_gyp \
+	ui_surface_surface_gyp \
 	sandbox_sandbox_services_gyp \
 	sandbox_seccomp_bpf_gyp \
 	components_webdata_common_gyp \
diff --git a/android_webview/libwebviewchromium.target.linux-arm.mk b/android_webview/libwebviewchromium.target.linux-arm.mk
index a634af8..fe7c5a0 100644
--- a/android_webview/libwebviewchromium.target.linux-arm.mk
+++ b/android_webview/libwebviewchromium.target.linux-arm.mk
@@ -38,6 +38,7 @@
 	$(call intermediates-dir-for,STATIC_LIBRARIES,skia_skia_opts_gyp)/skia_skia_opts_gyp.a \
 	$(call intermediates-dir-for,STATIC_LIBRARIES,skia_skia_opts_neon_gyp)/skia_skia_opts_neon_gyp.a \
 	$(call intermediates-dir-for,STATIC_LIBRARIES,third_party_zlib_zlib_gyp)/third_party_zlib_zlib_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,skia_skia_chrome_gyp)/skia_skia_chrome_gyp.a \
@@ -151,18 +152,10 @@
 	$(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,STATIC_LIBRARIES,webkit_support_glue_gyp)/webkit_support_glue_gyp.a \
 	$(call intermediates-dir-for,STATIC_LIBRARIES,printing_printing_gyp)/printing_printing_gyp.a \
-	$(call intermediates-dir-for,STATIC_LIBRARIES,webkit_plugins_plugins_common_gyp)/webkit_plugins_plugins_common_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,webkit_renderer_compositor_bindings_webkit_compositor_bindings_gyp)/webkit_renderer_compositor_bindings_webkit_compositor_bindings_gyp.a \
 	$(call intermediates-dir-for,STATIC_LIBRARIES,webkit_common_gpu_webkit_gpu_gyp)/webkit_common_gpu_webkit_gpu_gyp.a \
 	$(call intermediates-dir-for,GYP,webkit_webkit_strings_gyp)/webkit_strings.stamp \
-	$(call intermediates-dir-for,STATIC_LIBRARIES,webkit_support_plugins_gyp)/webkit_support_plugins_gyp.a \
-	$(call intermediates-dir-for,GYP,ppapi_ppapi_c_gyp)/ppapi_c.stamp \
-	$(call intermediates-dir-for,STATIC_LIBRARIES,ppapi_ppapi_shared_gyp)/ppapi_ppapi_shared_gyp.a \
-	$(call intermediates-dir-for,STATIC_LIBRARIES,ui_surface_surface_gyp)/ui_surface_surface_gyp.a \
-	$(call intermediates-dir-for,STATIC_LIBRARIES,webkit_support_glue_child_gyp)/webkit_support_glue_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_support_overscroller_jni_headers_gyp)/overscroller_jni_headers.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_common_aidl_gyp)/common_aidl.stamp \
@@ -179,6 +172,9 @@
 	$(call intermediates-dir-for,STATIC_LIBRARIES,ui_snapshot_snapshot_gyp)/ui_snapshot_snapshot_gyp.a \
 	$(call intermediates-dir-for,STATIC_LIBRARIES,content_content_gpu_gyp)/content_content_gpu_gyp.a \
 	$(call intermediates-dir-for,STATIC_LIBRARIES,content_content_child_gyp)/content_content_child_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,webkit_support_glue_child_gyp)/webkit_support_glue_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_support_overscroller_jni_headers_gyp)/overscroller_jni_headers.stamp \
 	$(call intermediates-dir-for,STATIC_LIBRARIES,content_content_utility_gyp)/content_content_utility_gyp.a \
 	$(call intermediates-dir-for,GYP,content_browser_devtools_devtools_resources_gyp)/devtools_resources.stamp \
 	$(call intermediates-dir-for,GYP,third_party_WebKit_Source_devtools_generate_devtools_grd_gyp)/generate_devtools_grd.stamp \
@@ -198,6 +194,7 @@
 	$(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_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,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 \
@@ -548,15 +545,9 @@
 	third_party_WebKit_Source_modules_modules_gyp \
 	webkit_support_glue_gyp \
 	printing_printing_gyp \
-	webkit_plugins_plugins_common_gyp \
 	webkit_renderer_compositor_bindings_webkit_compositor_support_gyp \
 	webkit_renderer_compositor_bindings_webkit_compositor_bindings_gyp \
 	webkit_common_gpu_webkit_gpu_gyp \
-	webkit_support_plugins_gyp \
-	ppapi_ppapi_shared_gyp \
-	ui_surface_surface_gyp \
-	webkit_support_glue_child_gyp \
-	ui_native_theme_native_theme_gyp \
 	components_encryptor_gyp \
 	components_user_prefs_gyp \
 	base_base_prefs_gyp \
@@ -568,8 +559,11 @@
 	ui_snapshot_snapshot_gyp \
 	content_content_gpu_gyp \
 	content_content_child_gyp \
+	webkit_support_glue_child_gyp \
+	ui_native_theme_native_theme_gyp \
 	content_content_utility_gyp \
 	net_http_server_gyp \
+	ui_surface_surface_gyp \
 	sandbox_sandbox_services_gyp \
 	sandbox_seccomp_bpf_gyp \
 	components_webdata_common_gyp \
diff --git a/android_webview/libwebviewchromium.target.linux-mips.mk b/android_webview/libwebviewchromium.target.linux-mips.mk
index a8686e5..f153051 100644
--- a/android_webview/libwebviewchromium.target.linux-mips.mk
+++ b/android_webview/libwebviewchromium.target.linux-mips.mk
@@ -37,6 +37,7 @@
 	$(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,third_party_zlib_zlib_gyp)/third_party_zlib_zlib_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,skia_skia_chrome_gyp)/skia_skia_chrome_gyp.a \
@@ -149,18 +150,10 @@
 	$(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,STATIC_LIBRARIES,webkit_support_glue_gyp)/webkit_support_glue_gyp.a \
 	$(call intermediates-dir-for,STATIC_LIBRARIES,printing_printing_gyp)/printing_printing_gyp.a \
-	$(call intermediates-dir-for,STATIC_LIBRARIES,webkit_plugins_plugins_common_gyp)/webkit_plugins_plugins_common_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,webkit_renderer_compositor_bindings_webkit_compositor_bindings_gyp)/webkit_renderer_compositor_bindings_webkit_compositor_bindings_gyp.a \
 	$(call intermediates-dir-for,STATIC_LIBRARIES,webkit_common_gpu_webkit_gpu_gyp)/webkit_common_gpu_webkit_gpu_gyp.a \
 	$(call intermediates-dir-for,GYP,webkit_webkit_strings_gyp)/webkit_strings.stamp \
-	$(call intermediates-dir-for,STATIC_LIBRARIES,webkit_support_plugins_gyp)/webkit_support_plugins_gyp.a \
-	$(call intermediates-dir-for,GYP,ppapi_ppapi_c_gyp)/ppapi_c.stamp \
-	$(call intermediates-dir-for,STATIC_LIBRARIES,ppapi_ppapi_shared_gyp)/ppapi_ppapi_shared_gyp.a \
-	$(call intermediates-dir-for,STATIC_LIBRARIES,ui_surface_surface_gyp)/ui_surface_surface_gyp.a \
-	$(call intermediates-dir-for,STATIC_LIBRARIES,webkit_support_glue_child_gyp)/webkit_support_glue_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_support_overscroller_jni_headers_gyp)/overscroller_jni_headers.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_common_aidl_gyp)/common_aidl.stamp \
@@ -177,6 +170,9 @@
 	$(call intermediates-dir-for,STATIC_LIBRARIES,ui_snapshot_snapshot_gyp)/ui_snapshot_snapshot_gyp.a \
 	$(call intermediates-dir-for,STATIC_LIBRARIES,content_content_gpu_gyp)/content_content_gpu_gyp.a \
 	$(call intermediates-dir-for,STATIC_LIBRARIES,content_content_child_gyp)/content_content_child_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,webkit_support_glue_child_gyp)/webkit_support_glue_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_support_overscroller_jni_headers_gyp)/overscroller_jni_headers.stamp \
 	$(call intermediates-dir-for,STATIC_LIBRARIES,content_content_utility_gyp)/content_content_utility_gyp.a \
 	$(call intermediates-dir-for,GYP,content_browser_devtools_devtools_resources_gyp)/devtools_resources.stamp \
 	$(call intermediates-dir-for,GYP,third_party_WebKit_Source_devtools_generate_devtools_grd_gyp)/generate_devtools_grd.stamp \
@@ -196,6 +192,7 @@
 	$(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_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,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,components_webdata_common_gyp)/components_webdata_common_gyp.a \
@@ -535,15 +532,9 @@
 	third_party_WebKit_Source_modules_modules_gyp \
 	webkit_support_glue_gyp \
 	printing_printing_gyp \
-	webkit_plugins_plugins_common_gyp \
 	webkit_renderer_compositor_bindings_webkit_compositor_support_gyp \
 	webkit_renderer_compositor_bindings_webkit_compositor_bindings_gyp \
 	webkit_common_gpu_webkit_gpu_gyp \
-	webkit_support_plugins_gyp \
-	ppapi_ppapi_shared_gyp \
-	ui_surface_surface_gyp \
-	webkit_support_glue_child_gyp \
-	ui_native_theme_native_theme_gyp \
 	components_encryptor_gyp \
 	components_user_prefs_gyp \
 	base_base_prefs_gyp \
@@ -555,8 +546,11 @@
 	ui_snapshot_snapshot_gyp \
 	content_content_gpu_gyp \
 	content_content_child_gyp \
+	webkit_support_glue_child_gyp \
+	ui_native_theme_native_theme_gyp \
 	content_content_utility_gyp \
 	net_http_server_gyp \
+	ui_surface_surface_gyp \
 	sandbox_sandbox_services_gyp \
 	components_webdata_common_gyp \
 	third_party_libjingle_libjingle_gyp \
diff --git a/android_webview/libwebviewchromium.target.linux-x86.mk b/android_webview/libwebviewchromium.target.linux-x86.mk
index b2cbb0e..5bc5e16 100644
--- a/android_webview/libwebviewchromium.target.linux-x86.mk
+++ b/android_webview/libwebviewchromium.target.linux-x86.mk
@@ -38,6 +38,7 @@
 	$(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,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,skia_skia_chrome_gyp)/skia_skia_chrome_gyp.a \
@@ -155,18 +156,10 @@
 	$(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,STATIC_LIBRARIES,webkit_support_glue_gyp)/webkit_support_glue_gyp.a \
 	$(call intermediates-dir-for,STATIC_LIBRARIES,printing_printing_gyp)/printing_printing_gyp.a \
-	$(call intermediates-dir-for,STATIC_LIBRARIES,webkit_plugins_plugins_common_gyp)/webkit_plugins_plugins_common_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,webkit_renderer_compositor_bindings_webkit_compositor_bindings_gyp)/webkit_renderer_compositor_bindings_webkit_compositor_bindings_gyp.a \
 	$(call intermediates-dir-for,STATIC_LIBRARIES,webkit_common_gpu_webkit_gpu_gyp)/webkit_common_gpu_webkit_gpu_gyp.a \
 	$(call intermediates-dir-for,GYP,webkit_webkit_strings_gyp)/webkit_strings.stamp \
-	$(call intermediates-dir-for,STATIC_LIBRARIES,webkit_support_plugins_gyp)/webkit_support_plugins_gyp.a \
-	$(call intermediates-dir-for,GYP,ppapi_ppapi_c_gyp)/ppapi_c.stamp \
-	$(call intermediates-dir-for,STATIC_LIBRARIES,ppapi_ppapi_shared_gyp)/ppapi_ppapi_shared_gyp.a \
-	$(call intermediates-dir-for,STATIC_LIBRARIES,ui_surface_surface_gyp)/ui_surface_surface_gyp.a \
-	$(call intermediates-dir-for,STATIC_LIBRARIES,webkit_support_glue_child_gyp)/webkit_support_glue_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_support_overscroller_jni_headers_gyp)/overscroller_jni_headers.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_common_aidl_gyp)/common_aidl.stamp \
@@ -183,6 +176,9 @@
 	$(call intermediates-dir-for,STATIC_LIBRARIES,ui_snapshot_snapshot_gyp)/ui_snapshot_snapshot_gyp.a \
 	$(call intermediates-dir-for,STATIC_LIBRARIES,content_content_gpu_gyp)/content_content_gpu_gyp.a \
 	$(call intermediates-dir-for,STATIC_LIBRARIES,content_content_child_gyp)/content_content_child_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,webkit_support_glue_child_gyp)/webkit_support_glue_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_support_overscroller_jni_headers_gyp)/overscroller_jni_headers.stamp \
 	$(call intermediates-dir-for,STATIC_LIBRARIES,content_content_utility_gyp)/content_content_utility_gyp.a \
 	$(call intermediates-dir-for,GYP,content_browser_devtools_devtools_resources_gyp)/devtools_resources.stamp \
 	$(call intermediates-dir-for,GYP,third_party_WebKit_Source_devtools_generate_devtools_grd_gyp)/generate_devtools_grd.stamp \
@@ -202,6 +198,7 @@
 	$(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_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,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 \
@@ -555,15 +552,9 @@
 	third_party_WebKit_Source_modules_modules_gyp \
 	webkit_support_glue_gyp \
 	printing_printing_gyp \
-	webkit_plugins_plugins_common_gyp \
 	webkit_renderer_compositor_bindings_webkit_compositor_support_gyp \
 	webkit_renderer_compositor_bindings_webkit_compositor_bindings_gyp \
 	webkit_common_gpu_webkit_gpu_gyp \
-	webkit_support_plugins_gyp \
-	ppapi_ppapi_shared_gyp \
-	ui_surface_surface_gyp \
-	webkit_support_glue_child_gyp \
-	ui_native_theme_native_theme_gyp \
 	components_encryptor_gyp \
 	components_user_prefs_gyp \
 	base_base_prefs_gyp \
@@ -575,8 +566,11 @@
 	ui_snapshot_snapshot_gyp \
 	content_content_gpu_gyp \
 	content_content_child_gyp \
+	webkit_support_glue_child_gyp \
+	ui_native_theme_native_theme_gyp \
 	content_content_utility_gyp \
 	net_http_server_gyp \
+	ui_surface_surface_gyp \
 	sandbox_sandbox_services_gyp \
 	sandbox_seccomp_bpf_gyp \
 	components_webdata_common_gyp \
diff --git a/android_webview/native/DEPS b/android_webview/native/DEPS
index b45be10..f2d6372 100644
--- a/android_webview/native/DEPS
+++ b/android_webview/native/DEPS
@@ -1,6 +1,7 @@
 include_rules = [
   "+content/public/browser",
   "+ui/gfx",
+  "+ui/shell_dialogs",
 
   # Components that Android WebView depends on.
   "+components/autofill/content/browser",
diff --git a/android_webview/native/android_webview_jni_registrar.cc b/android_webview/native/android_webview_jni_registrar.cc
index 9202999..4ee5a3b 100644
--- a/android_webview/native/android_webview_jni_registrar.cc
+++ b/android_webview/native/android_webview_jni_registrar.cc
@@ -11,6 +11,7 @@
 #include "android_webview/native/aw_contents_io_thread_client_impl.h"
 #include "android_webview/native/aw_form_database.h"
 #include "android_webview/native/aw_http_auth_handler.h"
+#include "android_webview/native/aw_picture.h"
 #include "android_webview/native/aw_quota_manager_bridge_impl.h"
 #include "android_webview/native/aw_resource.h"
 #include "android_webview/native/aw_settings.h"
@@ -31,8 +32,9 @@
   { "AwAutofillManagerDelegate", RegisterAwAutofillManagerDelegate },
   { "AwContents", RegisterAwContents },
   { "AwContentsClientBridge", RegisterAwContentsClientBridge },
-  { "AwContentsIoThreadClientImpl", RegisterAwContentsIoThreadClientImpl},
-  { "AwFormDatabase", RegisterAwFormDatabase},
+  { "AwContentsIoThreadClientImpl", RegisterAwContentsIoThreadClientImpl },
+  { "AwFormDatabase", RegisterAwFormDatabase },
+  { "AwPicture", RegisterAwPicture },
   { "AwSettings", RegisterAwSettings },
   { "AwHttpAuthHandler", RegisterAwHttpAuthHandler },
   { "AwQuotaManagerBridge", RegisterAwQuotaManagerBridge },
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 1669251..2519432 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
@@ -16,7 +16,7 @@
 
 
 ### 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/AwFormDatabase.java', '../java/src/org/chromium/android_webview/AwHttpAuthHandler.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/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', '--optimize_generation', '0', '--jarjar', '../../android_webview/build/jarjar-rules.txt'], 'message': 'Generating JNI bindings from $(RULE_SOURCES)'}":
+# "{'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/AwFormDatabase.java', '../java/src/org/chromium/android_webview/AwHttpAuthHandler.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/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', '--optimize_generation', '0', '--jarjar', '../../android_webview/build/jarjar-rules.txt'], '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))
@@ -97,6 +97,16 @@
 .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/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" --optimize_generation 0 --jarjar ../../android_webview/build/jarjar-rules.txt
+
+.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))
@@ -168,6 +178,7 @@
 	$(gyp_shared_intermediate_dir)/android_webview/jni/AwCookieManager_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/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 \
@@ -187,6 +198,7 @@
 	$(gyp_shared_intermediate_dir)/android_webview/jni/AwCookieManager_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/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 \
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 22ccb8f..e0d9362 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
@@ -16,7 +16,7 @@
 
 
 ### 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/AwFormDatabase.java', '../java/src/org/chromium/android_webview/AwHttpAuthHandler.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/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', '--optimize_generation', '0', '--jarjar', '../../android_webview/build/jarjar-rules.txt'], 'message': 'Generating JNI bindings from $(RULE_SOURCES)'}":
+# "{'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/AwFormDatabase.java', '../java/src/org/chromium/android_webview/AwHttpAuthHandler.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/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', '--optimize_generation', '0', '--jarjar', '../../android_webview/build/jarjar-rules.txt'], '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))
@@ -97,6 +97,16 @@
 .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/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" --optimize_generation 0 --jarjar ../../android_webview/build/jarjar-rules.txt
+
+.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))
@@ -168,6 +178,7 @@
 	$(gyp_shared_intermediate_dir)/android_webview/jni/AwCookieManager_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/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 \
@@ -187,6 +198,7 @@
 	$(gyp_shared_intermediate_dir)/android_webview/jni/AwCookieManager_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/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 \
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 4ae68f7..d9893f7 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
@@ -16,7 +16,7 @@
 
 
 ### 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/AwFormDatabase.java', '../java/src/org/chromium/android_webview/AwHttpAuthHandler.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/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', '--optimize_generation', '0', '--jarjar', '../../android_webview/build/jarjar-rules.txt'], 'message': 'Generating JNI bindings from $(RULE_SOURCES)'}":
+# "{'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/AwFormDatabase.java', '../java/src/org/chromium/android_webview/AwHttpAuthHandler.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/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', '--optimize_generation', '0', '--jarjar', '../../android_webview/build/jarjar-rules.txt'], '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))
@@ -97,6 +97,16 @@
 .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/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" --optimize_generation 0 --jarjar ../../android_webview/build/jarjar-rules.txt
+
+.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))
@@ -168,6 +178,7 @@
 	$(gyp_shared_intermediate_dir)/android_webview/jni/AwCookieManager_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/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 \
@@ -187,6 +198,7 @@
 	$(gyp_shared_intermediate_dir)/android_webview/jni/AwCookieManager_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/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 \
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 1669251..2519432 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
@@ -16,7 +16,7 @@
 
 
 ### 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/AwFormDatabase.java', '../java/src/org/chromium/android_webview/AwHttpAuthHandler.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/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', '--optimize_generation', '0', '--jarjar', '../../android_webview/build/jarjar-rules.txt'], 'message': 'Generating JNI bindings from $(RULE_SOURCES)'}":
+# "{'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/AwFormDatabase.java', '../java/src/org/chromium/android_webview/AwHttpAuthHandler.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/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', '--optimize_generation', '0', '--jarjar', '../../android_webview/build/jarjar-rules.txt'], '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))
@@ -97,6 +97,16 @@
 .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/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" --optimize_generation 0 --jarjar ../../android_webview/build/jarjar-rules.txt
+
+.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))
@@ -168,6 +178,7 @@
 	$(gyp_shared_intermediate_dir)/android_webview/jni/AwCookieManager_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/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 \
@@ -187,6 +198,7 @@
 	$(gyp_shared_intermediate_dir)/android_webview/jni/AwCookieManager_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/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 \
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 22ccb8f..e0d9362 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
@@ -16,7 +16,7 @@
 
 
 ### 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/AwFormDatabase.java', '../java/src/org/chromium/android_webview/AwHttpAuthHandler.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/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', '--optimize_generation', '0', '--jarjar', '../../android_webview/build/jarjar-rules.txt'], 'message': 'Generating JNI bindings from $(RULE_SOURCES)'}":
+# "{'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/AwFormDatabase.java', '../java/src/org/chromium/android_webview/AwHttpAuthHandler.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/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', '--optimize_generation', '0', '--jarjar', '../../android_webview/build/jarjar-rules.txt'], '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))
@@ -97,6 +97,16 @@
 .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/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" --optimize_generation 0 --jarjar ../../android_webview/build/jarjar-rules.txt
+
+.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))
@@ -168,6 +178,7 @@
 	$(gyp_shared_intermediate_dir)/android_webview/jni/AwCookieManager_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/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 \
@@ -187,6 +198,7 @@
 	$(gyp_shared_intermediate_dir)/android_webview/jni/AwCookieManager_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/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 \
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 4ae68f7..d9893f7 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
@@ -16,7 +16,7 @@
 
 
 ### 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/AwFormDatabase.java', '../java/src/org/chromium/android_webview/AwHttpAuthHandler.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/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', '--optimize_generation', '0', '--jarjar', '../../android_webview/build/jarjar-rules.txt'], 'message': 'Generating JNI bindings from $(RULE_SOURCES)'}":
+# "{'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/AwFormDatabase.java', '../java/src/org/chromium/android_webview/AwHttpAuthHandler.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/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', '--optimize_generation', '0', '--jarjar', '../../android_webview/build/jarjar-rules.txt'], '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))
@@ -97,6 +97,16 @@
 .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/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" --optimize_generation 0 --jarjar ../../android_webview/build/jarjar-rules.txt
+
+.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))
@@ -168,6 +178,7 @@
 	$(gyp_shared_intermediate_dir)/android_webview/jni/AwCookieManager_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/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 \
@@ -187,6 +198,7 @@
 	$(gyp_shared_intermediate_dir)/android_webview/jni/AwCookieManager_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/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 \
diff --git a/android_webview/native/aw_contents.cc b/android_webview/native/aw_contents.cc
index 4ef093e..4cabfe4 100644
--- a/android_webview/native/aw_contents.cc
+++ b/android_webview/native/aw_contents.cc
@@ -15,6 +15,7 @@
 #include "android_webview/native/aw_browser_dependency_factory.h"
 #include "android_webview/native/aw_contents_client_bridge.h"
 #include "android_webview/native/aw_contents_io_thread_client_impl.h"
+#include "android_webview/native/aw_picture.h"
 #include "android_webview/native/aw_web_contents_delegate.h"
 #include "android_webview/native/java_browser_view_renderer_helper.h"
 #include "android_webview/native/state_serializer.h"
@@ -45,6 +46,7 @@
 #include "content/public/common/ssl_status.h"
 #include "jni/AwContents_jni.h"
 #include "net/cert/x509_certificate.h"
+#include "third_party/skia/include/core/SkPicture.h"
 #include "ui/base/l10n/l10n_util_android.h"
 #include "ui/gfx/android/java_bitmap.h"
 #include "ui/gfx/image/image.h"
@@ -84,9 +86,7 @@
 namespace {
 
 JavaBrowserViewRendererHelper* java_renderer_helper() {
-  static JavaBrowserViewRendererHelper* g_instance
-      = new JavaBrowserViewRendererHelper;
-  return g_instance;
+  return JavaBrowserViewRendererHelper::GetInstance();
 }
 
 const void* kAwContentsUserDataKey = &kAwContentsUserDataKey;
@@ -758,11 +758,12 @@
                                                          page_scale_factor);
 }
 
-ScopedJavaLocalRef<jobject> AwContents::CapturePicture(JNIEnv* env,
-                                                       jobject obj,
-                                                       int width,
-                                                       int height) {
-  return browser_view_renderer_->CapturePicture(width, height);
+jint AwContents::CapturePicture(JNIEnv* env,
+                                jobject obj,
+                                int width,
+                                int height) {
+  return reinterpret_cast<jint>(new AwPicture(
+      browser_view_renderer_->CapturePicture(width, height)));
 }
 
 void AwContents::EnableOnNewPicture(JNIEnv* env,
diff --git a/android_webview/native/aw_contents.h b/android_webview/native/aw_contents.h
index 270201a..38b433d 100644
--- a/android_webview/native/aw_contents.h
+++ b/android_webview/native/aw_contents.h
@@ -117,10 +117,7 @@
                             jint visible_right,
                             jint visible_bottom);
   jint GetAwDrawGLViewContext(JNIEnv* env, jobject obj);
-  base::android::ScopedJavaLocalRef<jobject> CapturePicture(JNIEnv* env,
-                                                            jobject obj,
-                                                            int width,
-                                                            int height);
+  jint CapturePicture(JNIEnv* env, jobject obj, int width, int height);
   void EnableOnNewPicture(JNIEnv* env, jobject obj, jboolean enabled);
 
   // Geolocation API support
diff --git a/android_webview/native/aw_picture.cc b/android_webview/native/aw_picture.cc
new file mode 100644
index 0000000..bc02b5b
--- /dev/null
+++ b/android_webview/native/aw_picture.cc
@@ -0,0 +1,56 @@
+// 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/native/aw_picture.h"
+
+#include "android_webview/browser/in_process_view_renderer.h"
+#include "android_webview/native/java_browser_view_renderer_helper.h"
+#include "jni/AwPicture_jni.h"
+#include "third_party/skia/include/core/SkPicture.h"
+
+namespace android_webview {
+
+AwPicture::AwPicture(skia::RefPtr<SkPicture> picture)
+    : picture_(picture) {
+  DCHECK(picture_);
+}
+
+AwPicture::~AwPicture() {}
+
+void AwPicture::Destroy(JNIEnv* env, jobject obj) {
+  delete this;
+}
+
+jint AwPicture::GetWidth(JNIEnv* env, jobject obj) {
+  return picture_->width();
+}
+
+jint AwPicture::GetHeight(JNIEnv* env, jobject obj) {
+  return picture_->height();
+}
+
+namespace {
+bool RenderPictureToCanvas(SkPicture* picture, SkCanvas* canvas) {
+  picture->draw(canvas);
+  return true;
+}
+}
+
+void AwPicture::Draw(JNIEnv* env, jobject obj, jobject canvas,
+                     jint left, jint top, jint right, jint bottom) {
+  bool ok = InProcessViewRenderer::RenderViaAuxilaryBitmapIfNeeded(
+      canvas,
+      JavaBrowserViewRendererHelper::GetInstance(),
+      gfx::Vector2d(),
+      gfx::Rect(left, top, right - left, bottom - top),
+      base::Bind(&RenderPictureToCanvas, base::Unretained(picture_.get())),
+      this);
+  LOG_IF(ERROR, !ok) << "Couldn't draw picture";
+}
+
+bool RegisterAwPicture(JNIEnv* env) {
+  return RegisterNativesImpl(env) >= 0;
+}
+
+}  // namespace android_webview
diff --git a/android_webview/native/aw_picture.h b/android_webview/native/aw_picture.h
new file mode 100644
index 0000000..2cbb5b7
--- /dev/null
+++ b/android_webview/native/aw_picture.h
@@ -0,0 +1,42 @@
+// 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_NATIVE_AW_PICTURE_H_
+#define ANDROID_WEBVIEW_NATIVE_AW_PICTURE_H_
+
+#include <jni.h>
+
+#include "base/android/jni_helper.h"
+#include "base/android/scoped_java_ref.h"
+#include "base/memory/scoped_ptr.h"
+#include "content/public/browser/web_contents_observer.h"
+#include "skia/ext/refptr.h"
+
+class SkPicture;
+
+namespace android_webview {
+
+class AwPicture {
+ public:
+  AwPicture(skia::RefPtr<SkPicture> picture);
+  ~AwPicture();
+
+  // Methods called from Java.
+  void Destroy(JNIEnv* env, jobject obj);
+  jint GetWidth(JNIEnv* env, jobject obj);
+  jint GetHeight(JNIEnv* env, jobject obj);
+  void Draw(JNIEnv* env, jobject obj, jobject canvas,
+            jint left, jint top, jint right, jint bottom);
+
+ private:
+  skia::RefPtr<SkPicture> picture_;
+
+  DISALLOW_IMPLICIT_CONSTRUCTORS(AwPicture);
+};
+
+bool RegisterAwPicture(JNIEnv* env);
+
+}  // android_webview
+
+#endif  // ANDROID_WEBVIEW_NATIVE_AW_PICTURE_
diff --git a/android_webview/native/aw_web_contents_delegate.cc b/android_webview/native/aw_web_contents_delegate.cc
index 91454ae..ddd623d 100644
--- a/android_webview/native/aw_web_contents_delegate.cc
+++ b/android_webview/native/aw_web_contents_delegate.cc
@@ -7,20 +7,38 @@
 #include "android_webview/browser/aw_javascript_dialog_manager.h"
 #include "android_webview/browser/find_helper.h"
 #include "android_webview/native/aw_contents.h"
+#include "base/android/jni_array.h"
+#include "base/android/jni_string.h"
 #include "base/android/scoped_java_ref.h"
 #include "base/lazy_instance.h"
 #include "base/message_loop/message_loop.h"
+#include "base/strings/string_util.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 "content/public/common/file_chooser_params.h"
 #include "jni/AwWebContentsDelegate_jni.h"
+#include "ui/shell_dialogs/selected_file_info.h"
 
 using base::android::AttachCurrentThread;
+using base::android::ConvertUTF16ToJavaString;
+using base::android::ConvertUTF8ToJavaString;
 using base::android::ScopedJavaLocalRef;
+using content::FileChooserParams;
 using content::WebContents;
 
 namespace android_webview {
 
-static base::LazyInstance<AwJavaScriptDialogManager>::Leaky
+namespace {
+
+// WARNING: these constants are exposed in the public interface Java side, so
+// must remain in sync with what clients are expecting.
+const int kFileChooserModeOpenMultiple = 1 << 0;
+const int kFileChooserModeOpenFolder = 1 << 1;
+
+base::LazyInstance<AwJavaScriptDialogManager>::Leaky
     g_javascript_dialog_manager = LAZY_INSTANCE_INITIALIZER;
+}
 
 AwWebContentsDelegate::AwWebContentsDelegate(
     JNIEnv* env,
@@ -63,8 +81,44 @@
   callback.Run(false);
 }
 
-void AwWebContentsDelegate::AddNewContents(content::WebContents* source,
-                                           content::WebContents* new_contents,
+void AwWebContentsDelegate::RunFileChooser(WebContents* web_contents,
+                                           const FileChooserParams& params) {
+  JNIEnv* env = AttachCurrentThread();
+  ScopedJavaLocalRef<jobject> java_delegate = GetJavaDelegate(env);
+  if (!java_delegate.obj())
+    return;
+
+  int mode_flags = 0;
+  if (params.mode == FileChooserParams::OpenMultiple) {
+    mode_flags |= kFileChooserModeOpenMultiple;
+  } else if (params.mode == FileChooserParams::UploadFolder) {
+    // Folder implies multiple in Chrome.
+    mode_flags |= kFileChooserModeOpenMultiple | kFileChooserModeOpenFolder;
+  } else if (params.mode == FileChooserParams::Save) {
+    // Save not supported, so cancel it.
+    web_contents->GetRenderViewHost()->FilesSelectedInChooser(
+         std::vector<ui::SelectedFileInfo>(),
+         params.mode);
+    return;
+  } else {
+    DCHECK_EQ(FileChooserParams::Open, params.mode);
+  }
+  Java_AwWebContentsDelegate_runFileChooser(env,
+      java_delegate.obj(),
+      web_contents->GetRenderProcessHost()->GetID(),
+      web_contents->GetRenderViewHost()->GetRoutingID(),
+      mode_flags,
+      ConvertUTF16ToJavaString(env,
+        JoinString(params.accept_types, ',')).obj(),
+      params.title.empty() ? NULL :
+          ConvertUTF16ToJavaString(env, params.title).obj(),
+      params.default_file_name.empty() ? NULL :
+          ConvertUTF8ToJavaString(env, params.default_file_name.value()).obj(),
+      params.capture);
+}
+
+void AwWebContentsDelegate::AddNewContents(WebContents* source,
+                                           WebContents* new_contents,
                                            WindowOpenDisposition disposition,
                                            const gfx::Rect& initial_pos,
                                            bool user_gesture,
@@ -104,7 +158,7 @@
   }
 }
 
-void AwWebContentsDelegate::CloseContents(content::WebContents* source) {
+void AwWebContentsDelegate::CloseContents(WebContents* source) {
   JNIEnv* env = AttachCurrentThread();
 
   ScopedJavaLocalRef<jobject> java_delegate = GetJavaDelegate(env);
@@ -113,7 +167,7 @@
   }
 }
 
-void AwWebContentsDelegate::ActivateContents(content::WebContents* contents) {
+void AwWebContentsDelegate::ActivateContents(WebContents* contents) {
   JNIEnv* env = AttachCurrentThread();
 
   ScopedJavaLocalRef<jobject> java_delegate = GetJavaDelegate(env);
@@ -133,6 +187,38 @@
       env, obj.obj(), pref_size.width(), pref_size.height());
 }
 
+static void FilesSelectedInChooser(
+    JNIEnv* env, jclass clazz,
+    jint process_id, jint render_id, jint mode_flags,
+    jobjectArray file_paths) {
+  content::RenderViewHost* rvh = content::RenderViewHost::FromID(process_id,
+                                                                 render_id);
+  if (!rvh)
+    return;
+
+  std::vector<std::string> file_path_str;
+  // Note file_paths maybe NULL, but this will just yield a zero-length vector.
+  base::android::AppendJavaStringArrayToStringVector(env, file_paths,
+                                                     &file_path_str);
+  std::vector<ui::SelectedFileInfo> files;
+  files.reserve(file_path_str.size());
+  for (size_t i = 0; i < file_path_str.size(); ++i) {
+    files.push_back(ui::SelectedFileInfo(base::FilePath(file_path_str[i]),
+                                         base::FilePath()));
+  }
+  FileChooserParams::Mode mode;
+  if (mode_flags & kFileChooserModeOpenFolder) {
+    mode = FileChooserParams::UploadFolder;
+  } else if (mode_flags & kFileChooserModeOpenMultiple) {
+    mode = FileChooserParams::OpenMultiple;
+  } else {
+    mode = FileChooserParams::Open;
+  }
+  LOG(INFO) << "File Chooser result: mode = " << mode
+            << ", file paths = " << JoinString(file_path_str, ":");
+  rvh->FilesSelectedInChooser(files, mode);
+}
+
 bool RegisterAwWebContentsDelegate(JNIEnv* env) {
   return RegisterNativesImpl(env);
 }
diff --git a/android_webview/native/aw_web_contents_delegate.h b/android_webview/native/aw_web_contents_delegate.h
index 3d84fbe..d84ca6c 100644
--- a/android_webview/native/aw_web_contents_delegate.h
+++ b/android_webview/native/aw_web_contents_delegate.h
@@ -31,7 +31,9 @@
                            int request_id,
                            const std::string& request_method,
                            const base::Callback<void(bool)>& callback) OVERRIDE;
-
+  virtual void RunFileChooser(
+      content::WebContents* web_contents,
+      const content::FileChooserParams& params) OVERRIDE;
   virtual void AddNewContents(content::WebContents* source,
                               content::WebContents* new_contents,
                               WindowOpenDisposition disposition,
diff --git a/android_webview/native/java_browser_view_renderer_helper.cc b/android_webview/native/java_browser_view_renderer_helper.cc
index 0426bd1..b72e037 100644
--- a/android_webview/native/java_browser_view_renderer_helper.cc
+++ b/android_webview/native/java_browser_view_renderer_helper.cc
@@ -18,6 +18,13 @@
 JavaBrowserViewRendererHelper::~JavaBrowserViewRendererHelper() {
 }
 
+// static
+JavaBrowserViewRendererHelper* JavaBrowserViewRendererHelper::GetInstance() {
+  static JavaBrowserViewRendererHelper* g_instance =
+      new JavaBrowserViewRendererHelper;
+  return g_instance;
+}
+
 ScopedJavaLocalRef<jobject> JavaBrowserViewRendererHelper::CreateBitmap(
     JNIEnv* env,
     int width,
diff --git a/android_webview/native/java_browser_view_renderer_helper.h b/android_webview/native/java_browser_view_renderer_helper.h
index 2d1aadc..986d737 100644
--- a/android_webview/native/java_browser_view_renderer_helper.h
+++ b/android_webview/native/java_browser_view_renderer_helper.h
@@ -18,6 +18,8 @@
   JavaBrowserViewRendererHelper();
   virtual ~JavaBrowserViewRendererHelper();
 
+  static JavaBrowserViewRendererHelper* GetInstance();
+
   // BrowserViewRenderer::JavaHelper implementation.
   virtual base::android::ScopedJavaLocalRef<jobject> CreateBitmap(
       JNIEnv* env,
diff --git a/android_webview/native/webview_native.gyp b/android_webview/native/webview_native.gyp
index bc6d0e5..b1d7082 100644
--- a/android_webview/native/webview_native.gyp
+++ b/android_webview/native/webview_native.gyp
@@ -50,6 +50,8 @@
         'aw_geolocation_permission_context.h',
         'aw_http_auth_handler.cc',
         'aw_http_auth_handler.h',
+        'aw_picture.cc',
+        'aw_picture.h',
         'aw_quota_manager_bridge_impl.cc',
         'aw_quota_manager_bridge_impl.h',
         'aw_resource.cc',
@@ -94,6 +96,7 @@
           '../java/src/org/chromium/android_webview/AwCookieManager.java',
           '../java/src/org/chromium/android_webview/AwFormDatabase.java',
           '../java/src/org/chromium/android_webview/AwHttpAuthHandler.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',
diff --git a/android_webview/native/webview_native.target.darwin-arm.mk b/android_webview/native/webview_native.target.darwin-arm.mk
index 933ba49..4c5296c 100644
--- a/android_webview/native/webview_native.target.darwin-arm.mk
+++ b/android_webview/native/webview_native.target.darwin-arm.mk
@@ -37,6 +37,7 @@
 	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_picture.cc \
 	android_webview/native/aw_quota_manager_bridge_impl.cc \
 	android_webview/native/aw_resource.cc \
 	android_webview/native/aw_settings.cc \
@@ -104,6 +105,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
@@ -213,6 +215,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
diff --git a/android_webview/native/webview_native.target.darwin-mips.mk b/android_webview/native/webview_native.target.darwin-mips.mk
index 2f11f10..f639290 100644
--- a/android_webview/native/webview_native.target.darwin-mips.mk
+++ b/android_webview/native/webview_native.target.darwin-mips.mk
@@ -37,6 +37,7 @@
 	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_picture.cc \
 	android_webview/native/aw_quota_manager_bridge_impl.cc \
 	android_webview/native/aw_resource.cc \
 	android_webview/native/aw_settings.cc \
@@ -103,6 +104,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
@@ -211,6 +213,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
diff --git a/android_webview/native/webview_native.target.darwin-x86.mk b/android_webview/native/webview_native.target.darwin-x86.mk
index fd9bd3b..458710f 100644
--- a/android_webview/native/webview_native.target.darwin-x86.mk
+++ b/android_webview/native/webview_native.target.darwin-x86.mk
@@ -37,6 +37,7 @@
 	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_picture.cc \
 	android_webview/native/aw_quota_manager_bridge_impl.cc \
 	android_webview/native/aw_resource.cc \
 	android_webview/native/aw_settings.cc \
@@ -105,6 +106,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
@@ -216,6 +218,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
diff --git a/android_webview/native/webview_native.target.linux-arm.mk b/android_webview/native/webview_native.target.linux-arm.mk
index 933ba49..4c5296c 100644
--- a/android_webview/native/webview_native.target.linux-arm.mk
+++ b/android_webview/native/webview_native.target.linux-arm.mk
@@ -37,6 +37,7 @@
 	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_picture.cc \
 	android_webview/native/aw_quota_manager_bridge_impl.cc \
 	android_webview/native/aw_resource.cc \
 	android_webview/native/aw_settings.cc \
@@ -104,6 +105,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
@@ -213,6 +215,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
diff --git a/android_webview/native/webview_native.target.linux-mips.mk b/android_webview/native/webview_native.target.linux-mips.mk
index 2f11f10..f639290 100644
--- a/android_webview/native/webview_native.target.linux-mips.mk
+++ b/android_webview/native/webview_native.target.linux-mips.mk
@@ -37,6 +37,7 @@
 	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_picture.cc \
 	android_webview/native/aw_quota_manager_bridge_impl.cc \
 	android_webview/native/aw_resource.cc \
 	android_webview/native/aw_settings.cc \
@@ -103,6 +104,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
@@ -211,6 +213,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
diff --git a/android_webview/native/webview_native.target.linux-x86.mk b/android_webview/native/webview_native.target.linux-x86.mk
index fd9bd3b..458710f 100644
--- a/android_webview/native/webview_native.target.linux-x86.mk
+++ b/android_webview/native/webview_native.target.linux-x86.mk
@@ -37,6 +37,7 @@
 	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_picture.cc \
 	android_webview/native/aw_quota_manager_bridge_impl.cc \
 	android_webview/native/aw_resource.cc \
 	android_webview/native/aw_settings.cc \
@@ -105,6 +106,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
@@ -216,6 +218,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
diff --git a/android_webview/public/browser/draw_sw.h b/android_webview/public/browser/draw_sw.h
index 2cdb45b..463f59c 100644
--- a/android_webview/public/browser/draw_sw.h
+++ b/android_webview/public/browser/draw_sw.h
@@ -14,16 +14,28 @@
 
 class SkPicture;
 
+static const int kAwPixelInfoVersion = 2;
+
+// Values of the AwPixelInfo::config field.
+enum AwPixelConfig {
+  AwConfig_RGB_565 = 4,
+  AwConfig_ARGB_4444 = 5,
+  AwConfig_ARGB_8888 = 6,
+};
+
 // Holds the information required to implement the SW draw to system canvas.
 struct AwPixelInfo {
-  int config;         // In SkBitmap::Config format.
-  int width;          // In pixels.
-  int height;         // In pixels.
-  int row_bytes;      // Number of bytes from start of one line to next.
-  void* pixels;       // The pixels, all (height * row_bytes) of them.
-  float matrix[9];    // The matrix currently in effect on the canvas.
-  void* clip_region;  // Flattened clip region.
-  size_t clip_region_size;   // Number of bytes in |clip_region|.
+  int version;          // The kAwPixelInfoVersion this struct was built with.
+  int config;           // |pixel| format: a value from AwPixelConfig.
+  int width;            // In pixels.
+  int height;           // In pixels.
+  int row_bytes;        // Number of bytes from start of one line to next.
+  void* pixels;         // The pixels, all (height * row_bytes) of them.
+  // The Matrix and Clip are relative to |pixels|, not the source canvas.
+  float matrix[9];      // The matrix currently in effect on the canvas.
+  int clip_rect_count;  // Number of rects in |clip_rects|.
+  int* clip_rects;      // Clip area: 4 ints per rect in {x,y,w,h} format.
+  // NOTE: If you add more members, bump kAwPixelInfoVersion.
 };
 
 // Function that can be called to fish out the underlying native pixel data
diff --git a/android_webview/test/shell/src/org/chromium/android_webview/test/AwTestContainerView.java b/android_webview/test/shell/src/org/chromium/android_webview/test/AwTestContainerView.java
index b83690e..e3c5077 100644
--- a/android_webview/test/shell/src/org/chromium/android_webview/test/AwTestContainerView.java
+++ b/android_webview/test/shell/src/org/chromium/android_webview/test/AwTestContainerView.java
@@ -219,6 +219,11 @@
         }
 
         @Override
+        public int super_getScrollBarStyle() {
+            return AwTestContainerView.super.getScrollBarStyle();
+        }
+
+        @Override
         public boolean requestDrawGL(Canvas canvas) {
             return false;
         }
diff --git a/apps/DEPS b/apps/DEPS
index 0100480..7920f1a 100644
--- a/apps/DEPS
+++ b/apps/DEPS
@@ -20,6 +20,7 @@
   "+chrome/browser/lifetime/application_lifetime.h",
   "+chrome/browser/profiles",
   "+chrome/browser/sessions/session_id.h",
+  "+chrome/browser/ui/extensions/app_metro_infobar_delegate_win.h",
   "+chrome/browser/ui/host_desktop.h",
   "+chrome/common/chrome_switches.h",
   "+chrome/common/extensions",
diff --git a/apps/OWNERS b/apps/OWNERS
index ba62226..22c418a 100644
--- a/apps/OWNERS
+++ b/apps/OWNERS
@@ -4,4 +4,5 @@
 koz@chromium.org
 mek@chromium.org
 miket@chromium.org
+scheib@chromium.org
 tapted@chromium.org
diff --git a/apps/app_lifetime_monitor.cc b/apps/app_lifetime_monitor.cc
index 8e4819a..8547be9 100644
--- a/apps/app_lifetime_monitor.cc
+++ b/apps/app_lifetime_monitor.cc
@@ -15,7 +15,6 @@
 
 using extensions::Extension;
 using extensions::ExtensionHost;
-using extensions::ShellWindowRegistry;
 
 AppLifetimeMonitor::AppLifetimeMonitor(Profile* profile)
     : profile_(profile) {
diff --git a/apps/app_lifetime_monitor.h b/apps/app_lifetime_monitor.h
index f18a97d..2da6550 100644
--- a/apps/app_lifetime_monitor.h
+++ b/apps/app_lifetime_monitor.h
@@ -8,8 +8,8 @@
 #include <string>
 #include <vector>
 
+#include "apps/shell_window_registry.h"
 #include "base/observer_list.h"
-#include "chrome/browser/extensions/shell_window_registry.h"
 #include "components/browser_context_keyed_service/browser_context_keyed_service.h"
 #include "content/public/browser/notification_observer.h"
 #include "content/public/browser/notification_registrar.h"
@@ -26,7 +26,7 @@
 // events.
 class AppLifetimeMonitor : public BrowserContextKeyedService,
                            public content::NotificationObserver,
-                           public extensions::ShellWindowRegistry::Observer {
+                           public ShellWindowRegistry::Observer {
  public:
   class Observer {
    public:
@@ -61,7 +61,7 @@
                        const content::NotificationSource& source,
                        const content::NotificationDetails& details) OVERRIDE;
 
-  // extensions::ShellWindowRegistry::Observer overrides:
+  // ShellWindowRegistry::Observer overrides:
   virtual void OnShellWindowAdded(ShellWindow* shell_window) OVERRIDE;
   virtual void OnShellWindowIconChanged(ShellWindow* shell_window) OVERRIDE;
   virtual void OnShellWindowRemoved(ShellWindow* shell_window) OVERRIDE;
diff --git a/apps/app_lifetime_monitor_factory.cc b/apps/app_lifetime_monitor_factory.cc
index 4d828b0..1fb7994 100644
--- a/apps/app_lifetime_monitor_factory.cc
+++ b/apps/app_lifetime_monitor_factory.cc
@@ -5,7 +5,7 @@
 #include "apps/app_lifetime_monitor_factory.h"
 
 #include "apps/app_lifetime_monitor.h"
-#include "chrome/browser/extensions/shell_window_registry.h"
+#include "apps/shell_window_registry.h"
 #include "chrome/browser/profiles/incognito_helpers.h"
 #include "chrome/browser/profiles/profile.h"
 #include "components/browser_context_keyed_service/browser_context_dependency_manager.h"
@@ -26,7 +26,7 @@
     : BrowserContextKeyedServiceFactory(
         "AppLifetimeMonitor",
         BrowserContextDependencyManager::GetInstance()) {
-  DependsOn(extensions::ShellWindowRegistry::Factory::GetInstance());
+  DependsOn(ShellWindowRegistry::Factory::GetInstance());
 }
 
 AppLifetimeMonitorFactory::~AppLifetimeMonitorFactory() {}
diff --git a/apps/app_load_service.cc b/apps/app_load_service.cc
index d2423c0..a0a6a66 100644
--- a/apps/app_load_service.cc
+++ b/apps/app_load_service.cc
@@ -6,12 +6,12 @@
 
 #include "apps/app_load_service_factory.h"
 #include "apps/launcher.h"
+#include "apps/shell_window_registry.h"
 #include "chrome/browser/chrome_notification_types.h"
 #include "chrome/browser/extensions/extension_host.h"
 #include "chrome/browser/extensions/extension_prefs.h"
 #include "chrome/browser/extensions/extension_service.h"
 #include "chrome/browser/extensions/extension_system.h"
-#include "chrome/browser/extensions/shell_window_registry.h"
 #include "chrome/browser/extensions/unpacked_installer.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/common/extensions/extension.h"
@@ -125,7 +125,7 @@
 }
 
 bool AppLoadService::HasShellWindows(const std::string& extension_id) {
-  return !extensions::ShellWindowRegistry::Get(profile_)->
+  return !ShellWindowRegistry::Get(profile_)->
       GetShellWindowsForApp(extension_id).empty();
 }
 
diff --git a/apps/app_load_service_factory.cc b/apps/app_load_service_factory.cc
index 37c2d45..a68cf94 100644
--- a/apps/app_load_service_factory.cc
+++ b/apps/app_load_service_factory.cc
@@ -5,9 +5,9 @@
 #include "apps/app_load_service_factory.h"
 
 #include "apps/app_load_service.h"
+#include "apps/shell_window_registry.h"
 #include "chrome/browser/extensions/extension_prefs_factory.h"
 #include "chrome/browser/extensions/extension_system_factory.h"
-#include "chrome/browser/extensions/shell_window_registry.h"
 #include "chrome/browser/profiles/incognito_helpers.h"
 #include "chrome/browser/profiles/profile.h"
 #include "components/browser_context_keyed_service/browser_context_dependency_manager.h"
@@ -30,7 +30,7 @@
         BrowserContextDependencyManager::GetInstance()) {
   DependsOn(extensions::ExtensionPrefsFactory::GetInstance());
   DependsOn(extensions::ExtensionSystemFactory::GetInstance());
-  DependsOn(extensions::ShellWindowRegistry::Factory::GetInstance());
+  DependsOn(ShellWindowRegistry::Factory::GetInstance());
 }
 
 AppLoadServiceFactory::~AppLoadServiceFactory() {
diff --git a/apps/app_restore_service.h b/apps/app_restore_service.h
index 5a66005..425364e 100644
--- a/apps/app_restore_service.h
+++ b/apps/app_restore_service.h
@@ -9,7 +9,7 @@
 #include <vector>
 
 #include "apps/app_lifetime_monitor.h"
-#include "chrome/browser/extensions/shell_window_registry.h"
+#include "apps/shell_window_registry.h"
 #include "components/browser_context_keyed_service/browser_context_keyed_service.h"
 
 namespace extensions {
diff --git a/apps/app_shim/extension_app_shim_handler_mac.cc b/apps/app_shim/extension_app_shim_handler_mac.cc
index 9173767..130c7f1 100644
--- a/apps/app_shim/extension_app_shim_handler_mac.cc
+++ b/apps/app_shim/extension_app_shim_handler_mac.cc
@@ -9,6 +9,7 @@
 #include "apps/app_shim/app_shim_messages.h"
 #include "apps/native_app_window.h"
 #include "apps/shell_window.h"
+#include "apps/shell_window_registry.h"
 #include "base/files/file_path.h"
 #include "base/logging.h"
 #include "chrome/browser/browser_process.h"
@@ -16,7 +17,6 @@
 #include "chrome/browser/extensions/extension_host.h"
 #include "chrome/browser/extensions/extension_service.h"
 #include "chrome/browser/extensions/extension_system.h"
-#include "chrome/browser/extensions/shell_window_registry.h"
 #include "chrome/browser/lifetime/application_lifetime.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/profiles/profile_manager.h"
@@ -44,7 +44,7 @@
 
 void TerminateIfNoShellWindows() {
   bool shell_windows_left =
-      extensions::ShellWindowRegistry::IsShellWindowRegisteredInAnyProfile(0);
+      apps::ShellWindowRegistry::IsShellWindowRegisteredInAnyProfile(0);
   if (!shell_windows_left)
     chrome::AttemptExit();
 }
@@ -53,7 +53,7 @@
 
 namespace apps {
 
-typedef extensions::ShellWindowRegistry::ShellWindowList ShellWindowList;
+typedef ShellWindowRegistry::ShellWindowList ShellWindowList;
 
 bool ExtensionAppShimHandler::Delegate::ProfileExistsForPath(
     const base::FilePath& path) {
@@ -89,8 +89,7 @@
 ShellWindowList ExtensionAppShimHandler::Delegate::GetWindows(
     Profile* profile,
     const std::string& extension_id) {
-  return extensions::ShellWindowRegistry::Get(profile)->
-      GetShellWindowsForApp(extension_id);
+  return ShellWindowRegistry::Get(profile)->GetShellWindowsForApp(extension_id);
 }
 
 const extensions::Extension*
@@ -167,7 +166,7 @@
     handler->OnShimQuit(host);
   } else {
     // App shims might be disabled or the shim is still starting up.
-    extensions::ShellWindowRegistry::Get(shell_window->profile())->
+    ShellWindowRegistry::Get(shell_window->profile())->
         CloseAllShellWindowsForApp(shell_window->extension_id());
   }
 }
@@ -305,7 +304,7 @@
   const std::string& app_id = host->GetAppId();
   const ShellWindowList windows =
       delegate_->GetWindows(profile, app_id);
-  for (extensions::ShellWindowRegistry::const_iterator it = windows.begin();
+  for (ShellWindowRegistry::const_iterator it = windows.begin();
        it != windows.end(); ++it) {
     (*it)->GetBaseWindow()->Close();
   }
diff --git a/apps/app_shim/extension_app_shim_handler_mac.h b/apps/app_shim/extension_app_shim_handler_mac.h
index 616fd78..8a9f64e 100644
--- a/apps/app_shim/extension_app_shim_handler_mac.h
+++ b/apps/app_shim/extension_app_shim_handler_mac.h
@@ -10,9 +10,9 @@
 
 #include "apps/app_lifetime_monitor.h"
 #include "apps/app_shim/app_shim_handler_mac.h"
+#include "apps/shell_window_registry.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/memory/weak_ptr.h"
-#include "chrome/browser/extensions/shell_window_registry.h"
 #include "content/public/browser/notification_observer.h"
 #include "content/public/browser/notification_registrar.h"
 
@@ -47,7 +47,7 @@
     virtual void LoadProfileAsync(const base::FilePath& path,
                                   base::Callback<void(Profile*)> callback);
 
-    virtual extensions::ShellWindowRegistry::ShellWindowList GetWindows(
+    virtual ShellWindowRegistry::ShellWindowList GetWindows(
         Profile* profile, const std::string& extension_id);
 
     virtual const extensions::Extension* GetAppExtension(
diff --git a/apps/app_shim/extension_app_shim_handler_mac_unittest.cc b/apps/app_shim/extension_app_shim_handler_mac_unittest.cc
index 33941de..636ba1b 100644
--- a/apps/app_shim/extension_app_shim_handler_mac_unittest.cc
+++ b/apps/app_shim/extension_app_shim_handler_mac_unittest.cc
@@ -16,7 +16,7 @@
 namespace apps {
 
 using extensions::Extension;
-typedef extensions::ShellWindowRegistry::ShellWindowList ShellWindowList;
+typedef ShellWindowRegistry::ShellWindowList ShellWindowList;
 
 using ::testing::_;
 using ::testing::Invoke;
diff --git a/apps/apps.gypi b/apps/apps.gypi
index 59f4c75..7e2c179 100644
--- a/apps/apps.gypi
+++ b/apps/apps.gypi
@@ -70,6 +70,8 @@
         'shell_window.h',
         'shell_window_geometry_cache.cc',
         'shell_window_geometry_cache.h',
+        'shell_window_registry.cc',
+        'shell_window_registry.h',
         'switches.cc',
         'switches.h',
       ],
diff --git a/apps/launcher.cc b/apps/launcher.cc
index d892da6..9ebb46e 100644
--- a/apps/launcher.cc
+++ b/apps/launcher.cc
@@ -23,6 +23,7 @@
 #include "chrome/browser/extensions/extension_system.h"
 #include "chrome/browser/extensions/lazy_background_task_queue.h"
 #include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/ui/extensions/app_metro_infobar_delegate_win.h"
 #include "chrome/common/extensions/extension.h"
 #include "chrome/common/extensions/extension_messages.h"
 #include "content/public/browser/browser_thread.h"
@@ -285,6 +286,17 @@
                                       const Extension* extension,
                                       const CommandLine* command_line,
                                       const base::FilePath& current_directory) {
+#if defined(OS_WIN)
+    // On Windows 8's single window Metro mode we can not launch platform apps.
+    // Offer to switch Chrome to desktop mode.
+    if (win8::IsSingleWindowMetroMode()) {
+      AppMetroInfoBarDelegateWin::Create(
+          profile, AppMetroInfoBarDelegateWin::LAUNCH_PACKAGED_APP,
+          extension->id());
+      return;
+    }
+#endif
+
   base::FilePath path;
   if (!GetAbsolutePathFromCommandLine(command_line, current_directory, &path)) {
     LaunchPlatformAppWithNoData(profile, extension);
diff --git a/apps/shell_window.cc b/apps/shell_window.cc
index 12585aa..10ab851 100644
--- a/apps/shell_window.cc
+++ b/apps/shell_window.cc
@@ -6,13 +6,13 @@
 
 #include "apps/native_app_window.h"
 #include "apps/shell_window_geometry_cache.h"
+#include "apps/shell_window_registry.h"
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/values.h"
 #include "chrome/browser/chrome_notification_types.h"
 #include "chrome/browser/extensions/extension_process_manager.h"
 #include "chrome/browser/extensions/extension_system.h"
-#include "chrome/browser/extensions/shell_window_registry.h"
 #include "chrome/browser/extensions/suggest_permission_util.h"
 #include "chrome/browser/lifetime/application_lifetime.h"
 #include "chrome/browser/profiles/profile.h"
@@ -194,7 +194,7 @@
 
   UpdateExtensionAppIcon();
 
-  extensions::ShellWindowRegistry::Get(profile_)->AddShellWindow(this);
+  ShellWindowRegistry::Get(profile_)->AddShellWindow(this);
 }
 
 ShellWindow::~ShellWindow() {
@@ -280,7 +280,7 @@
 }
 
 void ShellWindow::OnNativeClose() {
-  extensions::ShellWindowRegistry::Get(profile_)->RemoveShellWindow(this);
+  ShellWindowRegistry::Get(profile_)->RemoveShellWindow(this);
   if (shell_window_contents_)
     shell_window_contents_->NativeWindowClosed();
   delete this;
@@ -293,7 +293,7 @@
 }
 
 void ShellWindow::OnNativeWindowActivated() {
-  extensions::ShellWindowRegistry::Get(profile_)->ShellWindowActivated(this);
+  ShellWindowRegistry::Get(profile_)->ShellWindowActivated(this);
 }
 
 scoped_ptr<gfx::Image> ShellWindow::GetAppListIcon() {
@@ -374,7 +374,7 @@
     return;
   app_icon_ = image;
   native_app_window_->UpdateWindowIcon();
-  extensions::ShellWindowRegistry::Get(profile_)->ShellWindowIconChanged(this);
+  ShellWindowRegistry::Get(profile_)->ShellWindowIconChanged(this);
 }
 
 void ShellWindow::Fullscreen() {
diff --git a/chrome/browser/extensions/shell_window_registry.cc b/apps/shell_window_registry.cc
similarity index 96%
rename from chrome/browser/extensions/shell_window_registry.cc
rename to apps/shell_window_registry.cc
index d4275af..301bcf1 100644
--- a/chrome/browser/extensions/shell_window_registry.cc
+++ b/apps/shell_window_registry.cc
@@ -1,11 +1,11 @@
-// Copyright (c) 2012 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.
 
 #include "apps/native_app_window.h"
 #include "apps/shell_window.h"
+#include "apps/shell_window_registry.h"
 #include "chrome/browser/browser_process.h"
-#include "chrome/browser/extensions/shell_window_registry.h"
 #include "chrome/browser/profiles/incognito_helpers.h"
 #include "chrome/browser/profiles/profile_manager.h"
 #include "chrome/common/extensions/extension.h"
@@ -17,8 +17,6 @@
 #include "content/public/browser/site_instance.h"
 #include "content/public/browser/web_contents.h"
 
-using apps::ShellWindow;
-
 namespace {
 
 // Create a key that identifies a ShellWindow in a RenderViewHost across App
@@ -27,9 +25,9 @@
 // |id|, the chrome-extension://extension-id/page.html URL will be used. If the
 // RenderViewHost is not for a ShellWindow, return an empty string.
 std::string GetWindowKeyForRenderViewHost(
-    const extensions::ShellWindowRegistry* registry,
+    const apps::ShellWindowRegistry* registry,
     content::RenderViewHost* render_view_host) {
-  ShellWindow* shell_window =
+  apps::ShellWindow* shell_window =
       registry->GetShellWindowForRenderViewHost(render_view_host);
   if (!shell_window)
     return std::string(); // Not a ShellWindow.
@@ -45,7 +43,7 @@
 
 }  // namespace
 
-namespace extensions {
+namespace apps {
 
 ShellWindowRegistry::ShellWindowRegistry(Profile* profile)
     : profile_(profile),
diff --git a/chrome/browser/extensions/shell_window_registry.h b/apps/shell_window_registry.h
similarity index 95%
rename from chrome/browser/extensions/shell_window_registry.h
rename to apps/shell_window_registry.h
index fb5f48e..e23c5e9 100644
--- a/chrome/browser/extensions/shell_window_registry.h
+++ b/apps/shell_window_registry.h
@@ -1,9 +1,9 @@
-// Copyright (c) 2012 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.
 
-#ifndef CHROME_BROWSER_EXTENSIONS_SHELL_WINDOW_REGISTRY_H_
-#define CHROME_BROWSER_EXTENSIONS_SHELL_WINDOW_REGISTRY_H_
+#ifndef APPS_SHELL_WINDOW_REGISTRY_H_
+#define APPS_SHELL_WINDOW_REGISTRY_H_
 
 #include <list>
 
@@ -17,16 +17,14 @@
 
 class Profile;
 
-namespace apps {
-class ShellWindow;
-}
-
 namespace content {
 class DevToolsAgentHost;
 class RenderViewHost;
 }
 
-namespace extensions {
+namespace apps {
+
+class ShellWindow;
 
 // The ShellWindowRegistry tracks the ShellWindows for all platform apps for a
 // particular profile.
@@ -150,4 +148,4 @@
 
 }  // namespace extensions
 
-#endif  // CHROME_BROWSER_EXTENSIONS_SHELL_WINDOW_REGISTRY_H_
+#endif  // APPS_SHELL_WINDOW_REGISTRY_H_
diff --git a/ash/accelerators/accelerator_controller.cc b/ash/accelerators/accelerator_controller.cc
index 2a75415..3d669bb 100644
--- a/ash/accelerators/accelerator_controller.cc
+++ b/ash/accelerators/accelerator_controller.cc
@@ -94,6 +94,12 @@
   return true;
 }
 
+bool HandleCycleWindowOverviewMRU(WindowSelector::Direction direction) {
+  Shell::GetInstance()->
+      window_selector_controller()->HandleCycleWindow(direction);
+  return true;
+}
+
 void HandleCycleWindowLinear(CycleDirection direction) {
   Shell::GetInstance()->
       window_cycle_controller()->HandleLinearCycleWindow();
@@ -518,11 +524,19 @@
     case CYCLE_BACKWARD_MRU:
       if (key_code == ui::VKEY_TAB)
         shell->delegate()->RecordUserMetricsAction(UMA_ACCEL_PREVWINDOW_TAB);
+      if (CommandLine::ForCurrentProcess()->HasSwitch(
+              switches::kAshEnableOverviewMode)) {
+        return HandleCycleWindowOverviewMRU(WindowSelector::BACKWARD);
+      }
       return HandleCycleWindowMRU(WindowCycleController::BACKWARD,
                                   accelerator.IsAltDown());
     case CYCLE_FORWARD_MRU:
       if (key_code == ui::VKEY_TAB)
         shell->delegate()->RecordUserMetricsAction(UMA_ACCEL_NEXTWINDOW_TAB);
+      if (CommandLine::ForCurrentProcess()->HasSwitch(
+              switches::kAshEnableOverviewMode)) {
+        return HandleCycleWindowOverviewMRU(WindowSelector::FORWARD);
+      }
       return HandleCycleWindowMRU(WindowCycleController::FORWARD,
                                   accelerator.IsAltDown());
     case CYCLE_BACKWARD_LINEAR:
diff --git a/ash/ash.gyp b/ash/ash.gyp
index 82fb264..7a3f1be 100644
--- a/ash/ash.gyp
+++ b/ash/ash.gyp
@@ -108,6 +108,8 @@
         'display/mouse_cursor_event_filter.h',
         'display/output_configurator_animation.cc',
         'display/output_configurator_animation.h',
+        'display/resolution_notification_controller.cc',
+        'display/resolution_notification_controller.h',
         'display/root_window_transformers.cc',
         'display/root_window_transformers.h',
         'display/screen_position_controller.cc',
@@ -258,6 +260,8 @@
         'system/chromeos/settings/tray_settings.h',
         'system/chromeos/tray_display.cc',
         'system/chromeos/tray_display.h',
+        'system/chromeos/tray_tracing.cc',
+        'system/chromeos/tray_tracing.h',
         'system/date/clock_observer.h',
         'system/date/date_view.cc',
         'system/date/date_view.h',
@@ -673,6 +677,7 @@
         'display/display_manager_unittest.cc',
         'display/mirror_window_controller_unittest.cc',
         'display/mouse_cursor_event_filter_unittest.cc',
+        'display/resolution_notification_controller_unittest.cc',
         'display/root_window_transformers_unittest.cc',
         'display/screen_position_controller_unittest.cc',
         'drag_drop/drag_drop_controller_unittest.cc',
diff --git a/ash/ash_chromeos_strings.grdp b/ash/ash_chromeos_strings.grdp
index 76b906b..1190db9 100644
--- a/ash/ash_chromeos_strings.grdp
+++ b/ash/ash_chromeos_strings.grdp
@@ -242,7 +242,10 @@
     Authentication certificate rejected remotely
   </message>
   <message name="IDS_CHROMEOS_NETWORK_ERROR_PPP_AUTH_FAILED" desc="Network error details in notifications: PPP_AUTH_FAILED">
-    Failed to authenticate with provided username or password
+    PPP authentication failed due to an incorrect username or password
+  </message>
+  <message name="IDS_CHROMEOS_NETWORK_ERROR_CONFIGURE_FAILED" desc="Network error details in notifications: Configuration error">
+    Failed to configure network
   </message>
   <message name="IDS_CHROMEOS_NETWORK_ERROR_UNRECOGNIZED" desc="Network error details in notifications: Unrecognized">
     Unrecognized error
diff --git a/ash/ash_strings.grd b/ash/ash_strings.grd
index f43ba86..2d75802 100644
--- a/ash/ash_strings.grd
+++ b/ash/ash_strings.grd
@@ -285,6 +285,9 @@
       <message name="IDS_ASH_STATUS_TRAY_BLUETOOTH_DISCOVERING" desc="The label used in the tray popup to show bluetooth is discovering devices.">
         Scanning for devices...
       </message>
+      <message name="IDS_ASH_STATUS_TRAY_TRACING" desc="The status tray item indicating that performance tracing is running.">
+        Performance tracing enabled
+      </message>
 
       <message name="IDS_ASH_STATUS_TRAY_UPDATE" desc="The label used in the tray popup to notify that the user should restart to get system updates.">
         Restart to update
@@ -325,10 +328,10 @@
         Dock mode
       </message>
       <message name="IDS_ASH_STATUS_TRAY_DISPLAY_RESOLUTION_CHANGED" desc="The label used in the tray to notify that the display resolution settings has changed.">
-        <ph name="DISPLAY_NAME">$1</ph> has been resized to <ph name="RESOLUTION">$2</ph>
+        <ph name="DISPLAY_NAME">$1</ph> resolution was changed to <ph name="RESOLUTION">$2</ph>
       </message>
       <message name="IDS_ASH_STATUS_TRAY_DISPLAY_ROTATED" desc="The label used in the tray to notify that the display rotation settings has changed.">
-        <ph name="DISPLAY_NAME">$1</ph> has been rotated
+        <ph name="DISPLAY_NAME">$1</ph> was rotated to <ph name="ROTATION">$2</ph>
       </message>
       <message name="IDS_ASH_STATUS_TRAY_DISPLAY_SINGLE_DISPLAY" desc="The label used in the tray to show a single display's configuration">
         <ph name="DISPLAY_NAME">$1</ph>: <ph name="ANNOTATION">$2</ph>
@@ -345,6 +348,18 @@
       <message name="IDS_ASH_STATUS_TRAY_DISPLAY_ANNOTATION_OVERSCAN" desc="Label used to describe that the system notice that this display device may have overscan area.">
         overscan
       </message>
+      <message name="IDS_ASH_STATUS_TRAY_DISPLAY_STANDARD_ORIENTATION" desc="The default value of display orientation option item.">
+        0&#x00B0;
+      </message>
+      <message name="IDS_ASH_STATUS_TRAY_DISPLAY_ORIENTATION_90" desc="The value of display orientation option item: 90-degree rotated">
+        90&#x00B0;
+      </message>
+      <message name="IDS_ASH_STATUS_TRAY_DISPLAY_ORIENTATION_180" desc="The value of display orientation option item: 180-degree rotated">
+        180&#x00B0;
+      </message>
+      <message name="IDS_ASH_STATUS_TRAY_DISPLAY_ORIENTATION_270" desc="The value of display orientation option item: 270-degree rotated">
+        270&#x00B0;
+      </message>
       <message name="IDS_ASH_STATUS_TRAY_DRIVE_SYNCING" desc="The label in the tray to indicate onoing file sync operations.">
         Syncing <ph name="count">$1<ex>3</ex></ph> file(s)
       </message>
@@ -524,6 +539,15 @@
       <message name="IDS_ASH_DISPLAY_FAILURE_ON_NON_MIRRORING" desc="An error message to show that the system failed to enter the extended desktop mode or unknown status. Please translate the parentized text.">
         Dear Monitor, it's not working out between us. (That monitor is not supported)
       </message>
+      <message name="IDS_ASH_DISPLAY_RESOLUTION_CHANGE_ACCEPT" desc="A button label shown in the notification for the resolution change to accept the change">
+        Accept
+      </message>
+      <message name="IDS_ASH_DISPLAY_RESOLUTION_CHANGE_REVERT" desc="A button label shown in the notification for the resolution change to revert the change">
+        Revert
+      </message>
+      <message name="IDS_ASH_DISPLAY_RESOLUTION_TIMEOUT" desc="A message for to notify the user about the timeout of display resolution change.">
+        Reverting to old resolution in <ph name="TIMEOUT_SECONDS">$1</ph>
+      </message>
       <message name="IDS_ASH_INTERNAL_DISPLAY_NAME" desc="The name of the internal display which is shown in the display settings.">
         Internal Display
       </message>
diff --git a/ash/display/display_controller.cc b/ash/display/display_controller.cc
index ccba3e0..fce5a82 100644
--- a/ash/display/display_controller.cc
+++ b/ash/display/display_controller.cc
@@ -404,6 +404,10 @@
     PreDisplayConfigurationChange();
     // TODO(oshima): Call UpdateDisplays instead.
     UpdateDisplayBoundsForLayout();
+    // Primary's bounds stay the same. Just notify bounds change
+    // on the secondary.
+    Shell::GetInstance()->screen()->NotifyBoundsChanged(
+        ScreenAsh::GetSecondaryDisplay());
     PostDisplayConfigurationChange();
   }
 }
diff --git a/ash/display/display_controller_unittest.cc b/ash/display/display_controller_unittest.cc
index e9baf90..9131468 100644
--- a/ash/display/display_controller_unittest.cc
+++ b/ash/display/display_controller_unittest.cc
@@ -33,35 +33,67 @@
 
 const char kDesktopBackgroundView[] = "DesktopBackgroundView";
 
-class TestObserver : public DisplayController::Observer {
+class TestObserver : public DisplayController::Observer,
+                     public gfx::DisplayObserver {
  public:
-  TestObserver() : changing_count_(0), changed_count_(0) {
+  TestObserver()
+      : changing_count_(0),
+        changed_count_(0),
+        bounds_changed_count_(0),
+        changed_display_id_(0) {
     Shell::GetInstance()->display_controller()->AddObserver(this);
+    Shell::GetScreen()->AddObserver(this);
   }
 
   virtual ~TestObserver() {
     Shell::GetInstance()->display_controller()->RemoveObserver(this);
+    Shell::GetScreen()->RemoveObserver(this);
   }
 
+  // Overridden from DisplayController::Observer
   virtual void OnDisplayConfigurationChanging() OVERRIDE {
     ++changing_count_;
   }
-
   virtual void OnDisplayConfigurationChanged() OVERRIDE {
     ++changed_count_;
   }
 
+  // Overrideen from gfx::DisplayObserver
+  virtual void OnDisplayBoundsChanged(const gfx::Display& display) OVERRIDE {
+    changed_display_id_ = display.id();
+    bounds_changed_count_ ++;
+  }
+  virtual void OnDisplayAdded(const gfx::Display& new_display) OVERRIDE {
+  }
+  virtual void OnDisplayRemoved(const gfx::Display& old_display) OVERRIDE {
+  }
+
   int CountAndReset() {
     EXPECT_EQ(changing_count_, changed_count_);
-    int c = changing_count_;
+    int count = changing_count_;
     changing_count_ = changed_count_ = 0;
-    return c;
+    return count;
+  }
+
+  int64 GetBoundsChangedCountAndReset() {
+    int count = bounds_changed_count_;
+    bounds_changed_count_ = 0;
+    return count;
+  }
+
+  int64 GetChangedDisplayIdAndReset() {
+    int64 id = changed_display_id_;
+    changed_display_id_ = 0;
+    return id;
   }
 
  private:
   int changing_count_;
   int changed_count_;
 
+  int bounds_changed_count_;
+  int64 changed_display_id_;
+
   DISALLOW_COPY_AND_ASSIGN(TestObserver);
 };
 
@@ -227,9 +259,11 @@
   TestObserver observer;
   UpdateDisplay("500x500,400x400");
   EXPECT_EQ(1, observer.CountAndReset());  // resize and add
+  EXPECT_EQ(1, observer.GetBoundsChangedCountAndReset());
   gfx::Insets insets(5, 5, 5, 5);
+  int64 secondary_display_id = ScreenAsh::GetSecondaryDisplay().id();
   Shell::GetInstance()->display_manager()->UpdateWorkAreaOfDisplay(
-      ScreenAsh::GetSecondaryDisplay().id(), insets);
+      secondary_display_id, insets);
 
   // Default layout is RIGHT.
   EXPECT_EQ("0,0 500x500", GetPrimaryDisplay().bounds().ToString());
@@ -239,6 +273,8 @@
   // Layout the secondary display to the bottom of the primary.
   SetSecondaryDisplayLayout(DisplayLayout::BOTTOM);
   EXPECT_EQ(1, observer.CountAndReset());
+  EXPECT_EQ(1, observer.GetBoundsChangedCountAndReset());
+  EXPECT_EQ(secondary_display_id, observer.GetChangedDisplayIdAndReset());
   EXPECT_EQ("0,0 500x500", GetPrimaryDisplay().bounds().ToString());
   EXPECT_EQ("0,500 400x400", GetSecondaryDisplay().bounds().ToString());
   EXPECT_EQ("5,505 390x390", GetSecondaryDisplay().work_area().ToString());
@@ -246,6 +282,8 @@
   // Layout the secondary display to the left of the primary.
   SetSecondaryDisplayLayout(DisplayLayout::LEFT);
   EXPECT_EQ(1, observer.CountAndReset());
+  EXPECT_EQ(1, observer.GetBoundsChangedCountAndReset());
+  EXPECT_EQ(secondary_display_id, observer.GetChangedDisplayIdAndReset());
   EXPECT_EQ("0,0 500x500", GetPrimaryDisplay().bounds().ToString());
   EXPECT_EQ("-400,0 400x400", GetSecondaryDisplay().bounds().ToString());
   EXPECT_EQ("-395,5 390x390", GetSecondaryDisplay().work_area().ToString());
@@ -253,6 +291,8 @@
   // Layout the secondary display to the top of the primary.
   SetSecondaryDisplayLayout(DisplayLayout::TOP);
   EXPECT_EQ(1, observer.CountAndReset());
+  EXPECT_EQ(1, observer.GetBoundsChangedCountAndReset());
+  EXPECT_EQ(secondary_display_id, observer.GetChangedDisplayIdAndReset());
   EXPECT_EQ("0,0 500x500", GetPrimaryDisplay().bounds().ToString());
   EXPECT_EQ("0,-400 400x400", GetSecondaryDisplay().bounds().ToString());
   EXPECT_EQ("5,-395 390x390", GetSecondaryDisplay().work_area().ToString());
@@ -260,36 +300,56 @@
   // Layout to the right with an offset.
   SetSecondaryDisplayLayoutAndOffset(DisplayLayout::RIGHT, 300);
   EXPECT_EQ(1, observer.CountAndReset());  // resize and add
+  EXPECT_EQ(1, observer.GetBoundsChangedCountAndReset());
+  EXPECT_EQ(secondary_display_id, observer.GetChangedDisplayIdAndReset());
   EXPECT_EQ("0,0 500x500", GetPrimaryDisplay().bounds().ToString());
   EXPECT_EQ("500,300 400x400", GetSecondaryDisplay().bounds().ToString());
 
   // Keep the minimum 100.
   SetSecondaryDisplayLayoutAndOffset(DisplayLayout::RIGHT, 490);
   EXPECT_EQ(1, observer.CountAndReset());  // resize and add
+  EXPECT_EQ(1, observer.GetBoundsChangedCountAndReset());
+  EXPECT_EQ(secondary_display_id, observer.GetChangedDisplayIdAndReset());
   EXPECT_EQ("0,0 500x500", GetPrimaryDisplay().bounds().ToString());
   EXPECT_EQ("500,400 400x400", GetSecondaryDisplay().bounds().ToString());
 
   SetSecondaryDisplayLayoutAndOffset(DisplayLayout::RIGHT, -400);
+  EXPECT_EQ(secondary_display_id, observer.GetChangedDisplayIdAndReset());
+  EXPECT_EQ(1, observer.GetBoundsChangedCountAndReset());
   EXPECT_EQ(1, observer.CountAndReset());  // resize and add
   EXPECT_EQ("0,0 500x500", GetPrimaryDisplay().bounds().ToString());
   EXPECT_EQ("500,-300 400x400", GetSecondaryDisplay().bounds().ToString());
 
   //  Layout to the bottom with an offset.
   SetSecondaryDisplayLayoutAndOffset(DisplayLayout::BOTTOM, -200);
+  EXPECT_EQ(secondary_display_id, observer.GetChangedDisplayIdAndReset());
+  EXPECT_EQ(1, observer.GetBoundsChangedCountAndReset());
   EXPECT_EQ(1, observer.CountAndReset());  // resize and add
   EXPECT_EQ("0,0 500x500", GetPrimaryDisplay().bounds().ToString());
   EXPECT_EQ("-200,500 400x400", GetSecondaryDisplay().bounds().ToString());
 
   // Keep the minimum 100.
   SetSecondaryDisplayLayoutAndOffset(DisplayLayout::BOTTOM, 490);
+  EXPECT_EQ(secondary_display_id, observer.GetChangedDisplayIdAndReset());
+  EXPECT_EQ(1, observer.GetBoundsChangedCountAndReset());
   EXPECT_EQ(1, observer.CountAndReset());  // resize and add
   EXPECT_EQ("0,0 500x500", GetPrimaryDisplay().bounds().ToString());
   EXPECT_EQ("400,500 400x400", GetSecondaryDisplay().bounds().ToString());
 
   SetSecondaryDisplayLayoutAndOffset(DisplayLayout::BOTTOM, -400);
+  EXPECT_EQ(secondary_display_id, observer.GetChangedDisplayIdAndReset());
+  EXPECT_EQ(1, observer.GetBoundsChangedCountAndReset());
   EXPECT_EQ(1, observer.CountAndReset());  // resize and add
   EXPECT_EQ("0,0 500x500", GetPrimaryDisplay().bounds().ToString());
   EXPECT_EQ("-300,500 400x400", GetSecondaryDisplay().bounds().ToString());
+
+  // Setting the same layout shouldn't invoke observers.
+  SetSecondaryDisplayLayoutAndOffset(DisplayLayout::BOTTOM, -400);
+  EXPECT_EQ(0, observer.GetChangedDisplayIdAndReset());
+  EXPECT_EQ(0, observer.GetBoundsChangedCountAndReset());
+  EXPECT_EQ(0, observer.CountAndReset());  // resize and add
+  EXPECT_EQ("0,0 500x500", GetPrimaryDisplay().bounds().ToString());
+  EXPECT_EQ("-300,500 400x400", GetSecondaryDisplay().bounds().ToString());
 }
 
 TEST_F(DisplayControllerTest, BoundsUpdated) {
diff --git a/ash/display/resolution_notification_controller.cc b/ash/display/resolution_notification_controller.cc
new file mode 100644
index 0000000..a765d61
--- /dev/null
+++ b/ash/display/resolution_notification_controller.cc
@@ -0,0 +1,296 @@
+// 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 "ash/display/resolution_notification_controller.h"
+
+#include "ash/display/display_controller.h"
+#include "ash/display/display_manager.h"
+#include "ash/shell.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"
+#include "ui/base/l10n/time_format.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/gfx/display.h"
+#include "ui/gfx/screen.h"
+#include "ui/message_center/message_center.h"
+#include "ui/message_center/notification.h"
+#include "ui/message_center/notification_delegate.h"
+
+using message_center::Notification;
+
+namespace ash {
+namespace internal {
+namespace {
+
+bool g_use_timer = true;
+
+class ResolutionChangeNotificationDelegate
+    : public message_center::NotificationDelegate {
+ public:
+  ResolutionChangeNotificationDelegate(
+      ResolutionNotificationController* controller,
+      bool has_timeout);
+
+ protected:
+  virtual ~ResolutionChangeNotificationDelegate();
+
+ private:
+  // message_center::NotificationDelegate overrides:
+  virtual void Display() OVERRIDE;
+  virtual void Error() OVERRIDE;
+  virtual void Close(bool by_user) OVERRIDE;
+  virtual void Click() OVERRIDE;
+  virtual bool HasClickedListener() OVERRIDE;
+  virtual void ButtonClick(int button_index) OVERRIDE;
+
+  ResolutionNotificationController* controller_;
+  bool has_timeout_;
+
+  DISALLOW_COPY_AND_ASSIGN(ResolutionChangeNotificationDelegate);
+};
+
+ResolutionChangeNotificationDelegate::ResolutionChangeNotificationDelegate(
+    ResolutionNotificationController* controller,
+    bool has_timeout)
+    : controller_(controller),
+      has_timeout_(has_timeout) {
+  DCHECK(controller_);
+}
+
+ResolutionChangeNotificationDelegate::~ResolutionChangeNotificationDelegate() {
+}
+
+void ResolutionChangeNotificationDelegate::Display() {
+}
+
+void ResolutionChangeNotificationDelegate::Error() {
+}
+
+void ResolutionChangeNotificationDelegate::Close(bool by_user) {
+  if (by_user)
+    controller_->AcceptResolutionChange();
+}
+
+void ResolutionChangeNotificationDelegate::Click() {
+  controller_->AcceptResolutionChange();
+}
+
+bool ResolutionChangeNotificationDelegate::HasClickedListener() {
+  return true;
+}
+
+void ResolutionChangeNotificationDelegate::ButtonClick(int button_index) {
+  // If there's the timeout, the first button is "Accept". Otherwise the
+  // button click should be "Revert".
+  if (has_timeout_ && button_index == 0)
+    controller_->AcceptResolutionChange();
+  else
+    controller_->RevertResolutionChange();
+}
+
+}  // namespace
+
+// static
+const int ResolutionNotificationController::kTimeoutInSec = 15;
+
+// static
+const char ResolutionNotificationController::kNotificationId[] =
+    "chrome://settings/display/resolution";
+
+struct ResolutionNotificationController::ResolutionChangeInfo {
+  ResolutionChangeInfo(int64 display_id,
+                       const gfx::Size& old_resolution,
+                       const gfx::Size& new_resolution,
+                       const base::Closure& accept_callback);
+  ~ResolutionChangeInfo();
+
+  // The id of the display where the resolution change happens.
+  int64 display_id;
+
+  // The resolution before the change.
+  gfx::Size old_resolution;
+
+  // The new resolution after the change.
+  gfx::Size new_resolution;
+
+  // The callback when accept is chosen.
+  base::Closure accept_callback;
+
+  // The remaining timeout in seconds. 0 if the change does not time out.
+  uint8 timeout_count;
+
+  // The timer to invoke OnTimerTick() every second. This cannot be
+  // OneShotTimer since the message contains text "automatically closed in xx
+  // seconds..." which has to be updated every second.
+  base::RepeatingTimer<ResolutionNotificationController> timer;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(ResolutionChangeInfo);
+};
+
+ResolutionNotificationController::ResolutionChangeInfo::ResolutionChangeInfo(
+    int64 display_id,
+    const gfx::Size& old_resolution,
+    const gfx::Size& new_resolution,
+    const base::Closure& accept_callback)
+    : display_id(display_id),
+      old_resolution(old_resolution),
+      new_resolution(new_resolution),
+      accept_callback(accept_callback),
+      timeout_count(0) {
+  DisplayManager* display_manager = Shell::GetInstance()->display_manager();
+  if (!display_manager->HasInternalDisplay() &&
+      display_manager->num_connected_displays() == 1u) {
+    timeout_count = kTimeoutInSec;
+  }
+}
+
+ResolutionNotificationController::ResolutionChangeInfo::
+    ~ResolutionChangeInfo() {
+}
+
+ResolutionNotificationController::ResolutionNotificationController() {
+  Shell::GetInstance()->display_controller()->AddObserver(this);
+  Shell::GetScreen()->AddObserver(this);
+}
+
+ResolutionNotificationController::~ResolutionNotificationController() {
+  Shell::GetInstance()->display_controller()->RemoveObserver(this);
+  Shell::GetScreen()->RemoveObserver(this);
+}
+
+void ResolutionNotificationController::SetDisplayResolutionAndNotify(
+    int64 display_id,
+    const gfx::Size& old_resolution,
+    const gfx::Size& new_resolution,
+    const base::Closure& accept_callback) {
+  // If multiple resolution changes are invoked for the same display,
+  // the original resolution for the first resolution change has to be used
+  // instead of the specified |old_resolution|.
+  gfx::Size original_resolution;
+  if (change_info_ && change_info_->display_id == display_id) {
+    DCHECK(change_info_->new_resolution == old_resolution);
+    original_resolution = change_info_->old_resolution;
+  }
+
+  change_info_.reset(new ResolutionChangeInfo(
+      display_id, old_resolution, new_resolution, accept_callback));
+  if (!original_resolution.IsEmpty())
+    change_info_->old_resolution = original_resolution;
+
+  // SetDisplayResolution() causes OnConfigurationChanged() and the notification
+  // will be shown at that point.
+  Shell::GetInstance()->display_manager()->SetDisplayResolution(
+      display_id, new_resolution);
+}
+
+bool ResolutionNotificationController::DoesNotificationTimeout() {
+  return change_info_ && change_info_->timeout_count > 0;
+}
+
+void ResolutionNotificationController::CreateOrUpdateNotification() {
+  message_center::MessageCenter* message_center =
+      message_center::MessageCenter::Get();
+  if (!change_info_) {
+    message_center->RemoveNotification(kNotificationId, false /* by_user */);
+    return;
+  }
+
+  base::string16 timeout_message;
+  message_center::RichNotificationData data;
+  if (change_info_->timeout_count > 0) {
+    data.buttons.push_back(message_center::ButtonInfo(
+        l10n_util::GetStringUTF16(IDS_ASH_DISPLAY_RESOLUTION_CHANGE_ACCEPT)));
+    timeout_message = l10n_util::GetStringFUTF16(
+        IDS_ASH_DISPLAY_RESOLUTION_TIMEOUT,
+        ui::TimeFormat::TimeDurationLong(
+            base::TimeDelta::FromSeconds(change_info_->timeout_count)));
+  }
+  data.buttons.push_back(message_center::ButtonInfo(
+        l10n_util::GetStringUTF16(IDS_ASH_DISPLAY_RESOLUTION_CHANGE_REVERT)));
+
+  ui::ResourceBundle& bundle = ui::ResourceBundle::GetSharedInstance();
+  scoped_ptr<Notification> notification(new Notification(
+      message_center::NOTIFICATION_TYPE_SIMPLE,
+      kNotificationId,
+      l10n_util::GetStringFUTF16(
+          IDS_ASH_STATUS_TRAY_DISPLAY_RESOLUTION_CHANGED,
+          UTF8ToUTF16(Shell::GetInstance()->display_manager()->
+              GetDisplayNameForId(change_info_->display_id)),
+          UTF8ToUTF16(change_info_->new_resolution.ToString())),
+      timeout_message,
+      bundle.GetImageNamed(IDR_AURA_UBER_TRAY_DISPLAY),
+      base::string16() /* display_source */,
+      std::string() /* extension_id */,
+      data,
+      new ResolutionChangeNotificationDelegate(
+          this, change_info_->timeout_count > 0)));
+  notification->SetSystemPriority();
+  message_center->AddNotification(notification.Pass());
+}
+
+void ResolutionNotificationController::OnTimerTick() {
+  if (!change_info_)
+    return;
+
+  --change_info_->timeout_count;
+  if (change_info_->timeout_count == 0)
+    RevertResolutionChange();
+  else
+    CreateOrUpdateNotification();
+}
+
+void ResolutionNotificationController::AcceptResolutionChange() {
+  message_center::MessageCenter::Get()->RemoveNotification(
+      kNotificationId, false /* by_user */);
+  base::Closure callback = change_info_->accept_callback;
+  change_info_.reset();
+  callback.Run();
+}
+
+void ResolutionNotificationController::RevertResolutionChange() {
+  message_center::MessageCenter::Get()->RemoveNotification(
+      kNotificationId, false /* by_user */);
+  int64 display_id = change_info_->display_id;
+  gfx::Size old_resolution = change_info_->old_resolution;
+  change_info_.reset();
+  Shell::GetInstance()->display_manager()->SetDisplayResolution(
+      display_id, old_resolution);
+}
+
+void ResolutionNotificationController::OnDisplayBoundsChanged(
+    const gfx::Display& display) {
+}
+
+void ResolutionNotificationController::OnDisplayAdded(
+    const gfx::Display& new_display) {
+}
+
+void ResolutionNotificationController::OnDisplayRemoved(
+    const gfx::Display& old_display) {
+  if (change_info_ && change_info_->display_id == old_display.id())
+    RevertResolutionChange();
+}
+
+void ResolutionNotificationController::OnDisplayConfigurationChanged() {
+  if (!change_info_)
+    return;
+
+  CreateOrUpdateNotification();
+  if (g_use_timer && change_info_->timeout_count > 0) {
+    change_info_->timer.Start(FROM_HERE,
+                              base::TimeDelta::FromSeconds(1),
+                              this,
+                              &ResolutionNotificationController::OnTimerTick);
+  }
+}
+
+void ResolutionNotificationController::SuppressTimerForTest() {
+  g_use_timer = false;
+}
+
+}  // namespace internal
+}  // namespace ash
diff --git a/ash/display/resolution_notification_controller.h b/ash/display/resolution_notification_controller.h
new file mode 100644
index 0000000..4de39c2
--- /dev/null
+++ b/ash/display/resolution_notification_controller.h
@@ -0,0 +1,95 @@
+// 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 ASH_DISPLAY_RESOLUTION_NOTIFICATION_CONTROLLER_H_
+#define ASH_DISPLAY_RESOLUTION_NOTIFICATION_CONTROLLER_H_
+
+#include "ash/ash_export.h"
+#include "ash/display/display_controller.h"
+#include "base/callback.h"
+#include "base/gtest_prod_util.h"
+#include "base/timer/timer.h"
+#include "ui/gfx/display_observer.h"
+#include "ui/gfx/size.h"
+
+namespace chromeos {
+FORWARD_DECLARE_TEST(DisplayPreferencesTest, PreventStore);
+}  // namespace chromeos
+
+namespace views {
+class Label;
+class Widget;
+}  // namespace views
+
+namespace ash {
+namespace internal {
+// A class which manages the notification of display resolution change and
+// also manages the timeout in case the new resolution is unusable.
+class ASH_EXPORT ResolutionNotificationController
+    : public gfx::DisplayObserver,
+      public DisplayController::Observer {
+ public:
+  ResolutionNotificationController();
+  virtual ~ResolutionNotificationController();
+
+  // Updates the display resolution for |display_id| to |new_resolution| and
+  // creates a notification for this change which offers a button to revert the
+  // change in case something goes wrong. The notification times out if there's
+  // only one display connected and the user is trying to modify its resolution.
+  // In that case, the timeout has to be set since the user cannot make any
+  // changes if something goes wrong.
+  void SetDisplayResolutionAndNotify(
+      int64 display_id,
+      const gfx::Size& old_resolution,
+      const gfx::Size& new_resolution,
+      const base::Closure& accept_callback);
+
+  // Returns true if the notification is visible or scheduled to be visible and
+  // the notification times out.
+  bool DoesNotificationTimeout();
+
+  // Called by the notification delegate when the user accepts the display
+  // resolution change.
+  void AcceptResolutionChange();
+
+  // Called by the notification delegate when the user wants to revert the
+  // display resolution change.
+  void RevertResolutionChange();
+
+ private:
+  friend class ResolutionNotificationControllerTest;
+  FRIEND_TEST_ALL_PREFIXES(ResolutionNotificationControllerTest, Timeout);
+  FRIEND_TEST_ALL_PREFIXES(chromeos::DisplayPreferencesTest, PreventStore);
+
+  // A struct to bundle the data for a single resolution change.
+  struct ResolutionChangeInfo;
+
+  static const int kTimeoutInSec;
+  static const char kNotificationId[];
+
+  // Create a new notification, or update its content if it already exists.
+  void CreateOrUpdateNotification();
+
+  // Called every second for timeout.
+  void OnTimerTick();
+
+  // gfx::DisplayObserver overrides:
+  virtual void OnDisplayBoundsChanged(const gfx::Display& display) OVERRIDE;
+  virtual void OnDisplayAdded(const gfx::Display& new_display) OVERRIDE;
+  virtual void OnDisplayRemoved(const gfx::Display& old_display) OVERRIDE;
+
+  // DisplayController::Observer overrides:
+  virtual void OnDisplayConfigurationChanged() OVERRIDE;
+
+  static void SuppressTimerForTest();
+
+  scoped_ptr<ResolutionChangeInfo> change_info_;
+
+  DISALLOW_COPY_AND_ASSIGN(ResolutionNotificationController);
+};
+
+}  // namespace internal
+}  // namespace ash
+
+#endif  // ASH_DISPLAY_RESOLUTION_NOTIFICATION_CONTROLLER_H_
diff --git a/ash/display/resolution_notification_controller_unittest.cc b/ash/display/resolution_notification_controller_unittest.cc
new file mode 100644
index 0000000..bdb6f12
--- /dev/null
+++ b/ash/display/resolution_notification_controller_unittest.cc
@@ -0,0 +1,283 @@
+// 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 "ash/display/resolution_notification_controller.h"
+
+#include "ash/display/display_manager.h"
+#include "ash/screen_ash.h"
+#include "ash/shell.h"
+#include "ash/test/ash_test_base.h"
+#include "base/bind.h"
+#include "ui/gfx/size.h"
+#include "ui/message_center/message_center.h"
+
+namespace ash {
+namespace internal {
+
+class ResolutionNotificationControllerTest : public ash::test::AshTestBase {
+ public:
+  ResolutionNotificationControllerTest()
+      : accept_count_(0) {
+  }
+
+  virtual ~ResolutionNotificationControllerTest() {}
+
+ protected:
+  virtual void SetUp() OVERRIDE {
+    ash::test::AshTestBase::SetUp();
+    ResolutionNotificationController::SuppressTimerForTest();
+  }
+
+  void SetDisplayResolutionAndNotify(const gfx::Display& display,
+                                     const gfx::Size& new_resolution) {
+    DisplayManager* display_manager = Shell::GetInstance()->display_manager();
+    const DisplayInfo& info = display_manager->GetDisplayInfo(display.id());
+    Shell::GetInstance()->resolution_notification_controller()->
+        SetDisplayResolutionAndNotify(
+            display.id(),
+            info.size_in_pixel(),
+            new_resolution,
+            base::Bind(&ResolutionNotificationControllerTest::OnAccepted,
+                       base::Unretained(this)));
+
+    // OnConfigurationChanged event won't be emitted in the test environment,
+    // so invoke UpdateDisplay() to emit that event explicitly.
+    std::string display_spec;
+    for (size_t i = 0; i < display_manager->GetNumDisplays(); ++i) {
+      if (i > 0)
+        display_spec.append(",");
+      int64 id = display_manager->GetDisplayAt(i).id();
+      gfx::Size size = (display.id() == id) ?
+          new_resolution : display_manager->GetDisplayInfo(id).size_in_pixel();
+      display_spec.append(size.ToString());
+    }
+    UpdateDisplay(display_spec);
+    RunAllPendingInMessageLoop();
+  }
+
+  void ClickOnNotification() {
+    message_center::MessageCenter::Get()->ClickOnNotification(
+        ResolutionNotificationController::kNotificationId);
+  }
+
+  void ClickOnNotificationButton(int index) {
+    message_center::MessageCenter::Get()->ClickOnNotificationButton(
+        ResolutionNotificationController::kNotificationId, index);
+  }
+
+  bool IsNotificationVisible() {
+    return message_center::MessageCenter::Get()->HasNotification(
+        ResolutionNotificationController::kNotificationId);
+  }
+
+  void TickTimer() {
+    controller()->OnTimerTick();
+  }
+
+  ResolutionNotificationController* controller() {
+    return Shell::GetInstance()->resolution_notification_controller();
+  }
+
+  int accept_count() const {
+    return accept_count_;
+  }
+
+ private:
+  void OnAccepted() {
+    EXPECT_FALSE(controller()->DoesNotificationTimeout());
+    accept_count_++;
+  }
+
+  int accept_count_;
+
+  DISALLOW_COPY_AND_ASSIGN(ResolutionNotificationControllerTest);
+};
+
+// Basic behaviors and verifies it doesn't cause crashes.
+TEST_F(ResolutionNotificationControllerTest, Basic) {
+  if (!SupportsMultipleDisplays())
+    return;
+
+  UpdateDisplay("100x100,150x150");
+  int64 id2 = ash::ScreenAsh::GetSecondaryDisplay().id();
+  ash::internal::DisplayManager* display_manager =
+      ash::Shell::GetInstance()->display_manager();
+  ASSERT_EQ(0, accept_count());
+  EXPECT_FALSE(IsNotificationVisible());
+
+  // Changes the resolution and apply the result.
+  SetDisplayResolutionAndNotify(
+      ScreenAsh::GetSecondaryDisplay(), gfx::Size(200, 200));
+  EXPECT_TRUE(IsNotificationVisible());
+  EXPECT_FALSE(controller()->DoesNotificationTimeout());
+  gfx::Size resolution;
+  EXPECT_TRUE(
+      display_manager->GetSelectedResolutionForDisplayId(id2, &resolution));
+  EXPECT_EQ("200x200", resolution.ToString());
+
+  // Click the revert button, which reverts the resolution.
+  ClickOnNotificationButton(0);
+  RunAllPendingInMessageLoop();
+  EXPECT_FALSE(IsNotificationVisible());
+  EXPECT_EQ(0, accept_count());
+  EXPECT_TRUE(
+      display_manager->GetSelectedResolutionForDisplayId(id2, &resolution));
+  EXPECT_EQ("150x150", resolution.ToString());
+}
+
+TEST_F(ResolutionNotificationControllerTest, ClickMeansAccept) {
+  if (!SupportsMultipleDisplays())
+    return;
+
+  UpdateDisplay("100x100,150x150");
+  int64 id2 = ash::ScreenAsh::GetSecondaryDisplay().id();
+  ash::internal::DisplayManager* display_manager =
+      ash::Shell::GetInstance()->display_manager();
+  ASSERT_EQ(0, accept_count());
+  EXPECT_FALSE(IsNotificationVisible());
+
+  // Changes the resolution and apply the result.
+  SetDisplayResolutionAndNotify(
+      ScreenAsh::GetSecondaryDisplay(), gfx::Size(200, 200));
+  EXPECT_TRUE(IsNotificationVisible());
+  EXPECT_FALSE(controller()->DoesNotificationTimeout());
+  gfx::Size resolution;
+  EXPECT_TRUE(
+      display_manager->GetSelectedResolutionForDisplayId(id2, &resolution));
+  EXPECT_EQ("200x200", resolution.ToString());
+
+  // Click the revert button, which reverts the resolution.
+  ClickOnNotification();
+  RunAllPendingInMessageLoop();
+  EXPECT_FALSE(IsNotificationVisible());
+  EXPECT_EQ(1, accept_count());
+  EXPECT_TRUE(
+      display_manager->GetSelectedResolutionForDisplayId(id2, &resolution));
+  EXPECT_EQ("200x200", resolution.ToString());
+}
+
+TEST_F(ResolutionNotificationControllerTest, AcceptButton) {
+  if (!SupportsMultipleDisplays())
+    return;
+
+  ash::internal::DisplayManager* display_manager =
+      ash::Shell::GetInstance()->display_manager();
+
+  UpdateDisplay("100x100");
+  const gfx::Display& display = ash::Shell::GetScreen()->GetPrimaryDisplay();
+  SetDisplayResolutionAndNotify(display, gfx::Size(200, 200));
+  EXPECT_TRUE(IsNotificationVisible());
+
+  // If there's a single display only, it will have timeout and the first button
+  // becomes accept.
+  EXPECT_TRUE(controller()->DoesNotificationTimeout());
+  ClickOnNotificationButton(0);
+  EXPECT_FALSE(IsNotificationVisible());
+  EXPECT_EQ(1, accept_count());
+  gfx::Size resolution;
+  EXPECT_TRUE(display_manager->GetSelectedResolutionForDisplayId(
+      display.id(), &resolution));
+  EXPECT_EQ("200x200", resolution.ToString());
+
+  // In that case the second button is revert.
+  UpdateDisplay("100x100");
+  SetDisplayResolutionAndNotify(display, gfx::Size(200, 200));
+  EXPECT_TRUE(IsNotificationVisible());
+
+  EXPECT_TRUE(controller()->DoesNotificationTimeout());
+  ClickOnNotificationButton(1);
+  EXPECT_FALSE(IsNotificationVisible());
+  EXPECT_EQ(1, accept_count());
+  EXPECT_TRUE(display_manager->GetSelectedResolutionForDisplayId(
+      display.id(), &resolution));
+  EXPECT_EQ("100x100", resolution.ToString());
+}
+
+TEST_F(ResolutionNotificationControllerTest, Timeout) {
+  if (!SupportsMultipleDisplays())
+    return;
+
+  UpdateDisplay("100x100");
+  const gfx::Display& display = ash::Shell::GetScreen()->GetPrimaryDisplay();
+  SetDisplayResolutionAndNotify(display, gfx::Size(200, 200));
+
+  for (int i = 0; i < ResolutionNotificationController::kTimeoutInSec; ++i) {
+    EXPECT_TRUE(IsNotificationVisible()) << "notification is closed after "
+                                         << i << "-th timer tick";
+    TickTimer();
+    RunAllPendingInMessageLoop();
+  }
+  EXPECT_FALSE(IsNotificationVisible());
+  EXPECT_EQ(0, accept_count());
+  gfx::Size resolution;
+  ash::internal::DisplayManager* display_manager =
+      ash::Shell::GetInstance()->display_manager();
+  EXPECT_TRUE(display_manager->GetSelectedResolutionForDisplayId(
+      display.id(), &resolution));
+  EXPECT_EQ("100x100", resolution.ToString());
+}
+
+TEST_F(ResolutionNotificationControllerTest, DisplayDisconnected) {
+  if (!SupportsMultipleDisplays())
+    return;
+
+  UpdateDisplay("100x100,150x150");
+  int64 id2 = ash::ScreenAsh::GetSecondaryDisplay().id();
+  ash::internal::DisplayManager* display_manager =
+      ash::Shell::GetInstance()->display_manager();
+  SetDisplayResolutionAndNotify(
+      ScreenAsh::GetSecondaryDisplay(), gfx::Size(200, 200));
+  ASSERT_TRUE(IsNotificationVisible());
+
+  // Disconnects the secondary display and verifies it doesn't cause crashes.
+  UpdateDisplay("100x100");
+  RunAllPendingInMessageLoop();
+  EXPECT_FALSE(IsNotificationVisible());
+  EXPECT_EQ(0, accept_count());
+  gfx::Size resolution;
+  EXPECT_TRUE(
+      display_manager->GetSelectedResolutionForDisplayId(id2, &resolution));
+  EXPECT_EQ("150x150", resolution.ToString());
+}
+
+TEST_F(ResolutionNotificationControllerTest, MultipleResolutionChange) {
+  if (!SupportsMultipleDisplays())
+    return;
+
+  UpdateDisplay("100x100,150x150");
+  int64 id2 = ash::ScreenAsh::GetSecondaryDisplay().id();
+  ash::internal::DisplayManager* display_manager =
+      ash::Shell::GetInstance()->display_manager();
+
+  SetDisplayResolutionAndNotify(
+      ScreenAsh::GetSecondaryDisplay(), gfx::Size(200, 200));
+  EXPECT_TRUE(IsNotificationVisible());
+  EXPECT_FALSE(controller()->DoesNotificationTimeout());
+  gfx::Size resolution;
+  EXPECT_TRUE(
+      display_manager->GetSelectedResolutionForDisplayId(id2, &resolution));
+  EXPECT_EQ("200x200", resolution.ToString());
+
+  // Invokes SetDisplayResolutionAndNotify during the previous notification is
+  // visible.
+  SetDisplayResolutionAndNotify(
+      ScreenAsh::GetSecondaryDisplay(), gfx::Size(250, 250));
+  EXPECT_TRUE(
+      display_manager->GetSelectedResolutionForDisplayId(id2, &resolution));
+  EXPECT_EQ("250x250", resolution.ToString());
+
+  // Then, click the revert button. Although |old_resolution| for the second
+  // SetDisplayResolutionAndNotify is 200x200, it should revert to the original
+  // size 150x150.
+  ClickOnNotificationButton(0);
+  RunAllPendingInMessageLoop();
+  EXPECT_FALSE(IsNotificationVisible());
+  EXPECT_EQ(0, accept_count());
+  EXPECT_TRUE(
+      display_manager->GetSelectedResolutionForDisplayId(id2, &resolution));
+  EXPECT_EQ("150x150", resolution.ToString());
+}
+
+}  // namespace internal
+}  // namespace ash
diff --git a/ash/launcher/alternate_app_list_button.cc b/ash/launcher/alternate_app_list_button.cc
index 9a2ffcc..0466c71 100644
--- a/ash/launcher/alternate_app_list_button.cc
+++ b/ash/launcher/alternate_app_list_button.cc
@@ -146,26 +146,5 @@
   state->name = host_->GetAccessibleName(this);
 }
 
-void AlternateAppListButton::OnGestureEvent(ui::GestureEvent* event) {
-  switch (event->type()) {
-    case ui::ET_GESTURE_SCROLL_BEGIN:
-      host_->PointerPressedOnButton(this, LauncherButtonHost::TOUCH, *event);
-      event->SetHandled();
-      return;
-    case ui::ET_GESTURE_SCROLL_UPDATE:
-      host_->PointerDraggedOnButton(this, LauncherButtonHost::TOUCH, *event);
-      event->SetHandled();
-      return;
-    case ui::ET_GESTURE_SCROLL_END:
-    case ui::ET_SCROLL_FLING_START:
-      host_->PointerReleasedOnButton(this, LauncherButtonHost::TOUCH, false);
-      event->SetHandled();
-      return;
-    default:
-      ImageButton::OnGestureEvent(event);
-      return;
-  }
-}
-
 }  // namespace internal
 }  // namespace ash
diff --git a/ash/launcher/alternate_app_list_button.h b/ash/launcher/alternate_app_list_button.h
index b03c31e..f68207c 100644
--- a/ash/launcher/alternate_app_list_button.h
+++ b/ash/launcher/alternate_app_list_button.h
@@ -43,9 +43,6 @@
   virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE;
   virtual void GetAccessibleState(ui::AccessibleViewState* state) OVERRIDE;
 
-  // ui::EventHandler overrides:
-  virtual void OnGestureEvent(ui::GestureEvent* event) OVERRIDE;
-
  private:
   LauncherButtonHost* host_;
   // Reference to the shelf widget containing this button, owned by the
diff --git a/ash/launcher/launcher.cc b/ash/launcher/launcher.cc
index 3dd2a14..5bd1262 100644
--- a/ash/launcher/launcher.cc
+++ b/ash/launcher/launcher.cc
@@ -142,6 +142,10 @@
   return launcher_view_->visible();
 }
 
+void Launcher::SchedulePaint() {
+  launcher_view_->SchedulePaintForAllButtons();
+}
+
 views::View* Launcher::GetAppListButtonView() const {
   return launcher_view_->GetAppListButtonView();
 }
diff --git a/ash/launcher/launcher.h b/ash/launcher/launcher.h
index c670801..6781058 100644
--- a/ash/launcher/launcher.h
+++ b/ash/launcher/launcher.h
@@ -89,6 +89,8 @@
   void SetVisible(bool visible) const;
   bool IsVisible() const;
 
+  void SchedulePaint();
+
   views::View* GetAppListButtonView() const;
 
   // Launch a 0-indexed launcher item in the Launcher.
diff --git a/ash/launcher/launcher_button.cc b/ash/launcher/launcher_button.cc
index 194c7c4..2859d98 100644
--- a/ash/launcher/launcher_button.cc
+++ b/ash/launcher/launcher_button.cc
@@ -33,7 +33,7 @@
 const int kIconSize = 32;
 const int kHopSpacing = 2;
 const int kIconPad = 8;
-const int kAlternateIconPad = 7;
+const int kAlternateIconPad = 5;
 const int kHopUpMS = 0;
 const int kHopDownMS = 200;
 const int kAttentionThrobDurationMS = 800;
diff --git a/ash/launcher/launcher_model.cc b/ash/launcher/launcher_model.cc
index 8daf561..9607de6 100644
--- a/ash/launcher/launcher_model.cc
+++ b/ash/launcher/launcher_model.cc
@@ -14,18 +14,34 @@
 namespace {
 
 int LauncherItemTypeToWeight(LauncherItemType type) {
-  switch (type) {
-    case TYPE_BROWSER_SHORTCUT:
-    case TYPE_APP_SHORTCUT:
-    case TYPE_WINDOWED_APP:
-      return 0;
-    case TYPE_TABBED:
-    case TYPE_PLATFORM_APP:
-      return 1;
-    case TYPE_APP_LIST:
-      return ash::switches::UseAlternateShelfLayout() ? 0 : 2;
-    case TYPE_APP_PANEL:
-      return 3;
+  if (ash::switches::UseAlternateShelfLayout()) {
+    switch (type) {
+      case TYPE_APP_LIST:
+        return 0;
+      case TYPE_BROWSER_SHORTCUT:
+      case TYPE_APP_SHORTCUT:
+      case TYPE_WINDOWED_APP:
+        return 1;
+      case TYPE_TABBED:
+      case TYPE_PLATFORM_APP:
+        return 2;
+      case TYPE_APP_PANEL:
+        return 3;
+    }
+  } else {
+    switch (type) {
+      case TYPE_BROWSER_SHORTCUT:
+      case TYPE_APP_SHORTCUT:
+      case TYPE_WINDOWED_APP:
+        return 0;
+      case TYPE_TABBED:
+      case TYPE_PLATFORM_APP:
+        return 1;
+      case TYPE_APP_LIST:
+        return 2;
+      case TYPE_APP_PANEL:
+        return 3;
+    }
   }
 
   NOTREACHED() << "Invalid type " << type;
diff --git a/ash/launcher/launcher_tooltip_manager.cc b/ash/launcher/launcher_tooltip_manager.cc
index d3b35b6..2d92e0f 100644
--- a/ash/launcher/launcher_tooltip_manager.cc
+++ b/ash/launcher/launcher_tooltip_manager.cc
@@ -75,6 +75,8 @@
     LauncherTooltipManager* host)
     : views::BubbleDelegateView(anchor, arrow),
       host_(host) {
+  // Make sure that the bubble follows the animation of the shelf.
+  set_move_with_anchor(true);
   gfx::Insets insets = gfx::Insets(kArrowOffsetTopBottom,
                                    kArrowOffsetLeftRight,
                                    kArrowOffsetTopBottom,
diff --git a/ash/launcher/launcher_view.cc b/ash/launcher/launcher_view.cc
index 3d32892..82f75be 100644
--- a/ash/launcher/launcher_view.cc
+++ b/ash/launcher/launcher_view.cc
@@ -65,6 +65,10 @@
 
 // Size between the buttons.
 const int kButtonSpacing = 4;
+const int kAlternateButtonSpacing = 10;
+
+// Size allocated to for each button.
+const int kButtonSize = 44;
 
 // Additional spacing for the left and right side of icons.
 const int kHorizontalIconSpacing = 2;
@@ -465,6 +469,15 @@
     overflow_bubble_->Hide();
 }
 
+void LauncherView::SchedulePaintForAllButtons() {
+  for (int i = 0; i < view_model_->view_size(); ++i) {
+    if (i >= first_visible_index_ && i <= last_visible_index_)
+      view_model_->view_at(i)->SchedulePaint();
+  }
+  if (overflow_button_ && overflow_button_->visible())
+    overflow_button_->SchedulePaint();
+}
+
 gfx::Rect LauncherView::GetIdealBoundsOfItemIcon(LauncherID id) {
   int index = model_->ItemIndexByID(id);
   if (index == -1 || (index > last_visible_index_ &&
@@ -685,28 +698,22 @@
     return;
 
   int first_panel_index = model_->FirstPanelIndex();
-  // TODO(harrym): if alternate shelf layout stays, rename app_list_index.
-  int app_list_index = first_panel_index - 1;
+  int last_button_index = first_panel_index - 1;
 
   // Initial x,y values account both leading_inset in primary
   // coordinate and secondary coordinate based on the dynamic edge of the
   // launcher (eg top edge on bottom-aligned launcher).
-  int x = shelf->SelectValueForShelfAlignment(
-      leading_inset(),
-      0,
-      0,
-      leading_inset());
-  int y = shelf->SelectValueForShelfAlignment(
-      0,
-      leading_inset(),
-      leading_inset(),
-      0);
+  int inset = ash::switches::UseAlternateShelfLayout() ? 0 : leading_inset();
+  int x = shelf->SelectValueForShelfAlignment(inset, 0, 0, inset);
+  int y = shelf->SelectValueForShelfAlignment(0, inset, inset, 0);
 
-  int shelf_size = ash::switches::UseAlternateShelfLayout() ?
-      ShelfLayoutManager::kShelfSize : kLauncherPreferredSize;
+  int button_size = ash::switches::UseAlternateShelfLayout() ?
+      kButtonSize : kLauncherPreferredSize;
+  int button_spacing = ash::switches::UseAlternateShelfLayout() ?
+      kAlternateButtonSpacing : kButtonSpacing;
 
-  int w = shelf->PrimaryAxisValue(shelf_size, width());
-  int h = shelf->PrimaryAxisValue(height(), shelf_size);
+  int w = shelf->PrimaryAxisValue(button_size, width());
+  int h = shelf->PrimaryAxisValue(height(), button_size);
   for (int i = 0; i < view_model_->view_size(); ++i) {
     if (i < first_visible_index_) {
       view_model_->set_ideal_bounds(i, gfx::Rect(x, y, 0, 0));
@@ -714,39 +721,42 @@
     }
 
     view_model_->set_ideal_bounds(i, gfx::Rect(x, y, w, h));
-    if (i != app_list_index) {
-      x = shelf->PrimaryAxisValue(x + w + kButtonSpacing, x);
-      y = shelf->PrimaryAxisValue(y, y + h + kButtonSpacing);
+    if (i != last_button_index) {
+      x = shelf->PrimaryAxisValue(x + w + button_spacing, x);
+      y = shelf->PrimaryAxisValue(y, y + h + button_spacing);
     }
   }
 
   if (is_overflow_mode()) {
     DCHECK_LT(last_visible_index_, view_model_->view_size());
     for (int i = 0; i < view_model_->view_size(); ++i) {
-      view_model_->view_at(i)->SetVisible(
-          i >= first_visible_index_ &&
-          i != app_list_index &&
-          i <= last_visible_index_);
+      bool visible = i >= first_visible_index_ &&
+          i <= last_visible_index_;
+      if (!ash::switches::UseAlternateShelfLayout())
+        visible &= i != last_button_index;
+      view_model_->view_at(i)->SetVisible(visible);
     }
     return;
   }
 
   // To address Fitt's law, we make the first launcher button include the
   // leading inset (if there is one).
-  if (view_model_->view_size() > 0) {
-    view_model_->set_ideal_bounds(0, gfx::Rect(gfx::Size(
-        shelf->PrimaryAxisValue(leading_inset() + w, w),
-        shelf->PrimaryAxisValue(h, leading_inset() + h))));
+  if (!ash::switches::UseAlternateShelfLayout()) {
+    if (view_model_->view_size() > 0) {
+      view_model_->set_ideal_bounds(0, gfx::Rect(gfx::Size(
+          shelf->PrimaryAxisValue(inset + w, w),
+          shelf->PrimaryAxisValue(h, inset + h))));
+    }
   }
 
   // Right aligned icons.
-  int end_position = available_size - kButtonSpacing;
+  int end_position = available_size - button_spacing;
   x = shelf->PrimaryAxisValue(end_position, 0);
   y = shelf->PrimaryAxisValue(0, end_position);
   for (int i = view_model_->view_size() - 1;
        i >= first_panel_index; --i) {
-    x = shelf->PrimaryAxisValue(x - w - kButtonSpacing, x);
-    y = shelf->PrimaryAxisValue(y, y - h - kButtonSpacing);
+    x = shelf->PrimaryAxisValue(x - w - button_spacing, x);
+    y = shelf->PrimaryAxisValue(y, y - h - button_spacing);
     view_model_->set_ideal_bounds(i, gfx::Rect(x, y, w, h));
     end_position = shelf->PrimaryAxisValue(x, y);
   }
@@ -754,9 +764,11 @@
   // Icons on the left / top are guaranteed up to kLeftIconProportion of
   // the available space.
   int last_icon_position = shelf->PrimaryAxisValue(
-      view_model_->ideal_bounds(first_panel_index - 1).right(),
-      view_model_->ideal_bounds(first_panel_index - 1).bottom()) +
-      2 * kLauncherPreferredSize + leading_inset();
+      view_model_->ideal_bounds(last_button_index).right(),
+      view_model_->ideal_bounds(last_button_index).bottom())
+      + button_size + inset;
+  if (!ash::switches::UseAlternateShelfLayout())
+      last_icon_position += button_size;
   int reserved_icon_space = available_size * kReservedNonPanelIconProportion;
   if (last_icon_position < reserved_icon_space)
     end_position = last_icon_position;
@@ -766,34 +778,37 @@
   bounds->overflow_bounds.set_size(gfx::Size(
       shelf->PrimaryAxisValue(w, width()),
       shelf->PrimaryAxisValue(height(), h)));
-  last_visible_index_ = DetermineLastVisibleIndex(
-      end_position - leading_inset() - 2 * kLauncherPreferredSize);
+  if (ash::switches::UseAlternateShelfLayout())
+    last_visible_index_ = DetermineLastVisibleIndex(
+        end_position - button_size);
+  else
+    last_visible_index_ = DetermineLastVisibleIndex(
+        end_position - inset - 2 * button_size);
   last_hidden_index_ = DetermineFirstVisiblePanelIndex(end_position) - 1;
-  bool show_overflow = (last_visible_index_ + 1 < app_list_index ||
-                        last_hidden_index_ >= first_panel_index);
+  bool show_overflow =
+      ((ash::switches::UseAlternateShelfLayout() ? 0 : 1) +
+      last_visible_index_ < last_button_index ||
+      last_hidden_index_ >= first_panel_index);
 
+  // Create Space for the overflow button
+  if (show_overflow && ash::switches::UseAlternateShelfLayout() &&
+      last_visible_index_ > 0)
+    --last_visible_index_;
   for (int i = 0; i < view_model_->view_size(); ++i) {
-    view_model_->view_at(i)->SetVisible(
-        i <= last_visible_index_ ||
-        i == app_list_index ||
-        i > last_hidden_index_);
+    bool visible = i <= last_visible_index_ || i > last_hidden_index_;
+    // Always show the app list.
+    if (!ash::switches::UseAlternateShelfLayout())
+      visible |= (i == last_button_index);
+    view_model_->view_at(i)->SetVisible(visible);
   }
 
   overflow_button_->SetVisible(show_overflow);
   if (show_overflow) {
     DCHECK_NE(0, view_model_->view_size());
     if (last_visible_index_ == -1) {
-      x = shelf->SelectValueForShelfAlignment(
-          leading_inset(),
-          0,
-          0,
-          leading_inset());
-      y = shelf->SelectValueForShelfAlignment(
-          0,
-          leading_inset(),
-          leading_inset(),
-          0);
-    } else if (last_visible_index_ == app_list_index) {
+      x = shelf->SelectValueForShelfAlignment(inset, 0, 0, inset);
+      y = shelf->SelectValueForShelfAlignment(0, inset, inset, 0);
+    } else if (last_visible_index_ == last_button_index) {
       x = view_model_->ideal_bounds(last_visible_index_).x();
       y = view_model_->ideal_bounds(last_visible_index_).y();
     } else {
@@ -804,20 +819,22 @@
           view_model_->ideal_bounds(last_visible_index_).y(),
           view_model_->ideal_bounds(last_visible_index_).bottom());
     }
-    gfx::Rect app_list_bounds = view_model_->ideal_bounds(app_list_index);
-    bounds->overflow_bounds.set_x(x);
-    bounds->overflow_bounds.set_y(y);
-
     // Set all hidden panel icon positions to be on the overflow button.
     for (int i = first_panel_index; i <= last_hidden_index_; ++i)
       view_model_->set_ideal_bounds(i, gfx::Rect(x, y, w, h));
 
-    x = shelf->PrimaryAxisValue(x + w + kButtonSpacing, x);
-    y = shelf->PrimaryAxisValue(y, y + h + kButtonSpacing);
-    app_list_bounds.set_x(x);
-    app_list_bounds.set_y(y);
-    view_model_->set_ideal_bounds(app_list_index, app_list_bounds);
+    bounds->overflow_bounds.set_x(x);
+    bounds->overflow_bounds.set_y(y);
+    if (!ash::switches::UseAlternateShelfLayout()) {
+      // Position app list after overflow button.
+      gfx::Rect app_list_bounds = view_model_->ideal_bounds(last_button_index);
 
+      x = shelf->PrimaryAxisValue(x + w + button_spacing, x);
+      y = shelf->PrimaryAxisValue(y, y + h + button_spacing);
+      app_list_bounds.set_x(x);
+      app_list_bounds.set_y(y);
+      view_model_->set_ideal_bounds(last_button_index, app_list_bounds);
+    }
     if (overflow_bubble_.get() && overflow_bubble_->IsShowing())
       UpdateOverflowRange(overflow_bubble_->launcher_view());
   } else {
@@ -1035,36 +1052,17 @@
 
 bool LauncherView::SameDragType(LauncherItemType typea,
                                 LauncherItemType typeb) const {
-  if (ash::switches::UseAlternateShelfLayout()) {
-    // TODO(harrym): Allow app list to be repositionable, if this goes live
-    // (no flag) the pref file has to be updated so the changes persist.
-    switch (typea) {
-     case TYPE_TABBED:
-     case TYPE_PLATFORM_APP:
+  switch (typea) {
+    case TYPE_TABBED:
+    case TYPE_PLATFORM_APP:
       return (typeb == TYPE_TABBED || typeb == TYPE_PLATFORM_APP);
-     case TYPE_APP_SHORTCUT:
-     case TYPE_APP_LIST:
-     case TYPE_BROWSER_SHORTCUT:
-      return (typeb == TYPE_APP_SHORTCUT ||
-              typeb == TYPE_APP_LIST ||
-              typeb == TYPE_BROWSER_SHORTCUT);
-     case TYPE_WINDOWED_APP:
-     case TYPE_APP_PANEL:
-       return typeb == typea;
-    }
-  } else {
-    switch (typea) {
-      case TYPE_TABBED:
-      case TYPE_PLATFORM_APP:
-        return (typeb == TYPE_TABBED || typeb == TYPE_PLATFORM_APP);
-      case TYPE_APP_SHORTCUT:
-      case TYPE_BROWSER_SHORTCUT:
-        return (typeb == TYPE_APP_SHORTCUT || typeb == TYPE_BROWSER_SHORTCUT);
-      case TYPE_WINDOWED_APP:
-      case TYPE_APP_LIST:
-      case TYPE_APP_PANEL:
-        return typeb == typea;
-    }
+    case TYPE_APP_SHORTCUT:
+    case TYPE_BROWSER_SHORTCUT:
+      return (typeb == TYPE_APP_SHORTCUT || typeb == TYPE_BROWSER_SHORTCUT);
+    case TYPE_WINDOWED_APP:
+    case TYPE_APP_LIST:
+    case TYPE_APP_PANEL:
+      return typeb == typea;
   }
   NOTREACHED();
   return false;
@@ -1110,6 +1108,9 @@
 }
 
 void LauncherView::UpdateFirstButtonPadding() {
+  if (ash::switches::UseAlternateShelfLayout())
+    return;
+
   ShelfLayoutManager* shelf = tooltip_->shelf_layout_manager();
 
   // Creates an empty border for first launcher button to make included leading
@@ -1420,9 +1421,12 @@
     CancelDrag(-1);
   } else if (drag_pointer_ == pointer) {
     drag_pointer_ = NONE;
-    drag_view_ = NULL;
     AnimateToIdealBounds();
   }
+  // If the drag pointer is NONE, no drag operation is going on and the
+  // drag_view can be released.
+  if (drag_pointer_ == NONE)
+    drag_view_ = NULL;
 }
 
 void LauncherView::MouseMovedOverButton(views::View* view) {
diff --git a/ash/launcher/launcher_view.h b/ash/launcher/launcher_view.h
index aa59f1e..507c768 100644
--- a/ash/launcher/launcher_view.h
+++ b/ash/launcher/launcher_view.h
@@ -67,6 +67,7 @@
   void Init();
 
   void OnShelfAlignmentChanged();
+  void SchedulePaintForAllButtons();
 
   // Returns the ideal bounds of the specified item, or an empty rect if id
   // isn't know.
diff --git a/ash/launcher/launcher_view_unittest.cc b/ash/launcher/launcher_view_unittest.cc
index 662284f..7731655 100644
--- a/ash/launcher/launcher_view_unittest.cc
+++ b/ash/launcher/launcher_view_unittest.cc
@@ -13,6 +13,7 @@
 #include "ash/launcher/launcher_icon_observer.h"
 #include "ash/launcher/launcher_model.h"
 #include "ash/launcher/launcher_tooltip_manager.h"
+#include "ash/launcher/launcher_types.h"
 #include "ash/root_window_controller.h"
 #include "ash/shelf/shelf_layout_manager.h"
 #include "ash/shelf/shelf_widget.h"
@@ -333,17 +334,33 @@
     }
   }
 
-  views::View* SimulateDrag(internal::LauncherButtonHost::Pointer pointer,
-                            int button_index,
-                            int destination_index) {
+  views::View* SimulateButtonPressed(
+      internal::LauncherButtonHost::Pointer pointer,
+      int button_index) {
     internal::LauncherButtonHost* button_host = launcher_view_;
-
-    // Mouse down.
     views::View* button = test_api_->GetButton(button_index);
     ui::MouseEvent click_event(ui::ET_MOUSE_PRESSED,
                                button->bounds().origin(),
                                button->bounds().origin(), 0);
     button_host->PointerPressedOnButton(button, pointer, click_event);
+    return button;
+  }
+
+  views::View* SimulateClick(internal::LauncherButtonHost::Pointer pointer,
+                             int button_index) {
+    internal::LauncherButtonHost* button_host = launcher_view_;
+    views::View* button = SimulateButtonPressed(pointer, button_index);
+    button_host->PointerReleasedOnButton(button,
+                                         internal::LauncherButtonHost::MOUSE,
+                                         false);
+    return button;
+  }
+
+  views::View* SimulateDrag(internal::LauncherButtonHost::Pointer pointer,
+                            int button_index,
+                            int destination_index) {
+    internal::LauncherButtonHost* button_host = launcher_view_;
+    views::View* button = SimulateButtonPressed(pointer, button_index);
 
     // Drag.
     views::View* destination = test_api_->GetButton(destination_index);
@@ -435,6 +452,49 @@
   EXPECT_EQ(item_bounds.y(), ideal_bounds.y());
 }
 
+// Checks that launcher view contents are considered in the correct drag group.
+TEST_F(LauncherViewTest, EnforceDragType) {
+  EXPECT_TRUE(test_api_->SameDragType(TYPE_TABBED, TYPE_TABBED));
+  EXPECT_TRUE(test_api_->SameDragType(TYPE_TABBED, TYPE_PLATFORM_APP));
+  EXPECT_FALSE(test_api_->SameDragType(TYPE_TABBED, TYPE_APP_SHORTCUT));
+  EXPECT_FALSE(test_api_->SameDragType(TYPE_TABBED, TYPE_BROWSER_SHORTCUT));
+  EXPECT_FALSE(test_api_->SameDragType(TYPE_TABBED, TYPE_WINDOWED_APP));
+  EXPECT_FALSE(test_api_->SameDragType(TYPE_TABBED, TYPE_APP_LIST));
+  EXPECT_FALSE(test_api_->SameDragType(TYPE_TABBED, TYPE_APP_PANEL));
+
+  EXPECT_TRUE(test_api_->SameDragType(TYPE_PLATFORM_APP, TYPE_PLATFORM_APP));
+  EXPECT_FALSE(test_api_->SameDragType(TYPE_PLATFORM_APP, TYPE_APP_SHORTCUT));
+  EXPECT_FALSE(test_api_->SameDragType(TYPE_PLATFORM_APP,
+                                       TYPE_BROWSER_SHORTCUT));
+  EXPECT_FALSE(test_api_->SameDragType(TYPE_PLATFORM_APP, TYPE_WINDOWED_APP));
+  EXPECT_FALSE(test_api_->SameDragType(TYPE_PLATFORM_APP, TYPE_APP_LIST));
+  EXPECT_FALSE(test_api_->SameDragType(TYPE_PLATFORM_APP, TYPE_APP_PANEL));
+
+  EXPECT_TRUE(test_api_->SameDragType(TYPE_APP_SHORTCUT, TYPE_APP_SHORTCUT));
+  EXPECT_TRUE(test_api_->SameDragType(TYPE_APP_SHORTCUT,
+                                      TYPE_BROWSER_SHORTCUT));
+  EXPECT_FALSE(test_api_->SameDragType(TYPE_APP_SHORTCUT,
+                                       TYPE_WINDOWED_APP));
+  EXPECT_FALSE(test_api_->SameDragType(TYPE_APP_SHORTCUT, TYPE_APP_LIST));
+  EXPECT_FALSE(test_api_->SameDragType(TYPE_APP_SHORTCUT, TYPE_APP_PANEL));
+
+  EXPECT_TRUE(test_api_->SameDragType(TYPE_BROWSER_SHORTCUT,
+                                      TYPE_BROWSER_SHORTCUT));
+  EXPECT_FALSE(test_api_->SameDragType(TYPE_BROWSER_SHORTCUT,
+                                       TYPE_WINDOWED_APP));
+  EXPECT_FALSE(test_api_->SameDragType(TYPE_BROWSER_SHORTCUT, TYPE_APP_LIST));
+  EXPECT_FALSE(test_api_->SameDragType(TYPE_BROWSER_SHORTCUT, TYPE_APP_PANEL));
+
+  EXPECT_TRUE(test_api_->SameDragType(TYPE_WINDOWED_APP, TYPE_WINDOWED_APP));
+  EXPECT_FALSE(test_api_->SameDragType(TYPE_WINDOWED_APP, TYPE_APP_LIST));
+  EXPECT_FALSE(test_api_->SameDragType(TYPE_WINDOWED_APP, TYPE_APP_PANEL));
+
+  EXPECT_TRUE(test_api_->SameDragType(TYPE_APP_LIST, TYPE_APP_LIST));
+  EXPECT_FALSE(test_api_->SameDragType(TYPE_APP_LIST, TYPE_APP_PANEL));
+
+  EXPECT_TRUE(test_api_->SameDragType(TYPE_APP_PANEL, TYPE_APP_PANEL));
+}
+
 // Adds browser button until overflow and verifies that the last added browser
 // button is hidden.
 TEST_F(LauncherViewTest, AddBrowserUntilOverflow) {
@@ -753,6 +813,31 @@
   ASSERT_NO_FATAL_FAILURE(CheckModelIDs(id_map));
 }
 
+// Check that clicking first on one item and then dragging another works as
+// expected.
+TEST_F(LauncherViewTest, ClickOneDragAnother) {
+  internal::LauncherButtonHost* button_host = launcher_view_;
+
+  std::vector<std::pair<LauncherID, views::View*> > id_map;
+  SetupForDragTest(&id_map);
+
+  // A click on item 1 is simulated.
+  SimulateClick(internal::LauncherButtonHost::MOUSE, 1);
+
+  // Dragging browser index at 0 should change the model order correctly.
+  EXPECT_TRUE(model_->items()[0].type == TYPE_BROWSER_SHORTCUT);
+  views::View* dragged_button = SimulateDrag(
+      internal::LauncherButtonHost::MOUSE, 0, 2);
+  std::rotate(id_map.begin(),
+              id_map.begin() + 1,
+              id_map.begin() + 3);
+  ASSERT_NO_FATAL_FAILURE(CheckModelIDs(id_map));
+  button_host->PointerReleasedOnButton(dragged_button,
+                                       internal::LauncherButtonHost::MOUSE,
+                                       false);
+  EXPECT_TRUE(model_->items()[2].type == TYPE_BROWSER_SHORTCUT);
+}
+
 // Confirm that item status changes are reflected in the buttons.
 TEST_F(LauncherViewTest, LauncherItemStatus) {
   ASSERT_EQ(test_api_->GetLastVisibleIndex() + 1,
diff --git a/ash/launcher/overflow_bubble.cc b/ash/launcher/overflow_bubble.cc
index 09613ca..7d84d1e 100644
--- a/ash/launcher/overflow_bubble.cc
+++ b/ash/launcher/overflow_bubble.cc
@@ -10,6 +10,7 @@
 #include "ash/launcher/launcher_view.h"
 #include "ash/root_window_controller.h"
 #include "ash/shelf/shelf_layout_manager.h"
+#include "ash/shelf/shelf_widget.h"
 #include "ash/shell.h"
 #include "ash/system/tray/system_tray.h"
 #include "ui/aura/root_window.h"
@@ -200,7 +201,7 @@
       views::BubbleBorder::is_arrow_on_horizontal(arrow()) ?
       bubble_insets.left() : bubble_insets.top();
   const int arrow_offset = border_size + kPadding + kLauncherViewLeadingInset +
-      kLauncherPreferredSize / 2;
+      ShelfLayoutManager::GetPreferredShelfSize() / 2;
 
   const gfx::Size content_size = GetPreferredSize();
   border->set_arrow_offset(arrow_offset);
@@ -276,6 +277,8 @@
   DCHECK(widget == bubble_->GetWidget());
   bubble_ = NULL;
   launcher_view_ = NULL;
+  ShelfLayoutManager::ForLauncher(
+      widget->GetNativeView())->shelf_widget()->launcher()->SchedulePaint();
 }
 
 }  // namespace internal
diff --git a/ash/launcher/overflow_button.cc b/ash/launcher/overflow_button.cc
index 8847468..c3d5a68 100644
--- a/ash/launcher/overflow_button.cc
+++ b/ash/launcher/overflow_button.cc
@@ -4,7 +4,9 @@
 
 #include "ash/launcher/overflow_button.h"
 
+#include "ash/ash_switches.h"
 #include "ash/shelf/shelf_layout_manager.h"
+#include "ash/shelf/shelf_widget.h"
 #include "grit/ash_resources.h"
 #include "grit/ash_strings.h"
 #include "third_party/skia/include/core/SkPaint.h"
@@ -13,6 +15,8 @@
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/base/resource/resource_bundle.h"
 #include "ui/gfx/canvas.h"
+#include "ui/gfx/image/image_skia_operations.h"
+#include "ui/gfx/skbitmap_operations.h"
 #include "ui/gfx/skia_util.h"
 #include "ui/gfx/transform.h"
 #include "ui/views/widget/widget.h"
@@ -30,29 +34,18 @@
 
 const int kBackgroundOffset = (48 - kButtonHoverSize) / 2;
 
-void RotateCounterclockwise(gfx::Transform* transform) {
-  SkMatrix44 rotation;
-  rotation.set3x3(0, -1, 0,
-                  1,  0, 0,
-                  0,  0, 1);
-  transform->matrix().preConcat(rotation);
-}
-
-void RotateClockwise(gfx::Transform* transform) {
-  SkMatrix44 rotation;
-  rotation.set3x3( 0, 1, 0,
-                  -1, 0, 0,
-                   0, 0, 1);
-  transform->matrix().preConcat(rotation);
-}
+// Padding from the inner edge of the shelf (towards center of display) to
+// the edge of the background image of the overflow button.
+const int kImagePaddingFromShelf = 5;
 
 }  // namesapce
 
 OverflowButton::OverflowButton(views::ButtonListener* listener)
     : CustomButton(listener),
-      image_(NULL) {
+      bottom_image_(NULL) {
   ResourceBundle& rb = ResourceBundle::GetSharedInstance();
-  image_ = rb.GetImageNamed(IDR_AURA_LAUNCHER_OVERFLOW).ToImageSkia();
+  bottom_image_ = rb.GetImageNamed(IDR_AURA_LAUNCHER_OVERFLOW).ToImageSkia();
+
 
   set_accessibility_focusable(true);
   SetAccessibleName(l10n_util::GetStringUTF16(IDS_ASH_SHELF_OVERFLOW_NAME));
@@ -96,55 +89,89 @@
 }
 
 void OverflowButton::OnPaint(gfx::Canvas* canvas) {
-  ShelfAlignment alignment = ShelfLayoutManager::ForLauncher(
-      GetWidget()->GetNativeView())->GetAlignment();
+  ShelfLayoutManager* layout_manager = ShelfLayoutManager::ForLauncher(
+      GetWidget()->GetNativeView());
+  ShelfAlignment alignment = layout_manager->GetAlignment();
 
-  if (hover_animation_->is_animating()) {
-    PaintBackground(
-        canvas,
-        kButtonHoverAlpha * hover_animation_->GetCurrentValue());
-  } else if (state() == STATE_HOVERED || state() == STATE_PRESSED) {
-    PaintBackground(canvas, kButtonHoverAlpha);
+  gfx::Rect bounds(GetContentsBounds());
+  if (ash::switches::UseAlternateShelfLayout()) {
+    ResourceBundle& rb = ResourceBundle::GetSharedInstance();
+    int background_image_id = 0;
+    if (layout_manager->shelf_widget()->launcher()->IsShowingOverflowBubble())
+      background_image_id = IDR_AURA_NOTIFICATION_BACKGROUND_PRESSED;
+    else if(layout_manager->shelf_widget()->GetDimsShelf())
+      background_image_id = IDR_AURA_NOTIFICATION_BACKGROUND_ON_BLACK;
+    else
+      background_image_id = IDR_AURA_NOTIFICATION_BACKGROUND_NORMAL;
+
+    const gfx::ImageSkia* background =
+        rb.GetImageNamed(background_image_id).ToImageSkia();
+    if (alignment == SHELF_ALIGNMENT_LEFT) {
+      bounds = gfx::Rect(
+          bounds.right() - background->width() - kImagePaddingFromShelf,
+          bounds.y() + (bounds.height() - background->height()) / 2,
+          background->width(), background->height());
+    } else if (alignment == SHELF_ALIGNMENT_RIGHT) {
+      bounds = gfx::Rect(
+          bounds.x() + kImagePaddingFromShelf,
+          bounds.y() + (bounds.height() - background->height()) / 2,
+          background->width(), background->height());
+    } else {
+      bounds = gfx::Rect(
+          bounds.x() + (bounds.width() - background->width()) / 2,
+          bounds.y() + kImagePaddingFromShelf,
+          background->width(), background->height());
+    }
+    canvas->DrawImageInt(*background, bounds.x(), bounds.y());
+  } else {
+    if (alignment == SHELF_ALIGNMENT_BOTTOM) {
+      bounds = gfx::Rect(
+          bounds.x() + ((bounds.width() - kButtonHoverSize) / 2) - 1,
+          bounds.y() + kBackgroundOffset - 1,
+          kButtonHoverSize, kButtonHoverSize);
+    } else {
+      bounds = gfx::Rect(
+          bounds.x() + kBackgroundOffset -1,
+          bounds.y() + ((bounds.height() - kButtonHoverSize) / 2) -1,
+          kButtonHoverSize, kButtonHoverSize);
+    }
+    if (hover_animation_->is_animating()) {
+      PaintBackground(
+          canvas,
+          kButtonHoverAlpha * hover_animation_->GetCurrentValue());
+    } else if (state() == STATE_HOVERED || state() == STATE_PRESSED) {
+      PaintBackground(canvas, kButtonHoverAlpha);
+    }
   }
 
   if (height() < kButtonHoverSize)
     return;
 
-  gfx::Transform transform;
+  const gfx::ImageSkia* image = NULL;
 
-  switch (alignment) {
-    case SHELF_ALIGNMENT_BOTTOM:
-      // Shift 1 pixel left to align with overflow bubble tip.
-      transform.Translate(-1, kBackgroundOffset);
-      break;
+  switch(alignment) {
     case SHELF_ALIGNMENT_LEFT:
-      transform.Translate(kBackgroundOffset, -1);
-      RotateClockwise(&transform);
+      if (left_image_.isNull()) {
+        left_image_ = gfx::ImageSkiaOperations::CreateRotatedImage(
+            *bottom_image_, SkBitmapOperations::ROTATION_90_CW);
+      }
+      image = &left_image_;
       break;
     case SHELF_ALIGNMENT_RIGHT:
-      transform.Translate(kBackgroundOffset, height());
-      RotateCounterclockwise(&transform);
+      if (right_image_.isNull()) {
+        right_image_ = gfx::ImageSkiaOperations::CreateRotatedImage(
+            *bottom_image_, SkBitmapOperations::ROTATION_270_CW);
+      }
+      image = &right_image_;
       break;
-    case SHELF_ALIGNMENT_TOP:
-      transform.Translate(1, kBackgroundOffset);
+    default:
+      image = bottom_image_;
       break;
   }
 
-  canvas->Save();
-  canvas->Transform(transform);
-
-  gfx::Rect rect(GetContentsBounds());
-  if (alignment == SHELF_ALIGNMENT_BOTTOM ||
-      alignment == SHELF_ALIGNMENT_TOP) {
-    canvas->DrawImageInt(*image_,
-                         rect.x() + (rect.width() - image_->width()) / 2,
-                         kButtonHoverSize - image_->height());
-  } else {
-    canvas->DrawImageInt(*image_,
-                         kButtonHoverSize - image_->width(),
-                         rect.y() + (rect.height() - image_->height()) / 2);
-  }
-  canvas->Restore();
+  canvas->DrawImageInt(*image,
+                       bounds.x() + ((bounds.width() - image->width()) / 2),
+                       bounds.y() + ((bounds.height() - image->height()) / 2));
 }
 
 }  // namespace internal
diff --git a/ash/launcher/overflow_button.h b/ash/launcher/overflow_button.h
index b1d2db1..0b225aa 100644
--- a/ash/launcher/overflow_button.h
+++ b/ash/launcher/overflow_button.h
@@ -8,12 +8,9 @@
 #include "ash/shelf/shelf_types.h"
 #include "base/basictypes.h"
 #include "base/compiler_specific.h"
+#include "ui/gfx/image/image_skia.h"
 #include "ui/views/controls/button/custom_button.h"
 
-namespace gfx {
-class ImageSkia;
-}
-
 namespace ash {
 namespace internal {
 
@@ -31,7 +28,12 @@
   // views::View overrides:
   virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE;
 
-  const gfx::ImageSkia* image_;
+  // Left and right images are rotations of bottom_image and are
+  // owned by the overflow button.
+  gfx::ImageSkia left_image_;
+  gfx::ImageSkia right_image_;
+  // Bottom image is owned by the resource bundle.
+  const gfx::ImageSkia* bottom_image_;
 
   DISALLOW_COPY_AND_ASSIGN(OverflowButton);
 };
diff --git a/ash/resources/ash_resources.grd b/ash/resources/ash_resources.grd
index 7640f65..166fe5f 100644
--- a/ash/resources/ash_resources.grd
+++ b/ash/resources/ash_resources.grd
@@ -159,6 +159,7 @@
       <structure type="chrome_scaled_image" name="IDR_AURA_UBER_TRAY_SHUTDOWN" file="cros/status/status_shutdown.png" />
       <structure type="chrome_scaled_image" name="IDR_AURA_UBER_TRAY_SHUTDOWN_HOVER" file="cros/status/status_shutdown_hover.png" />
       <structure type="chrome_scaled_image" name="IDR_AURA_UBER_TRAY_SMS" file="cros/status/status_sms.png" />
+      <structure type="chrome_scaled_image" name="IDR_AURA_UBER_TRAY_TRACING" file="cros/status/status_tracing.png" />
 
       <!-- ChromeOS specific icons -->
       <if expr="pp_ifdef('chromeos')">
@@ -176,6 +177,8 @@
         <structure type="chrome_scaled_image" name="IDR_AURA_UBER_TRAY_NETWORK_BARS_LIGHT" file="cros/network/statusbar_network_bars_light.png" />
         <structure type="chrome_scaled_image" name="IDR_AURA_UBER_TRAY_NETWORK_EDGE_DARK" file="cros/network/statusbar_network_edge_dark.png" />
         <structure type="chrome_scaled_image" name="IDR_AURA_UBER_TRAY_NETWORK_EDGE_LIGHT" file="cros/network/statusbar_network_edge_light.png" />
+        <structure type="chrome_scaled_image" name="IDR_AURA_UBER_TRAY_NETWORK_EVDO_DARK" file="cros/network/statusbar_network_evdo_dark.png" />
+        <structure type="chrome_scaled_image" name="IDR_AURA_UBER_TRAY_NETWORK_EVDO_LIGHT" file="cros/network/statusbar_network_evdo_light.png" />
         <structure type="chrome_scaled_image" name="IDR_AURA_UBER_TRAY_NETWORK_GPRS_DARK" file="cros/network/statusbar_network_gprs_dark.png" />
         <structure type="chrome_scaled_image" name="IDR_AURA_UBER_TRAY_NETWORK_GPRS_LIGHT" file="cros/network/statusbar_network_gprs_light.png" />
         <structure type="chrome_scaled_image" name="IDR_AURA_UBER_TRAY_NETWORK_HSPA_DARK" file="cros/network/statusbar_network_hspa_dark.png" />
diff --git a/ash/resources/default_100_percent/common/alert_small.png b/ash/resources/default_100_percent/common/alert_small.png
index 8873886..7b76b49 100644
--- a/ash/resources/default_100_percent/common/alert_small.png
+++ b/ash/resources/default_100_percent/common/alert_small.png
Binary files differ
diff --git a/ash/resources/default_100_percent/common/alt_launcher/status_guest_icon.png b/ash/resources/default_100_percent/common/alt_launcher/status_guest_icon.png
index 4ee416f..12ac2bb 100644
--- a/ash/resources/default_100_percent/common/alt_launcher/status_guest_icon.png
+++ b/ash/resources/default_100_percent/common/alt_launcher/status_guest_icon.png
Binary files differ
diff --git a/ash/resources/default_100_percent/common/alt_launcher/status_notification_icon.png b/ash/resources/default_100_percent/common/alt_launcher/status_notification_icon.png
index 388c1e0..a22e136 100644
--- a/ash/resources/default_100_percent/common/alt_launcher/status_notification_icon.png
+++ b/ash/resources/default_100_percent/common/alt_launcher/status_notification_icon.png
Binary files differ
diff --git a/ash/resources/default_100_percent/common/alt_launcher/status_tray_pressed_left.png b/ash/resources/default_100_percent/common/alt_launcher/status_tray_pressed_left.png
index 969c86b..3c97b3e 100644
--- a/ash/resources/default_100_percent/common/alt_launcher/status_tray_pressed_left.png
+++ b/ash/resources/default_100_percent/common/alt_launcher/status_tray_pressed_left.png
Binary files differ
diff --git a/ash/resources/default_100_percent/common/alt_launcher/status_tray_vertical_normal_bottom.png b/ash/resources/default_100_percent/common/alt_launcher/status_tray_vertical_normal_bottom.png
index 665f597..0b6bd70 100644
--- a/ash/resources/default_100_percent/common/alt_launcher/status_tray_vertical_normal_bottom.png
+++ b/ash/resources/default_100_percent/common/alt_launcher/status_tray_vertical_normal_bottom.png
Binary files differ
diff --git a/ash/resources/default_100_percent/common/alt_launcher/status_tray_vertical_normal_center.png b/ash/resources/default_100_percent/common/alt_launcher/status_tray_vertical_normal_center.png
index 5fe9808..91674cc 100644
--- a/ash/resources/default_100_percent/common/alt_launcher/status_tray_vertical_normal_center.png
+++ b/ash/resources/default_100_percent/common/alt_launcher/status_tray_vertical_normal_center.png
Binary files differ
diff --git a/ash/resources/default_100_percent/common/alt_launcher/status_tray_vertical_normal_onblack_bottom.png b/ash/resources/default_100_percent/common/alt_launcher/status_tray_vertical_normal_onblack_bottom.png
index 6aaddce..2b1b659 100644
--- a/ash/resources/default_100_percent/common/alt_launcher/status_tray_vertical_normal_onblack_bottom.png
+++ b/ash/resources/default_100_percent/common/alt_launcher/status_tray_vertical_normal_onblack_bottom.png
Binary files differ
diff --git a/ash/resources/default_100_percent/common/alt_launcher/status_tray_vertical_normal_onblack_center.png b/ash/resources/default_100_percent/common/alt_launcher/status_tray_vertical_normal_onblack_center.png
index a5da305..9e3bb3c 100644
--- a/ash/resources/default_100_percent/common/alt_launcher/status_tray_vertical_normal_onblack_center.png
+++ b/ash/resources/default_100_percent/common/alt_launcher/status_tray_vertical_normal_onblack_center.png
Binary files differ
diff --git a/ash/resources/default_100_percent/common/alt_launcher/status_tray_vertical_normal_onblack_top.png b/ash/resources/default_100_percent/common/alt_launcher/status_tray_vertical_normal_onblack_top.png
index 1b1ae62..d59b1ef 100644
--- a/ash/resources/default_100_percent/common/alt_launcher/status_tray_vertical_normal_onblack_top.png
+++ b/ash/resources/default_100_percent/common/alt_launcher/status_tray_vertical_normal_onblack_top.png
Binary files differ
diff --git a/ash/resources/default_100_percent/common/alt_launcher/status_tray_vertical_normal_top.png b/ash/resources/default_100_percent/common/alt_launcher/status_tray_vertical_normal_top.png
index 9dcf0fa..e0e0c5a 100644
--- a/ash/resources/default_100_percent/common/alt_launcher/status_tray_vertical_normal_top.png
+++ b/ash/resources/default_100_percent/common/alt_launcher/status_tray_vertical_normal_top.png
Binary files differ
diff --git a/ash/resources/default_100_percent/common/alt_launcher/status_tray_vertical_pressed_bottom.png b/ash/resources/default_100_percent/common/alt_launcher/status_tray_vertical_pressed_bottom.png
index 8701a76..b2762ba 100644
--- a/ash/resources/default_100_percent/common/alt_launcher/status_tray_vertical_pressed_bottom.png
+++ b/ash/resources/default_100_percent/common/alt_launcher/status_tray_vertical_pressed_bottom.png
Binary files differ
diff --git a/ash/resources/default_100_percent/common/alt_launcher/status_tray_vertical_pressed_center.png b/ash/resources/default_100_percent/common/alt_launcher/status_tray_vertical_pressed_center.png
index 560b350..7727193 100644
--- a/ash/resources/default_100_percent/common/alt_launcher/status_tray_vertical_pressed_center.png
+++ b/ash/resources/default_100_percent/common/alt_launcher/status_tray_vertical_pressed_center.png
Binary files differ
diff --git a/ash/resources/default_100_percent/common/alt_launcher/status_tray_vertical_pressed_top.png b/ash/resources/default_100_percent/common/alt_launcher/status_tray_vertical_pressed_top.png
index af88465..96453a6 100644
--- a/ash/resources/default_100_percent/common/alt_launcher/status_tray_vertical_pressed_top.png
+++ b/ash/resources/default_100_percent/common/alt_launcher/status_tray_vertical_pressed_top.png
Binary files differ
diff --git a/ash/resources/default_100_percent/common/launcher/launcher_incognito_browser.png b/ash/resources/default_100_percent/common/launcher/launcher_incognito_browser.png
index 690de02..f9c4918 100644
--- a/ash/resources/default_100_percent/common/launcher/launcher_incognito_browser.png
+++ b/ash/resources/default_100_percent/common/launcher/launcher_incognito_browser.png
Binary files differ
diff --git a/ash/resources/default_100_percent/common/launcher/launcher_underline_right_hover.png b/ash/resources/default_100_percent/common/launcher/launcher_underline_right_hover.png
index 01e392e..82572f2 100644
--- a/ash/resources/default_100_percent/common/launcher/launcher_underline_right_hover.png
+++ b/ash/resources/default_100_percent/common/launcher/launcher_underline_right_hover.png
Binary files differ
diff --git a/ash/resources/default_100_percent/common/window_close_fullscreen_pressed.png b/ash/resources/default_100_percent/common/window_close_fullscreen_pressed.png
index a0a0cc3..aa9219d 100644
--- a/ash/resources/default_100_percent/common/window_close_fullscreen_pressed.png
+++ b/ash/resources/default_100_percent/common/window_close_fullscreen_pressed.png
Binary files differ
diff --git a/ash/resources/default_100_percent/common/window_position_right_pressed.png b/ash/resources/default_100_percent/common/window_position_right_pressed.png
index f002fd4..7fa9303 100644
--- a/ash/resources/default_100_percent/common/window_position_right_pressed.png
+++ b/ash/resources/default_100_percent/common/window_position_right_pressed.png
Binary files differ
diff --git a/ash/resources/default_100_percent/cros/network/status_data_none.png b/ash/resources/default_100_percent/cros/network/status_data_none.png
index 07aee20..26d5028 100644
--- a/ash/resources/default_100_percent/cros/network/status_data_none.png
+++ b/ash/resources/default_100_percent/cros/network/status_data_none.png
Binary files differ
diff --git a/ash/resources/default_100_percent/cros/network/statusbar_network_evdo_dark.png b/ash/resources/default_100_percent/cros/network/statusbar_network_evdo_dark.png
new file mode 100644
index 0000000..85c0378
--- /dev/null
+++ b/ash/resources/default_100_percent/cros/network/statusbar_network_evdo_dark.png
Binary files differ
diff --git a/ash/resources/default_100_percent/cros/network/statusbar_network_evdo_light.png b/ash/resources/default_100_percent/cros/network/statusbar_network_evdo_light.png
new file mode 100644
index 0000000..1ae959b
--- /dev/null
+++ b/ash/resources/default_100_percent/cros/network/statusbar_network_evdo_light.png
Binary files differ
diff --git a/ash/resources/default_100_percent/cros/status/status_bluetooth.png b/ash/resources/default_100_percent/cros/status/status_bluetooth.png
index fd30d4d..25fbff0 100644
--- a/ash/resources/default_100_percent/cros/status/status_bluetooth.png
+++ b/ash/resources/default_100_percent/cros/status/status_bluetooth.png
Binary files differ
diff --git a/ash/resources/default_100_percent/cros/status/status_ime.png b/ash/resources/default_100_percent/cros/status/status_ime.png
index 267abd0..b40d41e 100644
--- a/ash/resources/default_100_percent/cros/status/status_ime.png
+++ b/ash/resources/default_100_percent/cros/status/status_ime.png
Binary files differ
diff --git a/ash/resources/default_100_percent/cros/status/status_more.png b/ash/resources/default_100_percent/cros/status/status_more.png
index 6c27f4e..41b5995 100644
--- a/ash/resources/default_100_percent/cros/status/status_more.png
+++ b/ash/resources/default_100_percent/cros/status/status_more.png
Binary files differ
diff --git a/ash/resources/default_100_percent/cros/status/status_tracing.png b/ash/resources/default_100_percent/cros/status/status_tracing.png
new file mode 100644
index 0000000..eaba620
--- /dev/null
+++ b/ash/resources/default_100_percent/cros/status/status_tracing.png
Binary files differ
diff --git a/ash/resources/default_100_percent/cros/status/status_update.png b/ash/resources/default_100_percent/cros/status/status_update.png
index 2489bbb..98256a8 100644
--- a/ash/resources/default_100_percent/cros/status/status_update.png
+++ b/ash/resources/default_100_percent/cros/status/status_update.png
Binary files differ
diff --git a/ash/resources/default_200_percent/common/alt_launcher/status_guest_icon.png b/ash/resources/default_200_percent/common/alt_launcher/status_guest_icon.png
index 86f6bf1..11aca56 100644
--- a/ash/resources/default_200_percent/common/alt_launcher/status_guest_icon.png
+++ b/ash/resources/default_200_percent/common/alt_launcher/status_guest_icon.png
Binary files differ
diff --git a/ash/resources/default_200_percent/common/alt_launcher/status_tray_pressed_left.png b/ash/resources/default_200_percent/common/alt_launcher/status_tray_pressed_left.png
index 0ad8bd1..8c6f84c 100644
--- a/ash/resources/default_200_percent/common/alt_launcher/status_tray_pressed_left.png
+++ b/ash/resources/default_200_percent/common/alt_launcher/status_tray_pressed_left.png
Binary files differ
diff --git a/ash/resources/default_200_percent/common/alt_launcher/status_tray_vertical_normal_bottom.png b/ash/resources/default_200_percent/common/alt_launcher/status_tray_vertical_normal_bottom.png
index 76a7e6c..0804518 100644
--- a/ash/resources/default_200_percent/common/alt_launcher/status_tray_vertical_normal_bottom.png
+++ b/ash/resources/default_200_percent/common/alt_launcher/status_tray_vertical_normal_bottom.png
Binary files differ
diff --git a/ash/resources/default_200_percent/common/alt_launcher/status_tray_vertical_normal_center.png b/ash/resources/default_200_percent/common/alt_launcher/status_tray_vertical_normal_center.png
index 22cba57..96859ea 100644
--- a/ash/resources/default_200_percent/common/alt_launcher/status_tray_vertical_normal_center.png
+++ b/ash/resources/default_200_percent/common/alt_launcher/status_tray_vertical_normal_center.png
Binary files differ
diff --git a/ash/resources/default_200_percent/common/alt_launcher/status_tray_vertical_normal_onblack_bottom.png b/ash/resources/default_200_percent/common/alt_launcher/status_tray_vertical_normal_onblack_bottom.png
index 16c8adc..85bd1f1 100644
--- a/ash/resources/default_200_percent/common/alt_launcher/status_tray_vertical_normal_onblack_bottom.png
+++ b/ash/resources/default_200_percent/common/alt_launcher/status_tray_vertical_normal_onblack_bottom.png
Binary files differ
diff --git a/ash/resources/default_200_percent/common/alt_launcher/status_tray_vertical_normal_onblack_center.png b/ash/resources/default_200_percent/common/alt_launcher/status_tray_vertical_normal_onblack_center.png
index ec56c28..d880b32 100644
--- a/ash/resources/default_200_percent/common/alt_launcher/status_tray_vertical_normal_onblack_center.png
+++ b/ash/resources/default_200_percent/common/alt_launcher/status_tray_vertical_normal_onblack_center.png
Binary files differ
diff --git a/ash/resources/default_200_percent/common/alt_launcher/status_tray_vertical_normal_onblack_top.png b/ash/resources/default_200_percent/common/alt_launcher/status_tray_vertical_normal_onblack_top.png
index da0ca49..1884826 100644
--- a/ash/resources/default_200_percent/common/alt_launcher/status_tray_vertical_normal_onblack_top.png
+++ b/ash/resources/default_200_percent/common/alt_launcher/status_tray_vertical_normal_onblack_top.png
Binary files differ
diff --git a/ash/resources/default_200_percent/common/alt_launcher/status_tray_vertical_normal_top.png b/ash/resources/default_200_percent/common/alt_launcher/status_tray_vertical_normal_top.png
index 37b820c..fed0cab 100644
--- a/ash/resources/default_200_percent/common/alt_launcher/status_tray_vertical_normal_top.png
+++ b/ash/resources/default_200_percent/common/alt_launcher/status_tray_vertical_normal_top.png
Binary files differ
diff --git a/ash/resources/default_200_percent/common/alt_launcher/status_tray_vertical_pressed_bottom.png b/ash/resources/default_200_percent/common/alt_launcher/status_tray_vertical_pressed_bottom.png
index 3aea89a..53b3a0d 100644
--- a/ash/resources/default_200_percent/common/alt_launcher/status_tray_vertical_pressed_bottom.png
+++ b/ash/resources/default_200_percent/common/alt_launcher/status_tray_vertical_pressed_bottom.png
Binary files differ
diff --git a/ash/resources/default_200_percent/common/alt_launcher/status_tray_vertical_pressed_center.png b/ash/resources/default_200_percent/common/alt_launcher/status_tray_vertical_pressed_center.png
index 02e2755..4ec633f 100644
--- a/ash/resources/default_200_percent/common/alt_launcher/status_tray_vertical_pressed_center.png
+++ b/ash/resources/default_200_percent/common/alt_launcher/status_tray_vertical_pressed_center.png
Binary files differ
diff --git a/ash/resources/default_200_percent/common/alt_launcher/status_tray_vertical_pressed_top.png b/ash/resources/default_200_percent/common/alt_launcher/status_tray_vertical_pressed_top.png
index 5cb6e48..e47b081 100644
--- a/ash/resources/default_200_percent/common/alt_launcher/status_tray_vertical_pressed_top.png
+++ b/ash/resources/default_200_percent/common/alt_launcher/status_tray_vertical_pressed_top.png
Binary files differ
diff --git a/ash/resources/default_200_percent/common/launcher/launcher_incognito_browser_panel.png b/ash/resources/default_200_percent/common/launcher/launcher_incognito_browser_panel.png
index d0e2c63..4ba2a86 100644
--- a/ash/resources/default_200_percent/common/launcher/launcher_incognito_browser_panel.png
+++ b/ash/resources/default_200_percent/common/launcher/launcher_incognito_browser_panel.png
Binary files differ
diff --git a/ash/resources/default_200_percent/common/launcher/launcher_underline_left_hover.png b/ash/resources/default_200_percent/common/launcher/launcher_underline_left_hover.png
index fc1ee96..c2937e7 100644
--- a/ash/resources/default_200_percent/common/launcher/launcher_underline_left_hover.png
+++ b/ash/resources/default_200_percent/common/launcher/launcher_underline_left_hover.png
Binary files differ
diff --git a/ash/resources/default_200_percent/common/window_close_short_black_hover.png b/ash/resources/default_200_percent/common/window_close_short_black_hover.png
index f237da7..13445f1 100644
--- a/ash/resources/default_200_percent/common/window_close_short_black_hover.png
+++ b/ash/resources/default_200_percent/common/window_close_short_black_hover.png
Binary files differ
diff --git a/ash/resources/default_200_percent/common/window_close_short_black_normal.png b/ash/resources/default_200_percent/common/window_close_short_black_normal.png
index 174bee2..12aa993 100644
--- a/ash/resources/default_200_percent/common/window_close_short_black_normal.png
+++ b/ash/resources/default_200_percent/common/window_close_short_black_normal.png
Binary files differ
diff --git a/ash/resources/default_200_percent/common/window_close_short_black_pressed.png b/ash/resources/default_200_percent/common/window_close_short_black_pressed.png
index c452fca..42c3ca7 100644
--- a/ash/resources/default_200_percent/common/window_close_short_black_pressed.png
+++ b/ash/resources/default_200_percent/common/window_close_short_black_pressed.png
Binary files differ
diff --git a/ash/resources/default_200_percent/common/window_close_short_pressed.png b/ash/resources/default_200_percent/common/window_close_short_pressed.png
index e136ec5..711c6de 100644
--- a/ash/resources/default_200_percent/common/window_close_short_pressed.png
+++ b/ash/resources/default_200_percent/common/window_close_short_pressed.png
Binary files differ
diff --git a/ash/resources/default_200_percent/common/window_minimize_short_hover.png b/ash/resources/default_200_percent/common/window_minimize_short_hover.png
index 452ebc8..61cd354 100644
--- a/ash/resources/default_200_percent/common/window_minimize_short_hover.png
+++ b/ash/resources/default_200_percent/common/window_minimize_short_hover.png
Binary files differ
diff --git a/ash/resources/default_200_percent/common/window_position_left_pressed_restore.png b/ash/resources/default_200_percent/common/window_position_left_pressed_restore.png
index 6b319db..0f9e0c9 100644
--- a/ash/resources/default_200_percent/common/window_position_left_pressed_restore.png
+++ b/ash/resources/default_200_percent/common/window_position_left_pressed_restore.png
Binary files differ
diff --git a/ash/resources/default_200_percent/common/window_size_fullscreen_hover.png b/ash/resources/default_200_percent/common/window_size_fullscreen_hover.png
index 2855067..1c466bd 100644
--- a/ash/resources/default_200_percent/common/window_size_fullscreen_hover.png
+++ b/ash/resources/default_200_percent/common/window_size_fullscreen_hover.png
Binary files differ
diff --git a/ash/resources/default_200_percent/common/window_size_fullscreen_normal.png b/ash/resources/default_200_percent/common/window_size_fullscreen_normal.png
index 688028d..3773c24 100644
--- a/ash/resources/default_200_percent/common/window_size_fullscreen_normal.png
+++ b/ash/resources/default_200_percent/common/window_size_fullscreen_normal.png
Binary files differ
diff --git a/ash/resources/default_200_percent/common/window_size_tall_hover.png b/ash/resources/default_200_percent/common/window_size_tall_hover.png
index 8d33073..cc7508c 100644
--- a/ash/resources/default_200_percent/common/window_size_tall_hover.png
+++ b/ash/resources/default_200_percent/common/window_size_tall_hover.png
Binary files differ
diff --git a/ash/resources/default_200_percent/cros/network/status_wifi_enabled.png b/ash/resources/default_200_percent/cros/network/status_wifi_enabled.png
index 4fae330..e951ff3 100644
--- a/ash/resources/default_200_percent/cros/network/status_wifi_enabled.png
+++ b/ash/resources/default_200_percent/cros/network/status_wifi_enabled.png
Binary files differ
diff --git a/ash/resources/default_200_percent/cros/network/status_wifi_enabled_hover.png b/ash/resources/default_200_percent/cros/network/status_wifi_enabled_hover.png
index bfb35bd..7a72884 100644
--- a/ash/resources/default_200_percent/cros/network/status_wifi_enabled_hover.png
+++ b/ash/resources/default_200_percent/cros/network/status_wifi_enabled_hover.png
Binary files differ
diff --git a/ash/resources/default_200_percent/cros/network/statusbar_network_evdo_dark.png b/ash/resources/default_200_percent/cros/network/statusbar_network_evdo_dark.png
new file mode 100644
index 0000000..7135146
--- /dev/null
+++ b/ash/resources/default_200_percent/cros/network/statusbar_network_evdo_dark.png
Binary files differ
diff --git a/ash/resources/default_200_percent/cros/network/statusbar_network_evdo_light.png b/ash/resources/default_200_percent/cros/network/statusbar_network_evdo_light.png
new file mode 100644
index 0000000..55b89af
--- /dev/null
+++ b/ash/resources/default_200_percent/cros/network/statusbar_network_evdo_light.png
Binary files differ
diff --git a/ash/resources/default_200_percent/cros/status/status_help.png b/ash/resources/default_200_percent/cros/status/status_help.png
index 97de651..a8a9977 100644
--- a/ash/resources/default_200_percent/cros/status/status_help.png
+++ b/ash/resources/default_200_percent/cros/status/status_help.png
Binary files differ
diff --git a/ash/resources/default_200_percent/cros/status/status_power_small_all_fluctuating.png b/ash/resources/default_200_percent/cros/status/status_power_small_all_fluctuating.png
index d46f7ca..be20d9b 100644
--- a/ash/resources/default_200_percent/cros/status/status_power_small_all_fluctuating.png
+++ b/ash/resources/default_200_percent/cros/status/status_power_small_all_fluctuating.png
Binary files differ
diff --git a/ash/resources/default_200_percent/cros/status/status_tracing.png b/ash/resources/default_200_percent/cros/status/status_tracing.png
new file mode 100644
index 0000000..4680f3f
--- /dev/null
+++ b/ash/resources/default_200_percent/cros/status/status_tracing.png
Binary files differ
diff --git a/ash/shelf/shelf_layout_manager.cc b/ash/shelf/shelf_layout_manager.cc
index c0e5f77..e392cc2 100644
--- a/ash/shelf/shelf_layout_manager.cc
+++ b/ash/shelf/shelf_layout_manager.cc
@@ -36,6 +36,7 @@
 #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/root_window.h"
 #include "ui/base/events/event.h"
 #include "ui/base/events/event_handler.h"
@@ -72,6 +73,9 @@
 // the auto hidden shelf when the shelf is on the boundary between displays.
 const int kMaxAutoHideShowShelfRegionSize = 10;
 
+// Const inset from the edget of the shelf to the edget of the status area.
+const int kStatusAreaInset = 3;
+
 ui::Layer* GetLayer(views::Widget* widget) {
   return widget->GetNativeView()->layer();
 }
@@ -280,7 +284,8 @@
   if (shelf_->launcher())
     shelf_->launcher()->SetLauncherViewBounds(
         target_bounds.launcher_bounds_in_shelf);
-  GetLayer(shelf_->status_area_widget())->SetOpacity(target_bounds.opacity);
+  GetLayer(shelf_->status_area_widget())->SetOpacity(
+      target_bounds.status_opacity);
   // TODO(harrym): Once status area widget is a child view of shelf
   // this can be simplified.
   gfx::Rect status_bounds = target_bounds.status_bounds_in_shelf;
@@ -571,12 +576,6 @@
   state.window_state = workspace_controller_ ?
       workspace_controller_->GetWindowState() : WORKSPACE_WINDOW_STATE_DEFAULT;
 
-  // It's possible for SetState() when a window becomes maximized but the state
-  // won't have changed value. Do the dimming check before the early exit.
-  shelf_->SetDimsShelf(
-      (state.visibility_state == SHELF_VISIBLE) &&
-      state.window_state == WORKSPACE_WINDOW_STATE_MAXIMIZED);
-
   if (state_.Equals(state))
     return;  // Nothing changed.
 
@@ -594,20 +593,6 @@
 
   StopAutoHideTimer();
 
-  // The transition of background from auto-hide to visible is janky if the
-  // transition also cause the shelf's slide animation from the bottom edge.
-  // This happens if:
-  //  - shelf is hidden
-  //  - or, shelf is visible but workspace state is maximized
-  bool keep_maximized = state_.window_state == state.window_state &&
-      state_.window_state == WORKSPACE_WINDOW_STATE_MAXIMIZED;
-  BackgroundAnimator::ChangeType change_type =
-      (state_.visibility_state == SHELF_AUTO_HIDE &&
-       state.visibility_state == SHELF_VISIBLE &&
-       (state_.auto_hide_state == SHELF_AUTO_HIDE_HIDDEN ||
-        keep_maximized)) ?
-      BackgroundAnimator::CHANGE_IMMEDIATE : BackgroundAnimator::CHANGE_ANIMATE;
-
   State old_state = state_;
   state_ = state;
   TargetBounds target_bounds;
@@ -631,29 +616,43 @@
   status_animation_setter.SetPreemptionStrategy(
       ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
 
-  // Delay updating the background when going from SHELF_AUTO_HIDE_SHOWN to
-  // SHELF_AUTO_HIDE_HIDDEN until the shelf animates out. Otherwise during the
-  // animation you see the background change.
-  // Also delay the animation when the shelf was hidden, and has just been made
-  // visible (e.g. using a gesture-drag).
-  // But do not delay if the transition happens when a window is maximized.
-  bool delay_shelf_update =
-      state.visibility_state == SHELF_AUTO_HIDE &&
-      state.auto_hide_state == SHELF_AUTO_HIDE_HIDDEN &&
-      old_state.visibility_state == SHELF_AUTO_HIDE;
+  BackgroundAnimator::ChangeType change_type =
+      BackgroundAnimator::CHANGE_ANIMATE;
+  bool delay_background_change = false;
 
-  if (!keep_maximized && state.visibility_state == SHELF_VISIBLE &&
-      old_state.visibility_state == SHELF_AUTO_HIDE &&
-      old_state.auto_hide_state == SHELF_AUTO_HIDE_HIDDEN)
-    delay_shelf_update = true;
+  // Do not animate the background when:
+  // - Going from a hidden / auto hidden shelf in fullscreen to a visible shelf
+  //   in maximized mode.
+  // - Going from an auto hidden shelf in maximized mode to a visible shelf in
+  //   maximized mode.
+  if (state.visibility_state == SHELF_VISIBLE &&
+      state.window_state == WORKSPACE_WINDOW_STATE_MAXIMIZED &&
+      old_state.visibility_state != SHELF_VISIBLE) {
+    change_type = BackgroundAnimator::CHANGE_IMMEDIATE;
+  } else {
+    // Delay the animation when the shelf was hidden, and has just been made
+    // visible (e.g. using a gesture-drag).
+    if (state.visibility_state == SHELF_VISIBLE &&
+        old_state.visibility_state == SHELF_AUTO_HIDE &&
+        old_state.auto_hide_state == SHELF_AUTO_HIDE_HIDDEN) {
+      delay_background_change = true;
+    }
+  }
 
-  if (delay_shelf_update) {
+  if (delay_background_change) {
     if (update_shelf_observer_)
       update_shelf_observer_->Detach();
     // UpdateShelfBackground deletes itself when the animation is done.
     update_shelf_observer_ = new UpdateShelfObserver(this);
     status_animation_setter.AddObserver(update_shelf_observer_);
+  } else {
+    UpdateShelfBackground(change_type);
   }
+
+  shelf_->SetDimsShelf(
+      state.visibility_state == SHELF_VISIBLE &&
+      state.window_state == WORKSPACE_WINDOW_STATE_MAXIMIZED);
+
   ui::Layer* layer = GetLayer(shelf_->status_area_widget());
   // TODO(harrym): Remove when status_area is view (crbug.com/180422).
   gfx::Rect status_bounds = target_bounds.status_bounds_in_shelf;
@@ -666,8 +665,6 @@
   Shell::GetInstance()->SetDisplayWorkAreaInsets(
       root_window_, target_bounds.work_area_insets);
   UpdateHitTestBounds();
-  if (!delay_shelf_update)
-    UpdateShelfBackground(change_type);
 
   // OnAutoHideStateChanged Should be emitted when:
   //  - firstly state changed to auto-hide from other state
@@ -747,6 +744,9 @@
   int status_inset = std::max(0, GetPreferredShelfSize() -
       PrimaryAxisValue(status_size.height(), status_size.width()));
 
+  if (ash::switches::UseAlternateShelfLayout())
+    status_inset = kStatusAreaInset;
+
   target_bounds->status_bounds_in_shelf = SelectValueForShelfAlignment(
       gfx::Rect(base::i18n::IsRTL() ? 0 : shelf_width - status_size.width(),
                     status_inset, status_size.width(), status_size.height()),
@@ -789,7 +789,8 @@
        state.visibility_state == SHELF_AUTO_HIDE) ? 1.0f : 0.0f;
   target_bounds->status_opacity =
       (state.visibility_state == SHELF_AUTO_HIDE &&
-       state.auto_hide_state == SHELF_AUTO_HIDE_HIDDEN) ?
+       state.auto_hide_state == SHELF_AUTO_HIDE_HIDDEN &&
+       gesture_drag_status_ != GESTURE_DRAG_IN_PROGRESS) ?
       0.0f : target_bounds->opacity;
 
   if (gesture_drag_status_ == GESTURE_DRAG_IN_PROGRESS)
@@ -855,12 +856,16 @@
           available_bounds.bottom() - shelf_height);
     }
 
-    // The statusbar should be in the center of the shelf.
-    gfx::Rect status_y = target_bounds->shelf_bounds_in_root;
-    status_y.set_y(0);
-    status_y.ClampToCenteredSize(
-        target_bounds->status_bounds_in_shelf.size());
-    target_bounds->status_bounds_in_shelf.set_y(status_y.y());
+    if (ash::switches::UseAlternateShelfLayout()) {
+      target_bounds->status_bounds_in_shelf.set_y(kStatusAreaInset);
+    } else {
+      // The statusbar should be in the center of the shelf.
+      gfx::Rect status_y = target_bounds->shelf_bounds_in_root;
+      status_y.set_y(0);
+      status_y.ClampToCenteredSize(
+          target_bounds->status_bounds_in_shelf.size());
+      target_bounds->status_bounds_in_shelf.set_y(status_y.y());
+    }
   } else {
     // Move and size the launcher with the gesture.
     int shelf_width = target_bounds->shelf_bounds_in_root.width();
@@ -875,12 +880,21 @@
           available_bounds.right() - shelf_width);
     }
 
-    // The statusbar should be in the center of the shelf.
-    gfx::Rect status_x = target_bounds->shelf_bounds_in_root;
-    status_x.set_x(0);
-    status_x.ClampToCenteredSize(
-        target_bounds->status_bounds_in_shelf.size());
-    target_bounds->status_bounds_in_shelf.set_x(status_x.x());
+    if (ash::switches::UseAlternateShelfLayout()) {
+      if (alignment_ == SHELF_ALIGNMENT_RIGHT) {
+        target_bounds->shelf_bounds_in_root.set_x(
+            available_bounds.right() - shelf_width + kStatusAreaInset);
+      } else {
+        target_bounds->shelf_bounds_in_root.set_x(kStatusAreaInset);
+      }
+    } else {
+      // The statusbar should be in the center of the shelf.
+      gfx::Rect status_x = target_bounds->shelf_bounds_in_root;
+      status_x.set_x(0);
+      status_x.ClampToCenteredSize(
+          target_bounds->status_bounds_in_shelf.size());
+      target_bounds->status_bounds_in_shelf.set_x(status_x.x());
+    }
   }
 }
 
@@ -941,9 +955,6 @@
   if (visibility_state != SHELF_AUTO_HIDE || !shelf_)
     return SHELF_AUTO_HIDE_HIDDEN;
 
-  if (gesture_drag_status_ == GESTURE_DRAG_COMPLETE_IN_PROGRESS)
-    return gesture_drag_auto_hide_state_;
-
   Shell* shell = Shell::GetInstance();
   if (shell->GetAppListTargetVisibility())
     return SHELF_AUTO_HIDE_SHOWN;
@@ -961,10 +972,36 @@
   if (shelf_->IsActive() || shelf_->status_area_widget()->IsActive())
     return SHELF_AUTO_HIDE_SHOWN;
 
+  const std::vector<aura::Window*> windows =
+      ash::MruWindowTracker::BuildWindowList(false);
+
+  // Process the window list and check if there are any visible windows.
+  bool visible_window = false;
+  for (size_t i = 0; i < windows.size(); ++i) {
+    if (windows[i] && windows[i]->IsVisible() &&
+        !ash::wm::IsWindowMinimized(windows[i]) &&
+        root_window_ == windows[i]->GetRootWindow()) {
+      visible_window = true;
+      break;
+    }
+  }
+  // If there are no visible windows do not hide the shelf.
+  if (!visible_window)
+    return SHELF_AUTO_HIDE_SHOWN;
+
+  if (gesture_drag_status_ == GESTURE_DRAG_COMPLETE_IN_PROGRESS)
+    return gesture_drag_auto_hide_state_;
+
   // Don't show if the user is dragging the mouse.
   if (auto_hide_event_filter_.get() && auto_hide_event_filter_->in_mouse_drag())
     return SHELF_AUTO_HIDE_HIDDEN;
 
+  // Ignore the mouse position if mouse events are disabled.
+  aura::client::CursorClient* cursor_client = aura::client::GetCursorClient(
+      shelf_->GetNativeWindow()->GetRootWindow());
+  if (!cursor_client->IsMouseEventsEnabled())
+    return SHELF_AUTO_HIDE_HIDDEN;
+
   gfx::Rect shelf_region = shelf_->GetWindowBoundsInScreen();
   if (shelf_->status_area_widget() &&
       shelf_->status_area_widget()->IsMessageBubbleShown() &&
@@ -1005,19 +1042,7 @@
     return SHELF_AUTO_HIDE_SHOWN;
   }
 
-  const std::vector<aura::Window*> windows =
-      ash::MruWindowTracker::BuildWindowList(false);
-
-  // Process the window list and check if there are any visible windows.
-  for (size_t i = 0; i < windows.size(); ++i) {
-    if (windows[i] && windows[i]->IsVisible() &&
-        !ash::wm::IsWindowMinimized(windows[i]) &&
-        root_window_ == windows[i]->GetRootWindow())
-      return SHELF_AUTO_HIDE_HIDDEN;
-  }
-
-  // If there are no visible windows do not hide the shelf.
-  return SHELF_AUTO_HIDE_SHOWN;
+  return SHELF_AUTO_HIDE_HIDDEN;
 }
 
 void ShelfLayoutManager::UpdateHitTestBounds() {
diff --git a/ash/shelf/shelf_layout_manager_unittest.cc b/ash/shelf/shelf_layout_manager_unittest.cc
index 2781e6c..e62bcec 100644
--- a/ash/shelf/shelf_layout_manager_unittest.cc
+++ b/ash/shelf/shelf_layout_manager_unittest.cc
@@ -576,6 +576,22 @@
   // is fullscreen status.
   widget->Close();
   RunAllPendingInMessageLoop();
+
+  // The shelf should be shown because there are no more visible windows.
+  EXPECT_EQ(SHELF_AUTO_HIDE, shelf->visibility_state());
+  EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, shelf->auto_hide_state());
+  EXPECT_EQ(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS, shelf->auto_hide_behavior());
+
+  // Swipe-up to hide. This should have no effect because there are no visible
+  // windows.
+  end = below_start - delta;
+  generator.GestureScrollSequenceWithCallback(below_start, end,
+      base::TimeDelta::FromMilliseconds(10), kNumScrollSteps,
+      base::Bind(&ShelfDragCallback::ProcessScroll,
+                 base::Unretained(&handler)));
+  EXPECT_EQ(SHELF_AUTO_HIDE, shelf->visibility_state());
+  EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, shelf->auto_hide_state());
+  EXPECT_EQ(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS, shelf->auto_hide_behavior());
 }
 
 // Fails on Mac only.  Need to be implemented.  http://crbug.com/111279.
diff --git a/ash/shelf/shelf_widget.cc b/ash/shelf/shelf_widget.cc
index 7c478c7..d16f876 100644
--- a/ash/shelf/shelf_widget.cc
+++ b/ash/shelf/shelf_widget.cc
@@ -541,8 +541,10 @@
 
 void ShelfWidget::SetDimsShelf(bool dimming) {
   delegate_view_->SetDimmed(dimming);
+  // Repaint all children, allowing updates to reflect dimmed state eg:
+  // status area background, app list button and overflow button.
   if (launcher_)
-    launcher_->GetAppListButtonView()->SchedulePaint();
+    launcher_->SchedulePaint();
   status_area_widget_->GetContentsView()->SchedulePaint();
 }
 
diff --git a/ash/shell.cc b/ash/shell.cc
index 1bade43..996c817 100644
--- a/ash/shell.cc
+++ b/ash/shell.cc
@@ -17,6 +17,7 @@
 #include "ash/display/display_manager.h"
 #include "ash/display/event_transformation_handler.h"
 #include "ash/display/mouse_cursor_event_filter.h"
+#include "ash/display/resolution_notification_controller.h"
 #include "ash/display/screen_position_controller.h"
 #include "ash/drag_drop/drag_drop_controller.h"
 #include "ash/focus_cycler.h"
@@ -312,6 +313,8 @@
   lock_state_controller_.reset();
   mru_window_tracker_.reset();
 
+  resolution_notification_controller_.reset();
+
   // This also deletes all RootWindows. Note that we invoke Shutdown() on
   // DisplayController before resetting |display_controller_|, since destruction
   // of its owned RootWindowControllers relies on the value.
@@ -505,6 +508,9 @@
   aura::RootWindow* root_window = display_controller_->GetPrimaryRootWindow();
   target_root_window_ = root_window;
 
+  resolution_notification_controller_.reset(
+      new internal::ResolutionNotificationController);
+
   cursor_manager_.SetDisplay(DisplayController::GetPrimaryDisplay());
 
 #if !defined(OS_MACOSX)
@@ -743,6 +749,18 @@
 
 void Shell::OnLockStateChanged(bool locked) {
   FOR_EACH_OBSERVER(ShellObserver, observers_, OnLockStateChanged(locked));
+#ifndef NDEBUG
+  // Make sure that there is no system modal in Lock layer when unlocked.
+  if (!locked) {
+    std::vector<aura::Window*> containers = GetContainersFromAllRootWindows(
+        internal::kShellWindowId_LockSystemModalContainer,
+        GetPrimaryRootWindow());
+    for (std::vector<aura::Window*>::const_iterator iter = containers.begin();
+         iter != containers.end(); ++iter) {
+      DCHECK_EQ(0u, (*iter)->children().size());
+    }
+  }
+#endif
 }
 
 void Shell::CreateLauncher() {
diff --git a/ash/shell.h b/ash/shell.h
index c3adade..ae08e7b 100644
--- a/ash/shell.h
+++ b/ash/shell.h
@@ -115,6 +115,7 @@
 class OutputConfiguratorAnimation;
 class OverlayEventFilter;
 class ResizeShadowController;
+class ResolutionNotificationController;
 class RootWindowController;
 class RootWindowLayoutManager;
 class ScopedTargetRootWindow;
@@ -450,6 +451,11 @@
   }
 #endif  // defined(OS_CHROMEOS) && defined(USE_X11)
 
+  internal::ResolutionNotificationController*
+      resolution_notification_controller() {
+    return resolution_notification_controller_.get();
+  }
+
   RootWindowHostFactory* root_window_host_factory() {
     return root_window_host_factory_.get();
   }
@@ -607,6 +613,9 @@
   scoped_ptr<internal::DisplayChangeObserverX11> display_change_observer_;
 #endif  // defined(OS_CHROMEOS) && defined(USE_X11)
 
+  scoped_ptr<internal::ResolutionNotificationController>
+      resolution_notification_controller_;
+
   // |native_cursor_manager_| is owned by |cursor_manager_|, but we keep a
   // pointer to vend to test code.
   AshNativeCursorManager* native_cursor_manager_;
diff --git a/ash/system/chromeos/managed/tray_locally_managed_user.cc b/ash/system/chromeos/managed/tray_locally_managed_user.cc
index 61e422d..49dea0c 100644
--- a/ash/system/chromeos/managed/tray_locally_managed_user.cc
+++ b/ash/system/chromeos/managed/tray_locally_managed_user.cc
@@ -10,46 +10,39 @@
 #include "ash/system/user/login_status.h"
 #include "base/logging.h"
 #include "grit/ash_resources.h"
+#include "ui/message_center/message_center.h"
+#include "ui/message_center/notification.h"
+#include "ui/message_center/notification_delegate.h"
+
+using message_center::Notification;
 
 namespace ash {
 namespace internal {
-
 namespace {
 
-class ManagedUserNotificationView : public TrayNotificationView {
- public:
-  explicit ManagedUserNotificationView(TrayLocallyManagedUser* tray_managed)
-      : TrayNotificationView(tray_managed, IDR_AURA_UBER_TRAY_MANAGED_USER),
-        tray_managed_(tray_managed) {
-    CreateMessageView();
-    InitView(message_view_);
-  }
+const char kLocallyManagedUserNotificationId[] =
+    "chrome://user/locally-managed";
 
-  void Update() {
-    CreateMessageView();
-    UpdateView(message_view_);
-  }
-
- private:
-  void CreateMessageView() {
-    message_view_ = new LabelTrayView(tray_managed_, 0);
-    base::string16 message = Shell::GetInstance()->system_tray_delegate()->
-        GetLocallyManagedUserMessage();
-    message_view_->SetMessage(message);
-  }
-
-  LabelTrayView* message_view_;
-  TrayLocallyManagedUser* tray_managed_;
-
-  DISALLOW_COPY_AND_ASSIGN(ManagedUserNotificationView);
-};
+void CreateOrUpdateNotification(const base::string16& new_message) {
+  scoped_ptr<Notification> notification(new Notification(
+      message_center::NOTIFICATION_TYPE_SIMPLE,
+      kLocallyManagedUserNotificationId,
+      new_message,
+      base::string16() /* body is empty */,
+      gfx::Image() /* icon */,
+      base::string16() /* display_source */,
+      std::string() /* extension_id */,
+      message_center::RichNotificationData(),
+      NULL /* no delegate */));
+  notification->SetSystemPriority();
+  message_center::MessageCenter::Get()->AddNotification(notification.Pass());
+}
 
 } // namespace
 
 TrayLocallyManagedUser::TrayLocallyManagedUser(SystemTray* system_tray)
     : SystemTrayItem(system_tray),
       tray_view_(NULL),
-      notification_view_(NULL),
       status_(ash::user::LOGGED_IN_NONE) {
 }
 
@@ -61,17 +54,10 @@
       GetLocallyManagedUserMessage();
   if (tray_view_)
     tray_view_->SetMessage(message);
-  if (notification_view_)
-    tray_view_->SetMessage(message);
-}
-
-views::View* TrayLocallyManagedUser::CreateNotificationView(
-    user::LoginStatus status) {
-  CHECK(!notification_view_);
-  if (status != ash::user::LOGGED_IN_LOCALLY_MANAGED)
-    return NULL;
-  notification_view_ = new ManagedUserNotificationView(this);
-  return notification_view_;
+  if (message_center::MessageCenter::Get()->HasNotification(
+          kLocallyManagedUserNotificationId)) {
+    CreateOrUpdateNotification(message);
+  }
 }
 
 views::View* TrayLocallyManagedUser::CreateDefaultView(
@@ -89,10 +75,6 @@
   tray_view_ = NULL;
 }
 
-void TrayLocallyManagedUser::DestroyNotificationView() {
-  notification_view_ = NULL;
-}
-
 void TrayLocallyManagedUser::OnViewClicked(views::View* sender) {
   Shell::GetInstance()->system_tray_delegate()->ShowLocallyManagedUserInfo();
 }
@@ -103,11 +85,11 @@
     return;
   if (status == ash::user::LOGGED_IN_LOCALLY_MANAGED &&
       status_ != ash::user::LOGGED_IN_LOCKED) {
-    ShowNotificationView();
+    SystemTrayDelegate* delegate = Shell::GetInstance()->system_tray_delegate();
+    CreateOrUpdateNotification(delegate->GetLocallyManagedUserMessage());
   }
   status_ = status;
 }
 
 } // namespace internal
 } // namespace ash
-
diff --git a/ash/system/chromeos/managed/tray_locally_managed_user.h b/ash/system/chromeos/managed/tray_locally_managed_user.h
index eda2be0..e028634 100644
--- a/ash/system/chromeos/managed/tray_locally_managed_user.h
+++ b/ash/system/chromeos/managed/tray_locally_managed_user.h
@@ -29,10 +29,7 @@
 
   // Overridden from SystemTrayItem.
   virtual views::View* CreateDefaultView(user::LoginStatus status) OVERRIDE;
-  virtual views::View* CreateNotificationView(
-     user::LoginStatus status) OVERRIDE;
   virtual void DestroyDefaultView() OVERRIDE;
-  virtual void DestroyNotificationView() OVERRIDE;
   virtual void UpdateAfterLoginStatusChange(user::LoginStatus status) OVERRIDE;
 
   // Overridden from ViewClickListener.
@@ -40,7 +37,6 @@
 
  private:
   LabelTrayView* tray_view_;
-  views::View* notification_view_;
   // Previous login status to avoid showing notification upon unlock.
   user::LoginStatus status_;
 
@@ -51,4 +47,3 @@
 } // namespace ash
 
 #endif  // ASH_SYSTEM_CHROMEOS_LOCALLY_MANAGED_TRAY_LOCALLY_MANAGED_USER_H
-
diff --git a/ash/system/chromeos/network/network_connect.cc b/ash/system/chromeos/network/network_connect.cc
index 5c62499..3aca162 100644
--- a/ash/system/chromeos/network/network_connect.cc
+++ b/ash/system/chromeos/network/network_connect.cc
@@ -13,77 +13,315 @@
 #include "base/memory/scoped_ptr.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/values.h"
+#include "chromeos/login/login_state.h"
+#include "chromeos/network/device_state.h"
+#include "chromeos/network/network_configuration_handler.h"
 #include "chromeos/network/network_connection_handler.h"
+#include "chromeos/network/network_event_log.h"
+#include "chromeos/network/network_handler_callbacks.h"
+#include "chromeos/network/network_profile.h"
+#include "chromeos/network/network_profile_handler.h"
 #include "chromeos/network/network_state.h"
 #include "chromeos/network/network_state_handler.h"
 #include "grit/ash_strings.h"
 #include "third_party/cros_system_api/dbus/service_constants.h"
 #include "ui/base/l10n/l10n_util.h"
 
+using chromeos::DeviceState;
+using chromeos::NetworkConfigurationHandler;
 using chromeos::NetworkConnectionHandler;
 using chromeos::NetworkHandler;
+using chromeos::NetworkProfile;
+using chromeos::NetworkProfileHandler;
 using chromeos::NetworkState;
 
 namespace ash {
 
 namespace {
 
+// TODO(stevenjb): This should be in service_constants.h
+const char kErrorInProgress[] = "org.chromium.flimflam.Error.InProgress";
+
+// Returns true for carriers that can be activated through Shill instead of
+// through a WebUI dialog.
+bool IsDirectActivatedCarrier(const std::string& carrier) {
+  if (carrier == shill::kCarrierSprint)
+    return true;
+  return false;
+}
+
+void ShowErrorNotification(const std::string& error,
+                           const std::string& service_path) {
+  Shell::GetInstance()->system_tray_notifier()->network_state_notifier()->
+      ShowNetworkConnectError(error, service_path);
+}
+
 void OnConnectFailed(const std::string& service_path,
+                     gfx::NativeWindow owning_window,
                      const std::string& error_name,
                      scoped_ptr<base::DictionaryValue> error_data) {
-  VLOG(1) << "Connect Failed for " << service_path << ": " << error_name;
-  if (error_name == NetworkConnectionHandler::kErrorPassphraseRequired) {
-    // TODO(stevenjb): Possibly add inline UI to handle passphrase entry here.
-    ash::Shell::GetInstance()->system_tray_delegate()->ConfigureNetwork(
-        service_path);
+  NET_LOG_ERROR("Connect Failed: " + error_name, service_path);
+
+  // If a new connect attempt canceled this connect, no need to notify the user.
+  if (error_name == NetworkConnectionHandler::kErrorConnectCanceled)
     return;
-  }
-  if (error_name == NetworkConnectionHandler::kErrorActivationRequired ||
-      error_name == NetworkConnectionHandler::kErrorCertificateRequired ||
+
+  if (error_name == NetworkConnectionHandler::kErrorPassphraseRequired ||
       error_name == NetworkConnectionHandler::kErrorConfigurationRequired ||
       error_name == NetworkConnectionHandler::kErrorAuthenticationRequired) {
     ash::Shell::GetInstance()->system_tray_delegate()->ConfigureNetwork(
         service_path);
     return;
   }
+
+  if (error_name == NetworkConnectionHandler::kErrorCertificateRequired) {
+    ash::Shell::GetInstance()->system_tray_delegate()->EnrollOrConfigureNetwork(
+        service_path, owning_window);
+    return;
+  }
+
+  if (error_name == NetworkConnectionHandler::kErrorActivationRequired) {
+    network_connect::ActivateCellular(service_path);
+    return;
+  }
+
   if (error_name == NetworkConnectionHandler::kErrorConnected ||
       error_name == NetworkConnectionHandler::kErrorConnecting) {
     ash::Shell::GetInstance()->system_tray_delegate()->ShowNetworkSettings(
         service_path);
     return;
   }
-  // Shill does not always provide a helpful error. In this case, show the
-  // configuration UI and a notification. See crbug.com/217033 for an example.
-  if (error_name == NetworkConnectionHandler::kErrorConnectFailed) {
-    ash::Shell::GetInstance()->system_tray_delegate()->ConfigureNetwork(
-        service_path);
-  }
-  ash::Shell::GetInstance()->system_tray_notifier()->network_state_notifier()->
-      ShowNetworkConnectError(error_name, service_path);
+
+  // ConnectFailed or unknown error; show a notification.
+  ShowErrorNotification(error_name, service_path);
+
+  // Show a configure dialog for ConnectFailed errors.
+  if (error_name != NetworkConnectionHandler::kErrorConnectFailed)
+    return;
+
+  // If Shill reports an InProgress error, don't try to configure the network.
+  std::string dbus_error_name;
+  error_data.get()->GetString(
+      chromeos::network_handler::kDbusErrorName, &dbus_error_name);
+  if (dbus_error_name == kErrorInProgress)
+    return;
+
+  ash::Shell::GetInstance()->system_tray_delegate()->ConfigureNetwork(
+      service_path);
 }
 
 void OnConnectSucceeded(const std::string& service_path) {
-  VLOG(1) << "Connect Succeeded for " << service_path;
+  NET_LOG_USER("Connect Succeeded", service_path);
   ash::Shell::GetInstance()->system_tray_notifier()->NotifyClearNetworkMessage(
       NetworkObserver::ERROR_CONNECT_FAILED);
 }
 
+// If |check_error_state| is true, error state for the network is checked,
+// otherwise any current error state is ignored (e.g. for recently configured
+// networks or repeat connect attempts). |owning_window| will be used to parent
+// any configuration UI on failure and may be NULL (in which case the default
+// window will be used).
+void CallConnectToNetwork(const std::string& service_path,
+                          bool check_error_state,
+                          gfx::NativeWindow owning_window) {
+  NET_LOG_USER("ConnectToNetwork", service_path);
+
+  ash::Shell::GetInstance()->system_tray_notifier()->NotifyClearNetworkMessage(
+      NetworkObserver::ERROR_CONNECT_FAILED);
+
+  NetworkHandler::Get()->network_connection_handler()->ConnectToNetwork(
+      service_path,
+      base::Bind(&OnConnectSucceeded, service_path),
+      base::Bind(&OnConnectFailed, service_path, owning_window),
+      check_error_state);
+}
+
+void OnActivateFailed(const std::string& service_path,
+                     const std::string& error_name,
+                      scoped_ptr<base::DictionaryValue> error_data) {
+  NET_LOG_ERROR("Unable to activate network", service_path);
+  ShowErrorNotification(
+      NetworkConnectionHandler::kErrorActivateFailed, service_path);
+}
+
+void OnActivateSucceeded(const std::string& service_path) {
+  NET_LOG_USER("Activation Succeeded", service_path);
+}
+
+void OnConfigureFailed(const std::string& error_name,
+                       scoped_ptr<base::DictionaryValue> error_data) {
+  NET_LOG_ERROR("Unable to configure network", "");
+  ShowErrorNotification(NetworkConnectionHandler::kErrorConfigureFailed, "");
+}
+
+void OnConfigureSucceeded(const std::string& service_path) {
+  NET_LOG_USER("Configure Succeeded", service_path);
+  // After configuring a network, ignore any (possibly stale) error state.
+  const bool check_error_state = false;
+  const gfx::NativeWindow owning_window = NULL;
+  CallConnectToNetwork(service_path, check_error_state, owning_window);
+}
+
+void SetPropertiesFailed(const std::string& desc,
+                         const std::string& service_path,
+                         const std::string& config_error_name,
+                         scoped_ptr<base::DictionaryValue> error_data) {
+  NET_LOG_ERROR(desc + ": Failed: " + config_error_name, service_path);
+  ShowErrorNotification(
+      NetworkConnectionHandler::kErrorConfigureFailed, service_path);
+}
+
+void SetPropertiesToClear(base::DictionaryValue* properties_to_set,
+                          std::vector<std::string>* properties_to_clear) {
+  // Move empty string properties to properties_to_clear.
+  for (base::DictionaryValue::Iterator iter(*properties_to_set);
+       !iter.IsAtEnd(); iter.Advance()) {
+    std::string value_str;
+    if (iter.value().GetAsString(&value_str) && value_str.empty())
+      properties_to_clear->push_back(iter.key());
+  }
+  // Remove cleared properties from properties_to_set.
+  for (std::vector<std::string>::iterator iter = properties_to_clear->begin();
+       iter != properties_to_clear->end(); ++iter) {
+    properties_to_set->RemoveWithoutPathExpansion(*iter, NULL);
+  }
+}
+
+void ClearPropertiesAndConnect(
+    const std::string& service_path,
+    const std::vector<std::string>& properties_to_clear) {
+  NET_LOG_USER("ClearPropertiesAndConnect", service_path);
+  // After configuring a network, ignore any (possibly stale) error state.
+  const bool check_error_state = false;
+  const gfx::NativeWindow owning_window = NULL;
+  NetworkHandler::Get()->network_configuration_handler()->ClearProperties(
+      service_path,
+      properties_to_clear,
+      base::Bind(&CallConnectToNetwork,
+                 service_path, check_error_state,
+                 owning_window),
+      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::kSharedProfilePath;
+    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) {
+  std::vector<std::string> properties_to_clear;
+  SetPropertiesToClear(properties_to_set.get(), &properties_to_clear);
+  NetworkHandler::Get()->network_configuration_handler()->SetProperties(
+      service_path,
+      *properties_to_set,
+      base::Bind(&ClearPropertiesAndConnect,
+                 service_path,
+                 properties_to_clear),
+      base::Bind(&SetPropertiesFailed, "SetProperties", service_path));
+}
+
 }  // namespace
 
 namespace network_connect {
 
-void ConnectToNetwork(const std::string& service_path) {
-  const NetworkState* network = NetworkHandler::Get()->network_state_handler()->
-      GetNetworkState(service_path);
-  if (!network)
+void ConnectToNetwork(const std::string& service_path,
+                      gfx::NativeWindow owning_window) {
+  const bool check_error_state = true;
+  CallConnectToNetwork(service_path, check_error_state, owning_window);
+}
+
+void ActivateCellular(const std::string& service_path) {
+  NET_LOG_USER("ActivateCellular", service_path);
+  const DeviceState* cellular_device =
+      NetworkHandler::Get()->network_state_handler()->
+      GetDeviceStateByType(flimflam::kTypeCellular);
+  if (!cellular_device) {
+    NET_LOG_ERROR("ActivateCellular with no Device", service_path);
     return;
-  ash::Shell::GetInstance()->system_tray_notifier()->NotifyClearNetworkMessage(
-      NetworkObserver::ERROR_CONNECT_FAILED);
-  NetworkHandler::Get()->network_connection_handler()->ConnectToNetwork(
+  }
+  if (!IsDirectActivatedCarrier(cellular_device->carrier())) {
+    // For non direct activation, show the mobile setup dialog which can be
+    // used to activate the network.
+    ash::Shell::GetInstance()->system_tray_delegate()->ShowMobileSetup(
+        service_path);
+    return;
+  }
+  const NetworkState* cellular =
+      NetworkHandler::Get()->network_state_handler()->
+      GetNetworkState(service_path);
+  if (!cellular || cellular->type() != flimflam::kTypeCellular) {
+    NET_LOG_ERROR("ActivateCellular with no Service", service_path);
+    return;
+  }
+  if (cellular->activation_state() == flimflam::kActivationStateActivated) {
+    NET_LOG_ERROR("ActivateCellular for activated service", service_path);
+    return;
+  }
+
+  NetworkHandler::Get()->network_connection_handler()->ActivateNetwork(
       service_path,
-      base::Bind(&OnConnectSucceeded, service_path),
-      base::Bind(&OnConnectFailed, service_path),
-      true /* check_error_state */);
+      "",  // carrier
+      base::Bind(&OnActivateSucceeded, service_path),
+      base::Bind(&OnActivateFailed, service_path));
+}
+
+void ConfigureNetworkAndConnect(const std::string& service_path,
+                                const base::DictionaryValue& properties,
+                                bool shared) {
+  NET_LOG_USER("ConfigureNetworkAndConnect", service_path);
+
+  scoped_ptr<base::DictionaryValue> properties_to_set(properties.DeepCopy());
+
+  std::string profile_path;
+  if (!GetNetworkProfilePath(shared, &profile_path)) {
+    ShowErrorNotification(
+        NetworkConnectionHandler::kErrorConfigureFailed, service_path);
+    return;
+  }
+  NetworkHandler::Get()->network_configuration_handler()->SetNetworkProfile(
+      service_path, profile_path,
+      base::Bind(&ConfigureSetProfileSucceeded,
+                 service_path, base::Passed(&properties_to_set)),
+      base::Bind(&SetPropertiesFailed,
+                 "SetProfile: " + profile_path, service_path));
+}
+
+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(
+      flimflam::kProfileProperty, profile_path);
+  NetworkHandler::Get()->network_configuration_handler()->CreateConfiguration(
+      *properties,
+      base::Bind(&OnConfigureSucceeded),
+      base::Bind(&OnConfigureFailed));
 }
 
 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 3966140..65c430d 100644
--- a/ash/system/chromeos/network/network_connect.h
+++ b/ash/system/chromeos/network/network_connect.h
@@ -9,12 +9,35 @@
 
 #include "ash/ash_export.h"
 #include "base/strings/string16.h"
+#include "ui/gfx/native_widget_types.h"  // gfx::NativeWindow
+
+namespace base {
+class DictionaryValue;
+}
 
 namespace ash {
 namespace network_connect {
 
-// Request a network connection and handle any errors and notifications.
-ASH_EXPORT void ConnectToNetwork(const std::string& service_path);
+// Requests a network connection and handles any errors and notifications.
+// |owning_window| is used to parent any UI on failure (e.g. for certificate
+// enrollment). If NULL, the default window will be used.
+ASH_EXPORT void ConnectToNetwork(const std::string& service_path,
+                                 gfx::NativeWindow owning_window);
+
+// Requests network activation and handles any errors and notifications.
+ASH_EXPORT void ActivateCellular(const std::string& service_path);
+
+// Configures a network with a dictionary of Shill properties, then sends a
+// connect request. The profile is set according to 'shared' if allowed.
+ASH_EXPORT void ConfigureNetworkAndConnect(
+    const std::string& service_path,
+    const 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 CreateConfigurationAndConnect(base::DictionaryValue* properties,
+                                              bool shared);
 
 // Returns the localized string for shill error string |error|.
 ASH_EXPORT base::string16 ErrorString(const std::string& error);
diff --git a/ash/system/chromeos/network/network_icon.cc b/ash/system/chromeos/network/network_icon.cc
index e931035..efe7e07 100644
--- a/ash/system/chromeos/network/network_icon.cc
+++ b/ash/system/chromeos/network/network_icon.cc
@@ -411,8 +411,8 @@
   const std::string& technology = network->network_technology();
   if (technology == flimflam::kNetworkTechnologyEvdo) {
     id = IconTypeIsDark(icon_type) ?
-        IDR_AURA_UBER_TRAY_NETWORK_3G_DARK :
-        IDR_AURA_UBER_TRAY_NETWORK_3G_LIGHT;
+        IDR_AURA_UBER_TRAY_NETWORK_EVDO_DARK :
+        IDR_AURA_UBER_TRAY_NETWORK_EVDO_LIGHT;
   } else if (technology == flimflam::kNetworkTechnology1Xrtt) {
     id = IDR_AURA_UBER_TRAY_NETWORK_1X;
   } else if (technology == flimflam::kNetworkTechnologyGprs) {
@@ -783,7 +783,6 @@
   // network.
   if (connecting_network &&
       (!connected_network ||
-       state_handler->connecting_network() == connecting_network->path() ||
        connect_handler->HasConnectingNetwork(connecting_network->path()))) {
     network = connecting_network;
   } else {
diff --git a/ash/system/chromeos/network/network_state_list_detailed_view.cc b/ash/system/chromeos/network/network_state_list_detailed_view.cc
index abc888a..64e6d3b 100644
--- a/ash/system/chromeos/network/network_state_list_detailed_view.cc
+++ b/ash/system/chromeos/network/network_state_list_detailed_view.cc
@@ -315,12 +315,8 @@
   if (!network || network->IsConnectedState() || network->IsConnectingState()) {
     Shell::GetInstance()->system_tray_delegate()->ShowNetworkSettings(
         service_path);
-  } else if (CommandLine::ForCurrentProcess()->HasSwitch(
-      chromeos::switches::kUseNewNetworkConnectionHandler)) {
-    ash::network_connect::ConnectToNetwork(service_path);
   } else {
-    Shell::GetInstance()->system_tray_delegate()->ConnectToNetwork(
-        service_path);
+    ash::network_connect::ConnectToNetwork(service_path, NULL);
   }
 }
 
diff --git a/ash/system/chromeos/network/network_state_notifier.cc b/ash/system/chromeos/network/network_state_notifier.cc
index a903505..1c971a3 100644
--- a/ash/system/chromeos/network/network_state_notifier.cc
+++ b/ash/system/chromeos/network/network_state_notifier.cc
@@ -32,6 +32,12 @@
 string16 GetConnectErrorString(const std::string& error_name) {
   if (error_name == NetworkConnectionHandler::kErrorNotFound)
     return l10n_util::GetStringUTF16(IDS_CHROMEOS_NETWORK_ERROR_CONNECT_FAILED);
+  if (error_name == NetworkConnectionHandler::kErrorConfigureFailed)
+    return l10n_util::GetStringUTF16(
+        IDS_CHROMEOS_NETWORK_ERROR_CONFIGURE_FAILED);
+  if (error_name == NetworkConnectionHandler::kErrorActivateFailed)
+    return l10n_util::GetStringUTF16(
+        IDS_CHROMEOS_NETWORK_ERROR_ACTIVATION_FAILED);
   return string16();
 }
 
@@ -41,17 +47,31 @@
 
 NetworkStateNotifier::NetworkStateNotifier()
     : cellular_out_of_credits_(false) {
-  if (NetworkHandler::IsInitialized()) {
-    NetworkHandler::Get()->network_state_handler()->AddObserver(
-        this, FROM_HERE);
-    InitializeNetworks();
-  }
+  if (!NetworkHandler::IsInitialized())
+    return;
+  NetworkHandler::Get()->network_state_handler()->AddObserver(this, FROM_HERE);
+
+  // Initialize |last_active_network_|.
+  const NetworkState* default_network =
+      NetworkHandler::Get()->network_state_handler()->DefaultNetwork();
+  if (default_network && default_network->IsConnectedState())
+    last_active_network_ = default_network->path();
 }
 
 NetworkStateNotifier::~NetworkStateNotifier() {
-  if (NetworkHandler::IsInitialized()) {
-    NetworkHandler::Get()->network_state_handler()->RemoveObserver(
-        this, FROM_HERE);
+  if (!NetworkHandler::IsInitialized())
+    return;
+  NetworkHandler::Get()->network_state_handler()->RemoveObserver(
+      this, FROM_HERE);
+}
+
+void NetworkStateNotifier::NetworkListChanged() {
+  // Trigger any pending connect failed error if the network list changes
+  // (which indicates all NetworkState entries are up to date). This is in
+  // case a connect attempt fails because a network is no longer visible.
+  if (!connect_failed_network_.empty()) {
+    ShowNetworkConnectError(
+        NetworkConnectionHandler::kErrorConnectFailed, connect_failed_network_);
   }
 }
 
@@ -65,40 +85,15 @@
   }
 }
 
-void NetworkStateNotifier::NetworkConnectionStateChanged(
-    const NetworkState* network) {
-  NetworkStateHandler* handler = NetworkHandler::Get()->network_state_handler();
-  std::string prev_state;
-  std::string new_state = network->connection_state();
-  CachedStateMap::iterator iter = cached_state_.find(network->path());
-  if (iter != cached_state_.end()) {
-    prev_state = iter->second;
-    if (prev_state == new_state)
-      return;  // No state change
-    VLOG(1) << "NetworkStateNotifier: State: " << prev_state
-            << " ->: " << new_state;
-    iter->second = new_state;
-  } else {
-    VLOG(1) << "NetworkStateNotifier: New Service: " << network->path()
-            << " State: " << new_state;
-    cached_state_[network->path()] = new_state;
-    return;  // New network, no state change
-  }
-
-  if (new_state != flimflam::kStateFailure)
-    return;
-
-  if (network->path() != handler->connecting_network())
-    return;  // Only show notifications for explicitly connected networks
-
-  NET_LOG_EVENT("ConnectionFailure", network->path());
-
-  ShowConnectError("", network);
-}
-
 void NetworkStateNotifier::NetworkPropertiesUpdated(
     const NetworkState* network) {
   DCHECK(network);
+  // Trigger a pending connect failed error for |network| when the Error
+  // property has been set.
+  if (network->path() == connect_failed_network_ && !network->error().empty()) {
+    ShowNetworkConnectError(
+        NetworkConnectionHandler::kErrorConnectFailed, connect_failed_network_);
+  }
   // Trigger "Out of credits" notification if the cellular network is the most
   // recent default network (i.e. we have not switched to another network).
   if (network->type() == flimflam::kTypeCellular &&
@@ -146,17 +141,24 @@
     const std::string& service_path) {
   const NetworkState* network = NetworkHandler::Get()->network_state_handler()->
       GetNetworkState(service_path);
-  ShowConnectError(error_name, network);
-}
+  if (error_name == NetworkConnectionHandler::kErrorConnectFailed &&
+      service_path != connect_failed_network_) {
+    // Shill may not have set the Error property yet. First request an update
+    // and wait for either the update to complete or the network list to be
+    // updated before displaying the error.
+    connect_failed_network_ = service_path;
+    return;
+  }
+  connect_failed_network_.clear();
 
-void NetworkStateNotifier::ShowConnectError(const std::string& error_name,
-                                            const NetworkState* network) {
-  std::vector<string16> no_links;
   string16 error = GetConnectErrorString(error_name);
   if (error.empty() && network)
     error = network_connect::ErrorString(network->error());
   if (error.empty())
     error = l10n_util::GetStringUTF16(IDS_CHROMEOS_NETWORK_ERROR_UNKNOWN);
+  NET_LOG_ERROR("Connect error notification: " + UTF16ToUTF8(error),
+                service_path);
+
   std::string name = network ? network->name() : "";
   string16 error_msg;
   if (network && !network->error_details().empty()) {
@@ -168,6 +170,8 @@
         IDS_NETWORK_CONNECTION_ERROR_MESSAGE_WITH_DETAILS,
         UTF8ToUTF16(name), error);
   }
+
+  std::vector<string16> no_links;
   ash::Shell::GetInstance()->system_tray_notifier()->NotifySetNetworkMessage(
       this,
       NetworkObserver::ERROR_CONNECT_FAILED,
@@ -177,21 +181,4 @@
       no_links);
 }
 
-void NetworkStateNotifier::InitializeNetworks() {
-  NetworkStateHandler::NetworkStateList network_list;
-  NetworkHandler::Get()->network_state_handler()->GetNetworkList(&network_list);
-  VLOG(1) << "NetworkStateNotifier:InitializeNetworks: "
-          << network_list.size();
-  for (NetworkStateHandler::NetworkStateList::iterator iter =
-           network_list.begin(); iter != network_list.end(); ++iter) {
-    const NetworkState* network = *iter;
-    VLOG(2) << " Network: " << network->path();
-    cached_state_[network->path()] = network->connection_state();
-  }
-  const NetworkState* default_network =
-      NetworkHandler::Get()->network_state_handler()->DefaultNetwork();
-  if (default_network && default_network->IsConnectedState())
-    last_active_network_ = default_network->path();
-}
-
 }  // namespace ash
diff --git a/ash/system/chromeos/network/network_state_notifier.h b/ash/system/chromeos/network/network_state_notifier.h
index cfcc4b7..30a41b3 100644
--- a/ash/system/chromeos/network/network_state_notifier.h
+++ b/ash/system/chromeos/network/network_state_notifier.h
@@ -20,12 +20,19 @@
 
 namespace ash {
 
-// This class observes NetworkStateHandler and generates notifications
-// on connection failures. NOTE: The Observer for this class only triggers
-// "Out of credits" notifications, and failures triggered from NetworkLibrary
-// calls (which sets NetworkStateHandler::connecting_network()).
-// Failures from NetworkStateListDetailedView::ConnectToNetwork are now
-// handled by the ConnectToNetwork callbacks.
+// This class has two purposes:
+// 1. ShowNetworkConnectError() gets called after any user initiated connect
+//    failure. This will handle displaying an error notification.
+//    NOTE: Because Shill sets the Error property of a Service *after*
+//    the Connect call fails, this class will delay the notification if
+//    necessary until the Error property is set so that the correct
+//    message can be displayed.
+//    TODO(stevenjb): convert this class to use the new MessageCenter
+//    notification system, generate a notification immediately, and update
+//    it when the Error property is set to guarantee that a notification is
+//    displayed for every failure.
+// 2. It observes NetworkState changes to generate notifications when a
+//    Cellular network is out of credits.
 class ASH_EXPORT NetworkStateNotifier :
       public chromeos::NetworkStateHandlerObserver,
       public NetworkTrayDelegate {
@@ -34,10 +41,9 @@
   virtual ~NetworkStateNotifier();
 
   // NetworkStateHandlerObserver
+  virtual void NetworkListChanged() OVERRIDE;
   virtual void DefaultNetworkChanged(
       const chromeos::NetworkState* network) OVERRIDE;
-  virtual void NetworkConnectionStateChanged(
-      const chromeos::NetworkState* network) OVERRIDE;
   virtual void NetworkPropertiesUpdated(
       const chromeos::NetworkState* network) OVERRIDE;
 
@@ -53,14 +59,9 @@
  private:
   typedef std::map<std::string, std::string> CachedStateMap;
 
-  void ShowConnectError(const std::string& error_name,
-                        const chromeos::NetworkState* network);
-
-  void InitializeNetworks();
-
-  CachedStateMap cached_state_;
   std::string last_active_network_;
   std::string cellular_network_;
+  std::string connect_failed_network_;
   bool cellular_out_of_credits_;
   base::Time out_of_credits_notify_time_;
 
diff --git a/ash/system/chromeos/network/network_state_notifier_unittest.cc b/ash/system/chromeos/network/network_state_notifier_unittest.cc
index 2f681bc..6e2069d 100644
--- a/ash/system/chromeos/network/network_state_notifier_unittest.cc
+++ b/ash/system/chromeos/network/network_state_notifier_unittest.cc
@@ -7,13 +7,14 @@
 #include "ash/root_window_controller.h"
 #include "ash/shelf/shelf_widget.h"
 #include "ash/shell.h"
+#include "ash/system/chromeos/network/network_connect.h"
 #include "ash/system/status_area_widget.h"
 #include "ash/system/tray/system_tray.h"
 #include "ash/test/ash_test_base.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/shill_device_client.h"
 #include "chromeos/dbus/shill_service_client.h"
-#include "chromeos/network/network_state_handler.h"
+#include "chromeos/network/network_connection_handler.h"
 #include "third_party/cros_system_api/dbus/service_constants.h"
 
 namespace {
@@ -27,7 +28,7 @@
 
 using chromeos::DBusThreadManager;
 using chromeos::NetworkHandler;
-using chromeos::NetworkStateHandler;
+using chromeos::NetworkConnectionHandler;
 using chromeos::ShillDeviceClient;
 using chromeos::ShillServiceClient;
 
@@ -71,17 +72,17 @@
     const bool add_to_visible = true;
     // Create wifi and cellular networks and set to online.
     service_test->AddService("wifi1", "wifi1",
-                             flimflam::kTypeWifi, flimflam::kStateOnline,
+                             flimflam::kTypeWifi, flimflam::kStateIdle,
                              add_to_visible, add_to_watchlist);
-    RunAllPendingInMessageLoop();
-  }
-
-  void SetServiceState(const std::string& service_path,
-                       const std::string& state) {
-    ShillServiceClient::TestInterface* service_test =
-        DBusThreadManager::Get()->GetShillServiceClient()->GetTestInterface();
-    service_test->SetServiceProperty(service_path, flimflam::kStateProperty,
-                                     base::StringValue(state));
+    service_test->SetServiceProperty("wifi1",
+                                     flimflam::kSecurityProperty,
+                                     base::StringValue(flimflam::kSecurityWep));
+    service_test->SetServiceProperty("wifi1",
+                                     flimflam::kConnectableProperty,
+                                     base::FundamentalValue(true));
+    service_test->SetServiceProperty("wifi1",
+                                     flimflam::kPassphraseProperty,
+                                     base::StringValue("failure"));
     RunAllPendingInMessageLoop();
   }
 
@@ -91,20 +92,10 @@
 
 TEST_F(NetworkStateNotifierTest, ConnectionFailure) {
   EXPECT_FALSE(GetSystemTray()->HasNotificationBubble());
-  // State -> Failure for non connecting network should not spawn a notification
-  SetServiceState("wifi1", flimflam::kStateFailure);
-  EXPECT_FALSE(GetSystemTray()->CloseNotificationBubbleForTest());
-  // State -> Failure for connecting network should spawn a notification
-  SetServiceState("wifi1", flimflam::kStateAssociation);
-  NetworkHandler::Get()->network_state_handler()->SetConnectingNetwork("wifi1");
-  SetServiceState("wifi1", flimflam::kStateFailure);
+  ash::network_connect::ConnectToNetwork("wifi1", NULL /* owning_window */);
+  RunAllPendingInMessageLoop();
+  // Failure should spawn a notification.
   EXPECT_TRUE(GetSystemTray()->CloseNotificationBubbleForTest());
-  // Failure -> Idle should not spawn a notification
-  SetServiceState("wifi1", flimflam::kStateIdle);
-  EXPECT_FALSE(GetSystemTray()->HasNotificationBubble());
-  // Idle  -> Failure should also not spawn a notification
-  SetServiceState("wifi1", flimflam::kStateFailure);
-  EXPECT_FALSE(GetSystemTray()->HasNotificationBubble());
 }
 
 }  // namespace test
diff --git a/ash/system/chromeos/tray_display.cc b/ash/system/chromeos/tray_display.cc
index 4f4e8c1..ebafa37 100644
--- a/ash/system/chromeos/tray_display.cc
+++ b/ash/system/chromeos/tray_display.cc
@@ -195,7 +195,7 @@
       message_center::NOTIFICATION_TYPE_SIMPLE,
       kDisplayNotificationId,
       message,
-      GetAllDisplayInfo(),
+      base::string16(),  // body is intentionally empty, see crbug.com/265915
       bundle.GetImageNamed(IDR_AURA_UBER_TRAY_DISPLAY),
       base::string16(),  // display_source
       "",  // extension_id
@@ -367,8 +367,25 @@
       return true;
     }
     if (iter->second.rotation() != old_iter->second.rotation()) {
+      int rotation_text_id = 0;
+      switch (iter->second.rotation()) {
+        case gfx::Display::ROTATE_0:
+          rotation_text_id = IDS_ASH_STATUS_TRAY_DISPLAY_STANDARD_ORIENTATION;
+          break;
+        case gfx::Display::ROTATE_90:
+          rotation_text_id = IDS_ASH_STATUS_TRAY_DISPLAY_ORIENTATION_90;
+          break;
+        case gfx::Display::ROTATE_180:
+          rotation_text_id = IDS_ASH_STATUS_TRAY_DISPLAY_ORIENTATION_180;
+          break;
+        case gfx::Display::ROTATE_270:
+          rotation_text_id = IDS_ASH_STATUS_TRAY_DISPLAY_ORIENTATION_270;
+          break;
+      }
       *message = l10n_util::GetStringFUTF16(
-          IDS_ASH_STATUS_TRAY_DISPLAY_ROTATED, GetDisplayName(iter->first));
+          IDS_ASH_STATUS_TRAY_DISPLAY_ROTATED,
+          GetDisplayName(iter->first),
+          l10n_util::GetStringUTF16(rotation_text_id));
       return true;
     }
   }
diff --git a/ash/system/chromeos/tray_display_unittest.cc b/ash/system/chromeos/tray_display_unittest.cc
index 8fa2949..1c5970d 100644
--- a/ash/system/chromeos/tray_display_unittest.cc
+++ b/ash/system/chromeos/tray_display_unittest.cc
@@ -326,13 +326,21 @@
 
   // rotation.
   UpdateDisplay("400x400/r");
-  base::string16 rotation_message = l10n_util::GetStringFUTF16(
-      IDS_ASH_STATUS_TRAY_DISPLAY_ROTATED, GetFirstDisplayName());
-  EXPECT_EQ(rotation_message, GetDisplayNotificationText());
+  EXPECT_EQ(
+      l10n_util::GetStringFUTF16(
+          IDS_ASH_STATUS_TRAY_DISPLAY_ROTATED, GetFirstDisplayName(),
+          l10n_util::GetStringUTF16(
+              IDS_ASH_STATUS_TRAY_DISPLAY_ORIENTATION_90)),
+      GetDisplayNotificationText());
 
   CloseNotification();
   UpdateDisplay("400x400");
-  EXPECT_EQ(rotation_message, GetDisplayNotificationText());
+  EXPECT_EQ(
+      l10n_util::GetStringFUTF16(
+          IDS_ASH_STATUS_TRAY_DISPLAY_ROTATED, GetFirstDisplayName(),
+          l10n_util::GetStringUTF16(
+              IDS_ASH_STATUS_TRAY_DISPLAY_STANDARD_ORIENTATION)),
+      GetDisplayNotificationText());
 
   // UI-scale
   CloseNotification();
@@ -395,7 +403,10 @@
   UpdateDisplay("400x400@1.5,200x200/r");
   EXPECT_EQ(
       l10n_util::GetStringFUTF16(
-          IDS_ASH_STATUS_TRAY_DISPLAY_ROTATED, GetSecondDisplayName()),
+          IDS_ASH_STATUS_TRAY_DISPLAY_ROTATED,
+          GetSecondDisplayName(),
+          l10n_util::GetStringUTF16(
+              IDS_ASH_STATUS_TRAY_DISPLAY_ORIENTATION_90)),
       GetDisplayNotificationText());
 }
 
diff --git a/ash/system/chromeos/tray_tracing.cc b/ash/system/chromeos/tray_tracing.cc
new file mode 100644
index 0000000..b6a8cf1
--- /dev/null
+++ b/ash/system/chromeos/tray_tracing.cc
@@ -0,0 +1,112 @@
+// 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 "ash/system/chromeos/tray_tracing.h"
+
+#include "ash/system/tray/actionable_view.h"
+#include "ash/system/tray/fixed_sized_image_view.h"
+#include "ash/system/tray/system_tray.h"
+#include "ash/system/tray/system_tray_delegate.h"
+#include "ash/system/tray/system_tray_notifier.h"
+#include "ash/system/tray/tray_constants.h"
+#include "grit/ash_resources.h"
+#include "grit/ash_strings.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/gfx/image/image.h"
+#include "ui/views/controls/image_view.h"
+#include "ui/views/controls/label.h"
+#include "ui/views/layout/box_layout.h"
+
+namespace ash {
+namespace internal {
+
+namespace tray {
+
+class DefaultTracingView : public ash::internal::ActionableView {
+ public:
+  DefaultTracingView() {
+    SetLayoutManager(new views::BoxLayout(
+        views::BoxLayout::kHorizontal,
+        ash::kTrayPopupPaddingHorizontal, 0,
+        ash::kTrayPopupPaddingBetweenItems));
+
+    ui::ResourceBundle& bundle = ui::ResourceBundle::GetSharedInstance();
+    image_ =
+        new ash::internal::FixedSizedImageView(0, ash::kTrayPopupItemHeight);
+    image_->SetImage(
+        bundle.GetImageNamed(IDR_AURA_UBER_TRAY_TRACING).ToImageSkia());
+    AddChildView(image_);
+
+    label_ = new views::Label();
+    label_->SetMultiLine(true);
+    label_->SetHorizontalAlignment(gfx::ALIGN_LEFT);
+    label_->SetText(bundle.GetLocalizedString(IDS_ASH_STATUS_TRAY_TRACING));
+    AddChildView(label_);
+  }
+
+  virtual ~DefaultTracingView() {}
+
+ private:
+  // Overridden from ActionableView.
+  virtual bool PerformAction(const ui::Event& event) OVERRIDE {
+    ash::Shell::GetInstance()->system_tray_delegate()->ShowChromeSlow();
+    return true;
+  }
+
+  views::ImageView* image_;
+  views::Label* label_;
+
+  DISALLOW_COPY_AND_ASSIGN(DefaultTracingView);
+};
+
+}  // namespace tray
+
+////////////////////////////////////////////////////////////////////////////////
+// ash::internal::TrayTracing
+
+TrayTracing::TrayTracing(SystemTray* system_tray)
+    : TrayImageItem(system_tray, IDR_AURA_UBER_TRAY_TRACING),
+      default_(NULL) {
+  DCHECK(Shell::GetInstance()->delegate());
+  DCHECK(system_tray);
+  Shell::GetInstance()->system_tray_notifier()->AddTracingObserver(this);
+}
+
+TrayTracing::~TrayTracing() {
+  Shell::GetInstance()->system_tray_notifier()->RemoveTracingObserver(this);
+}
+
+void TrayTracing::SetTrayIconVisible(bool visible) {
+  if (tray_view())
+    tray_view()->SetVisible(visible);
+}
+
+bool TrayTracing::GetInitialVisibility() {
+  return false;
+}
+
+views::View* TrayTracing::CreateDefaultView(user::LoginStatus status) {
+  CHECK(default_ == NULL);
+  default_ = new tray::DefaultTracingView();
+  return default_;
+}
+
+views::View* TrayTracing::CreateDetailedView(user::LoginStatus status) {
+  return NULL;
+}
+
+void TrayTracing::DestroyDefaultView() {
+  default_ = NULL;
+}
+
+void TrayTracing::DestroyDetailedView() {
+}
+
+void TrayTracing::OnTracingModeChanged(bool value) {
+  SetTrayIconVisible(value);
+}
+
+}  // namespace internal
+}  // namespace ash
diff --git a/ash/system/chromeos/tray_tracing.h b/ash/system/chromeos/tray_tracing.h
new file mode 100644
index 0000000..f9491e1
--- /dev/null
+++ b/ash/system/chromeos/tray_tracing.h
@@ -0,0 +1,57 @@
+// 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 ASH_SYSTEM_TRAY_TRACING_H_
+#define ASH_SYSTEM_TRAY_TRACING_H_
+
+#include "ash/ash_export.h"
+#include "ash/system/tray/tray_image_item.h"
+
+namespace views {
+class View;
+}
+
+namespace ash {
+
+class ASH_EXPORT TracingObserver {
+ public:
+  virtual ~TracingObserver() {}
+
+  // Notifies when tracing mode changes.
+  virtual void OnTracingModeChanged(bool value) = 0;
+};
+
+namespace internal {
+
+// This is the item that displays when users enable performance tracing at
+// chrome://slow.  It alerts them that this mode is running, and provides an
+// easy way to open the page to disable it.
+class TrayTracing : public TrayImageItem,
+                    public TracingObserver {
+ public:
+  explicit TrayTracing(SystemTray* system_tray);
+  virtual ~TrayTracing();
+
+ private:
+  void SetTrayIconVisible(bool visible);
+
+  // Overridden from TrayImageItem.
+  virtual bool GetInitialVisibility() OVERRIDE;
+  virtual views::View* CreateDefaultView(user::LoginStatus status) OVERRIDE;
+  virtual views::View* CreateDetailedView(user::LoginStatus status) OVERRIDE;
+  virtual void DestroyDefaultView() OVERRIDE;
+  virtual void DestroyDetailedView() OVERRIDE;
+
+  // Overridden from TracingObserver.
+  virtual void OnTracingModeChanged(bool value) OVERRIDE;
+
+  views::View* default_;
+
+  DISALLOW_COPY_AND_ASSIGN(TrayTracing);
+};
+
+}  // namespace internal
+}  // namespace ash
+
+#endif  // ASH_SYSTEM_TRAY_TRACING_H_
diff --git a/ash/system/locale/locale_notification_controller.cc b/ash/system/locale/locale_notification_controller.cc
index bc515e9..342c5a6 100644
--- a/ash/system/locale/locale_notification_controller.cc
+++ b/ash/system/locale/locale_notification_controller.cc
@@ -63,10 +63,11 @@
 }
 
 bool LocaleNotificationDelegate::HasClickedListener() {
-  return false;
+  return true;
 }
 
 void LocaleNotificationDelegate::Click() {
+  delegate_->AcceptLocaleChange();
 }
 
 void LocaleNotificationDelegate::ButtonClick(int button_index) {
diff --git a/ash/system/status_area_widget_delegate.cc b/ash/system/status_area_widget_delegate.cc
index 77d3cbf..7e15b7e 100644
--- a/ash/system/status_area_widget_delegate.cc
+++ b/ash/system/status_area_widget_delegate.cc
@@ -5,6 +5,7 @@
 #include "ash/system/status_area_widget_delegate.h"
 
 #include "ash/ash_export.h"
+#include "ash/ash_switches.h"
 #include "ash/focus_cycler.h"
 #include "ash/shell.h"
 #include "ash/shell_window_ids.h"
@@ -98,7 +99,7 @@
       if (!child->visible())
         continue;
       if (!is_first_visible_child)
-        columns->AddPaddingColumn(0, kTraySpacing);
+        columns->AddPaddingColumn(0, GetTraySpacing());
       is_first_visible_child = false;
       columns->AddColumn(views::GridLayout::CENTER, views::GridLayout::FILL,
                          0, /* resize percent */
@@ -124,7 +125,7 @@
       if (!child->visible())
         continue;
       if (!is_first_visible_child)
-        layout->AddPaddingRow(0, kTraySpacing);
+        layout->AddPaddingRow(0, GetTraySpacing());
       is_first_visible_child = false;
       layout->StartRow(0, 0);
       layout->AddView(child);
diff --git a/ash/system/tray/system_tray.cc b/ash/system/tray/system_tray.cc
index c93efc9..122253f 100644
--- a/ash/system/tray/system_tray.cc
+++ b/ash/system/tray/system_tray.cc
@@ -11,6 +11,7 @@
 #include "ash/shell_window_ids.h"
 #include "ash/system/bluetooth/tray_bluetooth.h"
 #include "ash/system/brightness/tray_brightness.h"
+#include "ash/system/chromeos/tray_tracing.h"
 #include "ash/system/date/tray_date.h"
 #include "ash/system/drive/tray_drive.h"
 #include "ash/system/ime/tray_ime.h"
@@ -167,6 +168,7 @@
   tray_accessibility_ = new internal::TrayAccessibility(this);
   AddTrayItem(tray_accessibility_);
 #if defined(OS_CHROMEOS)
+  AddTrayItem(new internal::TrayTracing(this));
   AddTrayItem(
       new internal::TrayPower(this, message_center::MessageCenter::Get()));
 #endif
diff --git a/ash/system/tray/system_tray_delegate.h b/ash/system/tray/system_tray_delegate.h
index 45b0c71..0dcc07d 100644
--- a/ash/system/tray/system_tray_delegate.h
+++ b/ash/system/tray/system_tray_delegate.h
@@ -15,6 +15,7 @@
 #include "base/memory/scoped_ptr.h"
 #include "base/strings/string16.h"
 #include "ui/gfx/image/image_skia.h"
+#include "ui/gfx/native_widget_types.h"
 
 namespace base {
 class TimeDelta;
@@ -136,10 +137,11 @@
   // Returns notification for enterprise enrolled devices.
   virtual const base::string16 GetEnterpriseMessage() const = 0;
 
-  // Returns the email of user that manages current locally managed user.
+  // Returns the display email of user that manages current
+  // locally managed user.
   virtual const std::string GetLocallyManagedUserManager() const = 0;
 
-  // Returns the email of user that manages current locally managed user.
+  // Returns the name of user that manages current locally managed user.
   virtual const base::string16 GetLocallyManagedUserManagerName() const = 0;
 
   // Returns notification for locally managed users.
@@ -167,6 +169,9 @@
   // Shows settings related to multiple displays.
   virtual void ShowDisplaySettings() = 0;
 
+  // Shows the page that lets you disable performance tracing.
+  virtual void ShowChromeSlow() = 0;
+
   // Returns true if the notification for the display configuration change
   // should appear.
   virtual bool ShouldShowDisplayNotification() = 0;
@@ -250,8 +255,11 @@
   // Shows UI to configure or activate the network specified by |network_id|.
   virtual void ConfigureNetwork(const std::string& network_id) = 0;
 
-  // Sends a connect request for the network specified by |network_id|.
-  virtual void ConnectToNetwork(const std::string& network_id) = 0;
+  // Shows UI to enroll the network specified by |network_id| if appropriate,
+  // otherwise behaves the same as ConfigureNetwork. |parent_window| is used
+  // to parent any configuration UI. If NULL a default window will be used.
+  virtual void EnrollOrConfigureNetwork(const std::string& network_id,
+                                        gfx::NativeWindow parent_window) = 0;
 
   // Shows UI to manage bluetooth devices.
   virtual void ManageBluetoothDevices() = 0;
@@ -262,6 +270,9 @@
   // Shows UI to unlock a mobile sim.
   virtual void ShowMobileSimDialog() = 0;
 
+  // Shows UI to setup a mobile network.
+  virtual void ShowMobileSetup(const std::string& network_id) = 0;
+
   // Shows UI to connect to an unlisted wifi network.
   virtual void ShowOtherWifi() = 0;
 
diff --git a/ash/system/tray/system_tray_notifier.cc b/ash/system/tray/system_tray_notifier.cc
index f726a8f..73f6195 100644
--- a/ash/system/tray/system_tray_notifier.cc
+++ b/ash/system/tray/system_tray_notifier.cc
@@ -106,6 +106,14 @@
   session_length_limit_observers_.RemoveObserver(observer);
 }
 
+void SystemTrayNotifier::AddTracingObserver(TracingObserver* observer) {
+  tracing_observers_.AddObserver(observer);
+}
+
+void SystemTrayNotifier::RemoveTracingObserver(TracingObserver* observer) {
+  tracing_observers_.RemoveObserver(observer);
+}
+
 void SystemTrayNotifier::AddUpdateObserver(UpdateObserver* observer) {
   update_observers_.AddObserver(observer);
 }
@@ -179,6 +187,13 @@
       OnAccessibilityModeChanged(notify));
 }
 
+void SystemTrayNotifier::NotifyTracingModeChanged(bool value) {
+  FOR_EACH_OBSERVER(
+      TracingObserver,
+      tracing_observers_,
+      OnTracingModeChanged(value));
+}
+
 void SystemTrayNotifier::NotifyRefreshBluetooth() {
   FOR_EACH_OBSERVER(BluetoothObserver,
                     bluetooth_observers_,
diff --git a/ash/system/tray/system_tray_notifier.h b/ash/system/tray/system_tray_notifier.h
index 5546be0..86210b4 100644
--- a/ash/system/tray/system_tray_notifier.h
+++ b/ash/system/tray/system_tray_notifier.h
@@ -14,6 +14,7 @@
 #include "ash/system/chromeos/enterprise/enterprise_domain_observer.h"
 #include "ash/system/chromeos/network/network_observer.h"
 #include "ash/system/chromeos/network/sms_observer.h"
+#include "ash/system/chromeos/tray_tracing.h"
 #include "ash/system/date/clock_observer.h"
 #include "ash/system/drive/drive_observer.h"
 #include "ash/system/ime/ime_observer.h"
@@ -74,6 +75,9 @@
   void AddSessionLengthLimitObserver(SessionLengthLimitObserver* observer);
   void RemoveSessionLengthLimitObserver(SessionLengthLimitObserver* observer);
 
+  void AddTracingObserver(TracingObserver* observer);
+  void RemoveTracingObserver(TracingObserver* observer);
+
   void AddUpdateObserver(UpdateObserver* observer);
   void RemoveUpdateObserver(UpdateObserver* observer);
 
@@ -99,6 +103,7 @@
 
   void NotifyAccessibilityModeChanged(
       AccessibilityNotificationVisibility notify);
+  void NotifyTracingModeChanged(bool value);
   void NotifyRefreshBluetooth();
   void NotifyBluetoothDiscoveringChanged();
   void NotifyBrightnessChanged(double level, bool user_initialted);
@@ -151,6 +156,7 @@
   ObserverList<LocaleObserver> locale_observers_;
   ObserverList<LogoutButtonObserver> logout_button_observers_;
   ObserverList<SessionLengthLimitObserver> session_length_limit_observers_;
+  ObserverList<TracingObserver> tracing_observers_;
   ObserverList<UpdateObserver> update_observers_;
   ObserverList<UserObserver> user_observers_;
 #if defined(OS_CHROMEOS)
diff --git a/ash/system/tray/test_system_tray_delegate.cc b/ash/system/tray/test_system_tray_delegate.cc
index 33d912a..c3a2bfc 100644
--- a/ash/system/tray/test_system_tray_delegate.cc
+++ b/ash/system/tray/test_system_tray_delegate.cc
@@ -127,6 +127,9 @@
 void TestSystemTrayDelegate::ShowDisplaySettings() {
 }
 
+void TestSystemTrayDelegate::ShowChromeSlow() {
+}
+
 bool TestSystemTrayDelegate::ShouldShowDisplayNotification() {
   return should_show_display_notification_;
 }
@@ -212,7 +215,9 @@
 void TestSystemTrayDelegate::ConfigureNetwork(const std::string& network_id) {
 }
 
-void TestSystemTrayDelegate::ConnectToNetwork(const std::string& network_id) {
+void TestSystemTrayDelegate::EnrollOrConfigureNetwork(
+    const std::string& network_id,
+    gfx::NativeWindow parent_window) {
 }
 
 void TestSystemTrayDelegate::ManageBluetoothDevices() {
@@ -229,6 +234,9 @@
 void TestSystemTrayDelegate::ShowMobileSimDialog() {
 }
 
+void TestSystemTrayDelegate::ShowMobileSetup(const std::string& network_id) {
+}
+
 void TestSystemTrayDelegate::ShowOtherWifi() {
 }
 
diff --git a/ash/system/tray/test_system_tray_delegate.h b/ash/system/tray/test_system_tray_delegate.h
index 26a3dc7..4dc847d 100644
--- a/ash/system/tray/test_system_tray_delegate.h
+++ b/ash/system/tray/test_system_tray_delegate.h
@@ -42,6 +42,7 @@
   virtual void ShowNetworkSettings(const std::string& service_path) OVERRIDE;
   virtual void ShowBluetoothSettings() OVERRIDE;
   virtual void ShowDisplaySettings() OVERRIDE;
+  virtual void ShowChromeSlow() OVERRIDE;
   virtual bool ShouldShowDisplayNotification() OVERRIDE;
   virtual void ShowDriveSettings() OVERRIDE;
   virtual void ShowIMESettings() OVERRIDE;
@@ -69,11 +70,14 @@
   virtual void GetDriveOperationStatusList(
       ash::DriveOperationStatusList*) OVERRIDE;
   virtual void ConfigureNetwork(const std::string& network_id) OVERRIDE;
-  virtual void ConnectToNetwork(const std::string& network_id) OVERRIDE;
+  virtual void EnrollOrConfigureNetwork(
+      const std::string& network_id,
+      gfx::NativeWindow parent_window) OVERRIDE;
   virtual void ManageBluetoothDevices() OVERRIDE;
   virtual void ToggleBluetooth() OVERRIDE;
   virtual bool IsBluetoothDiscovering() OVERRIDE;
   virtual void ShowMobileSimDialog() OVERRIDE;
+  virtual void ShowMobileSetup(const std::string& network_id) OVERRIDE;
   virtual void ShowOtherWifi() OVERRIDE;
   virtual void ShowOtherVPN() OVERRIDE;
   virtual void ShowOtherCellular() OVERRIDE;
diff --git a/ash/system/tray/tray_background_view.cc b/ash/system/tray/tray_background_view.cc
index 2d788d6..9f84322 100644
--- a/ash/system/tray/tray_background_view.cc
+++ b/ash/system/tray/tray_background_view.cc
@@ -288,8 +288,8 @@
     set_border(views::Border::CreateEmptyBorder(
         vertical_padding,
         horizontal_padding,
-        horizontal_padding,
-        vertical_padding));
+        vertical_padding,
+        horizontal_padding));
 
     views::BoxLayout* layout =
         new views::BoxLayout(views::BoxLayout::kHorizontal, 0, 0, 0);
@@ -530,11 +530,15 @@
       }
     } else if (anchor_type == TrayBubbleView::ANCHOR_TYPE_BUBBLE) {
       // Invert the offsets to align with the bubble below.
+      // Note that with the alternate shelf layout the tips are not shown and
+      // the offsets for left and right alignment do not need to be applied.
+      int vertical_alignment = ash::switches::UseAlternateShelfLayout() ?
+          0 : kPaddingFromInnerEdgeOfLauncherVerticalAlignment;
       if (anchor_alignment == TrayBubbleView::ANCHOR_ALIGNMENT_LEFT) {
-        rect.Inset(kPaddingFromInnerEdgeOfLauncherVerticalAlignment,
+        rect.Inset(vertical_alignment,
                    0, 0, kPaddingFromBottomOfScreenVerticalAlignment);
       } else if (anchor_alignment == TrayBubbleView::ANCHOR_ALIGNMENT_RIGHT) {
-        rect.Inset(0, 0, kPaddingFromInnerEdgeOfLauncherVerticalAlignment,
+        rect.Inset(0, 0, vertical_alignment,
                    kPaddingFromBottomOfScreenVerticalAlignment);
       }
     }
diff --git a/ash/system/tray/tray_constants.cc b/ash/system/tray/tray_constants.cc
index 45047e7..6d108c8 100644
--- a/ash/system/tray/tray_constants.cc
+++ b/ash/system/tray/tray_constants.cc
@@ -4,6 +4,7 @@
 
 #include "ash/system/tray/tray_constants.h"
 
+#include "ash/ash_switches.h"
 #include "third_party/skia/include/core/SkColor.h"
 
 namespace ash {
@@ -65,5 +66,13 @@
     (kNotificationIconWidth + kNotificationButtonWidth +
      (kTrayPopupPaddingHorizontal / 2) * 3);
 const int kTraySpacing = 8;
+const int kAlternateTraySpacing = 4;
+
+// Returns kTraySpacing or kAlternateTraySpacing as applicable
+// (Determined by ash::switches::UseAlternateShelfLayout).
+int GetTraySpacing() {
+  return ash::switches::UseAlternateShelfLayout() ?
+      kAlternateTraySpacing : kTraySpacing;
+}
 
 }  // namespace ash
diff --git a/ash/system/tray/tray_constants.h b/ash/system/tray/tray_constants.h
index 2b0f5ae..480d5d5 100644
--- a/ash/system/tray/tray_constants.h
+++ b/ash/system/tray/tray_constants.h
@@ -62,7 +62,9 @@
 extern const int kNotificationButtonWidth;
 extern const int kTrayNotificationContentsWidth;
 
-extern const int kTraySpacing;
+// Returns kTraySpacing or kAlternateTraySpacing as applicable
+// (Determined by ash::switches::UseAlternateShelfLayout).
+int GetTraySpacing();
 
 }  // namespace ash
 
diff --git a/ash/system/user/tray_user.cc b/ash/system/user/tray_user.cc
index e50aece..2ab24a8 100644
--- a/ash/system/user/tray_user.cc
+++ b/ash/system/user/tray_user.cc
@@ -1202,30 +1202,14 @@
         bundle.GetLocalizedString(IDS_ASH_STATUS_TRAY_LOCALLY_MANAGED_LABEL));
   }
 
-  int icon_size = kUserIconSize;
   if (avatar_ && ash::switches::UseAlternateShelfLayout()) {
-    icon_size = kUserIconLargeSize;
     avatar_->SetCornerRadii(0,
                             kUserIconLargeCornerRadius,
                             kUserIconLargeCornerRadius,
                             0);
     avatar_->set_border(NULL);
   }
-  if (avatar_) {
-    if (status == user::LOGGED_IN_GUEST) {
-      int image_name = ash::switches::UseAlternateShelfLayout() ?
-          IDR_AURA_UBER_TRAY_GUEST_ICON_LARGE :
-          IDR_AURA_UBER_TRAY_GUEST_ICON;
-      avatar_->SetImage(*ui::ResourceBundle::GetSharedInstance().
-          GetImageNamed(image_name).ToImageSkia(),
-          gfx::Size(icon_size, icon_size));
-    } else {
-      avatar_->SetImage(
-          ash::Shell::GetInstance()->session_state_delegate()->GetUserImage(
-              multiprofile_index_),
-          gfx::Size(icon_size, icon_size));
-    }
-  }
+  UpdateAvatarImage(status);
 }
 
 void TrayUser::UpdateAfterShelfAlignmentChange(ShelfAlignment alignment) {
@@ -1281,10 +1265,25 @@
 }
 
 void TrayUser::OnUserUpdate() {
-  // Check for null to avoid crbug.com/150944.
-  if (avatar_) {
-    int icon_size = ash::switches::UseAlternateShelfLayout() ?
-        kUserIconLargeSize : kUserIconSize;
+  UpdateAvatarImage(Shell::GetInstance()->system_tray_delegate()->
+      GetUserLoginStatus());
+}
+
+void TrayUser::UpdateAvatarImage(user::LoginStatus status) {
+  if (!avatar_)
+    return;
+
+  int icon_size = ash::switches::UseAlternateShelfLayout() ?
+      kUserIconLargeSize : kUserIconSize;
+
+  if (status == user::LOGGED_IN_GUEST) {
+    int image_name = ash::switches::UseAlternateShelfLayout() ?
+        IDR_AURA_UBER_TRAY_GUEST_ICON_LARGE :
+        IDR_AURA_UBER_TRAY_GUEST_ICON;
+    avatar_->SetImage(*ui::ResourceBundle::GetSharedInstance().
+        GetImageNamed(image_name).ToImageSkia(),
+        gfx::Size(icon_size, icon_size));
+  } else {
     avatar_->SetImage(
         ash::Shell::GetInstance()->session_state_delegate()->GetUserImage(
             multiprofile_index_),
diff --git a/ash/system/user/tray_user.h b/ash/system/user/tray_user.h
index fa10bf2..70b54bb 100644
--- a/ash/system/user/tray_user.h
+++ b/ash/system/user/tray_user.h
@@ -68,6 +68,8 @@
   // Overridden from UserObserver.
   virtual void OnUserUpdate() OVERRIDE;
 
+  void UpdateAvatarImage(user::LoginStatus status);
+
   // The user index to use.
   MultiProfileIndex multiprofile_index_;
 
diff --git a/ash/system/web_notification/web_notification_tray.cc b/ash/system/web_notification/web_notification_tray.cc
index 2b33e44..2a6e2de 100644
--- a/ash/system/web_notification/web_notification_tray.cc
+++ b/ash/system/web_notification/web_notification_tray.cc
@@ -330,7 +330,8 @@
       NOTREACHED();
   }
 
-  message_center_bubble->SetMaxHeight(std::max(0, max_height - kTraySpacing));
+  message_center_bubble->SetMaxHeight(std::max(0,
+                                               max_height - GetTraySpacing()));
   if (show_settings)
     message_center_bubble->SetSettingsVisible();
   message_center_bubble_.reset(
diff --git a/ash/test/launcher_view_test_api.cc b/ash/test/launcher_view_test_api.cc
index 13881b3..e357920 100644
--- a/ash/test/launcher_view_test_api.cc
+++ b/ash/test/launcher_view_test_api.cc
@@ -95,5 +95,10 @@
   launcher_view_->bounds_animator_->RemoveObserver(observer.get());
 }
 
+bool LauncherViewTestAPI::SameDragType(LauncherItemType typea,
+                                       LauncherItemType typeb) const {
+  return launcher_view_->SameDragType(typea, typeb);
+}
+
 }  // namespace test
 }  // namespace ash
diff --git a/ash/test/launcher_view_test_api.h b/ash/test/launcher_view_test_api.h
index 35cb444..0162f7f 100644
--- a/ash/test/launcher_view_test_api.h
+++ b/ash/test/launcher_view_test_api.h
@@ -5,6 +5,7 @@
 #ifndef ASH_TEST_LAUNCHER_VIEW_TEST_API_H_
 #define ASH_TEST_LAUNCHER_VIEW_TEST_API_H_
 
+#include "ash/launcher/launcher_types.h"
 #include "base/basictypes.h"
 
 namespace gfx {
@@ -54,6 +55,9 @@
   // An accessor for |launcher_view|.
   internal::LauncherView* launcher_view() { return launcher_view_; }
 
+  // Wrapper for LauncherView::SameDragType.
+  bool SameDragType(LauncherItemType typea, LauncherItemType typeb) const;
+
  private:
   internal::LauncherView* launcher_view_;
 
diff --git a/ash/wm/resize_shadow.h b/ash/wm/resize_shadow.h
index d9f2452..f61f393 100644
--- a/ash/wm/resize_shadow.h
+++ b/ash/wm/resize_shadow.h
@@ -47,6 +47,10 @@
   // Updates the effect positions based on the |bounds| of the window.
   void Layout(const gfx::Rect& bounds);
 
+  int GetLastHitTestForTest() const {
+    return last_hit_test_;
+  }
+
  private:
   // Images for the shadow effect.
   scoped_ptr<views::corewm::ImageGrid> image_grid_;
diff --git a/ash/wm/resize_shadow_controller.cc b/ash/wm/resize_shadow_controller.cc
index c875265..85778d3 100644
--- a/ash/wm/resize_shadow_controller.cc
+++ b/ash/wm/resize_shadow_controller.cc
@@ -35,6 +35,11 @@
     shadow->Hide();
 }
 
+ResizeShadow* ResizeShadowController::GetShadowForWindowForTest(
+    aura::Window* window) {
+  return GetShadowForWindow(window);
+}
+
 void ResizeShadowController::OnWindowBoundsChanged(
     aura::Window* window,
     const gfx::Rect& old_bounds,
diff --git a/ash/wm/resize_shadow_controller.h b/ash/wm/resize_shadow_controller.h
index d818a75..1eccf4c 100644
--- a/ash/wm/resize_shadow_controller.h
+++ b/ash/wm/resize_shadow_controller.h
@@ -7,6 +7,7 @@
 
 #include <map>
 
+#include "ash/ash_export.h"
 #include "base/basictypes.h"
 #include "base/compiler_specific.h"
 #include "base/memory/linked_ptr.h"
@@ -23,7 +24,7 @@
 
 // ResizeShadowController observes changes to resizable windows and shows
 // a resize handle visual effect when the cursor is near the edges.
-class ResizeShadowController : public aura::WindowObserver {
+class ASH_EXPORT ResizeShadowController : public aura::WindowObserver {
  public:
   ResizeShadowController();
   virtual ~ResizeShadowController();
@@ -34,6 +35,8 @@
   // Hides the shadow for a |window|, if it has one.
   void HideShadow(aura::Window* window);
 
+  ResizeShadow* GetShadowForWindowForTest(aura::Window* window);
+
   // aura::WindowObserver overrides:
   virtual void OnWindowBoundsChanged(
       aura::Window* window,
diff --git a/ash/wm/toplevel_window_event_handler.cc b/ash/wm/toplevel_window_event_handler.cc
index 71753c4..a0d4b5e 100644
--- a/ash/wm/toplevel_window_event_handler.cc
+++ b/ash/wm/toplevel_window_event_handler.cc
@@ -215,6 +215,25 @@
     return;
 
   switch (event->type()) {
+    case ui::ET_GESTURE_TAP_DOWN: {
+      int component =
+          target->delegate()->GetNonClientComponent(event->location());
+      if (!(WindowResizer::GetBoundsChangeForWindowComponent(component) &
+            WindowResizer::kBoundsChange_Resizes))
+        return;
+      internal::ResizeShadowController* controller =
+          Shell::GetInstance()->resize_shadow_controller();
+      if (controller)
+        controller->ShowShadow(target, component);
+      return;
+    }
+    case ui::ET_GESTURE_END: {
+      internal::ResizeShadowController* controller =
+          Shell::GetInstance()->resize_shadow_controller();
+      if (controller)
+        controller->HideShadow(target);
+      return;
+    }
     case ui::ET_GESTURE_SCROLL_BEGIN: {
       if (in_gesture_drag_)
         return;
@@ -481,7 +500,7 @@
     if (event->flags() & ui::EF_IS_NON_CLIENT) {
       int component =
           target->delegate()->GetNonClientComponent(event->location());
-        controller->ShowShadow(target, component);
+      controller->ShowShadow(target, component);
     } else {
       controller->HideShadow(target);
     }
diff --git a/ash/wm/toplevel_window_event_handler_unittest.cc b/ash/wm/toplevel_window_event_handler_unittest.cc
index 0076d3d..c84f8b3 100644
--- a/ash/wm/toplevel_window_event_handler_unittest.cc
+++ b/ash/wm/toplevel_window_event_handler_unittest.cc
@@ -4,12 +4,15 @@
 
 #include "ash/wm/toplevel_window_event_handler.h"
 
+#include "ash/ash_constants.h"
 #include "ash/root_window_controller.h"
 #include "ash/shell.h"
 #include "ash/shell_window_ids.h"
 #include "ash/test/ash_test_base.h"
 #include "ash/wm/lock_state_controller_impl2.h"
 #include "ash/wm/property_util.h"
+#include "ash/wm/resize_shadow.h"
+#include "ash/wm/resize_shadow_controller.h"
 #include "ash/wm/window_util.h"
 #include "ash/wm/workspace/snap_sizer.h"
 #include "ash/wm/workspace_controller.h"
@@ -42,30 +45,17 @@
 // requested and applies a minimum size constraint if there is one.
 class TestWindowDelegate : public aura::test::TestWindowDelegate {
  public:
-  explicit TestWindowDelegate(int hittest_code)
-      : hittest_code_(hittest_code) {
+  explicit TestWindowDelegate(int hittest_code) {
+    set_window_component(hittest_code);
   }
   virtual ~TestWindowDelegate() {}
 
-  void set_min_size(const gfx::Size& size) {
-    min_size_ = size;
-  }
-
  private:
   // Overridden from aura::Test::TestWindowDelegate:
-  virtual gfx::Size GetMinimumSize() const OVERRIDE {
-    return min_size_;
-  }
-  virtual int GetNonClientComponent(const gfx::Point& point) const OVERRIDE {
-    return hittest_code_;
-  }
   virtual void OnWindowDestroyed() OVERRIDE {
     delete this;
   }
 
-  int hittest_code_;
-  gfx::Size min_size_;
-
   DISALLOW_COPY_AND_ASSIGN(TestWindowDelegate);
 };
 
@@ -137,8 +127,8 @@
 TEST_F(ToplevelWindowEventHandlerTest, GrowBox) {
   scoped_ptr<aura::Window> w1(CreateWindow(HTGROWBOX));
   TestWindowDelegate* window_delegate =
-    static_cast<TestWindowDelegate*>(w1->delegate());
-  window_delegate->set_min_size(gfx::Size(40, 40));
+      static_cast<TestWindowDelegate*>(w1->delegate());
+  window_delegate->set_minimum_size(gfx::Size(40, 40));
 
   gfx::Point position = w1->bounds().origin();
   aura::test::EventGenerator generator(Shell::GetPrimaryRootWindow());
@@ -239,7 +229,7 @@
   scoped_ptr<aura::Window> w1(CreateWindow(HTLEFT));
   TestWindowDelegate* window_delegate =
       static_cast<TestWindowDelegate*>(w1->delegate());
-  window_delegate->set_min_size(gfx::Size(40, 40));
+  window_delegate->set_minimum_size(gfx::Size(40, 40));
 
   // Simulate a large left-to-right drag.  Window width should be clamped to
   // minimum and position change should be limited as well.
@@ -252,7 +242,7 @@
   scoped_ptr<aura::Window> w1(CreateWindow(HTRIGHT));
   TestWindowDelegate* window_delegate =
       static_cast<TestWindowDelegate*>(w1->delegate());
-  window_delegate->set_min_size(gfx::Size(40, 40));
+  window_delegate->set_minimum_size(gfx::Size(40, 40));
   gfx::Point position = w1->bounds().origin();
 
   // Simulate a large right-to-left drag.  Window width should be clamped to
@@ -266,7 +256,7 @@
   scoped_ptr<aura::Window> w1(CreateWindow(HTTOPLEFT));
   TestWindowDelegate* window_delegate =
       static_cast<TestWindowDelegate*>(w1->delegate());
-  window_delegate->set_min_size(gfx::Size(40, 40));
+  window_delegate->set_minimum_size(gfx::Size(40, 40));
 
   // Simulate a large top-left to bottom-right drag.  Window width should be
   // clamped to minimum and position should be limited.
@@ -279,7 +269,7 @@
   scoped_ptr<aura::Window> w1(CreateWindow(HTTOPRIGHT));
   TestWindowDelegate* window_delegate =
       static_cast<TestWindowDelegate*>(w1->delegate());
-  window_delegate->set_min_size(gfx::Size(40, 40));
+  window_delegate->set_minimum_size(gfx::Size(40, 40));
 
   // Simulate a large top-right to bottom-left drag.  Window size should be
   // clamped to minimum, x position should not change, and y position should
@@ -293,7 +283,7 @@
   scoped_ptr<aura::Window> w1(CreateWindow(HTBOTTOMLEFT));
   TestWindowDelegate* window_delegate =
       static_cast<TestWindowDelegate*>(w1->delegate());
-  window_delegate->set_min_size(gfx::Size(40, 40));
+  window_delegate->set_minimum_size(gfx::Size(40, 40));
 
   // Simulate a large bottom-left to top-right drag.  Window size should be
   // clamped to minimum, x position should be clamped, and y position should
@@ -307,7 +297,7 @@
   scoped_ptr<aura::Window> w1(CreateWindow(HTBOTTOMRIGHT));
   TestWindowDelegate* window_delegate =
       static_cast<TestWindowDelegate*>(w1->delegate());
-  window_delegate->set_min_size(gfx::Size(40, 40));
+  window_delegate->set_minimum_size(gfx::Size(40, 40));
   gfx::Point position = w1->bounds().origin();
 
   // Simulate a large bottom-right to top-left drag.  Window size should be
@@ -696,5 +686,131 @@
   }
 }
 
+// Test class for mouse and touch resize shadow tests.
+class ToplevelWindowEventHandlerResizeTest
+    : public ToplevelWindowEventHandlerTest {
+ public:
+  ToplevelWindowEventHandlerResizeTest() : delegate_(NULL) {}
+  virtual ~ToplevelWindowEventHandlerResizeTest() {}
+
+  virtual void SetUp() OVERRIDE {
+    ToplevelWindowEventHandlerTest::SetUp();
+
+    delegate_ = new TestWindowDelegate(HTNOWHERE);
+    target_.reset(CreateTestWindowInShellWithDelegate(
+        delegate_, 0, gfx::Rect(0, 0, 100, 100)));
+
+    gfx::Insets mouse_insets = gfx::Insets(-ash::kResizeOutsideBoundsSize,
+                                           -ash::kResizeOutsideBoundsSize,
+                                           -ash::kResizeOutsideBoundsSize,
+                                           -ash::kResizeOutsideBoundsSize);
+    gfx::Insets touch_insets =
+        mouse_insets.Scale(ash::kResizeOutsideBoundsScaleForTouch);
+    target_->SetHitTestBoundsOverrideOuter(mouse_insets, touch_insets);
+    target_->set_hit_test_bounds_override_inner(mouse_insets);
+  }
+
+  virtual void TearDown() OVERRIDE {
+    target_.reset();
+    ToplevelWindowEventHandlerTest::TearDown();
+  }
+
+  // Called on each scroll event. Checks if the correct resize shadow is shown.
+  void ProcessEvent(ui::EventType type, const gfx::Vector2dF& delta) {
+    if (type == ui::ET_GESTURE_SCROLL_END) {
+      // After gesture scroll ends, there should be no resize shadow.
+      EXPECT_FALSE(HasResizeShadow());
+    } else {
+      // Check if there is a resize shadow under the correct border.
+      ASSERT_TRUE(HasResizeShadow());
+      EXPECT_EQ(HTBOTTOMRIGHT, ResizeShadowLastHitTest());
+    }
+  }
+
+ protected:
+  void SetHittestCode(int hittest_code) {
+    delegate_->set_window_component(hittest_code);
+  }
+
+  aura::Window* target() { return target_.get(); }
+
+  bool HasResizeShadow() const {
+    // There is no shadow if no ResizeShadow object is associated with the
+    // window or there is one but its hit test is set to HTNOWHERE. Since we
+    // don't want to tie tests to that implementation detail, both cases are
+    // considered here.
+    return ResizeShadow() && ResizeShadowLastHitTest() != HTNOWHERE;
+  }
+
+  int ResizeShadowLastHitTest() const {
+    return ResizeShadow()->GetLastHitTestForTest();
+  }
+
+ private:
+  internal::ResizeShadow* ResizeShadow() const {
+    return Shell::GetInstance()->resize_shadow_controller()->
+        GetShadowForWindowForTest(target_.get());
+  }
+
+  TestWindowDelegate* delegate_;
+  scoped_ptr<aura::Window> target_;
+
+  DISALLOW_COPY_AND_ASSIGN(ToplevelWindowEventHandlerResizeTest);
+};
+
+// Tests resize shadows for touch resizing.
+TEST_F(ToplevelWindowEventHandlerResizeTest, TouchResizeShadows) {
+  aura::test::EventGenerator generator(Shell::GetPrimaryRootWindow(), target());
+
+  // Drag bottom right border of the window and check for the resize shadows.
+  // Shadows are checked in the callback function.
+  SetHittestCode(HTBOTTOMRIGHT);
+  generator.GestureScrollSequenceWithCallback(
+      gfx::Point(105, 105),
+      gfx::Point(150, 150),
+      base::TimeDelta::FromMilliseconds(100),
+      3,
+      base::Bind(&ToplevelWindowEventHandlerResizeTest::ProcessEvent,
+                 base::Unretained(this)));
+  RunAllPendingInMessageLoop();
+}
+
+// Tests resize shadows for mouse resizing.
+TEST_F(ToplevelWindowEventHandlerResizeTest, MouseResizeShadows) {
+  aura::test::EventGenerator generator(Shell::GetPrimaryRootWindow(), target());
+
+  // There should be no shadow at the beginning.
+  EXPECT_FALSE(HasResizeShadow());
+
+  // Move mouse over the right border. Shadows should appear.
+  SetHittestCode(HTRIGHT);
+  generator.MoveMouseTo(gfx::Point(100, 50));
+  ASSERT_TRUE(HasResizeShadow());
+  EXPECT_EQ(HTRIGHT, ResizeShadowLastHitTest());
+
+  // Move mouse over the bottom right border. Shadows should stay.
+  SetHittestCode(HTBOTTOMRIGHT);
+  generator.MoveMouseTo(100, 100);
+  ASSERT_TRUE(HasResizeShadow());
+  EXPECT_EQ(HTBOTTOMRIGHT, ResizeShadowLastHitTest());
+
+  // Move mouse into the window. Shadows should disappear.
+  SetHittestCode(HTCLIENT);
+  generator.MoveMouseTo(50, 50);
+  EXPECT_FALSE(HasResizeShadow());
+
+  // Move mouse over the bottom order. Shadows should reappear.
+  SetHittestCode(HTBOTTOM);
+  generator.MoveMouseTo(50, 100);
+  ASSERT_TRUE(HasResizeShadow());
+  EXPECT_EQ(HTBOTTOM, ResizeShadowLastHitTest());
+
+  // Move mouse out of the window. Shadows should disappear.
+  generator.MoveMouseTo(150, 150);
+  EXPECT_FALSE(HasResizeShadow());
+
+  RunAllPendingInMessageLoop();
+}
+
 }  // namespace test
 }  // namespace ash
diff --git a/ash/wm/window_selector.cc b/ash/wm/window_selector.cc
index f9de84c..8e87a95 100644
--- a/ash/wm/window_selector.cc
+++ b/ash/wm/window_selector.cc
@@ -12,29 +12,273 @@
 #include "ash/wm/window_selector_delegate.h"
 #include "ash/wm/window_util.h"
 #include "base/memory/scoped_ptr.h"
+#include "third_party/skia/include/core/SkColor.h"
 #include "ui/aura/client/aura_constants.h"
+#include "ui/aura/client/screen_position_client.h"
 #include "ui/aura/root_window.h"
 #include "ui/aura/window.h"
 #include "ui/base/events/event.h"
+#include "ui/compositor/layer_animation_observer.h"
 #include "ui/compositor/scoped_layer_animation_settings.h"
+#include "ui/gfx/display.h"
 #include "ui/gfx/interpolated_transform.h"
 #include "ui/gfx/transform_util.h"
+#include "ui/views/corewm/shadow_types.h"
 #include "ui/views/corewm/window_animations.h"
+#include "ui/views/corewm/window_util.h"
+#include "ui/views/widget/widget.h"
 
 namespace ash {
 
 namespace {
 
 const float kCardAspectRatio = 4.0f / 3.0f;
-const int kWindowMargin = 20;
+const int kWindowMargin = 30;
 const int kMinCardsMajor = 3;
 const int kOverviewTransitionMilliseconds = 100;
+const SkColor kWindowSelectorSelectionColor = SK_ColorBLACK;
+const float kWindowSelectorSelectionOpacity = 0.5f;
+const int kWindowSelectorSelectionPadding = 15;
 
-// Applies a transform to |window| to fit within |target_bounds| while
-// maintaining its aspect ratio.
-void TransformWindowToFitBounds(aura::Window* window,
-                                const gfx::Rect& target_bounds) {
-  const gfx::Rect bounds = window->bounds();
+// Creates a copy of |window| with |recreated_layer| in the |target_root|.
+views::Widget* CreateCopyOfWindow(aura::RootWindow* target_root,
+                                  aura::Window* src_window,
+                                  ui::Layer* recreated_layer) {
+  views::Widget* widget = new views::Widget;
+  views::Widget::InitParams params(views::Widget::InitParams::TYPE_POPUP);
+  params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW;
+  params.parent = src_window->parent();
+  params.can_activate = false;
+  params.keep_on_top = true;
+  widget->set_focus_on_creation(false);
+  widget->Init(params);
+  widget->SetVisibilityChangedAnimationsEnabled(false);
+  std::string name = src_window->name() + " (Copy)";
+  widget->GetNativeWindow()->SetName(name);
+  views::corewm::SetShadowType(widget->GetNativeWindow(),
+                               views::corewm::SHADOW_TYPE_RECTANGULAR);
+
+  // Set the bounds in the target root window.
+  gfx::Display target_display =
+      Shell::GetScreen()->GetDisplayNearestWindow(target_root);
+  aura::client::ScreenPositionClient* screen_position_client =
+      aura::client::GetScreenPositionClient(src_window->GetRootWindow());
+  if (screen_position_client && target_display.is_valid()) {
+    screen_position_client->SetBounds(widget->GetNativeWindow(),
+        src_window->GetBoundsInScreen(), target_display);
+  } else {
+    widget->SetBounds(src_window->GetBoundsInScreen());
+  }
+  widget->StackAbove(src_window);
+
+  // Move the |recreated_layer| to the newly created window.
+  recreated_layer->set_delegate(src_window->layer()->delegate());
+  gfx::Rect layer_bounds = recreated_layer->bounds();
+  layer_bounds.set_origin(gfx::Point(0, 0));
+  recreated_layer->SetBounds(layer_bounds);
+  recreated_layer->SetVisible(false);
+  recreated_layer->parent()->Remove(recreated_layer);
+
+  aura::Window* window = widget->GetNativeWindow();
+  recreated_layer->SetVisible(true);
+  window->layer()->Add(recreated_layer);
+  window->layer()->StackAtTop(recreated_layer);
+  window->layer()->SetOpacity(1);
+  window->Show();
+  return widget;
+}
+
+// An observer which closes the widget and deletes the layer after an
+// animation finishes.
+class CleanupWidgetAfterAnimationObserver : public ui::LayerAnimationObserver {
+ public:
+  CleanupWidgetAfterAnimationObserver(views::Widget* widget, ui::Layer* layer);
+
+  virtual void OnLayerAnimationEnded(
+      ui::LayerAnimationSequence* sequence) OVERRIDE;
+  virtual void OnLayerAnimationAborted(
+      ui::LayerAnimationSequence* sequence) OVERRIDE;
+  virtual void OnLayerAnimationScheduled(
+      ui::LayerAnimationSequence* sequence) OVERRIDE;
+
+ protected:
+  virtual ~CleanupWidgetAfterAnimationObserver();
+
+ private:
+  views::Widget* widget_;
+  ui::Layer* layer_;
+
+  DISALLOW_COPY_AND_ASSIGN(CleanupWidgetAfterAnimationObserver);
+};
+
+CleanupWidgetAfterAnimationObserver::CleanupWidgetAfterAnimationObserver(
+        views::Widget* widget,
+        ui::Layer* layer)
+    : widget_(widget),
+      layer_(layer) {
+  widget_->GetNativeWindow()->layer()->GetAnimator()->AddObserver(this);
+}
+
+void CleanupWidgetAfterAnimationObserver::OnLayerAnimationEnded(
+    ui::LayerAnimationSequence* sequence) {
+  delete this;
+}
+
+void CleanupWidgetAfterAnimationObserver::OnLayerAnimationAborted(
+    ui::LayerAnimationSequence* sequence) {
+  delete this;
+}
+
+void CleanupWidgetAfterAnimationObserver::OnLayerAnimationScheduled(
+    ui::LayerAnimationSequence* sequence) {
+}
+
+CleanupWidgetAfterAnimationObserver::~CleanupWidgetAfterAnimationObserver() {
+  widget_->GetNativeWindow()->layer()->GetAnimator()->RemoveObserver(this);
+  widget_->Close();
+  widget_ = NULL;
+  if (layer_) {
+    views::corewm::DeepDeleteLayers(layer_);
+    layer_ = NULL;
+  }
+}
+
+// The animation settings used for window selector animations.
+class WindowSelectorAnimationSettings
+    : public ui::ScopedLayerAnimationSettings {
+ public:
+  WindowSelectorAnimationSettings(aura::Window* window) :
+      ui::ScopedLayerAnimationSettings(window->layer()->GetAnimator()) {
+    SetPreemptionStrategy(
+        ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
+    SetTransitionDuration(
+        base::TimeDelta::FromMilliseconds(kOverviewTransitionMilliseconds));
+  }
+
+  virtual ~WindowSelectorAnimationSettings() {
+  }
+};
+
+}  // namespace
+
+// TODO(flackr): Split up into separate file under subdirectory in ash/wm.
+class WindowSelectorWindow {
+ public:
+  explicit WindowSelectorWindow(aura::Window* window);
+  virtual ~WindowSelectorWindow();
+
+  aura::Window* window() { return window_; }
+  const aura::Window* window() const { return window_; }
+
+  // Returns true if this window selector window contains the |target|. This is
+  // used to determine if an event targetted this window.
+  bool Contains(const aura::Window* target) const;
+
+  // Restores this window on exit rather than returning it to a minimized state
+  // if it was minimized on entering overview mode.
+  void RestoreWindowOnExit();
+
+  // Informs the WindowSelectorWindow that the window being watched was
+  // destroyed. This resets the internal window pointer to avoid calling
+  // anything on the window at destruction time.
+  void OnWindowDestroyed();
+
+  // Applies a transform to the window to fit within |target_bounds| while
+  // maintaining its aspect ratio.
+  void TransformToFitBounds(aura::RootWindow* root_window,
+                            const gfx::Rect& target_bounds);
+
+  gfx::Rect bounds() { return fit_bounds_; }
+
+ private:
+  // A weak pointer to the real window in the overview.
+  aura::Window* window_;
+
+  // A copy of the window used to transition the window to another root.
+  views::Widget* window_copy_;
+
+  // A weak pointer to a deep copy of the window's layers.
+  ui::Layer* layer_;
+
+  // If true, the window was minimized and should be restored if the window
+  // was not selected.
+  bool minimized_;
+
+  // The original transform of the window before entering overview mode.
+  gfx::Transform original_transform_;
+
+  // The bounds this window is fit to.
+  gfx::Rect fit_bounds_;
+
+  DISALLOW_COPY_AND_ASSIGN(WindowSelectorWindow);
+};
+
+WindowSelectorWindow::WindowSelectorWindow(aura::Window* window)
+    : window_(window),
+      window_copy_(NULL),
+      layer_(NULL),
+      minimized_(window->GetProperty(aura::client::kShowStateKey) ==
+                 ui::SHOW_STATE_MINIMIZED),
+      original_transform_(window->layer()->transform()) {
+  if (minimized_)
+    window_->Show();
+}
+
+WindowSelectorWindow::~WindowSelectorWindow() {
+  if (window_) {
+    WindowSelectorAnimationSettings animation_settings(window_);
+    gfx::Transform transform;
+    window_->SetTransform(original_transform_);
+    if (minimized_) {
+      // Setting opacity 0 and visible false ensures that the property change
+      // to SHOW_STATE_MINIMIZED will not animate the window from its original
+      // bounds to the minimized position.
+      window_->layer()->SetOpacity(0);
+      window_->layer()->SetVisible(false);
+      window_->SetProperty(aura::client::kShowStateKey,
+                           ui::SHOW_STATE_MINIMIZED);
+    }
+  }
+  // If a copy of the window was created, clean it up.
+  if (window_copy_) {
+    if (window_) {
+      // If the initial window wasn't destroyed, the copy needs to be animated
+      // out. CleanupWidgetAfterAnimationObserver will destroy the widget and
+      // layer after the animation is complete.
+      new CleanupWidgetAfterAnimationObserver(window_copy_, layer_);
+      WindowSelectorAnimationSettings animation_settings(
+          window_copy_->GetNativeWindow());
+      window_copy_->GetNativeWindow()->SetTransform(original_transform_);
+    } else {
+      window_copy_->Close();
+      if (layer_)
+        views::corewm::DeepDeleteLayers(layer_);
+    }
+    window_copy_ = NULL;
+    layer_ = NULL;
+  }
+}
+
+bool WindowSelectorWindow::Contains(const aura::Window* window) const {
+  if (window_copy_ && window_copy_->GetNativeWindow()->Contains(window))
+    return true;
+  return window_->Contains(window);
+}
+
+void WindowSelectorWindow::RestoreWindowOnExit() {
+  minimized_ = false;
+  original_transform_ = gfx::Transform();
+}
+
+void WindowSelectorWindow::OnWindowDestroyed() {
+  window_ = NULL;
+}
+
+void WindowSelectorWindow::TransformToFitBounds(
+    aura::RootWindow* root_window,
+    const gfx::Rect& target_bounds) {
+  fit_bounds_ = target_bounds;
+  const gfx::Rect bounds = window_->GetBoundsInScreen();
   float scale = std::min(1.0f,
       std::min(static_cast<float>(target_bounds.width()) / bounds.width(),
                static_cast<float>(target_bounds.height()) / bounds.height()));
@@ -45,137 +289,188 @@
   transform.Translate(target_bounds.x() - bounds.x() + offset.x(),
                       target_bounds.y() - bounds.y() + offset.y());
   transform.Scale(scale, scale);
-  // TODO(flackr): The window bounds or transform could change during overview
-  // mode. WindowSelector should create a copy of the window so that the
-  // displayed windows are not affected by changes happening in the background.
-  // This will be necessary for alt-tab cycling as well, as some windows will
-  // be coming from other displays: http://crbug.com/263481.
-  window->SetTransform(transform);
+  if (root_window != window_->GetRootWindow()) {
+    if (!window_copy_) {
+      DCHECK(!layer_);
+      layer_ = views::corewm::RecreateWindowLayers(window_, true);
+      window_copy_ = CreateCopyOfWindow(root_window, window_, layer_);
+    }
+    WindowSelectorAnimationSettings animation_settings(
+        window_copy_->GetNativeWindow());
+    window_copy_->GetNativeWindow()->SetTransform(transform);
+  }
+  WindowSelectorAnimationSettings animation_settings(window_);
+  window_->SetTransform(transform);
 }
 
-}  // namespace
+// A comparator for locating a given target window.
+struct WindowSelectorWindowComparator
+    : public std::unary_function<WindowSelectorWindow*, bool> {
+  explicit WindowSelectorWindowComparator(const aura::Window* target_window)
+      : target(target_window) {
+  }
+
+  bool operator()(const WindowSelectorWindow* window) const {
+    return target == window->window();
+  }
+
+  const aura::Window* target;
+};
 
 WindowSelector::WindowSelector(const WindowList& windows,
+                               WindowSelector::Mode mode,
                                WindowSelectorDelegate* delegate)
-      : delegate_(delegate) {
+    : mode_(mode),
+      delegate_(delegate),
+      selected_window_(0),
+      selection_root_(NULL) {
   DCHECK(delegate_);
   for (size_t i = 0; i < windows.size(); ++i) {
     windows[i]->AddObserver(this);
-    WindowDetails details;
-    details.window = windows[i];
-    details.minimized = windows[i]->GetProperty(aura::client::kShowStateKey) ==
-                        ui::SHOW_STATE_MINIMIZED;
-    details.original_transform = windows[i]->layer()->transform();
-    if (details.minimized) {
-      windows[i]->Show();
-    }
-    windows_.push_back(details);
+    windows_.push_back(new WindowSelectorWindow(windows[i]));
   }
+  if (mode == WindowSelector::CYCLE)
+    selection_root_ = ash::Shell::GetActiveRootWindow();
   PositionWindows();
   ash::Shell::GetInstance()->AddPreTargetHandler(this);
 }
 
 WindowSelector::~WindowSelector() {
   for (size_t i = 0; i < windows_.size(); i++) {
-    ui::ScopedLayerAnimationSettings animation_settings(
-        windows_[i].window->layer()->GetAnimator());
-    animation_settings.SetPreemptionStrategy(
-        ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
-    animation_settings.SetTransitionDuration(
-        base::TimeDelta::FromMilliseconds(kOverviewTransitionMilliseconds));
-    windows_[i].window->RemoveObserver(this);
-    gfx::Transform transform;
-    windows_[i].window->SetTransform(windows_[i].original_transform);
-    if (windows_[i].minimized) {
-      // Setting opacity 0 and visible false ensures that the property change
-      // to SHOW_STATE_MINIMIZED will not animate the window from its original
-      // bounds to the minimized position.
-      windows_[i].window->layer()->SetOpacity(0);
-      windows_[i].window->layer()->SetVisible(false);
-      windows_[i].window->SetProperty(aura::client::kShowStateKey,
-                                      ui::SHOW_STATE_MINIMIZED);
-    }
+    windows_[i]->window()->RemoveObserver(this);
   }
   ash::Shell::GetInstance()->RemovePreTargetHandler(this);
 }
 
+void WindowSelector::Step(WindowSelector::Direction direction) {
+  DCHECK(windows_.size() > 0);
+  if (!selection_widget_)
+    InitializeSelectionWidget();
+  selected_window_ = (selected_window_ + windows_.size() +
+      (direction == WindowSelector::FORWARD ? 1 : -1)) % windows_.size();
+  UpdateSelectionLocation(true);
+}
+
+void WindowSelector::SelectWindow() {
+  delegate_->OnWindowSelected(windows_[selected_window_]->window());
+}
+
 void WindowSelector::OnEvent(ui::Event* event) {
-  // TODO(flackr): This will prevent anything else from working while overview
-  // mode is active. This should only stop events from being sent to the windows
-  // in the overview but still allow interaction with the launcher / tray and
-  // hotkeys http://crbug.com/264289.
-  EventHandler::OnEvent(event);
-  event->StopPropagation();
+  // If the event is targetted at any of the windows in the overview, then
+  // prevent it from propagating.
+  aura::Window* target = static_cast<aura::Window*>(event->target());
+  for (size_t i = 0; i < windows_.size(); ++i) {
+    if (windows_[i]->Contains(target)) {
+      event->StopPropagation();
+      break;
+    }
+  }
+
+  // This object may not be valid after this call as a selection event can
+  // trigger deletion of the window selector.
+  ui::EventHandler::OnEvent(event);
 }
 
 void WindowSelector::OnMouseEvent(ui::MouseEvent* event) {
   if (event->type() != ui::ET_MOUSE_RELEASED)
     return;
-  aura::Window* target = static_cast<aura::Window*>(event->target());
-  if (!target->HitTest(event->location()))
+  WindowSelectorWindow* target = GetEventTarget(event);
+  if (!target)
     return;
 
-  HandleSelectionEvent(event);
+  HandleSelectionEvent(target);
 }
 
 void WindowSelector::OnGestureEvent(ui::GestureEvent* event) {
   if (event->type() != ui::ET_GESTURE_TAP)
     return;
-  HandleSelectionEvent(event);
+  WindowSelectorWindow* target = GetEventTarget(event);
+  if (!target)
+    return;
+
+  HandleSelectionEvent(target);
 }
 
 void WindowSelector::OnWindowDestroyed(aura::Window* window) {
-  std::vector<WindowDetails>::iterator iter =
-      std::find(windows_.begin(), windows_.end(), window);
+  ScopedVector<WindowSelectorWindow>::iterator iter =
+      std::find_if(windows_.begin(), windows_.end(),
+                   WindowSelectorWindowComparator(window));
   DCHECK(iter != windows_.end());
+  size_t deleted_index = iter - windows_.begin();
+  (*iter)->OnWindowDestroyed();
   windows_.erase(iter);
   if (windows_.empty()) {
     delegate_->OnSelectionCanceled();
     return;
   }
+  if (selected_window_ >= deleted_index) {
+    if (selected_window_ > deleted_index)
+      selected_window_--;
+    selected_window_ = selected_window_ % windows_.size();
+    UpdateSelectionLocation(true);
+  }
 
   PositionWindows();
 }
 
-void WindowSelector::HandleSelectionEvent(ui::Event* event) {
+WindowSelectorWindow* WindowSelector::GetEventTarget(ui::LocatedEvent* event) {
   aura::Window* target = static_cast<aura::Window*>(event->target());
+  // If the target window doesn't actually contain the event location (i.e.
+  // mouse down over the window and mouse up elsewhere) then do not select the
+  // window.
+  if (!target->HitTest(event->location()))
+    return NULL;
 
   for (size_t i = 0; i < windows_.size(); i++) {
-    if (windows_[i].window->Contains(target)) {
-      // The selected window should not be minimized when window selection is
-      // ended.
-      windows_[i].minimized = false;
-      windows_[i].original_transform = gfx::Transform();
-
-      // The delegate may delete the WindowSelector, assume the object may no
-      // longer valid after calling this.
-      delegate_->OnWindowSelected(windows_[i].window);
-      return;
-    }
+    if (windows_[i]->Contains(target))
+      return windows_[i];
   }
+  return NULL;
+}
+
+void WindowSelector::HandleSelectionEvent(WindowSelectorWindow* target) {
+  // The selected window should not be minimized when window selection is
+  // ended.
+  target->RestoreWindowOnExit();
+  delegate_->OnWindowSelected(target->window());
 }
 
 void WindowSelector::PositionWindows() {
-  Shell::RootWindowList root_window_list = Shell::GetAllRootWindows();
-  for (size_t i = 0; i < root_window_list.size(); ++i) {
-    PositionWindowsOnRoot(root_window_list[i]);
+  if (selection_root_) {
+    DCHECK_EQ(mode_, CYCLE);
+    std::vector<WindowSelectorWindow*> windows;
+    for (size_t i = 0; i < windows_.size(); ++i)
+      windows.push_back(windows_[i]);
+    PositionWindowsOnRoot(selection_root_, windows);
+  } else {
+    DCHECK_EQ(mode_, OVERVIEW);
+    Shell::RootWindowList root_window_list = Shell::GetAllRootWindows();
+    for (size_t i = 0; i < root_window_list.size(); ++i)
+      PositionWindowsFromRoot(root_window_list[i]);
   }
 }
 
-void WindowSelector::PositionWindowsOnRoot(aura::RootWindow* root_window) {
-  gfx::Size window_size;
-  gfx::Rect total_bounds = ScreenAsh::GetDisplayWorkAreaBoundsInParent(
-      Shell::GetContainer(root_window,
-                          internal::kShellWindowId_DefaultContainer));
-
-  std::vector<WindowDetails> windows;
+void WindowSelector::PositionWindowsFromRoot(aura::RootWindow* root_window) {
+  std::vector<WindowSelectorWindow*> windows;
   for (size_t i = 0; i < windows_.size(); ++i) {
-    if (windows_[i].window->GetRootWindow() == root_window)
+    if (windows_[i]->window()->GetRootWindow() == root_window)
       windows.push_back(windows_[i]);
   }
+  PositionWindowsOnRoot(root_window, windows);
+}
+
+void WindowSelector::PositionWindowsOnRoot(
+    aura::RootWindow* root_window,
+    const std::vector<WindowSelectorWindow*>& windows) {
   if (windows.empty())
     return;
 
+  gfx::Size window_size;
+  gfx::Rect total_bounds = ScreenAsh::ConvertRectToScreen(root_window,
+      ScreenAsh::GetDisplayWorkAreaBoundsInParent(
+      Shell::GetContainer(root_window,
+                          internal::kShellWindowId_DefaultContainer)));
+
   // Find the minimum number of windows per row that will fit all of the
   // windows on screen.
   size_t columns = std::max(
@@ -195,12 +490,6 @@
   int y_offset = total_bounds.y() + (total_bounds.height() -
       rows * window_size.height()) / 2;
   for (size_t i = 0; i < windows.size(); ++i) {
-    ui::ScopedLayerAnimationSettings animation_settings(
-        windows[i].window->layer()->GetAnimator());
-    animation_settings.SetPreemptionStrategy(
-        ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
-    animation_settings.SetTransitionDuration(
-        base::TimeDelta::FromMilliseconds(kOverviewTransitionMilliseconds));
     gfx::Transform transform;
     int column = i % columns;
     int row = i / columns;
@@ -209,7 +498,48 @@
                             window_size.width(),
                             window_size.height());
     target_bounds.Inset(kWindowMargin, kWindowMargin);
-    TransformWindowToFitBounds(windows[i].window, target_bounds);
+    windows[i]->TransformToFitBounds(root_window, target_bounds);
+  }
+}
+
+void WindowSelector::InitializeSelectionWidget() {
+  selection_widget_.reset(new views::Widget);
+  views::Widget::InitParams params;
+  params.type = views::Widget::InitParams::TYPE_POPUP;
+  params.can_activate = false;
+  params.keep_on_top = false;
+  params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
+  params.opacity = views::Widget::InitParams::OPAQUE_WINDOW;
+  params.parent = Shell::GetContainer(
+      selection_root_,
+      internal::kShellWindowId_DefaultContainer);
+  params.accept_events = false;
+  selection_widget_->set_focus_on_creation(false);
+  selection_widget_->Init(params);
+  views::View* content_view = new views::View;
+  content_view->set_background(
+      views::Background::CreateSolidBackground(kWindowSelectorSelectionColor));
+  selection_widget_->SetContentsView(content_view);
+  UpdateSelectionLocation(false);
+  selection_widget_->GetNativeWindow()->parent()->StackChildAtBottom(
+      selection_widget_->GetNativeWindow());
+  selection_widget_->Show();
+  selection_widget_->GetNativeWindow()->layer()->SetOpacity(
+      kWindowSelectorSelectionOpacity);
+}
+
+void WindowSelector::UpdateSelectionLocation(bool animate) {
+  if (!selection_widget_)
+    return;
+  gfx::Rect target_bounds = windows_[selected_window_]->bounds();
+  target_bounds.Inset(-kWindowSelectorSelectionPadding,
+                      -kWindowSelectorSelectionPadding);
+  if (animate) {
+    WindowSelectorAnimationSettings animation_settings(
+        selection_widget_->GetNativeWindow());
+    selection_widget_->SetBounds(target_bounds);
+  } else {
+    selection_widget_->SetBounds(target_bounds);
   }
 }
 
diff --git a/ash/wm/window_selector.h b/ash/wm/window_selector.h
index 900787d..92ed607 100644
--- a/ash/wm/window_selector.h
+++ b/ash/wm/window_selector.h
@@ -8,6 +8,8 @@
 #include <vector>
 
 #include "base/compiler_specific.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/memory/scoped_vector.h"
 #include "ui/aura/window_observer.h"
 #include "ui/base/events/event_handler.h"
 #include "ui/gfx/transform.h"
@@ -16,21 +18,49 @@
 class RootWindow;
 }
 
+namespace ui {
+class LocatedEvent;
+}
+
+namespace views {
+class Widget;
+}
+
 namespace ash {
 
 class WindowSelectorDelegate;
+class WindowSelectorWindow;
 
 // The WindowSelector shows a grid of all of your windows and allows selecting
-// a window by clicking or tapping on it.
+// a window by clicking or tapping on it (OVERVIEW mode) or by alt-tabbing to
+// it (CYCLE mode).
 class WindowSelector : public ui::EventHandler,
                        public aura::WindowObserver {
  public:
+  enum Direction {
+    FORWARD,
+    BACKWARD
+  };
+  enum Mode {
+    CYCLE,
+    OVERVIEW
+  };
+
   typedef std::vector<aura::Window*> WindowList;
 
   WindowSelector(const WindowList& windows,
+                 Mode mode,
                  WindowSelectorDelegate* delegate);
   virtual ~WindowSelector();
 
+  // Step to the next window in |direction|.
+  void Step(Direction direction);
+
+  // Select the current window.
+  void SelectWindow();
+
+  Mode mode() { return mode_; }
+
   // ui::EventHandler:
   virtual void OnEvent(ui::Event* event) OVERRIDE;
   virtual void OnMouseEvent(ui::MouseEvent* event) OVERRIDE;
@@ -40,37 +70,48 @@
   virtual void OnWindowDestroyed(aura::Window* window) OVERRIDE;
 
  private:
-  struct WindowDetails {
-    WindowDetails() : window(NULL), minimized(false) {}
+  // Returns the target of |event| or NULL if the event is not targeted at
+  // any of the windows in the selector.
+  WindowSelectorWindow* GetEventTarget(ui::LocatedEvent* event);
 
-    bool operator==(const aura::Window* other_window) const {
-      return window == other_window;
-    }
+  // Handles a selection event for |target|.
+  void HandleSelectionEvent(WindowSelectorWindow* target);
 
-    // A weak pointer to the window.
-    aura::Window* window;
-
-    // If true, the window was minimized and this should be restored if the
-    // window was not selected.
-    bool minimized;
-
-    // The original transform of the window before entering overview mode.
-    gfx::Transform original_transform;
-  };
-
-  void HandleSelectionEvent(ui::Event* event);
+  // Position all of the windows based on the current selection mode.
   void PositionWindows();
-  void PositionWindowsOnRoot(aura::RootWindow* root_window);
+  // Position all of the windows from |root_window| on |root_window|.
+  void PositionWindowsFromRoot(aura::RootWindow* root_window);
+  // Position all of the |windows| to fit on the |root_window|.
+  void PositionWindowsOnRoot(aura::RootWindow* root_window,
+                             const std::vector<WindowSelectorWindow*>& windows);
 
-  void SelectWindow(aura::Window*);
+  void InitializeSelectionWidget();
 
-  // List of weak pointers of windows to select from.
-  std::vector<WindowDetails> windows_;
+  // Updates the selection widget's location to the currently selected window.
+  // If |animate| the transition to the new location is animated.
+  void UpdateSelectionLocation(bool animate);
+
+  // The collection of windows in the overview wrapped by a helper class which
+  // restores their state and helps transform them to other root windows.
+  ScopedVector<WindowSelectorWindow> windows_;
+
+  // The window selection mode.
+  Mode mode_;
 
   // Weak pointer to the selector delegate which will be called when a
   // selection is made.
   WindowSelectorDelegate* delegate_;
 
+  // Index of the currently selected window if the mode is CYCLE.
+  size_t selected_window_;
+
+  // Widget indicating which window is currently selected.
+  scoped_ptr<views::Widget> selection_widget_;
+
+  // In CYCLE mode, the root window in which selection is taking place.
+  // NULL otherwise.
+  aura::RootWindow* selection_root_;
+
   DISALLOW_COPY_AND_ASSIGN(WindowSelector);
 };
 
diff --git a/ash/wm/window_selector_controller.cc b/ash/wm/window_selector_controller.cc
index c7fe696..e6cd383 100644
--- a/ash/wm/window_selector_controller.cc
+++ b/ash/wm/window_selector_controller.cc
@@ -9,9 +9,47 @@
 #include "ash/wm/mru_window_tracker.h"
 #include "ash/wm/window_selector.h"
 #include "ash/wm/window_util.h"
+#include "ui/base/events/event.h"
+#include "ui/base/events/event_handler.h"
 
 namespace ash {
 
+namespace {
+
+// Filter to watch for the termination of a keyboard gesture to cycle through
+// multiple windows.
+class WindowSelectorEventFilter : public ui::EventHandler {
+ public:
+  WindowSelectorEventFilter();
+  virtual ~WindowSelectorEventFilter();
+
+  // Overridden from ui::EventHandler:
+  virtual void OnKeyEvent(ui::KeyEvent* event) OVERRIDE;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(WindowSelectorEventFilter);
+};
+
+// Watch for all keyboard events by filtering the root window.
+WindowSelectorEventFilter::WindowSelectorEventFilter() {
+  Shell::GetInstance()->AddPreTargetHandler(this);
+}
+
+WindowSelectorEventFilter::~WindowSelectorEventFilter() {
+  Shell::GetInstance()->RemovePreTargetHandler(this);
+}
+
+void WindowSelectorEventFilter::OnKeyEvent(ui::KeyEvent* event) {
+  // Views uses VKEY_MENU for both left and right Alt keys.
+  if (event->key_code() == ui::VKEY_MENU &&
+      event->type() == ui::ET_KEY_RELEASED) {
+    Shell::GetInstance()->window_selector_controller()->AltKeyReleased();
+    // Warning: |this| will be deleted from here on.
+  }
+}
+
+}  // namespace
+
 WindowSelectorController::WindowSelectorController() {
 }
 
@@ -41,10 +79,33 @@
     aura::Window* active_window = wm::GetActiveWindow();
     if (active_window)
       wm::DeactivateWindow(active_window);
-    window_selector_.reset(new WindowSelector(windows, this));
+    window_selector_.reset(
+        new WindowSelector(windows, WindowSelector::OVERVIEW, this));
   }
 }
 
+void WindowSelectorController::HandleCycleWindow(
+    WindowSelector::Direction direction) {
+  if (!CanSelect())
+    return;
+
+  if (!IsSelecting()) {
+    event_handler_.reset(new WindowSelectorEventFilter());
+    std::vector<aura::Window*> windows = ash::Shell::GetInstance()->
+        mru_window_tracker()->BuildMruWindowList();
+    window_selector_.reset(
+        new WindowSelector(windows, WindowSelector::CYCLE, this));
+    window_selector_->Step(direction);
+  } else if (window_selector_->mode() == WindowSelector::CYCLE) {
+    window_selector_->Step(direction);
+  }
+}
+
+void WindowSelectorController::AltKeyReleased() {
+  event_handler_.reset();
+  window_selector_->SelectWindow();
+}
+
 bool WindowSelectorController::IsSelecting() {
   return window_selector_.get() != NULL;
 }
diff --git a/ash/wm/window_selector_controller.h b/ash/wm/window_selector_controller.h
index 8b11005..385c30e 100644
--- a/ash/wm/window_selector_controller.h
+++ b/ash/wm/window_selector_controller.h
@@ -9,6 +9,7 @@
 #include <vector>
 
 #include "ash/ash_export.h"
+#include "ash/wm/window_selector.h"
 #include "ash/wm/window_selector_delegate.h"
 #include "base/basictypes.h"
 #include "base/memory/scoped_ptr.h"
@@ -18,6 +19,10 @@
 class Window;
 }
 
+namespace ui {
+class EventHandler;
+}
+
 namespace ash {
 
 class WindowSelector;
@@ -39,6 +44,15 @@
   // or touch rather than keypresses.
   void ToggleOverview();
 
+  // Cycles between windows in the given |direction|. It is assumed that the
+  // alt key is held down and a key filter is installed to watch for alt being
+  // released.
+  void HandleCycleWindow(WindowSelector::Direction direction);
+
+  // Informs the controller that the Alt key has been released and it can
+  // terminate the existing multi-step cycle.
+  void AltKeyReleased();
+
   // Returns true if window selection mode is active.
   bool IsSelecting();
 
@@ -48,6 +62,7 @@
 
  private:
   scoped_ptr<WindowSelector> window_selector_;
+  scoped_ptr<ui::EventHandler> event_handler_;
 
   DISALLOW_COPY_AND_ASSIGN(WindowSelectorController);
 };
diff --git a/ash/wm/window_selector_unittest.cc b/ash/wm/window_selector_unittest.cc
index 01a96bf..9ac15d6 100644
--- a/ash/wm/window_selector_unittest.cc
+++ b/ash/wm/window_selector_unittest.cc
@@ -107,6 +107,27 @@
     }
   }
 
+  void Cycle(WindowSelector::Direction direction) {
+    if (!IsSelecting()) {
+      std::vector<aura::Window*> windows = ash::Shell::GetInstance()->
+          mru_window_tracker()->BuildMruWindowList();
+      ScopedVector<LayerAnimationObserver> animations;
+      for (size_t i = 0; i < windows.size(); ++i)
+        animations.push_back(new LayerAnimationObserver(windows[i]->layer()));
+      ash::Shell::GetInstance()->window_selector_controller()->
+          HandleCycleWindow(direction);
+      for (size_t i = 0; i < animations.size(); ++i)
+        animations[i]->WaitUntilDone();
+    } else {
+      ash::Shell::GetInstance()->window_selector_controller()->
+          HandleCycleWindow(direction);
+    }
+  }
+
+  void StopCycling() {
+    ash::Shell::GetInstance()->window_selector_controller()->AltKeyReleased();
+  }
+
   gfx::RectF GetTransformedBounds(aura::Window* window) {
     gfx::RectF bounds(window->layer()->bounds());
     window->layer()->transform().TransformRect(&bounds);
@@ -125,6 +146,11 @@
     event_generator.ClickLeftButton();
   }
 
+  bool IsSelecting() {
+    return ash::Shell::GetInstance()->window_selector_controller()->
+        IsSelecting();
+  }
+
  private:
   aura::test::TestWindowDelegate wd;
 
@@ -151,6 +177,29 @@
   EXPECT_FALSE(wm::IsActiveWindow(window2.get()));
 }
 
+// Tests entering overview mode with three windows and cycling through them.
+TEST_F(WindowSelectorTest, BasicCycle) {
+  gfx::Rect bounds(0, 0, 400, 400);
+  scoped_ptr<aura::Window> window1(CreateWindow(bounds));
+  scoped_ptr<aura::Window> window2(CreateWindow(bounds));
+  scoped_ptr<aura::Window> window3(CreateWindow(bounds));
+  wm::ActivateWindow(window3.get());
+  wm::ActivateWindow(window2.get());
+  wm::ActivateWindow(window1.get());
+  EXPECT_TRUE(wm::IsActiveWindow(window1.get()));
+  EXPECT_FALSE(wm::IsActiveWindow(window2.get()));
+  EXPECT_FALSE(wm::IsActiveWindow(window3.get()));
+
+  Cycle(WindowSelector::FORWARD);
+  EXPECT_TRUE(IsSelecting());
+  Cycle(WindowSelector::FORWARD);
+  StopCycling();
+  EXPECT_FALSE(IsSelecting());
+  EXPECT_FALSE(wm::IsActiveWindow(window1.get()));
+  EXPECT_FALSE(wm::IsActiveWindow(window2.get()));
+  EXPECT_TRUE(wm::IsActiveWindow(window3.get()));
+}
+
 // Tests that overview mode is exited if the last remaining window is destroyed.
 TEST_F(WindowSelectorTest, LastWindowDestroyed) {
   gfx::Rect bounds(0, 0, 400, 400);
@@ -160,8 +209,7 @@
 
   window1.reset();
   window2.reset();
-  EXPECT_FALSE(ash::Shell::GetInstance()->window_selector_controller()->
-               IsSelecting());
+  EXPECT_FALSE(IsSelecting());
 }
 
 // Tests that windows remain on the display they are currently on in overview
diff --git a/ash/wm/workspace/workspace_event_handler_unittest.cc b/ash/wm/workspace/workspace_event_handler_unittest.cc
index e592ad5..9f4d326 100644
--- a/ash/wm/workspace/workspace_event_handler_unittest.cc
+++ b/ash/wm/workspace/workspace_event_handler_unittest.cc
@@ -16,7 +16,6 @@
 #include "ui/aura/test/event_generator.h"
 #include "ui/aura/test/test_window_delegate.h"
 #include "ui/aura/window.h"
-#include "ui/aura/window_property.h"
 #include "ui/base/hit_test.h"
 #include "ui/gfx/screen.h"
 
diff --git a/ash/wm/workspace/workspace_layout_manager.cc b/ash/wm/workspace/workspace_layout_manager.cc
index 2fd56af..c748d9a 100644
--- a/ash/wm/workspace/workspace_layout_manager.cc
+++ b/ash/wm/workspace/workspace_layout_manager.cc
@@ -4,6 +4,7 @@
 
 #include "ash/wm/workspace/workspace_layout_manager.h"
 
+#include "ash/display/display_controller.h"
 #include "ash/root_window_controller.h"
 #include "ash/screen_ash.h"
 #include "ash/shelf/shelf_layout_manager.h"
@@ -41,6 +42,33 @@
       state == ui::SHOW_STATE_FULLSCREEN;
 }
 
+void MoveToDisplayForRestore(aura::Window* window) {
+  const gfx::Rect* restore_bounds = GetRestoreBoundsInScreen(window);
+  if (!restore_bounds)
+    return;
+
+  // Move only if the restore bounds is outside of
+  // the root window. There is no information about in which
+  // display it should be restored, so this is best guess.
+  // TODO(oshima): Restore information should contain the
+  // work area information like WindowResizer does for the
+  // last window location.
+  if (!window->GetRootWindow()->GetBoundsInScreen().Intersects(
+          *restore_bounds)) {
+    DisplayController* display_controller =
+        Shell::GetInstance()->display_controller();
+    const gfx::Display& display =
+        display_controller->GetDisplayMatching(*restore_bounds);
+    aura::RootWindow* new_root =
+        display_controller->GetRootWindowForDisplayId(display.id());
+    if (new_root != window->GetRootWindow()) {
+      aura::Window* new_container =
+          Shell::GetContainer(new_root, window->parent()->id());
+      new_container->AddChild(window);
+    }
+  }
+}
+
 }  // namespace
 
 WorkspaceLayoutManager::WorkspaceLayoutManager(aura::Window* window)
@@ -285,14 +313,15 @@
     }
 
     case ui::SHOW_STATE_MAXIMIZED:
+      MoveToDisplayForRestore(window);
       CrossFadeToBounds(window, ScreenAsh::GetMaximizedWindowBoundsInParent(
           window->parent()->parent()));
       break;
     case ui::SHOW_STATE_FULLSCREEN:
+      MoveToDisplayForRestore(window);
       CrossFadeToBounds(window, ScreenAsh::GetDisplayBoundsInParent(
           window->parent()->parent()));
       break;
-
     default:
       break;
   }
diff --git a/ash/wm/workspace/workspace_layout_manager_unittest.cc b/ash/wm/workspace/workspace_layout_manager_unittest.cc
index 3e3a1c7..3dce5b0 100644
--- a/ash/wm/workspace/workspace_layout_manager_unittest.cc
+++ b/ash/wm/workspace/workspace_layout_manager_unittest.cc
@@ -17,11 +17,35 @@
 #include "ui/aura/test/test_windows.h"
 #include "ui/aura/window.h"
 #include "ui/gfx/insets.h"
+#include "ui/views/widget/widget.h"
+#include "ui/views/widget/widget_delegate.h"
 
 namespace ash {
-
 namespace {
 
+class MaximizeDelegateView : public views::WidgetDelegateView {
+ public:
+  MaximizeDelegateView(const gfx::Rect& initial_bounds)
+      : initial_bounds_(initial_bounds) {
+  }
+  virtual ~MaximizeDelegateView() {}
+
+  virtual bool GetSavedWindowPlacement(
+      gfx::Rect* bounds,
+      ui::WindowShowState* show_state) const OVERRIDE {
+    *bounds = initial_bounds_;
+    *show_state = ui::SHOW_STATE_MAXIMIZED;
+    return true;
+  }
+
+ private:
+  const gfx::Rect initial_bounds_;
+
+  DISALLOW_COPY_AND_ASSIGN(MaximizeDelegateView);
+};
+
+}  // namespace
+
 typedef test::AshTestBase WorkspaceLayoutManagerTest;
 
 // Verifies that a window containing a restore coordinate will be restored to
@@ -98,6 +122,91 @@
   EXPECT_EQ("-20,-30 30x40", window->bounds().ToString());
 }
 
+TEST_F(WorkspaceLayoutManagerTest, MaximizeInDisplayToBeRestored) {
+  if (!SupportsMultipleDisplays())
+    return;
+  UpdateDisplay("300x400,400x500");
+
+  Shell::RootWindowList root_windows = Shell::GetAllRootWindows();
+
+  scoped_ptr<aura::Window> window(
+      CreateTestWindowInShellWithBounds(gfx::Rect(1, 2, 30, 40)));
+  EXPECT_EQ(root_windows[0], window->GetRootWindow());
+
+  SetRestoreBoundsInScreen(window.get(), gfx::Rect(400, 0, 30, 40));
+  // Maximize the window in 2nd display as the restore bounds
+  // is inside 2nd display.
+  wm::MaximizeWindow(window.get());
+  EXPECT_EQ(root_windows[1], window->GetRootWindow());
+  EXPECT_EQ("300,0 400x452", window->GetBoundsInScreen().ToString());
+
+  wm::RestoreWindow(window.get());
+  EXPECT_EQ(root_windows[1], window->GetRootWindow());
+  EXPECT_EQ("400,0 30x40", window->GetBoundsInScreen().ToString());
+
+  // If the restore bounds intersects with the current display,
+  // don't move.
+  SetRestoreBoundsInScreen(window.get(), gfx::Rect(280, 0, 30, 40));
+  wm::MaximizeWindow(window.get());
+  EXPECT_EQ(root_windows[1], window->GetRootWindow());
+  EXPECT_EQ("300,0 400x452", window->GetBoundsInScreen().ToString());
+
+  wm::RestoreWindow(window.get());
+  EXPECT_EQ(root_windows[1], window->GetRootWindow());
+  EXPECT_EQ("280,0 30x40", window->GetBoundsInScreen().ToString());
+
+  // Restoring widget state.
+  scoped_ptr<views::Widget> w1(new views::Widget);
+  views::Widget::InitParams params;
+  params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
+  params.delegate = new MaximizeDelegateView(gfx::Rect(400, 0, 30, 40));
+  params.context = root_windows[0];
+  w1->Init(params);
+  w1->Show();
+  EXPECT_TRUE(w1->IsMaximized());
+  EXPECT_EQ(root_windows[1], w1->GetNativeView()->GetRootWindow());
+  EXPECT_EQ("300,0 400x452", w1->GetWindowBoundsInScreen().ToString());
+  w1->Restore();
+  EXPECT_EQ(root_windows[1], w1->GetNativeView()->GetRootWindow());
+  EXPECT_EQ("400,0 30x40", w1->GetWindowBoundsInScreen().ToString());
+}
+
+TEST_F(WorkspaceLayoutManagerTest, FullscreenInDisplayToBeRestored) {
+  if (!SupportsMultipleDisplays())
+    return;
+  UpdateDisplay("300x400,400x500");
+
+  Shell::RootWindowList root_windows = Shell::GetAllRootWindows();
+
+  scoped_ptr<aura::Window> window(
+      CreateTestWindowInShellWithBounds(gfx::Rect(1, 2, 30, 40)));
+  EXPECT_EQ(root_windows[0], window->GetRootWindow());
+
+  SetRestoreBoundsInScreen(window.get(), gfx::Rect(400, 0, 30, 40));
+  // Maximize the window in 2nd display as the restore bounds
+  // is inside 2nd display.
+  window->SetProperty(aura::client::kShowStateKey,
+                      ui::SHOW_STATE_FULLSCREEN);
+  EXPECT_EQ(root_windows[1], window->GetRootWindow());
+  EXPECT_EQ("300,0 400x500", window->GetBoundsInScreen().ToString());
+
+  wm::RestoreWindow(window.get());
+  EXPECT_EQ(root_windows[1], window->GetRootWindow());
+  EXPECT_EQ("400,0 30x40", window->GetBoundsInScreen().ToString());
+
+  // If the restore bounds intersects with the current display,
+  // don't move.
+  SetRestoreBoundsInScreen(window.get(), gfx::Rect(280, 0, 30, 40));
+  window->SetProperty(aura::client::kShowStateKey,
+                      ui::SHOW_STATE_FULLSCREEN);
+  EXPECT_EQ(root_windows[1], window->GetRootWindow());
+  EXPECT_EQ("300,0 400x500", window->GetBoundsInScreen().ToString());
+
+  wm::RestoreWindow(window.get());
+  EXPECT_EQ(root_windows[1], window->GetRootWindow());
+  EXPECT_EQ("280,0 30x40", window->GetBoundsInScreen().ToString());
+}
+
 // WindowObserver implementation used by DontClobberRestoreBoundsWindowObserver.
 // This code mirrors what BrowserFrameAura does. In particular when this code
 // sees the window was maximized it changes the bounds of a secondary
@@ -250,5 +359,4 @@
       window->bounds().ToString());
 }
 
-}  // namespace
 }  // namespace ash
diff --git a/base/base.gyp b/base/base.gyp
index 4b92a91..e2af06b 100644
--- a/base/base.gyp
+++ b/base/base.gyp
@@ -877,6 +877,8 @@
         'test/null_task_runner.h',
         'test/perf_test_suite.cc',
         'test/perf_test_suite.h',
+        'test/power_monitor_test_base.cc',
+        'test/power_monitor_test_base.h',
         'test/scoped_locale.cc',
         'test/scoped_locale.h',
         'test/scoped_path_override.cc',
diff --git a/base/base.gypi b/base/base.gypi
index bfe5a57..6d82ee3 100644
--- a/base/base.gypi
+++ b/base/base.gypi
@@ -390,8 +390,6 @@
           'power_monitor/power_monitor_device_source_win.cc',
           'power_monitor/power_monitor_source.cc',
           'power_monitor/power_monitor_source.h',
-          'power_monitor/power_monitor_test_base.cc',
-          'power_monitor/power_monitor_test_base.h',
           'power_monitor/power_observer.h',
           'process/internal_linux.cc',
           'process/internal_linux.h',
@@ -417,6 +415,7 @@
           'process/process_handle_posix.cc',
           'process/process_handle_win.cc',
           'process/process_info.h',
+          'process/process_info_linux.cc',
           'process/process_info_mac.cc',
           'process/process_info_win.cc',
           'process/process_iterator.cc',
diff --git a/base/base.target.darwin-arm.mk b/base/base.target.darwin-arm.mk
index dfa23a3..27dc2e8 100644
--- a/base/base.target.darwin-arm.mk
+++ b/base/base.target.darwin-arm.mk
@@ -148,7 +148,6 @@
 	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/power_monitor/power_monitor_test_base.cc \
 	base/process/internal_linux.cc \
 	base/process/kill.cc \
 	base/process/kill_posix.cc \
diff --git a/base/base.target.darwin-mips.mk b/base/base.target.darwin-mips.mk
index 2847ad4..acca7ec 100644
--- a/base/base.target.darwin-mips.mk
+++ b/base/base.target.darwin-mips.mk
@@ -148,7 +148,6 @@
 	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/power_monitor/power_monitor_test_base.cc \
 	base/process/internal_linux.cc \
 	base/process/kill.cc \
 	base/process/kill_posix.cc \
diff --git a/base/base.target.darwin-x86.mk b/base/base.target.darwin-x86.mk
index d3c3e49..293ec02 100644
--- a/base/base.target.darwin-x86.mk
+++ b/base/base.target.darwin-x86.mk
@@ -149,7 +149,6 @@
 	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/power_monitor/power_monitor_test_base.cc \
 	base/process/internal_linux.cc \
 	base/process/kill.cc \
 	base/process/kill_posix.cc \
diff --git a/base/base.target.linux-arm.mk b/base/base.target.linux-arm.mk
index dfa23a3..27dc2e8 100644
--- a/base/base.target.linux-arm.mk
+++ b/base/base.target.linux-arm.mk
@@ -148,7 +148,6 @@
 	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/power_monitor/power_monitor_test_base.cc \
 	base/process/internal_linux.cc \
 	base/process/kill.cc \
 	base/process/kill_posix.cc \
diff --git a/base/base.target.linux-mips.mk b/base/base.target.linux-mips.mk
index 2847ad4..acca7ec 100644
--- a/base/base.target.linux-mips.mk
+++ b/base/base.target.linux-mips.mk
@@ -148,7 +148,6 @@
 	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/power_monitor/power_monitor_test_base.cc \
 	base/process/internal_linux.cc \
 	base/process/kill.cc \
 	base/process/kill_posix.cc \
diff --git a/base/base.target.linux-x86.mk b/base/base.target.linux-x86.mk
index d3c3e49..293ec02 100644
--- a/base/base.target.linux-x86.mk
+++ b/base/base.target.linux-x86.mk
@@ -149,7 +149,6 @@
 	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/power_monitor/power_monitor_test_base.cc \
 	base/process/internal_linux.cc \
 	base/process/kill.cc \
 	base/process/kill_posix.cc \
diff --git a/base/debug/trace_event.h b/base/debug/trace_event.h
index f6a903d..6805513 100644
--- a/base/debug/trace_event.h
+++ b/base/debug/trace_event.h
@@ -17,13 +17,14 @@
 // Events are issued against categories. Whereas LOG's
 // categories are statically defined, TRACE categories are created
 // implicitly with a string. For example:
-//   TRACE_EVENT_INSTANT0("MY_SUBSYSTEM", "SomeImportantEvent")
+//   TRACE_EVENT_INSTANT0("MY_SUBSYSTEM", "SomeImportantEvent",
+//                        TRACE_EVENT_SCOPE_THREAD)
 //
 // It is often the case that one trace may belong in multiple categories at the
 // same time. The first argument to the trace can be a comma-separated list of
 // categories, forming a category group, like:
 //
-// TRACE_EVENT_INSTANT0("input,views", "OnMouseOver")
+// TRACE_EVENT_INSTANT0("input,views", "OnMouseOver", TRACE_EVENT_SCOPE_THREAD)
 //
 // We can enable/disable tracing of OnMouseOver by enabling/disabling either
 // category.
@@ -97,7 +98,7 @@
 // This indicates to the tracing UI that these counters should be displayed
 // in a single graph, as a summed area chart.
 //
-// Since counters are in a global namespace, you may want to disembiguate with a
+// Since counters are in a global namespace, you may want to disambiguate with a
 // unique ID, by using the TRACE_COUNTER_ID* variations.
 //
 // By default, trace collection is compiled in, but turned off at runtime.
@@ -132,7 +133,7 @@
 //                  "arg1", std::string("string will be copied"));
 //
 //
-// Convertable notes:
+// Convertible notes:
 // Converting a large data type to a string can be costly. To help with this,
 // the trace framework provides an interface ConvertableToTraceFormat. If you
 // inherit from it and implement the AppendAsTraceFormat method the trace
@@ -183,7 +184,7 @@
 // again under lock.
 //
 // Without the use of these static category pointers and enabled flags all
-// trace points would carry a significant performance cost of aquiring a lock
+// trace points would carry a significant performance cost of acquiring a lock
 // and resolving the category.
 
 #ifndef BASE_DEBUG_TRACE_EVENT_H_
@@ -688,7 +689,7 @@
         category_group, name, id, TRACE_EVENT_FLAG_COPY, \
         arg1_name, arg1_val, arg2_name, arg2_val)
 
-// Macros to track the life time and value of arbitratry client objects.
+// Macros to track the life time and value of arbitrary client objects.
 // See also TraceTrackableObject.
 #define TRACE_EVENT_OBJECT_CREATED_WITH_ID(category_group, name, id) \
     INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_CREATE_OBJECT, \
@@ -803,7 +804,7 @@
 
 // Implementation detail: trace event macros create temporary variables
 // to keep instrumentation overhead low. These macros give each temporary
-// variable a unique name based on the line number to prevent name collissions.
+// variable a unique name based on the line number to prevent name collisions.
 #define INTERNAL_TRACE_EVENT_UID3(a,b) \
     trace_event_unique_##a##b
 #define INTERNAL_TRACE_EVENT_UID2(a,b) \
diff --git a/base/debug/trace_event_impl.cc b/base/debug/trace_event_impl.cc
index 6e1f08c..cc22424 100644
--- a/base/debug/trace_event_impl.cc
+++ b/base/debug/trace_event_impl.cc
@@ -1174,12 +1174,6 @@
     unsigned char flags) {
   DCHECK(name);
 
-  TimeDelta duration;
-  if (phase == TRACE_EVENT_PHASE_END && trace_options_ & ECHO_TO_CONSOLE) {
-    duration = timestamp - thread_event_start_times_[thread_id].top();
-    thread_event_start_times_[thread_id].pop();
-  }
-
   if (flags & TRACE_EVENT_FLAG_MANGLE_ID)
     id ^= process_id_hash_;
 
@@ -1189,20 +1183,17 @@
                flags);
 #endif
 
+  if (!IsCategoryGroupEnabled(category_group_enabled))
+    return;
+
   TimeTicks now = timestamp - time_offset_;
   EventCallback event_callback_copy;
 
   NotificationHelper notifier(this);
 
-  do {
-    AutoLock lock(lock_);
-    if (!IsCategoryGroupEnabled(category_group_enabled))
-      return;
-
-    event_callback_copy = event_callback_;
-    if (logged_events_->IsFull())
-      break;
-
+  // Check and update the current thread name only if the event is for the
+  // current thread to avoid locks in most cases.
+  if (thread_id == static_cast<int>(PlatformThread::CurrentId())) {
     const char* new_name = ThreadIdNameManager::GetInstance()->
         GetName(thread_id);
     // Check if the thread name has been set or changed since the previous
@@ -1213,6 +1204,7 @@
         new_name && *new_name) {
       g_current_thread_name.Get().Set(new_name);
 
+      AutoLock lock(lock_);
       hash_map<int, std::string>::iterator existing_name =
           thread_names_.find(thread_id);
       if (existing_name == thread_names_.end()) {
@@ -1232,15 +1224,29 @@
         }
       }
     }
+  }
 
-    TraceEvent trace_event(thread_id,
-        now, phase, category_group_enabled, name, id,
-        num_args, arg_names, arg_types, arg_values,
-        convertable_values, flags);
+  TraceEvent trace_event(thread_id,
+      now, phase, category_group_enabled, name, id,
+      num_args, arg_names, arg_types, arg_values,
+      convertable_values, flags);
+
+  do {
+    AutoLock lock(lock_);
+
+    event_callback_copy = event_callback_;
+    if (logged_events_->IsFull())
+      break;
 
     logged_events_->AddEvent(trace_event);
 
     if (trace_options_ & ECHO_TO_CONSOLE) {
+      TimeDelta duration;
+      if (phase == TRACE_EVENT_PHASE_END) {
+        duration = timestamp - thread_event_start_times_[thread_id].top();
+        thread_event_start_times_[thread_id].pop();
+      }
+
       std::string thread_name = thread_names_[thread_id];
       if (thread_colors_.find(thread_name) == thread_colors_.end())
         thread_colors_[thread_name] = (thread_colors_.size() % 6) + 1;
@@ -1263,6 +1269,9 @@
         log << base::StringPrintf(" (%.3f ms)", duration.InMillisecondsF());
 
       LOG(ERROR) << log.str() << "\x1b[0;m";
+
+      if (phase == TRACE_EVENT_PHASE_BEGIN)
+        thread_event_start_times_[thread_id].push(timestamp);
     }
 
     if (logged_events_->IsFull())
@@ -1272,9 +1281,6 @@
       notifier.AddNotificationWhileLocked(EVENT_WATCH_NOTIFICATION);
   } while (0); // release lock
 
-  if (phase == TRACE_EVENT_PHASE_BEGIN && trace_options_ & ECHO_TO_CONSOLE)
-    thread_event_start_times_[thread_id].push(timestamp);
-
   notifier.SendNotificationIfAny();
   if (event_callback_copy != NULL) {
     event_callback_copy(phase, category_group_enabled, name, id,
@@ -1455,6 +1461,7 @@
 }
 
 void TraceLog::RemoveProcessLabel(int label_id) {
+  AutoLock lock(lock_);
   base::hash_map<int, std::string>::iterator it = process_labels_.find(
         label_id);
   if (it == process_labels_.end())
diff --git a/base/debug/trace_event_impl.h b/base/debug/trace_event_impl.h
index c3ceec6..be1a104 100644
--- a/base/debug/trace_event_impl.h
+++ b/base/debug/trace_event_impl.h
@@ -55,7 +55,7 @@
   virtual ~ConvertableToTraceFormat() {}
 
   // Append the class info to the provided |out| string. The appended
-  // data must be a valid JSON object. Strings must be propertly quoted, and
+  // data must be a valid JSON object. Strings must be properly quoted, and
   // escaped. There is no processing applied to the content after it is
   // appended.
   virtual void AppendAsTraceFormat(std::string* out) const = 0;
@@ -65,7 +65,7 @@
 
 // Output records are "Events" and can be obtained via the
 // OutputCallback whenever the tracing system decides to flush. This
-// can happen at any time, on any thread, or you can programatically
+// can happen at any time, on any thread, or you can programmatically
 // force it to happen.
 class BASE_EXPORT TraceEvent {
  public:
@@ -291,7 +291,7 @@
     // Enable the sampling profiler.
     ENABLE_SAMPLING = 1 << 2,
 
-    // Echo to console. Events are discared.
+    // Echo to console. Events are discarded.
     ECHO_TO_CONSOLE = 1 << 3
   };
 
@@ -357,8 +357,8 @@
   typedef base::Callback<void(int)> NotificationCallback;
   void SetNotificationCallback(const NotificationCallback& cb);
 
-  // Not using base::Callback because of its limited by 7 parameteters.
-  // Also, using primitive type allows directly passsing callback from WebCore.
+  // Not using base::Callback because of its limited by 7 parameters.
+  // Also, using primitive type allows directly passing callback from WebCore.
   // WARNING: It is possible for the previously set callback to be called
   // after a call to SetEventCallback() that replaces or clears the callback.
   // This callback may be invoked on any thread.
@@ -511,7 +511,7 @@
     inline ~NotificationHelper();
 
     // Called only while TraceLog::lock_ is held. This ORs the given
-    // notification with any existing notifcations.
+    // notification with any existing notifications.
     inline void AddNotificationWhileLocked(int notification);
 
     // Called only while TraceLog::lock_ is NOT held. If there are any pending
diff --git a/base/platform_file_posix.cc b/base/platform_file_posix.cc
index e1bab1e..056577c 100644
--- a/base/platform_file_posix.cc
+++ b/base/platform_file_posix.cc
@@ -379,9 +379,50 @@
   info->is_directory = S_ISDIR(file_info.st_mode);
   info->is_symbolic_link = S_ISLNK(file_info.st_mode);
   info->size = file_info.st_size;
-  info->last_modified = base::Time::FromTimeT(file_info.st_mtime);
-  info->last_accessed = base::Time::FromTimeT(file_info.st_atime);
-  info->creation_time = base::Time::FromTimeT(file_info.st_ctime);
+
+#if defined(OS_LINUX)
+  const time_t last_modified_sec = file_info.st_mtim.tv_sec;
+  const int64 last_modified_nsec = file_info.st_mtim.tv_nsec;
+  const time_t last_accessed_sec = file_info.st_atim.tv_sec;
+  const int64 last_accessed_nsec = file_info.st_atim.tv_nsec;
+  const time_t creation_time_sec = file_info.st_ctim.tv_sec;
+  const int64 creation_time_nsec = file_info.st_ctim.tv_nsec;
+#elif defined(OS_ANDROID)
+  const time_t last_modified_sec = file_info.st_mtime;
+  const int64 last_modified_nsec = file_info.st_mtime_nsec;
+  const time_t last_accessed_sec = file_info.st_atime;
+  const int64 last_accessed_nsec = file_info.st_atime_nsec;
+  const time_t creation_time_sec = file_info.st_ctime;
+  const int64 creation_time_nsec = file_info.st_ctime_nsec;
+#elif defined(OS_MACOSX) || defined(OS_IOS) || defined(OS_BSD)
+  const time_t last_modified_sec = file_info.st_mtimespec.tv_sec;
+  const int64 last_modified_nsec = file_info.st_mtimespec.tv_nsec;
+  const time_t last_accessed_sec = file_info.st_atimespec.tv_sec;
+  const int64 last_accessed_nsec = file_info.st_atimespec.tv_nsec;
+  const time_t creation_time_sec = file_info.st_ctimespec.tv_sec;
+  const int64 creation_time_nsec = file_info.st_ctimespec.tv_nsec;
+#else
+  // TODO(gavinp): Investigate a good high resolution option for OS_NACL.
+  const time_t last_modified_sec = file_info.st_mtime;
+  const int64 last_modified_nsec = 0;
+  const time_t last_accessed_sec = file_info.st_atime;
+  const int64 last_accessed_nsec = 0;
+  const time_t creation_time_sec = file_info.st_ctime;
+  const int64 creation_time_nsec = 0;
+#endif
+
+  info->last_modified =
+      base::Time::FromTimeT(last_modified_sec) +
+      base::TimeDelta::FromMicroseconds(last_modified_nsec /
+                                        base::Time::kNanosecondsPerMicrosecond);
+  info->last_accessed =
+      base::Time::FromTimeT(last_accessed_sec) +
+      base::TimeDelta::FromMicroseconds(last_accessed_nsec /
+                                        base::Time::kNanosecondsPerMicrosecond);
+  info->creation_time =
+      base::Time::FromTimeT(creation_time_sec) +
+      base::TimeDelta::FromMicroseconds(creation_time_nsec /
+                                        base::Time::kNanosecondsPerMicrosecond);
   return true;
 }
 
diff --git a/base/power_monitor/power_monitor_unittest.cc b/base/power_monitor/power_monitor_unittest.cc
index 61b720e..5f7b531 100644
--- a/base/power_monitor/power_monitor_unittest.cc
+++ b/base/power_monitor/power_monitor_unittest.cc
@@ -3,7 +3,7 @@
 // found in the LICENSE file.
 
 #include "base/power_monitor/power_monitor.h"
-#include "base/power_monitor/power_monitor_test_base.h"
+#include "base/test/power_monitor_test_base.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace base {
diff --git a/base/process/internal_linux.cc b/base/process/internal_linux.cc
index 7da50b3..ee1107c 100644
--- a/base/process/internal_linux.cc
+++ b/base/process/internal_linux.cc
@@ -6,6 +6,7 @@
 
 #include <unistd.h>
 
+#include <map>
 #include <string>
 #include <vector>
 
@@ -15,6 +16,7 @@
 #include "base/strings/string_split.h"
 #include "base/strings/string_util.h"
 #include "base/threading/thread_restrictions.h"
+#include "base/time/time.h"
 
 namespace base {
 namespace internal {
@@ -47,19 +49,23 @@
   return pid;
 }
 
-bool ReadProcStats(pid_t pid, std::string* buffer) {
+bool ReadProcFile(const FilePath& file, std::string* buffer) {
   buffer->clear();
   // Synchronously reading files in /proc is safe.
   ThreadRestrictions::ScopedAllowIO allow_io;
 
-  FilePath stat_file = internal::GetProcPidDir(pid).Append(kStatFile);
-  if (!file_util::ReadFileToString(stat_file, buffer)) {
-    DLOG(WARNING) << "Failed to get process stats.";
+  if (!file_util::ReadFileToString(file, buffer)) {
+    DLOG(WARNING) << "Failed to read " << file.MaybeAsASCII();
     return false;
   }
   return !buffer->empty();
 }
 
+bool ReadProcStats(pid_t pid, std::string* buffer) {
+  FilePath stat_file = internal::GetProcPidDir(pid).Append(kStatFile);
+  return ReadProcFile(stat_file, buffer);
+}
+
 bool ParseProcStats(const std::string& stats_data,
                     std::vector<std::string>* proc_stats) {
   // |stats_data| may be empty if the process disappeared somehow.
@@ -98,6 +104,17 @@
   return true;
 }
 
+typedef std::map<std::string, std::string> ProcStatMap;
+void ParseProcStat(const std::string& contents, ProcStatMap* output) {
+  typedef std::pair<std::string, std::string> StringPair;
+  std::vector<StringPair> key_value_pairs;
+  SplitStringIntoKeyValuePairs(contents, ' ', '\n', &key_value_pairs);
+  for (size_t i = 0; i < key_value_pairs.size(); ++i) {
+    const StringPair& key_value_pair = key_value_pairs[i];
+    output->insert(key_value_pair);
+  }
+}
+
 int GetProcStatsFieldAsInt(const std::vector<std::string>& proc_stats,
                            ProcStatsFields field_num) {
   DCHECK_GE(field_num, VM_PPID);
@@ -138,5 +155,36 @@
   return GetProcStatsFieldAsSizeT(proc_stats, field_num);
 }
 
+Time GetBootTime() {
+  FilePath path("/proc/stat");
+  std::string contents;
+  if (!ReadProcFile(path, &contents))
+    return Time();
+  ProcStatMap proc_stat;
+  ParseProcStat(contents, &proc_stat);
+  ProcStatMap::const_iterator btime_it = proc_stat.find("btime");
+  if (btime_it == proc_stat.end())
+    return Time();
+  int btime;
+  if (!StringToInt(btime_it->second, &btime))
+    return Time();
+  return Time::FromTimeT(btime);
+}
+
+TimeDelta ClockTicksToTimeDelta(int clock_ticks) {
+  // This queries the /proc-specific scaling factor which is
+  // conceptually the system hertz.  To dump this value on another
+  // system, try
+  //   od -t dL /proc/self/auxv
+  // and look for the number after 17 in the output; mine is
+  //   0000040          17         100           3   134512692
+  // which means the answer is 100.
+  // It may be the case that this value is always 100.
+  static const int kHertz = sysconf(_SC_CLK_TCK);
+
+  return TimeDelta::FromMicroseconds(
+      Time::kMicrosecondsPerSecond * clock_ticks / kHertz);
+}
+
 }  // namespace internal
 }  // namespace base
diff --git a/base/process/internal_linux.h b/base/process/internal_linux.h
index 88d32ee..a10cee3 100644
--- a/base/process/internal_linux.h
+++ b/base/process/internal_linux.h
@@ -11,6 +11,10 @@
 #include "base/files/file_path.h"
 
 namespace base {
+
+class Time;
+class TimeDelta;
+
 namespace internal {
 
 // "/proc"
@@ -49,6 +53,7 @@
   VM_UTIME          = 13,  // Time scheduled in user mode in clock ticks.
   VM_STIME          = 14,  // Time scheduled in kernel mode in clock ticks.
   VM_NUMTHREADS     = 19,  // Number of threads.
+  VM_STARTTIME      = 21,  // The time the process started in clock ticks.
   VM_VSIZE          = 22,  // Virtual memory size in bytes.
   VM_RSS            = 23,  // Resident Set Size in pages.
 };
@@ -72,6 +77,12 @@
 size_t ReadProcStatsAndGetFieldAsSizeT(pid_t pid,
                                        ProcStatsFields field_num);
 
+// Returns the time that the OS started. Clock ticks are relative to this.
+Time GetBootTime();
+
+// Converts Linux clock ticks to a wall time delta.
+TimeDelta ClockTicksToTimeDelta(int clock_ticks);
+
 }  // namespace internal
 }  // namespace base
 
diff --git a/base/process/process_info.h b/base/process/process_info.h
index e72c56b..e9e7b4e 100644
--- a/base/process/process_info.h
+++ b/base/process/process_info.h
@@ -15,9 +15,9 @@
 // Vends information about the current process.
 class BASE_EXPORT CurrentProcessInfo {
  public:
-  // Returns the time at which the process was launched or NULL if an error
-  // occurred retrieving the information.
-  static const Time* CreationTime();
+  // Returns the time at which the process was launched. May be empty if an
+  // error occurred retrieving the information.
+  static const Time CreationTime();
 };
 
 }  // namespace base
diff --git a/base/process/process_info_linux.cc b/base/process/process_info_linux.cc
new file mode 100644
index 0000000..da34c18
--- /dev/null
+++ b/base/process/process_info_linux.cc
@@ -0,0 +1,27 @@
+// 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/process/process_info.h"
+
+#include "base/basictypes.h"
+#include "base/logging.h"
+#include "base/process/internal_linux.h"
+#include "base/process/process_handle.h"
+#include "base/time/time.h"
+
+namespace base {
+
+//static
+const Time CurrentProcessInfo::CreationTime() {
+  ProcessHandle pid = GetCurrentProcessHandle();
+  int start_ticks = internal::ReadProcStatsAndGetFieldAsInt(
+      pid, internal::VM_STARTTIME);
+  DCHECK(start_ticks);
+  TimeDelta start_offset = internal::ClockTicksToTimeDelta(start_ticks);
+  Time boot_time = internal::GetBootTime();
+  DCHECK(!boot_time.is_null());
+  return Time(boot_time + start_offset);
+}
+
+}  // namespace base
diff --git a/base/process/process_info_mac.cc b/base/process/process_info_mac.cc
index d83acd1..ab8394b 100644
--- a/base/process/process_info_mac.cc
+++ b/base/process/process_info_mac.cc
@@ -12,32 +12,20 @@
 #include "base/memory/scoped_ptr.h"
 #include "base/time/time.h"
 
-namespace {
+namespace base {
 
-using base::Time;
-
-// Returns the process creation time, or NULL if an error occurred.
-Time* ProcessCreationTimeInternal() {
+//static
+const Time CurrentProcessInfo::CreationTime() {
   int mib[] = { CTL_KERN, KERN_PROC, KERN_PROC_PID, getpid() };
   size_t len = 0;
   if (sysctl(mib, arraysize(mib), NULL, &len, NULL, 0) < 0)
-    return NULL;
+    return Time();
 
   scoped_ptr_malloc<struct kinfo_proc>
       proc(static_cast<struct kinfo_proc*>(malloc(len)));
   if (sysctl(mib, arraysize(mib), proc.get(), &len, NULL, 0) < 0)
-    return NULL;
-  return new Time(Time::FromTimeVal(proc->kp_proc.p_un.__p_starttime));
-}
-
-}  // namespace
-
-namespace base {
-
-//static
-const Time* CurrentProcessInfo::CreationTime() {
-  static Time* process_creation_time = ProcessCreationTimeInternal();
-  return process_creation_time;
+    return Time();
+  return Time::FromTimeVal(proc->kp_proc.p_un.__p_starttime);
 }
 
 }  // namespace base
diff --git a/base/process/process_info_win.cc b/base/process/process_info_win.cc
index 5290b76..b930ae6 100644
--- a/base/process/process_info_win.cc
+++ b/base/process/process_info_win.cc
@@ -9,29 +9,17 @@
 #include "base/basictypes.h"
 #include "base/time/time.h"
 
-namespace {
+namespace base {
 
-using base::Time;
-
-// Returns the process creation time, or NULL if an error occurred.
-Time* ProcessCreationTimeInternal() {
+//static
+const Time CurrentProcessInfo::CreationTime() {
   FILETIME creation_time = {};
   FILETIME ignore = {};
   if (::GetProcessTimes(::GetCurrentProcess(), &creation_time, &ignore,
       &ignore, &ignore) == false)
-    return NULL;
+    return Time();
 
-  return new Time(Time::FromFileTime(creation_time));
-}
-
-}  // namespace
-
-namespace base {
-
-//static
-const Time* CurrentProcessInfo::CreationTime() {
-  static Time* process_creation_time = ProcessCreationTimeInternal();
-  return process_creation_time;
+  return Time::FromFileTime(creation_time);
 }
 
 }  // namespace base
diff --git a/base/process/process_metrics_linux.cc b/base/process/process_metrics_linux.cc
index 0171020..1c86ee4 100644
--- a/base/process/process_metrics_linux.cc
+++ b/base/process/process_metrics_linux.cc
@@ -167,16 +167,6 @@
 }
 
 double ProcessMetrics::GetCPUUsage() {
-  // This queries the /proc-specific scaling factor which is
-  // conceptually the system hertz.  To dump this value on another
-  // system, try
-  //   od -t dL /proc/self/auxv
-  // and look for the number after 17 in the output; mine is
-  //   0000040          17         100           3   134512692
-  // which means the answer is 100.
-  // It may be the case that this value is always 100.
-  static const int kHertz = sysconf(_SC_CLK_TCK);
-
   struct timeval now;
   int retval = gettimeofday(&now, NULL);
   if (retval)
@@ -200,8 +190,10 @@
   // We have the number of jiffies in the time period.  Convert to percentage.
   // Note this means we will go *over* 100 in the case where multiple threads
   // are together adding to more than one CPU's worth.
-  int percentage = 100 * (cpu - last_cpu_) /
-      (kHertz * TimeDelta::FromMicroseconds(time_delta).InSecondsF());
+  TimeDelta cpu_time = internal::ClockTicksToTimeDelta(cpu);
+  TimeDelta last_cpu_time = internal::ClockTicksToTimeDelta(last_cpu_);
+  int percentage = 100 * (cpu_time - last_cpu_time).InSecondsF() /
+      TimeDelta::FromMicroseconds(time_delta).InSecondsF();
 
   last_time_ = time;
   last_cpu_ = cpu;
diff --git a/base/strings/string_split.cc b/base/strings/string_split.cc
index d959fd0..210789c 100644
--- a/base/strings/string_split.cc
+++ b/base/strings/string_split.cc
@@ -80,12 +80,11 @@
   return true;
 }
 
-bool SplitStringIntoKeyValuePairs(
-    const std::string& line,
-    char key_value_delimiter,
-    char key_value_pair_delimiter,
-    std::vector<std::pair<std::string, std::string> >* kv_pairs) {
-  kv_pairs->clear();
+bool SplitStringIntoKeyValuePairs(const std::string& line,
+                                  char key_value_delimiter,
+                                  char key_value_pair_delimiter,
+                                  StringPairs* key_value_pairs) {
+  key_value_pairs->clear();
 
   std::vector<std::string> pairs;
   SplitString(line, key_value_pair_delimiter, &pairs);
@@ -107,7 +106,7 @@
       success = false;
     }
     DCHECK_LE(value.size(), 1U);
-    kv_pairs->push_back(
+    key_value_pairs->push_back(
         make_pair(key, value.empty() ? std::string() : value[0]));
   }
   return success;
diff --git a/base/strings/string_split.h b/base/strings/string_split.h
index 2803752..faf08d6 100644
--- a/base/strings/string_split.h
+++ b/base/strings/string_split.h
@@ -36,11 +36,13 @@
                                           std::string* key,
                                           std::vector<std::string>* values);
 
+typedef std::vector<std::pair<std::string, std::string> > StringPairs;;
+
 BASE_EXPORT bool SplitStringIntoKeyValuePairs(
     const std::string& line,
     char key_value_delimiter,
     char key_value_pair_delimiter,
-    std::vector<std::pair<std::string, std::string> >* kv_pairs);
+    StringPairs* key_value_pairs);
 
 // The same as SplitString, but use a substring delimiter instead of a char.
 BASE_EXPORT void SplitStringUsingSubstr(const string16& str,
diff --git a/base/power_monitor/power_monitor_test_base.cc b/base/test/power_monitor_test_base.cc
similarity index 96%
rename from base/power_monitor/power_monitor_test_base.cc
rename to base/test/power_monitor_test_base.cc
index 990b8d1..73438ea 100644
--- a/base/power_monitor/power_monitor_test_base.cc
+++ b/base/test/power_monitor_test_base.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 "base/power_monitor/power_monitor_test_base.h"
+#include "base/test/power_monitor_test_base.h"
 
 #include "base/message_loop/message_loop.h"
 #include "base/power_monitor/power_monitor.h"
diff --git a/base/power_monitor/power_monitor_test_base.h b/base/test/power_monitor_test_base.h
similarity index 84%
rename from base/power_monitor/power_monitor_test_base.h
rename to base/test/power_monitor_test_base.h
index 6f82fc0..95b530e 100644
--- a/base/power_monitor/power_monitor_test_base.h
+++ b/base/test/power_monitor_test_base.h
@@ -2,13 +2,16 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#ifndef BASE_TEST_POWER_MONITOR_TEST_BASE_H_
+#define BASE_TEST_POWER_MONITOR_TEST_BASE_H_
+
 #include "base/message_loop/message_loop.h"
 #include "base/power_monitor/power_monitor.h"
 #include "base/power_monitor/power_monitor_source.h"
 
 namespace base {
 
-class BASE_EXPORT PowerMonitorTestSource : public PowerMonitorSource {
+class PowerMonitorTestSource : public PowerMonitorSource {
  public:
   PowerMonitorTestSource();
   virtual ~PowerMonitorTestSource();
@@ -24,7 +27,7 @@
   MessageLoop message_loop_;
 };
 
-class BASE_EXPORT PowerMonitorTestObserver : public PowerObserver {
+class PowerMonitorTestObserver : public PowerObserver {
  public:
   PowerMonitorTestObserver();
   virtual ~PowerMonitorTestObserver();
@@ -47,4 +50,6 @@
   int resumes_;  // Count of OnResume notifications.
 };
 
-}  // namespace base
\ No newline at end of file
+}  // namespace base
+
+#endif  // BASE_TEST_POWER_MONITOR_TEST_BASE_H_
\ No newline at end of file
diff --git a/base/win/registry.cc b/base/win/registry.cc
index 588bd27..8bfe432 100644
--- a/base/win/registry.cc
+++ b/base/win/registry.cc
@@ -39,6 +39,11 @@
       watch_event_(0) {
 }
 
+RegKey::RegKey(HKEY key)
+    : key_(key),
+      watch_event_(0) {
+}
+
 RegKey::RegKey(HKEY rootkey, const wchar_t* subkey, REGSAM access)
     : key_(NULL),
       watch_event_(0) {
@@ -112,6 +117,20 @@
   }
 }
 
+void RegKey::Set(HKEY key) {
+  if (key_ != key) {
+    Close();
+    key_ = key;
+  }
+}
+
+HKEY RegKey::Take() {
+  StopWatching();
+  HKEY key = key_;
+  key_ = NULL;
+  return key;
+}
+
 bool RegKey::HasValue(const wchar_t* name) const {
   return RegQueryValueEx(key_, name, 0, NULL, NULL, NULL) == ERROR_SUCCESS;
 }
diff --git a/base/win/registry.h b/base/win/registry.h
index 7a3d970..f97f4f5 100644
--- a/base/win/registry.h
+++ b/base/win/registry.h
@@ -26,6 +26,7 @@
 class BASE_EXPORT RegKey {
  public:
   RegKey();
+  explicit RegKey(HKEY key);
   RegKey(HKEY rootkey, const wchar_t* subkey, REGSAM access);
   ~RegKey();
 
@@ -46,6 +47,12 @@
   // Closes this reg key.
   void Close();
 
+  // Replaces the handle of the registry key and takes ownership of the handle.
+  void Set(HKEY key);
+
+  // Transfers ownership away from this object.
+  HKEY Take();
+
   // Returns false if this key does not have the specified value, of if an error
   // occurrs while attempting to access it.
   bool HasValue(const wchar_t* value_name) const;
diff --git a/build/all.gyp b/build/all.gyp
index 865bb18..d90b5a5 100644
--- a/build/all.gyp
+++ b/build/all.gyp
@@ -255,7 +255,7 @@
             '../sandbox/sandbox.gyp:sbox_integration_tests',
             '../sandbox/sandbox.gyp:sbox_unittests',
             '../sandbox/sandbox.gyp:sbox_validation_tests',
-            '../third_party/WebKit/Tools/DumpRenderTree/DumpRenderTree.gyp/DumpRenderTree.gyp:copy_TestNetscapePlugIn',
+            '../third_party/WebKit/public/blink_test_plugin.gyp:blink_test_plugin',
             '../ui/app_list/app_list.gyp:app_list_unittests',
             '../ui/views/views.gyp:views_unittests',
           ],
@@ -645,7 +645,7 @@
             '../ui/views/views.gyp:views_unittests',
             '../url/url.gyp:url_unittests',
             '../webkit/renderer/compositor_bindings/compositor_bindings_tests.gyp:webkit_compositor_bindings_unittests',
-            '../third_party/WebKit/Tools/DumpRenderTree/DumpRenderTree.gyp/DumpRenderTree.gyp:copy_TestNetscapePlugIn',
+            '../third_party/WebKit/public/blink_test_plugin.gyp:blink_test_plugin',
           ],
           'conditions': [
              ['target_arch!="x64"', {
diff --git a/build/android/ant/apk-codegen.xml b/build/android/ant/apk-codegen.xml
index e60d6ca..37abb07 100644
--- a/build/android/ant/apk-codegen.xml
+++ b/build/android/ant/apk-codegen.xml
@@ -26,15 +26,13 @@
 
   <!-- tools location -->
   <property name="sdk.dir" location="${ANDROID_SDK_ROOT}"/>
-  <property name="target" value="android-${ANDROID_SDK_VERSION}"/>
-  <property name="android.tools.dir" location="${sdk.dir}/tools" />
-  <property name="android.platform.tools.dir" location="${sdk.dir}/platform-tools" />
-  <property name="aapt" location="${android.platform.tools.dir}/aapt" />
+  <property name="android.sdk.tools.dir" location="${ANDROID_SDK_TOOLS}" />
+  <property name="aapt" location="${android.sdk.tools.dir}/aapt" />
   <property name="project.target.android.jar" location="${ANDROID_SDK_JAR}" />
 
   <!-- jar file from where the tasks are loaded -->
   <path id="android.antlibs">
-      <pathelement path="${sdk.dir}/tools/lib/anttasks.jar" />
+      <pathelement path="${sdk.dir}/tools/lib/ant-tasks.jar" />
   </path>
 
   <!-- Custom tasks -->
diff --git a/build/android/ant/apk-compile.xml b/build/android/ant/apk-compile.xml
index 10ffd37..4f3d664 100644
--- a/build/android/ant/apk-compile.xml
+++ b/build/android/ant/apk-compile.xml
@@ -39,7 +39,7 @@
 
   <!-- jar file from where the tasks are loaded -->
   <path id="android.antlibs">
-      <pathelement path="${sdk.dir}/tools/lib/anttasks.jar" />
+      <pathelement path="${sdk.dir}/tools/lib/ant-tasks.jar" />
   </path>
 
   <!-- Custom tasks -->
diff --git a/build/android/ant/apk-obfuscate.xml b/build/android/ant/apk-obfuscate.xml
index d0600ca..b15ce73 100644
--- a/build/android/ant/apk-obfuscate.xml
+++ b/build/android/ant/apk-obfuscate.xml
@@ -26,7 +26,6 @@
 
   <!-- tools location -->
   <property name="sdk.dir" location="${ANDROID_SDK_ROOT}"/>
-  <property name="target" value="android-${ANDROID_SDK_VERSION}"/>
   <property name="android.tools.dir" location="${sdk.dir}/tools" />
 
   <property name="project.target.android.jar" location="${ANDROID_SDK_JAR}" />
@@ -37,7 +36,7 @@
 
   <!-- jar file from where the tasks are loaded -->
   <path id="android.antlibs">
-      <pathelement path="${sdk.dir}/tools/lib/anttasks.jar" />
+      <pathelement path="${sdk.dir}/tools/lib/ant-tasks.jar" />
   </path>
 
   <!-- Custom tasks -->
diff --git a/build/android/ant/apk-package-resources.xml b/build/android/ant/apk-package-resources.xml
index c29dff7..3bfd3c9 100644
--- a/build/android/ant/apk-package-resources.xml
+++ b/build/android/ant/apk-package-resources.xml
@@ -24,12 +24,11 @@
   <!-- tools location -->
   <property name="sdk.dir" location="${ANDROID_SDK_ROOT}"/>
   <property name="project.target.android.jar" location="${ANDROID_SDK_JAR}" />
-  <property name="android.tools.dir" location="${sdk.dir}/tools" />
-  <property name="android.platform.tools.dir" location="${sdk.dir}/platform-tools" />
+  <property name="android.sdk.tools.dir" location="${ANDROID_SDK_TOOLS}" />
 
   <!-- jar file from where the tasks are loaded -->
   <path id="android.antlibs">
-    <pathelement path="${sdk.dir}/tools/lib/anttasks.jar" />
+    <pathelement path="${sdk.dir}/tools/lib/ant-tasks.jar" />
   </path>
 
   <!-- Custom tasks -->
@@ -48,7 +47,7 @@
   <property name="asset.dir" value="${ASSET_DIR}" />
   <property name="asset.absolute.dir" location="${asset.dir}" />
 
-  <property name="aapt" location="${android.platform.tools.dir}/aapt" />
+  <property name="aapt" location="${android.sdk.tools.dir}/aapt" />
 
   <property name="version.code" value="${APP_MANIFEST_VERSION_CODE}"/>
   <property name="version.name" value="${APP_MANIFEST_VERSION_NAME}"/>
diff --git a/build/android/ant/apk-package.xml b/build/android/ant/apk-package.xml
index 61524f9..eeb156c 100644
--- a/build/android/ant/apk-package.xml
+++ b/build/android/ant/apk-package.xml
@@ -24,7 +24,7 @@
 
   <!-- jar file from where the tasks are loaded -->
   <path id="android.antlibs">
-    <pathelement path="${sdk.dir}/tools/lib/anttasks.jar" />
+    <pathelement path="${sdk.dir}/tools/lib/ant-tasks.jar" />
   </path>
 
   <!-- Custom tasks -->
diff --git a/build/android/bb_run_sharded_steps.py b/build/android/bb_run_sharded_steps.py
index 086a3a1..9b36957 100755
--- a/build/android/bb_run_sharded_steps.py
+++ b/build/android/bb_run_sharded_steps.py
@@ -175,12 +175,10 @@
           os.kill(int(pid), signal.SIGQUIT)
         except Exception as e:
           logging.warning('Failed killing %s %s %s', server, pid, e)
-  # Restart the adb server with full trace, and redirect stderr to stdout
-  # so the extra tracing won't confuse higher up layers.
-  os.environ['ADB_TRACE'] = 'all'
+  # Restart the adb server with taskset to set a single CPU affinity.
   cmd_helper.RunCmd(['adb', 'kill-server'])
-  cmd_helper.RunCmd(['adb', 'start-server'])
-  cmd_helper.RunCmd(['adb', 'root'])
+  cmd_helper.RunCmd(['taskset', '-c', '0', 'adb', 'start-server'])
+  cmd_helper.RunCmd(['taskset', '-c', '0', 'adb', 'root'])
   i = 1
   while not android_commands.GetAttachedDevices():
     time.sleep(i)
diff --git a/build/android/buildbot/bb_device_steps.py b/build/android/buildbot/bb_device_steps.py
index 8bc537f..32438ae 100755
--- a/build/android/buildbot/bb_device_steps.py
+++ b/build/android/buildbot/bb_device_steps.py
@@ -64,7 +64,8 @@
       'webview:android_webview/test/data/device_files'),
     ])
 
-VALID_TESTS = set(['chromedriver', 'ui', 'unit', 'webkit', 'webkit_layout'])
+VALID_TESTS = set(['chromedriver', 'ui', 'unit', 'webkit', 'webkit_layout',
+                   'webrtc'])
 
 RunCmd = bb_utils.RunCmd
 
@@ -277,13 +278,18 @@
   RunWebkitLint(options.target)
 
 
+def RunWebRTCTests(options):
+  RunTestSuites(options, gtest_config.WEBRTC_TEST_SUITES)
+
+
 def GetTestStepCmds():
   return [
       ('chromedriver', RunChromeDriverTests),
       ('unit', RunUnitTests),
       ('ui', RunInstrumentationTests),
       ('webkit', RunWebkitTests),
-      ('webkit_layout', RunWebkitLayoutTests)
+      ('webkit_layout', RunWebkitLayoutTests),
+      ('webrtc', RunWebRTCTests),
   ]
 
 
diff --git a/build/android/buildbot/bb_run_bot.py b/build/android/buildbot/bb_run_bot.py
index 6718aef..7637024 100755
--- a/build/android/buildbot/bb_run_bot.py
+++ b/build/android/buildbot/bb_run_bot.py
@@ -161,6 +161,7 @@
       B('webkit-latest-contentshell', H(compile_step),
         T(['webkit_layout'], ['--auto-reconnect'])),
       B('builder-unit-tests', H(compile_step), T(['unit'])),
+      B('webrtc-tests', H(std_test_steps), T(['webrtc'], [flakiness_server])),
 
       # Generic builder config (for substring match).
       B('builder', H(std_build_steps)),
@@ -179,6 +180,7 @@
       ('try-tests', 'main-tests'),
       ('try-fyi-tests', 'fyi-tests'),
       ('webkit-latest-tests', 'main-tests'),
+      ('webrtc-builder', 'main-builder-rel'),
   ]
   for to_id, from_id in copy_map:
     assert to_id not in bot_map
diff --git a/build/android/dex_action.gypi b/build/android/dex_action.gypi
index c41effb..ac956b6 100644
--- a/build/android/dex_action.gypi
+++ b/build/android/dex_action.gypi
@@ -47,7 +47,7 @@
   'action': [
     'python', '<(DEPTH)/build/android/gyp/dex.py',
     '--dex-path=<(output_path)',
-    '--android-sdk-root=<(android_sdk_root)',
+    '--android-sdk-tools=<(android_sdk_tools)',
     '--configuration-name=<(CONFIGURATION_NAME)',
     '--proguard-enabled=<(proguard_enabled)',
     '--proguard-enabled-input-path=<(proguard_enabled_input_path)',
diff --git a/build/android/envsetup.sh b/build/android/envsetup.sh
index 33b6764..f9e3e5e 100755
--- a/build/android/envsetup.sh
+++ b/build/android/envsetup.sh
@@ -88,9 +88,6 @@
   echo "${CHROME_SRC}"
 fi
 
-# Android sdk platform version to use
-export ANDROID_SDK_VERSION=17
-
 if [[ "${ANDROID_SDK_BUILD}" -eq 1 ]]; then
   if [[ -z "${TARGET_ARCH}" ]]; then
     return 1
diff --git a/build/android/envsetup_functions.sh b/build/android/envsetup_functions.sh
index d1a894b..9554bc9 100755
--- a/build/android/envsetup_functions.sh
+++ b/build/android/envsetup_functions.sh
@@ -62,6 +62,8 @@
   export PATH=$PATH:${ANDROID_NDK_ROOT}
   export PATH=$PATH:${ANDROID_SDK_ROOT}/tools
   export PATH=$PATH:${ANDROID_SDK_ROOT}/platform-tools
+  export PATH=$PATH:${ANDROID_SDK_ROOT}/build-tools/\
+${ANDROID_SDK_BUILD_TOOLS_VERSION}
 
   # This must be set before ANDROID_TOOLCHAIN, so that clang could find the
   # gold linker.
@@ -216,6 +218,9 @@
 #  > make
 ################################################################################
 sdk_build_init() {
+  export ANDROID_SDK_VERSION=18
+  export ANDROID_SDK_BUILD_TOOLS_VERSION=18.0.1
+
   # If ANDROID_NDK_ROOT is set when envsetup is run, use the ndk pointed to by
   # the environment variable.  Otherwise, use the default ndk from the tree.
   if [[ -z "${ANDROID_NDK_ROOT}" || ! -d "${ANDROID_NDK_ROOT}" ]]; then
@@ -252,6 +257,9 @@
     return 1
   fi
 
+  # Directory containing build-tools: aapt, aidl, dx
+  export ANDROID_SDK_TOOLS="${ANDROID_SDK_ROOT}/build-tools/\
+${ANDROID_SDK_BUILD_TOOLS_VERSION}"
 }
 
 ################################################################################
@@ -260,6 +268,9 @@
 # settings specified there.
 #############################################################################
 webview_build_init() {
+  # Use the latest API in the AOSP prebuilts directory (change with AOSP roll).
+  export ANDROID_SDK_VERSION=17
+
   # For the WebView build we always use the NDK and SDK in the Android tree,
   # and we don't touch ANDROID_TOOLCHAIN which is already set by Android.
   export ANDROID_NDK_ROOT=${ANDROID_BUILD_TOP}/prebuilts/ndk/8
diff --git a/build/android/findbugs_filter/findbugs_exclude.xml b/build/android/findbugs_filter/findbugs_exclude.xml
index ab27ae4..7b6860d 100644
--- a/build/android/findbugs_filter/findbugs_exclude.xml
+++ b/build/android/findbugs_filter/findbugs_exclude.xml
@@ -21,11 +21,16 @@
   <Match>
     <Class name="~org\.chromium\.content\..*\.NativeLibraries.*?" />
   </Match>
+  <!-- Ignore errors in JavaBridge due to reflection. -->
   <Match>
     <Class name="~.*\.JavaBridge.*"/>
-    <!-- Ignore errors in JavaBridge due to reflection. -->
     <Bug code="UuF,UrF,UMAC" />
   </Match>
+  <!-- "Struct" like classes expect to have unused public data members -->
+  <Match>
+    <Class name="~.*android_webview.*FileChooserParams"/>
+    <Bug code="UrF" />
+  </Match>
   <!-- Ignore "reliance on default String encoding" warnings, as we're not multi-platform -->
   <Bug pattern="DM_DEFAULT_ENCODING" />
   <!-- Ignore bugs that are often false-positives in test code -->
diff --git a/build/android/gyp/apk_install.py b/build/android/gyp/apk_install.py
index f0ed973..e308aab 100755
--- a/build/android/gyp/apk_install.py
+++ b/build/android/gyp/apk_install.py
@@ -54,8 +54,6 @@
 
 def main(argv):
   parser = optparse.OptionParser()
-  parser.add_option('--android-sdk-tools',
-      help='Path to Android SDK tools.')
   parser.add_option('--apk-path',
       help='Path to .apk to install.')
   parser.add_option('--install-record',
diff --git a/build/android/gyp/dex.py b/build/android/gyp/dex.py
index 86f3878..21e1183 100755
--- a/build/android/gyp/dex.py
+++ b/build/android/gyp/dex.py
@@ -14,7 +14,7 @@
 
 
 def DoDex(options, paths):
-  dx_binary = os.path.join(options.android_sdk_root, 'platform-tools', 'dx')
+  dx_binary = os.path.join(options.android_sdk_tools, 'dx')
   dex_cmd = [dx_binary, '--dex', '--output', options.dex_path] + paths
 
   record_path = '%s.md5.stamp' % options.dex_path
@@ -29,7 +29,8 @@
 
 def main(argv):
   parser = optparse.OptionParser()
-  parser.add_option('--android-sdk-root', help='Android sdk root directory.')
+  parser.add_option('--android-sdk-tools',
+                    help='Android sdk build tools directory.')
   parser.add_option('--dex-path', help='Dex output path.')
   parser.add_option('--configuration-name',
       help='The build CONFIGURATION_NAME.')
diff --git a/build/android/gyp/process_resources.py b/build/android/gyp/process_resources.py
index 40f1017..393a666 100755
--- a/build/android/gyp/process_resources.py
+++ b/build/android/gyp/process_resources.py
@@ -21,7 +21,7 @@
   parser = optparse.OptionParser()
   parser.add_option('--android-sdk', help='path to the Android SDK folder')
   parser.add_option('--android-sdk-tools',
-                    help='path to the Android SDK platform tools folder')
+                    help='path to the Android SDK build tools folder')
   parser.add_option('--R-dir', help='directory to hold generated R.java')
   parser.add_option('--res-dirs',
                     help='directories containing resources to be packaged')
@@ -43,8 +43,8 @@
     parser.error('No positional arguments should be given.')
 
   # Check that required options have been provided.
-  required_options = ('android_sdk', 'android_sdk_tools', 'R_dir', 'res_dirs',
-                      'crunch_input_dir', 'crunch_output_dir')
+  required_options = ('android_sdk', 'android_sdk_tools', 'R_dir',
+                      'res_dirs', 'crunch_input_dir', 'crunch_output_dir')
   build_utils.CheckOptions(options, parser, required=required_options)
 
   return options
diff --git a/build/android/pylib/cmd_helper.py b/build/android/pylib/cmd_helper.py
index de091ef..1237912 100644
--- a/build/android/pylib/cmd_helper.py
+++ b/build/android/pylib/cmd_helper.py
@@ -100,7 +100,8 @@
 
 
 class OutDirectory(object):
-  _out_directory = os.path.join(constants.DIR_SOURCE_ROOT, 'out')
+  _out_directory = os.path.join(constants.DIR_SOURCE_ROOT,
+      os.environ.get('CHROMIUM_OUT_DIR','out'))
   @staticmethod
   def set(out_directory):
     OutDirectory._out_directory = out_directory
diff --git a/build/android/pylib/constants.py b/build/android/pylib/constants.py
index 6ca9a31..6cbe727 100644
--- a/build/android/pylib/constants.py
+++ b/build/android/pylib/constants.py
@@ -74,7 +74,7 @@
 
 SCREENSHOTS_DIR = os.path.join(DIR_SOURCE_ROOT, 'out_screenshots')
 
-ANDROID_SDK_VERSION = 17
+ANDROID_SDK_VERSION = 18
 ANDROID_SDK_ROOT = os.path.join(DIR_SOURCE_ROOT,
                                 'third_party/android_tools/sdk')
 ANDROID_NDK_ROOT = os.path.join(DIR_SOURCE_ROOT,
diff --git a/build/android/pylib/gtest/filter/ui_unittests_disabled b/build/android/pylib/gtest/filter/ui_unittests_disabled
index ac8c536..57db61f 100644
--- a/build/android/pylib/gtest/filter/ui_unittests_disabled
+++ b/build/android/pylib/gtest/filter/ui_unittests_disabled
@@ -4,10 +4,13 @@
 CanvasTest.StringWidth
 ClipboardTest.RTFTest
 FontListTest.FontDescString_FromFont
+FontListTest.FontDescString_FromFontNamesStyleAndSize
 FontListTest.FontDescString_FromFontVector
 FontListTest.FontDescString_FromFontWithNonNormalStyle
 FontListTest.Fonts_DeriveFontList
 FontListTest.Fonts_DeriveFontListWithSize
+FontListTest.Fonts_DeriveFontListWithSizeDelta
+FontListTest.Fonts_DeriveFontListWithSizeDeltaAndStyle
 FontListTest.Fonts_DescStringWithStyleInFlexibleFormat_RoundTrip
 FontListTest.Fonts_FontVector_RoundTrip
 FontListTest.Fonts_FromDescString
diff --git a/build/android/pylib/gtest/gtest_config.py b/build/android/pylib/gtest/gtest_config.py
index d74c032..f77d858 100644
--- a/build/android/pylib/gtest/gtest_config.py
+++ b/build/android/pylib/gtest/gtest_config.py
@@ -6,7 +6,6 @@
 
 # Add new suites here before upgrading them to the stable list below.
 EXPERIMENTAL_TEST_SUITES = [
-    'content_browsertests',
 ]
 
 # Do not modify this list without approval of an android owner.
@@ -30,4 +29,20 @@
     'webkit_unit_tests',
     'breakpad_unittests',
     'sandbox_linux_unittests',
+    'content_browsertests',
+]
+
+WEBRTC_TEST_SUITES = [
+    'audio_decoder_unittests',
+    'common_audio_unittests',
+    'common_video_unittests',
+    'metrics_unittests',
+    'modules_integrationtests',
+    'modules_unittests',
+    'neteq_unittests',
+    'system_wrappers_unittests',
+    'test_support_unittests',
+    'tools_unittests',
+    'video_engine_core_unittests',
+    'voice_engine_unittests',
 ]
diff --git a/build/android/test_runner.py b/build/android/test_runner.py
index 8655720..acee213 100755
--- a/build/android/test_runner.py
+++ b/build/android/test_runner.py
@@ -357,16 +357,22 @@
 
 def AddMonkeyTestOptions(option_parser):
   """Adds monkey test options to |option_parser|."""
+
+  option_parser.usage = '%prog monkey [options]'
+  option_parser.command_list = []
+  option_parser.example = (
+      '%prog monkey --package-name=org.chromium.content_shell_apk'
+      ' --activity-name=.ContentShellActivity')
+
   option_parser.add_option('--package-name', help='Allowed package.')
   option_parser.add_option(
-      '--activity-name', default='com.google.android.apps.chrome.Main',
-      help='Name of the activity to start [default: %default].')
+      '--activity-name', help='Name of the activity to start.')
   option_parser.add_option(
       '--event-count', default=10000, type='int',
       help='Number of events to generate [default: %default].')
   option_parser.add_option(
       '--category', default='',
-      help='A list of allowed categories [default: %default].')
+      help='A list of allowed categories.')
   option_parser.add_option(
       '--throttle', default=100, type='int',
       help='Delay between events (ms) [default: %default]. ')
@@ -676,8 +682,7 @@
       command_list=VALID_COMMANDS.keys())
 
   if len(argv) < 2 or argv[1] not in VALID_COMMANDS:
-    option_parser.print_help()
-    return 0
+    option_parser.error('Invalid command.')
   command = argv[1]
   VALID_COMMANDS[command].add_options_func(option_parser)
   options, args = option_parser.parse_args(argv)
diff --git a/build/common.gypi b/build/common.gypi
index 72e9ecb7..1589955 100644
--- a/build/common.gypi
+++ b/build/common.gypi
@@ -530,8 +530,8 @@
           'native_memory_pressure_signals%': 1,
         }],
 
-        # Enable autofill dialog for Mac and Views-enabled platforms for now.
-        ['toolkit_views==1 or OS=="mac"', {
+        # Enable autofill dialog for Android, Mac and Views-enabled platforms.
+        ['toolkit_views==1 or (OS=="android" and android_webview_build==0) or OS=="mac"', {
           'enable_autofill_dialog%': 1
         }],
 
@@ -963,11 +963,6 @@
     # remaining.
     'win_third_party_warn_as_error%': 'true',
 
-    # This is the location of the sandbox binary. Chrome looks for this before
-    # running the zygote process. If found, and SUID, it will be used to
-    # sandbox the zygote process and, thus, all renderer processes.
-    'linux_sandbox_path%': '',
-
     # Clang stuff.
     'clang%': '<(clang)',
     'make_clang_dir%': 'third_party/llvm-build/Release+Asserts',
@@ -1227,12 +1222,15 @@
              'android_sdk_root%': '<!(cd <(DEPTH) && pwd -P)/third_party/android_tools/sdk/',
              'android_host_arch%': '<!(uname -m)',
              # Android API-level of the SDK used for compilation.
-             'android_sdk_version%': '17',
+             'android_sdk_version%': '<!(/bin/echo -n ${ANDROID_SDK_VERSION})',
+             # Android SDK build tools (e.g. dx, aapt, aidl)
+             'android_sdk_tools%': '<!(/bin/echo -n ${ANDROID_SDK_TOOLS})',
           },
           # Copy conditionally-set variables out one scope.
           'android_ndk_root%': '<(android_ndk_root)',
           'android_sdk_root%': '<(android_sdk_root)',
           'android_sdk_version%': '<(android_sdk_version)',
+          'android_sdk_tools%': '<(android_sdk_tools)',
           'android_stlport_root': '<(android_ndk_root)/sources/cxx-stl/stlport',
 
           'android_sdk%': '<(android_sdk_root)/platforms/android-<(android_sdk_version)',
@@ -1278,7 +1276,7 @@
 
         'android_ndk_include': '<(android_ndk_sysroot)/usr/include',
         'android_ndk_lib': '<(android_ndk_sysroot)/usr/lib',
-        'android_sdk_tools%': '<(android_sdk_root)/platform-tools',
+        'android_sdk_tools%': '<(android_sdk_tools)',
         'android_sdk%': '<(android_sdk)',
         'android_sdk_jar%': '<(android_sdk)/android.jar',
 
diff --git a/build/install-build-deps-android.sh b/build/install-build-deps-android.sh
index d8bc11a..f6b445b 100755
--- a/build/install-build-deps-android.sh
+++ b/build/install-build-deps-android.sh
@@ -46,6 +46,9 @@
 # common
 sudo apt-get -y install lighttpd python-pexpect xvfb x11-utils
 
+# Few binaries in the Android SDK require 32-bit libraries on the host.
+sudo apt-get -y install lib32z1 g++-multilib
+
 if /usr/bin/lsb_release -r -s | grep -q "12."; then
   # Ubuntu 12.x
   sudo apt-get -y install ant
diff --git a/build/ios/grit_whitelist.txt b/build/ios/grit_whitelist.txt
index 277e3fe..ed15d46 100644
--- a/build/ios/grit_whitelist.txt
+++ b/build/ios/grit_whitelist.txt
@@ -204,6 +204,7 @@
 IDS_CERT_ERROR_WEAK_SIGNATURE_ALGORITHM_TITLE
 IDS_CHROME_TO_DEVICE_PRINT_TO_PHONE
 IDS_CHROME_TO_DEVICE_SNAPSHOTS
+IDS_CONTENT_CONTEXT_SEARCHWEBFORIMAGE
 IDS_COPY_URL_MAC
 IDS_COULDNT_OPEN_PROFILE_ERROR
 IDS_CRASHES_BUG_LINK_LABEL
diff --git a/build/java_apk.gypi b/build/java_apk.gypi
index e388690..2457d3a 100644
--- a/build/java_apk.gypi
+++ b/build/java_apk.gypi
@@ -364,7 +364,6 @@
           ],
           'action': [
             'python', '<(DEPTH)/build/android/gyp/apk_install.py',
-            '--android-sdk-tools=<(android_sdk_tools)',
             '--apk-path=<(incomplete_apk_path)',
             '--build-device-configuration=<(build_device_config_path)',
             '--install-record=<(apk_install_record)',
@@ -408,6 +407,7 @@
         '-DANDROID_SDK_JAR=<(android_sdk_jar)',
         '-DANDROID_SDK_ROOT=<(android_sdk_root)',
         '-DANDROID_SDK_VERSION=<(android_sdk_version)',
+        '-DANDROID_SDK_TOOLS=<(android_sdk_tools)',
         '-DLIBRARY_MANIFEST_PATHS=>(library_manifest_paths)',
         '-DOUT_DIR=<(intermediate_dir)',
         '-DRESOURCE_DIR=<(resource_dir)',
@@ -504,6 +504,7 @@
         '-DANDROID_SDK_JAR=<(android_sdk_jar)',
         '-DANDROID_SDK_ROOT=<(android_sdk_root)',
         '-DANDROID_SDK_VERSION=<(android_sdk_version)',
+        '-DANDROID_SDK_TOOLS=<(android_sdk_tools)',
         '-DAPK_NAME=<(apk_name)',
         '-DCREATE_TEST_JAR_PATH=<(DEPTH)/build/android/ant/create-test-jar.js',
         '-DCONFIGURATION_NAME=<(CONFIGURATION_NAME)',
@@ -576,6 +577,7 @@
         '-DADDITIONAL_R_TEXT_FILES=>(additional_R_text_files)',
         '-DANDROID_SDK_JAR=<(android_sdk_jar)',
         '-DANDROID_SDK_ROOT=<(android_sdk_root)',
+        '-DANDROID_SDK_TOOLS=<(android_sdk_tools)',
         '-DAPK_NAME=<(apk_name)',
         '-DAPP_MANIFEST_VERSION_CODE=<(app_manifest_version_code)',
         '-DAPP_MANIFEST_VERSION_NAME=<(app_manifest_version_name)',
@@ -616,6 +618,7 @@
         'python', '<(DEPTH)/build/android/gyp/ant.py',
         '-quiet',
         '-DANDROID_SDK_ROOT=<(android_sdk_root)',
+        '-DANDROID_SDK_TOOLS=<(android_sdk_tools)',
         '-DAPK_NAME=<(apk_name)',
         '-DCONFIGURATION_NAME=<(CONFIGURATION_NAME)',
         '-DNATIVE_LIBS_DIR=<(apk_package_native_libs_dir)',
diff --git a/build/java_prebuilt.gypi b/build/java_prebuilt.gypi
index fdc20ce..8000374 100644
--- a/build/java_prebuilt.gypi
+++ b/build/java_prebuilt.gypi
@@ -46,7 +46,7 @@
       'action': [
         'python', '<(DEPTH)/build/android/gyp/dex.py',
         '--dex-path=<(dex_path)',
-        '--android-sdk-root=<(android_sdk_root)',
+        '--android-sdk-tools=<(android_sdk_tools)',
 
         # TODO(newt): remove this once http://crbug.com/177552 is fixed in ninja.
         '--ignore=>!(echo \'>(_inputs)\' | md5sum)',
diff --git a/build/uiautomator_test.gypi b/build/uiautomator_test.gypi
index 20c96c7..2fcc3d8 100644
--- a/build/uiautomator_test.gypi
+++ b/build/uiautomator_test.gypi
@@ -35,7 +35,7 @@
       'action': [
         'python', '<(DEPTH)/build/android/gyp/dex.py',
         '--dex-path=<(output_dex_path)',
-        '--android-sdk-root=<(android_sdk_root)',
+        '--android-sdk-tools=<(android_sdk_tools)',
 
         # TODO(newt): remove this once http://crbug.com/177552 is fixed in ninja.
         '--ignore=>!(echo \'>(_inputs)\' | md5sum)',
diff --git a/build/util/LASTCHANGE b/build/util/LASTCHANGE
index aae8668..63a3a52 100644
--- a/build/util/LASTCHANGE
+++ b/build/util/LASTCHANGE
@@ -1 +1 @@
-LASTCHANGE=216370
+LASTCHANGE=216972
diff --git a/build/util/LASTCHANGE.blink b/build/util/LASTCHANGE.blink
index 03e4ec2..aa8f059 100644
--- a/build/util/LASTCHANGE.blink
+++ b/build/util/LASTCHANGE.blink
@@ -1 +1 @@
-LASTCHANGE=155688
+LASTCHANGE=155921
diff --git a/build/whitespace_file.txt b/build/whitespace_file.txt
index 4d8ced4..405a489 100644
--- a/build/whitespace_file.txt
+++ b/build/whitespace_file.txt
@@ -58,7 +58,7 @@
 
 CHAPTER 5:
 Many years later, Mr. Usagi would laugh at the memory of the earnest,
-well-intentioned Domo-Kun. Another day in the life...
+well-intentioned Domo-Kun. Another day in the life.
 
 TRUISMS (1978-1983)
 JENNY HOLZER
diff --git a/cc/base/math_util.cc b/cc/base/math_util.cc
index 39a183e..fa7b21a 100644
--- a/cc/base/math_util.cc
+++ b/cc/base/math_util.cc
@@ -487,6 +487,13 @@
   return res.PassAs<base::Value>();
 }
 
+scoped_ptr<base::Value> MathUtil::AsValue(gfx::SizeF s) {
+  scoped_ptr<base::DictionaryValue> res(new base::DictionaryValue());
+  res->SetDouble("width", s.width());
+  res->SetDouble("height", s.height());
+  return res.PassAs<base::Value>();
+}
+
 scoped_ptr<base::Value> MathUtil::AsValue(gfx::Rect r) {
   scoped_ptr<base::ListValue> res(new base::ListValue());
   res->AppendInteger(r.x());
@@ -546,6 +553,16 @@
   return res.PassAs<base::Value>();
 }
 
+scoped_ptr<base::Value> MathUtil::AsValue(const gfx::Transform& transform) {
+  scoped_ptr<base::ListValue> res(new base::ListValue());
+  const SkMatrix44& m = transform.matrix();
+  for (int row = 0; row < 4; ++row) {
+    for (int col = 0; col < 4; ++col)
+      res->AppendDouble(m.getDouble(row, col));
+  }
+  return res.PassAs<base::Value>();
+}
+
 scoped_ptr<base::Value> MathUtil::AsValueSafely(double value) {
   return scoped_ptr<base::Value>(base::Value::CreateDoubleValue(
       std::min(value, std::numeric_limits<double>::max())));
diff --git a/cc/base/math_util.h b/cc/base/math_util.h
index 23eb20f..37f0c07 100644
--- a/cc/base/math_util.h
+++ b/cc/base/math_util.h
@@ -156,11 +156,13 @@
 
   // Conversion to value.
   static scoped_ptr<base::Value> AsValue(gfx::Size s);
+  static scoped_ptr<base::Value> AsValue(gfx::SizeF s);
   static scoped_ptr<base::Value> AsValue(gfx::Rect r);
   static bool FromValue(const base::Value*, gfx::Rect* out_rect);
   static scoped_ptr<base::Value> AsValue(gfx::PointF q);
   static scoped_ptr<base::Value> AsValue(const gfx::QuadF& q);
   static scoped_ptr<base::Value> AsValue(const gfx::RectF& rect);
+  static scoped_ptr<base::Value> AsValue(const gfx::Transform& transform);
 
   // Returns a base::Value representation of the floating point value.
   // If the value is inf, returns max double/float representation.
diff --git a/cc/cc.target.darwin-arm.mk b/cc/cc.target.darwin-arm.mk
index 7029dcc..68deea0 100644
--- a/cc/cc.target.darwin-arm.mk
+++ b/cc/cc.target.darwin-arm.mk
@@ -249,6 +249,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DMEDIA_DISABLE_LIBVPX' \
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-DPOSIX_AVOID_MMAP' \
@@ -364,6 +365,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DMEDIA_DISABLE_LIBVPX' \
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-DPOSIX_AVOID_MMAP' \
diff --git a/cc/cc.target.darwin-mips.mk b/cc/cc.target.darwin-mips.mk
index d0f7ee7..d633058 100644
--- a/cc/cc.target.darwin-mips.mk
+++ b/cc/cc.target.darwin-mips.mk
@@ -248,6 +248,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DMEDIA_DISABLE_LIBVPX' \
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-DPOSIX_AVOID_MMAP' \
@@ -362,6 +363,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DMEDIA_DISABLE_LIBVPX' \
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-DPOSIX_AVOID_MMAP' \
diff --git a/cc/cc.target.darwin-x86.mk b/cc/cc.target.darwin-x86.mk
index 3f83839..84112c8 100644
--- a/cc/cc.target.darwin-x86.mk
+++ b/cc/cc.target.darwin-x86.mk
@@ -251,6 +251,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DMEDIA_DISABLE_LIBVPX' \
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-DU_USING_ICU_NAMESPACE=0' \
@@ -368,6 +369,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DMEDIA_DISABLE_LIBVPX' \
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-DU_USING_ICU_NAMESPACE=0' \
diff --git a/cc/cc.target.linux-arm.mk b/cc/cc.target.linux-arm.mk
index 7029dcc..68deea0 100644
--- a/cc/cc.target.linux-arm.mk
+++ b/cc/cc.target.linux-arm.mk
@@ -249,6 +249,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DMEDIA_DISABLE_LIBVPX' \
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-DPOSIX_AVOID_MMAP' \
@@ -364,6 +365,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DMEDIA_DISABLE_LIBVPX' \
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-DPOSIX_AVOID_MMAP' \
diff --git a/cc/cc.target.linux-mips.mk b/cc/cc.target.linux-mips.mk
index d0f7ee7..d633058 100644
--- a/cc/cc.target.linux-mips.mk
+++ b/cc/cc.target.linux-mips.mk
@@ -248,6 +248,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DMEDIA_DISABLE_LIBVPX' \
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-DPOSIX_AVOID_MMAP' \
@@ -362,6 +363,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DMEDIA_DISABLE_LIBVPX' \
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-DPOSIX_AVOID_MMAP' \
diff --git a/cc/cc.target.linux-x86.mk b/cc/cc.target.linux-x86.mk
index 3f83839..84112c8 100644
--- a/cc/cc.target.linux-x86.mk
+++ b/cc/cc.target.linux-x86.mk
@@ -251,6 +251,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DMEDIA_DISABLE_LIBVPX' \
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-DU_USING_ICU_NAMESPACE=0' \
@@ -368,6 +369,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DMEDIA_DISABLE_LIBVPX' \
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-DU_USING_ICU_NAMESPACE=0' \
diff --git a/cc/debug/traced_value.cc b/cc/debug/traced_value.cc
index 637c700..fbca5c6 100644
--- a/cc/debug/traced_value.cc
+++ b/cc/debug/traced_value.cc
@@ -21,6 +21,15 @@
   dict->SetString("id", base::StringPrintf("%s/%p", object_name, id));
 }
 
+void TracedValue::MakeDictIntoImplicitSnapshotWithCategory(
+    const char* category,
+    base::DictionaryValue* dict,
+    const char* object_name,
+    const void* id) {
+  dict->SetString("cat", category);
+  MakeDictIntoImplicitSnapshot(dict, object_name, id);
+}
+
 scoped_ptr<base::debug::ConvertableToTraceFormat> TracedValue::FromValue(
     base::Value* value) {
   TracedValue* ptr = new TracedValue(value);
diff --git a/cc/debug/traced_value.h b/cc/debug/traced_value.h
index e5d63a1..148aca8 100644
--- a/cc/debug/traced_value.h
+++ b/cc/debug/traced_value.h
@@ -21,6 +21,11 @@
   static scoped_ptr<base::Value> CreateIDRef(const void* id);
   static void MakeDictIntoImplicitSnapshot(
       base::DictionaryValue* dict, const char* object_name, const void* id);
+  static void MakeDictIntoImplicitSnapshotWithCategory(
+      const char* category,
+      base::DictionaryValue* dict,
+      const char* object_name,
+      const void* id);
   static scoped_ptr<ConvertableToTraceFormat> FromValue(
       base::Value* value);
 
diff --git a/cc/layers/delegated_renderer_layer.cc b/cc/layers/delegated_renderer_layer.cc
index cbff44e..66064d9 100644
--- a/cc/layers/delegated_renderer_layer.cc
+++ b/cc/layers/delegated_renderer_layer.cc
@@ -41,28 +41,19 @@
 
   delegated_impl->SetDisplaySize(display_size_);
 
-  if (!frame_data_) {
-    delegated_impl->SetFrameData(scoped_ptr<DelegatedFrameData>(),
-                                 gfx::Rect(),
-                                 &unused_resources_for_child_compositor_);
-  } else if (frame_size_.IsEmpty()) {
-    scoped_ptr<DelegatedFrameData> empty_frame(new DelegatedFrameData);
-    delegated_impl->SetFrameData(empty_frame.Pass(),
-                                 gfx::Rect(),
-                                 &unused_resources_for_child_compositor_);
-  } else {
-    delegated_impl->SetFrameData(frame_data_.Pass(),
-                                 damage_in_frame_,
-                                 &unused_resources_for_child_compositor_);
-  }
+  if (frame_data_)
+    delegated_impl->SetFrameData(frame_data_.Pass(), damage_in_frame_);
   frame_data_.reset();
   damage_in_frame_ = gfx::RectF();
 
+  delegated_impl->CollectUnusedResources(
+      &unused_resources_for_child_compositor_);
+
   if (client_)
     client_->DidCommitFrameData();
 
   // TODO(danakj): TakeUnusedResourcesForChildCompositor requires a push
-  // properties to happen in order to push up newly unused resources returned
+  // properties to happen in order to collect unused resources returned
   // from the parent compositor. crbug.com/259090
   needs_push_properties_ = true;
 }
diff --git a/cc/layers/delegated_renderer_layer_impl.cc b/cc/layers/delegated_renderer_layer_impl.cc
index 31b0a8d..2dfdac6 100644
--- a/cc/layers/delegated_renderer_layer_impl.cc
+++ b/cc/layers/delegated_renderer_layer_impl.cc
@@ -92,8 +92,13 @@
 
 void DelegatedRendererLayerImpl::SetFrameData(
     scoped_ptr<DelegatedFrameData> frame_data,
-    gfx::RectF damage_in_frame,
-    TransferableResourceArray* resources_for_ack) {
+    gfx::RectF damage_in_frame) {
+  DCHECK(frame_data);
+
+  // A frame with an empty root render pass is invalid.
+  DCHECK(frame_data->render_pass_list.empty() ||
+         !frame_data->render_pass_list.back()->output_rect.IsEmpty());
+
   CreateChildIdIfNeeded();
   DCHECK(child_id_);
 
@@ -101,48 +106,53 @@
     const ResourceProvider::ResourceIdMap& resource_map =
         resource_provider->GetChildToParentMap(child_id_);
 
-  if (frame_data) {
-    // A frame with an empty root render pass is invalid.
-    DCHECK(frame_data->render_pass_list.empty() ||
-           !frame_data->render_pass_list.back()->output_rect.IsEmpty());
+  resource_provider->ReceiveFromChild(child_id_, frame_data->resource_list);
 
-    // Display size is already set so we can compute what the damage rect
-    // will be in layer space.
-    if (!frame_data->render_pass_list.empty()) {
-      RenderPass* new_root_pass = frame_data->render_pass_list.back();
-      gfx::RectF damage_in_layer = MathUtil::MapClippedRect(
-          DelegatedFrameToLayerSpaceTransform(
-              new_root_pass->output_rect.size()),
-          damage_in_frame);
-      set_update_rect(gfx::UnionRects(update_rect(), damage_in_layer));
-    }
-
-    resource_provider->ReceiveFromChild(child_id_, frame_data->resource_list);
-
-    bool invalid_frame = false;
-    ResourceProvider::ResourceIdSet used_resources;
-    DrawQuad::ResourceIteratorCallback remap_resources_to_parent_callback =
-        base::Bind(&ResourceRemapHelper,
-                   &invalid_frame,
-                   resource_map,
-                   &used_resources);
-    for (size_t i = 0; i < frame_data->render_pass_list.size(); ++i) {
-      RenderPass* pass = frame_data->render_pass_list[i];
-      for (size_t j = 0; j < pass->quad_list.size(); ++j) {
-        DrawQuad* quad = pass->quad_list[j];
-        quad->IterateResources(remap_resources_to_parent_callback);
-      }
-    }
-
-    if (!invalid_frame) {
-      // Save the remapped quads on the layer. This steals the quads and render
-      // passes from the frame_data.
-      SetRenderPasses(&frame_data->render_pass_list);
-      resources_.swap(used_resources);
-      have_render_passes_to_push_ = true;
+  bool invalid_frame = false;
+  ResourceProvider::ResourceIdSet used_resources;
+  DrawQuad::ResourceIteratorCallback remap_resources_to_parent_callback =
+      base::Bind(&ResourceRemapHelper,
+                 &invalid_frame,
+                 resource_map,
+                 &used_resources);
+  for (size_t i = 0; i < frame_data->render_pass_list.size(); ++i) {
+    RenderPass* pass = frame_data->render_pass_list[i];
+    for (size_t j = 0; j < pass->quad_list.size(); ++j) {
+      DrawQuad* quad = pass->quad_list[j];
+      quad->IterateResources(remap_resources_to_parent_callback);
     }
   }
 
+  if (invalid_frame)
+    return;
+
+  // Display size is already set so we can compute what the damage rect
+  // will be in layer space.
+  if (!frame_data->render_pass_list.empty()) {
+    RenderPass* new_root_pass = frame_data->render_pass_list.back();
+    gfx::RectF damage_in_layer = MathUtil::MapClippedRect(
+        DelegatedFrameToLayerSpaceTransform(
+            new_root_pass->output_rect.size()),
+        damage_in_frame);
+    set_update_rect(gfx::UnionRects(update_rect(), damage_in_layer));
+  }
+
+  // Save the remapped quads on the layer. This steals the quads and render
+  // passes from the frame_data.
+  SetRenderPasses(&frame_data->render_pass_list);
+  resources_.swap(used_resources);
+  have_render_passes_to_push_ = true;
+}
+
+void DelegatedRendererLayerImpl::CollectUnusedResources(
+    TransferableResourceArray* resources_for_ack) {
+  CreateChildIdIfNeeded();
+  DCHECK(child_id_);
+
+  ResourceProvider* resource_provider = layer_tree_impl()->resource_provider();
+    const ResourceProvider::ResourceIdMap& resource_map =
+        resource_provider->GetChildToParentMap(child_id_);
+
   ResourceProvider::ResourceIdArray unused_resources;
   for (ResourceProvider::ResourceIdMap::const_iterator it =
            resource_map.begin();
diff --git a/cc/layers/delegated_renderer_layer_impl.h b/cc/layers/delegated_renderer_layer_impl.h
index 5725454..9cfdcb6 100644
--- a/cc/layers/delegated_renderer_layer_impl.h
+++ b/cc/layers/delegated_renderer_layer_impl.h
@@ -41,8 +41,9 @@
   void AppendContributingRenderPasses(RenderPassSink* render_pass_sink);
 
   void SetFrameData(scoped_ptr<DelegatedFrameData> frame_data,
-                    gfx::RectF damage_in_frame,
-                    TransferableResourceArray* resources_for_ack);
+                    gfx::RectF damage_in_frame);
+
+  void CollectUnusedResources(TransferableResourceArray* resources_for_ack);
 
   void SetDisplaySize(gfx::Size size);
 
diff --git a/cc/output/filter_operation.cc b/cc/output/filter_operation.cc
index de59cfc..6a77838 100644
--- a/cc/output/filter_operation.cc
+++ b/cc/output/filter_operation.cc
@@ -4,6 +4,7 @@
 
 #include <algorithm>
 
+#include "base/values.h"
 #include "cc/base/math_util.h"
 #include "cc/output/filter_operation.h"
 #include "third_party/skia/include/core/SkMath.h"
@@ -217,4 +218,40 @@
   return blended_filter;
 }
 
+scoped_ptr<base::Value> FilterOperation::AsValue() const {
+  scoped_ptr<base::DictionaryValue> value(new DictionaryValue);
+  value->SetInteger("type", type_);
+  switch (type_) {
+    case FilterOperation::GRAYSCALE:
+    case FilterOperation::SEPIA:
+    case FilterOperation::SATURATE:
+    case FilterOperation::HUE_ROTATE:
+    case FilterOperation::INVERT:
+    case FilterOperation::BRIGHTNESS:
+    case FilterOperation::CONTRAST:
+    case FilterOperation::OPACITY:
+    case FilterOperation::BLUR:
+    case FilterOperation::SATURATING_BRIGHTNESS:
+      value->SetDouble("amount", amount_);
+      break;
+    case FilterOperation::DROP_SHADOW:
+      value->SetDouble("std_deviation", amount_);
+      value->Set("offset", MathUtil::AsValue(drop_shadow_offset_).release());
+      value->SetInteger("color", drop_shadow_color_);
+      break;
+    case FilterOperation::COLOR_MATRIX: {
+      scoped_ptr<ListValue> matrix(new ListValue);
+      for (size_t i = 0; i < arraysize(matrix_); ++i)
+        matrix->AppendDouble(matrix_[i]);
+      value->Set("matrix", matrix.release());
+      break;
+    }
+    case FilterOperation::ZOOM:
+      value->SetDouble("amount", amount_);
+      value->SetDouble("inset", zoom_inset_);
+      break;
+  }
+  return value.PassAs<base::Value>();
+}
+
 }  // namespace cc
diff --git a/cc/output/filter_operation.h b/cc/output/filter_operation.h
index ad25cf4..f561762 100644
--- a/cc/output/filter_operation.h
+++ b/cc/output/filter_operation.h
@@ -6,11 +6,16 @@
 #define CC_OUTPUT_FILTER_OPERATION_H_
 
 #include "base/logging.h"
+#include "base/memory/scoped_ptr.h"
 #include "cc/base/cc_export.h"
 #include "third_party/skia/include/core/SkColor.h"
 #include "third_party/skia/include/core/SkScalar.h"
 #include "ui/gfx/point.h"
 
+namespace base {
+class Value;
+}
+
 namespace cc {
 
 class CC_EXPORT FilterOperation {
@@ -161,6 +166,8 @@
                                const FilterOperation* to,
                                double progress);
 
+  scoped_ptr<base::Value> AsValue() const;
+
  private:
   FilterOperation(FilterType type, float amount);
 
diff --git a/cc/output/filter_operations.cc b/cc/output/filter_operations.cc
index 4331527..2420841 100644
--- a/cc/output/filter_operations.cc
+++ b/cc/output/filter_operations.cc
@@ -4,9 +4,11 @@
 
 #include <cmath>
 
-#include "cc/output/filter_operation.h"
 #include "cc/output/filter_operations.h"
 
+#include "base/values.h"
+#include "cc/output/filter_operation.h"
+
 namespace cc {
 
 FilterOperations::FilterOperations() {}
@@ -145,4 +147,11 @@
   return blended_filters;
 }
 
+scoped_ptr<base::Value> FilterOperations::AsValue() const {
+  scoped_ptr<base::ListValue> value(new ListValue);
+  for (size_t i = 0; i < operations_.size(); ++i)
+    value->Append(operations_[i].AsValue().release());
+  return value.PassAs<base::Value>();
+}
+
 }  // namespace cc
diff --git a/cc/output/filter_operations.h b/cc/output/filter_operations.h
index d7198d1..aa8d58d 100644
--- a/cc/output/filter_operations.h
+++ b/cc/output/filter_operations.h
@@ -8,8 +8,13 @@
 #include <vector>
 
 #include "base/logging.h"
+#include "base/memory/scoped_ptr.h"
 #include "cc/output/filter_operation.h"
 
+namespace base {
+class Value;
+}
+
 namespace cc {
 
 // An ordered list of filter operations.
@@ -62,6 +67,8 @@
   // of this.
   FilterOperations Blend(const FilterOperations& from, double progress) const;
 
+  scoped_ptr<base::Value> AsValue() const;
+
  private:
   std::vector<FilterOperation> operations_;
 };
diff --git a/cc/quads/checkerboard_draw_quad.cc b/cc/quads/checkerboard_draw_quad.cc
index fcc6dc5..5e17d88 100644
--- a/cc/quads/checkerboard_draw_quad.cc
+++ b/cc/quads/checkerboard_draw_quad.cc
@@ -5,6 +5,7 @@
 #include "cc/quads/checkerboard_draw_quad.h"
 
 #include "base/logging.h"
+#include "base/values.h"
 
 namespace cc {
 
@@ -45,4 +46,8 @@
   return static_cast<const CheckerboardDrawQuad*>(quad);
 }
 
+void CheckerboardDrawQuad::ExtendValue(base::DictionaryValue* value) const {
+  value->SetInteger("color", color);
+}
+
 }  // namespace cc
diff --git a/cc/quads/checkerboard_draw_quad.h b/cc/quads/checkerboard_draw_quad.h
index b2ed876..4f7452eb 100644
--- a/cc/quads/checkerboard_draw_quad.h
+++ b/cc/quads/checkerboard_draw_quad.h
@@ -35,6 +35,7 @@
   static const CheckerboardDrawQuad* MaterialCast(const DrawQuad*);
 
  private:
+  virtual void ExtendValue(base::DictionaryValue* value) const OVERRIDE;
   CheckerboardDrawQuad();
 };
 
diff --git a/cc/quads/content_draw_quad_base.cc b/cc/quads/content_draw_quad_base.cc
index 2c2b4ae..947af0b 100644
--- a/cc/quads/content_draw_quad_base.cc
+++ b/cc/quads/content_draw_quad_base.cc
@@ -5,6 +5,8 @@
 #include "cc/quads/content_draw_quad_base.h"
 
 #include "base/logging.h"
+#include "base/values.h"
+#include "cc/base/math_util.h"
 
 namespace cc {
 
@@ -47,4 +49,10 @@
   this->swizzle_contents = swizzle_contents;
 }
 
+void ContentDrawQuadBase::ExtendValue(base::DictionaryValue* value) const {
+  value->Set("tex_coord_rect", MathUtil::AsValue(tex_coord_rect).release());
+  value->Set("texture_size", MathUtil::AsValue(texture_size).release());
+  value->SetBoolean("swizzle_contents", swizzle_contents);
+}
+
 }  // namespace cc
diff --git a/cc/quads/content_draw_quad_base.h b/cc/quads/content_draw_quad_base.h
index b2c936f..cbf18ca 100644
--- a/cc/quads/content_draw_quad_base.h
+++ b/cc/quads/content_draw_quad_base.h
@@ -41,6 +41,7 @@
  protected:
   ContentDrawQuadBase();
   virtual ~ContentDrawQuadBase();
+  virtual void ExtendValue(base::DictionaryValue* value) const OVERRIDE;
 };
 
 }  // namespace cc
diff --git a/cc/quads/debug_border_draw_quad.cc b/cc/quads/debug_border_draw_quad.cc
index 1ebc0a6..89ee8e0 100644
--- a/cc/quads/debug_border_draw_quad.cc
+++ b/cc/quads/debug_border_draw_quad.cc
@@ -5,6 +5,7 @@
 #include "cc/quads/debug_border_draw_quad.h"
 
 #include "base/logging.h"
+#include "base/values.h"
 
 namespace cc {
 
@@ -52,4 +53,9 @@
   return static_cast<const DebugBorderDrawQuad*>(quad);
 }
 
+void DebugBorderDrawQuad::ExtendValue(base::DictionaryValue* value) const {
+  value->SetInteger("color", color);
+  value->SetInteger("width", width);
+}
+
 }  // namespace cc
diff --git a/cc/quads/debug_border_draw_quad.h b/cc/quads/debug_border_draw_quad.h
index 2f4b3ca..5b36951 100644
--- a/cc/quads/debug_border_draw_quad.h
+++ b/cc/quads/debug_border_draw_quad.h
@@ -39,6 +39,7 @@
 
  private:
   DebugBorderDrawQuad();
+  virtual void ExtendValue(base::DictionaryValue* value) const OVERRIDE;
 };
 
 }  // namespace cc
diff --git a/cc/quads/draw_quad.cc b/cc/quads/draw_quad.cc
index 6c8d9b6..0d021d9 100644
--- a/cc/quads/draw_quad.cc
+++ b/cc/quads/draw_quad.cc
@@ -5,6 +5,9 @@
 #include "cc/quads/draw_quad.h"
 
 #include "base/logging.h"
+#include "base/values.h"
+#include "cc/base/math_util.h"
+#include "cc/debug/traced_value.h"
 #include "cc/quads/checkerboard_draw_quad.h"
 #include "cc/quads/debug_border_draw_quad.h"
 #include "cc/quads/io_surface_draw_quad.h"
@@ -15,6 +18,7 @@
 #include "cc/quads/texture_draw_quad.h"
 #include "cc/quads/tile_draw_quad.h"
 #include "cc/quads/yuv_video_draw_quad.h"
+#include "ui/gfx/quad_f.h"
 
 namespace {
 template<typename T> T* TypedCopy(const cc::DrawQuad* other) {
@@ -90,4 +94,48 @@
   return copy_quad.Pass();
 }
 
+scoped_ptr<base::Value> DrawQuad::AsValue() const {
+  scoped_ptr<base::DictionaryValue> value(new base::DictionaryValue());
+  value->SetInteger("material", material);
+  value->Set("shared_state",
+             TracedValue::CreateIDRef(shared_quad_state).release());
+
+  value->Set("content_space_rect", MathUtil::AsValue(rect).release());
+  bool rect_is_clipped;
+  gfx::QuadF rect_as_target_space_quad = MathUtil::MapQuad(
+      shared_quad_state->content_to_target_transform,
+      gfx::QuadF(rect),
+      &rect_is_clipped);
+  value->Set("rect_as_target_space_quad",
+             MathUtil::AsValue(rect_as_target_space_quad).release());
+  value->SetBoolean("rect_is_clipped", rect_is_clipped);
+
+  value->Set("content_space_opaque_rect",
+             MathUtil::AsValue(opaque_rect).release());
+  bool opaque_rect_is_clipped;
+  gfx::QuadF opaque_rect_as_target_space_quad = MathUtil::MapQuad(
+      shared_quad_state->content_to_target_transform,
+      gfx::QuadF(opaque_rect),
+      &opaque_rect_is_clipped);
+  value->Set("opaque_rect_as_target_space_quad",
+             MathUtil::AsValue(opaque_rect_as_target_space_quad).release());
+  value->SetBoolean("opaque_rect_is_clipped", opaque_rect_is_clipped);
+
+  value->Set("content_space_visible_rect",
+             MathUtil::AsValue(visible_rect).release());
+  bool visible_rect_is_clipped;
+  gfx::QuadF visible_rect_as_target_space_quad = MathUtil::MapQuad(
+      shared_quad_state->content_to_target_transform,
+      gfx::QuadF(visible_rect),
+      &visible_rect_is_clipped);
+  value->Set("visible_rect_as_target_space_quad",
+             MathUtil::AsValue(visible_rect_as_target_space_quad).release());
+  value->SetBoolean("visible_rect_is_clipped", visible_rect_is_clipped);
+
+  value->SetBoolean("needs_blending", needs_blending);
+  value->SetBoolean("should_draw_with_blending", ShouldDrawWithBlending());
+  ExtendValue(value.get());
+  return value.PassAs<base::Value>();
+}
+
 }  // namespace cc
diff --git a/cc/quads/draw_quad.h b/cc/quads/draw_quad.h
index a92cddf..c3696d6 100644
--- a/cc/quads/draw_quad.h
+++ b/cc/quads/draw_quad.h
@@ -10,12 +10,24 @@
 #include "cc/quads/shared_quad_state.h"
 #include "cc/resources/resource_provider.h"
 
+namespace base {
+class Value;
+class DictionaryValue;
+}
+
 namespace cc {
 
 // DrawQuad is a bag of data used for drawing a quad. Because different
 // materials need different bits of per-quad data to render, classes that derive
 // from DrawQuad store additional data in their derived instance. The Material
 // enum is used to "safely" downcast to the derived class.
+// Note: quads contain rects and sizes, which live in different spaces. There is
+// the "content space", which is the arbitrary space in which the quad's
+// geometry is defined (generally related to the layer that produced the quad,
+// e.g. the content space for TiledLayerImpls, or the geometry space for
+// PictureLayerImpls). There is also the "target space", which is the space, in
+// "physical" pixels, of the render target where the quads is drawn. The quad's
+// transform maps the content space to the target space.
 class CC_EXPORT DrawQuad {
  public:
   enum Material {
@@ -51,14 +63,15 @@
   Material material;
 
   // This rect, after applying the quad_transform(), gives the geometry that
-  // this quad should draw to.
+  // this quad should draw to. This rect lives in content space.
   gfx::Rect rect;
 
-  // This specifies the region of the quad that is opaque.
+  // This specifies the region of the quad that is opaque. This rect lives in
+  // content space.
   gfx::Rect opaque_rect;
 
   // Allows changing the rect that gets drawn to make it smaller. This value
-  // should be clipped to |rect|.
+  // should be clipped to |rect|. This rect lives in content space.
   gfx::Rect visible_rect;
 
   // By default blending is used when some part of the quad is not opaque.
@@ -111,6 +124,8 @@
     return IsLeftEdge() || IsTopEdge() || IsRightEdge() || IsBottomEdge();
   }
 
+  scoped_ptr<base::Value> AsValue() const;
+
  protected:
   DrawQuad();
 
@@ -120,6 +135,7 @@
               gfx::Rect opaque_rect,
               gfx::Rect visible_rect,
               bool needs_blending);
+  virtual void ExtendValue(base::DictionaryValue* value) const = 0;
 };
 
 }  // namespace cc
diff --git a/cc/quads/io_surface_draw_quad.cc b/cc/quads/io_surface_draw_quad.cc
index 1bbf8a4..2c986dd 100644
--- a/cc/quads/io_surface_draw_quad.cc
+++ b/cc/quads/io_surface_draw_quad.cc
@@ -5,6 +5,8 @@
 #include "cc/quads/io_surface_draw_quad.h"
 
 #include "base/logging.h"
+#include "base/values.h"
+#include "cc/base/math_util.h"
 
 namespace cc {
 
@@ -58,4 +60,20 @@
   return static_cast<const IOSurfaceDrawQuad*>(quad);
 }
 
+void IOSurfaceDrawQuad::ExtendValue(base::DictionaryValue* value) const {
+  value->Set("io_surface_size", MathUtil::AsValue(io_surface_size).release());
+  value->SetInteger("io_surface_resource_id", io_surface_resource_id);
+  const char* orientation_string = NULL;
+  switch (orientation) {
+    case FLIPPED:
+      orientation_string = "flipped";
+      break;
+    case UNFLIPPED:
+      orientation_string = "unflipped";
+      break;
+  }
+
+  value->SetString("orientation", orientation_string);
+}
+
 }  // namespace cc
diff --git a/cc/quads/io_surface_draw_quad.h b/cc/quads/io_surface_draw_quad.h
index 1a30c90..fc8b501 100644
--- a/cc/quads/io_surface_draw_quad.h
+++ b/cc/quads/io_surface_draw_quad.h
@@ -48,6 +48,7 @@
 
  private:
   IOSurfaceDrawQuad();
+  virtual void ExtendValue(base::DictionaryValue* value) const OVERRIDE;
 };
 
 }  // namespace cc
diff --git a/cc/quads/picture_draw_quad.cc b/cc/quads/picture_draw_quad.cc
index 81f7913..0494764 100644
--- a/cc/quads/picture_draw_quad.cc
+++ b/cc/quads/picture_draw_quad.cc
@@ -4,6 +4,9 @@
 
 #include "cc/quads/picture_draw_quad.h"
 
+#include "base/values.h"
+#include "cc/base/math_util.h"
+
 namespace cc {
 
 PictureDrawQuad::PictureDrawQuad() {
@@ -68,4 +71,13 @@
   return static_cast<const PictureDrawQuad*>(quad);
 }
 
+void PictureDrawQuad::ExtendValue(base::DictionaryValue* value) const {
+  ContentDrawQuadBase::ExtendValue(value);
+  value->Set("content_rect", MathUtil::AsValue(content_rect).release());
+  value->SetDouble("contents_scale", contents_scale);
+  value->SetBoolean("can_draw_direct_to_backbuffer",
+                    can_draw_direct_to_backbuffer);
+  // TODO(piman): picture_pile?
+}
+
 }  // namespace cc
diff --git a/cc/quads/picture_draw_quad.h b/cc/quads/picture_draw_quad.h
index 29af6d5..beec88c 100644
--- a/cc/quads/picture_draw_quad.h
+++ b/cc/quads/picture_draw_quad.h
@@ -58,6 +58,7 @@
 
  private:
   PictureDrawQuad();
+  virtual void ExtendValue(base::DictionaryValue* value) const OVERRIDE;
 };
 
 }  // namespace cc
diff --git a/cc/quads/render_pass.cc b/cc/quads/render_pass.cc
index ef6308c..50d5028 100644
--- a/cc/quads/render_pass.cc
+++ b/cc/quads/render_pass.cc
@@ -4,12 +4,20 @@
 
 #include "cc/quads/render_pass.h"
 
+#include "base/values.h"
+#include "cc/base/math_util.h"
+#include "cc/debug/traced_value.h"
 #include "cc/output/copy_output_request.h"
 #include "cc/quads/draw_quad.h"
 #include "cc/quads/shared_quad_state.h"
 
 namespace cc {
 
+void* RenderPass::Id::AsTracingId() const {
+  COMPILE_ASSERT(sizeof(size_t) <= sizeof(void*), size_t_bigger_than_pointer);
+  return reinterpret_cast<void*>(base::HashPair(layer_id, index));
+}
+
 scoped_ptr<RenderPass> RenderPass::Create() {
   return make_scoped_ptr(new RenderPass);
 }
@@ -19,7 +27,11 @@
       has_transparent_background(true),
       has_occlusion_from_outside_target_surface(false) {}
 
-RenderPass::~RenderPass() {}
+RenderPass::~RenderPass() {
+  TRACE_EVENT_OBJECT_DELETED_WITH_ID(
+      TRACE_DISABLED_BY_DEFAULT("cc.debug.quads"),
+      "cc::RenderPass", id.AsTracingId());
+}
 
 scoped_ptr<RenderPass> RenderPass::Copy(Id new_id) const {
   scoped_ptr<RenderPass> copy_pass(Create());
@@ -69,4 +81,29 @@
   DCHECK(shared_quad_state_list.empty());
 }
 
+scoped_ptr<base::Value> RenderPass::AsValue() const {
+  scoped_ptr<base::DictionaryValue> value(new base::DictionaryValue());
+  value->Set("output_rect", MathUtil::AsValue(output_rect).release());
+  value->Set("damage_rect", MathUtil::AsValue(damage_rect).release());
+  value->SetBoolean("has_transparent_background", has_transparent_background);
+  value->SetBoolean("has_occlusion_from_outside_target_surface",
+                    has_occlusion_from_outside_target_surface);
+  value->SetInteger("copy_requests", copy_requests.size());
+  scoped_ptr<base::ListValue> shared_states_value(new base::ListValue());
+  for (size_t i = 0; i < shared_quad_state_list.size(); ++i) {
+    shared_states_value->Append(shared_quad_state_list[i]->AsValue().release());
+  }
+  value->Set("shared_quad_state_list", shared_states_value.release());
+  scoped_ptr<base::ListValue> quad_list_value(new base::ListValue());
+  for (size_t i = 0; i < quad_list.size(); ++i) {
+    quad_list_value->Append(quad_list[i]->AsValue().release());
+  }
+  value->Set("quad_list", quad_list_value.release());
+
+  TracedValue::MakeDictIntoImplicitSnapshotWithCategory(
+      TRACE_DISABLED_BY_DEFAULT("cc.debug.quads"),
+      value.get(), "cc::RenderPass", id.AsTracingId());
+  return value.PassAs<base::Value>();
+}
+
 }  // namespace cc
diff --git a/cc/quads/render_pass.h b/cc/quads/render_pass.h
index 3d5a37c..224a050 100644
--- a/cc/quads/render_pass.h
+++ b/cc/quads/render_pass.h
@@ -20,6 +20,10 @@
 #include "ui/gfx/rect_f.h"
 #include "ui/gfx/transform.h"
 
+namespace base {
+class Value;
+};
+
 namespace cc {
 
 class DrawQuad;
@@ -47,6 +51,7 @@
     int index;
 
     Id(int layer_id, int index) : layer_id(layer_id), index(index) {}
+    void* AsTracingId() const;
 
     bool operator==(const Id& other) const {
       return layer_id == other.layer_id && index == other.index;
@@ -79,6 +84,8 @@
               bool has_transparent_background,
               bool has_occlusion_from_outside_target_surface);
 
+  scoped_ptr<base::Value> AsValue() const;
+
   // Uniquely identifies the render pass in the compositor's current frame.
   Id id;
 
diff --git a/cc/quads/render_pass_draw_quad.cc b/cc/quads/render_pass_draw_quad.cc
index ead3d79..0528cd5 100644
--- a/cc/quads/render_pass_draw_quad.cc
+++ b/cc/quads/render_pass_draw_quad.cc
@@ -4,6 +4,10 @@
 
 #include "cc/quads/render_pass_draw_quad.h"
 
+#include "base/values.h"
+#include "cc/base/math_util.h"
+#include "cc/debug/traced_value.h"
+
 namespace cc {
 
 RenderPassDrawQuad::RenderPassDrawQuad()
@@ -93,4 +97,19 @@
   return static_cast<const RenderPassDrawQuad*>(quad);
 }
 
+void RenderPassDrawQuad::ExtendValue(base::DictionaryValue* value) const {
+  value->Set("render_pass_id",
+             TracedValue::CreateIDRef(render_pass_id.AsTracingId()).release());
+  value->SetBoolean("is_replica", is_replica);
+  value->SetInteger("mask_resource_id", mask_resource_id);
+  value->Set("contents_changed_since_last_frame",
+             MathUtil::AsValue(contents_changed_since_last_frame).release());
+  value->Set("mask_uv_rect", MathUtil::AsValue(mask_uv_rect).release());
+  value->Set("filters", filters.AsValue().release());
+  // TODO(piman): dump SkImageFilters rather than just indicating if there are
+  // any or not.
+  value->SetBoolean("has_filter", !!filter);
+  value->Set("background_filters", background_filters.AsValue().release());
+}
+
 }  // namespace cc
diff --git a/cc/quads/render_pass_draw_quad.h b/cc/quads/render_pass_draw_quad.h
index f0c76a9..e253dec 100644
--- a/cc/quads/render_pass_draw_quad.h
+++ b/cc/quads/render_pass_draw_quad.h
@@ -72,6 +72,7 @@
 
  private:
   RenderPassDrawQuad();
+  virtual void ExtendValue(base::DictionaryValue* value) const OVERRIDE;
 };
 
 }  // namespace cc
diff --git a/cc/quads/shared_quad_state.cc b/cc/quads/shared_quad_state.cc
index 7bfb2b4..6a53d9f 100644
--- a/cc/quads/shared_quad_state.cc
+++ b/cc/quads/shared_quad_state.cc
@@ -4,11 +4,19 @@
 
 #include "cc/quads/shared_quad_state.h"
 
+#include "base/values.h"
+#include "cc/base/math_util.h"
+#include "cc/debug/traced_value.h"
+
 namespace cc {
 
 SharedQuadState::SharedQuadState() : is_clipped(false), opacity(0.f) {}
 
-SharedQuadState::~SharedQuadState() {}
+SharedQuadState::~SharedQuadState() {
+  TRACE_EVENT_OBJECT_DELETED_WITH_ID(
+      TRACE_DISABLED_BY_DEFAULT("cc.debug.quads"),
+      "cc::SharedQuadState", this);
+}
 
 scoped_ptr<SharedQuadState> SharedQuadState::Create() {
   return make_scoped_ptr(new SharedQuadState);
@@ -33,4 +41,21 @@
   this->opacity = opacity;
 }
 
+scoped_ptr<base::Value> SharedQuadState::AsValue() const {
+  scoped_ptr<base::DictionaryValue> value(new base::DictionaryValue());
+  value->Set("transform",
+             MathUtil::AsValue(content_to_target_transform).release());
+  value->Set("layer_content_bounds",
+             MathUtil::AsValue(content_bounds).release());
+  value->Set("layer_visible_content_rect",
+             MathUtil::AsValue(visible_content_rect).release());
+  value->SetBoolean("is_clipped", is_clipped);
+  value->Set("clip_rect", MathUtil::AsValue(clip_rect).release());
+  value->SetDouble("opacity", opacity);
+  TracedValue::MakeDictIntoImplicitSnapshotWithCategory(
+      TRACE_DISABLED_BY_DEFAULT("cc.debug.quads"),
+      value.get(), "cc::SharedQuadState", this);
+  return value.PassAs<base::Value>();
+}
+
 }  // namespace cc
diff --git a/cc/quads/shared_quad_state.h b/cc/quads/shared_quad_state.h
index eb3e91e..79bd09b 100644
--- a/cc/quads/shared_quad_state.h
+++ b/cc/quads/shared_quad_state.h
@@ -10,6 +10,10 @@
 #include "ui/gfx/rect.h"
 #include "ui/gfx/transform.h"
 
+namespace base {
+class Value;
+}
+
 namespace cc {
 
 class CC_EXPORT SharedQuadState {
@@ -25,12 +29,15 @@
               gfx::Rect clip_rect,
               bool is_clipped,
               float opacity);
+  scoped_ptr<base::Value> AsValue() const;
 
   // Transforms from quad's original content space to its target content space.
   gfx::Transform content_to_target_transform;
-  // This rect lives in the content space for the quad's originating layer.
+  // This size lives in the content space for the quad's originating layer.
   gfx::Size content_bounds;
+  // This rect lives in the content space for the quad's originating layer.
   gfx::Rect visible_content_rect;
+  // This rect lives in the target content space.
   gfx::Rect clip_rect;
   bool is_clipped;
   float opacity;
diff --git a/cc/quads/solid_color_draw_quad.cc b/cc/quads/solid_color_draw_quad.cc
index 5575aaf..ae3b914 100644
--- a/cc/quads/solid_color_draw_quad.cc
+++ b/cc/quads/solid_color_draw_quad.cc
@@ -5,6 +5,7 @@
 #include "cc/quads/solid_color_draw_quad.h"
 
 #include "base/logging.h"
+#include "base/values.h"
 
 namespace cc {
 
@@ -50,4 +51,9 @@
   return static_cast<const SolidColorDrawQuad*>(quad);
 }
 
-}  // namespacec cc
+void SolidColorDrawQuad::ExtendValue(base::DictionaryValue* value) const {
+  value->SetInteger("color", color);
+  value->SetBoolean("force_anti_aliasing_off", force_anti_aliasing_off);
+}
+
+}  // namespace cc
diff --git a/cc/quads/solid_color_draw_quad.h b/cc/quads/solid_color_draw_quad.h
index 4d7ab9f..2c41243 100644
--- a/cc/quads/solid_color_draw_quad.h
+++ b/cc/quads/solid_color_draw_quad.h
@@ -39,6 +39,7 @@
 
  private:
   SolidColorDrawQuad();
+  virtual void ExtendValue(base::DictionaryValue* value) const OVERRIDE;
 };
 
 }  // namespace cc
diff --git a/cc/quads/stream_video_draw_quad.cc b/cc/quads/stream_video_draw_quad.cc
index 831304f..c239256 100644
--- a/cc/quads/stream_video_draw_quad.cc
+++ b/cc/quads/stream_video_draw_quad.cc
@@ -5,6 +5,8 @@
 #include "cc/quads/stream_video_draw_quad.h"
 
 #include "base/logging.h"
+#include "base/values.h"
+#include "cc/base/math_util.h"
 
 namespace cc {
 
@@ -51,4 +53,9 @@
   return static_cast<const StreamVideoDrawQuad*>(quad);
 }
 
+void StreamVideoDrawQuad::ExtendValue(base::DictionaryValue* value) const {
+  value->SetInteger("resource_id", resource_id);
+  value->Set("matrix", MathUtil::AsValue(matrix).release());
+}
+
 }  // namespace cc
diff --git a/cc/quads/stream_video_draw_quad.h b/cc/quads/stream_video_draw_quad.h
index 0ce31af..e610f43 100644
--- a/cc/quads/stream_video_draw_quad.h
+++ b/cc/quads/stream_video_draw_quad.h
@@ -40,6 +40,7 @@
 
  private:
   StreamVideoDrawQuad();
+  virtual void ExtendValue(base::DictionaryValue* value) const OVERRIDE;
 };
 
 }  // namespace cc
diff --git a/cc/quads/texture_draw_quad.cc b/cc/quads/texture_draw_quad.cc
index c894985..ae7cfd6 100644
--- a/cc/quads/texture_draw_quad.cc
+++ b/cc/quads/texture_draw_quad.cc
@@ -5,6 +5,8 @@
 #include "cc/quads/texture_draw_quad.h"
 
 #include "base/logging.h"
+#include "base/values.h"
+#include "cc/base/math_util.h"
 #include "ui/gfx/vector2d_f.h"
 
 namespace cc {
@@ -156,4 +158,17 @@
   return true;
 }
 
+void TextureDrawQuad::ExtendValue(base::DictionaryValue* value) const {
+  value->SetInteger("resource_id", resource_id);
+  value->SetBoolean("premultiplied_alpha", premultiplied_alpha);
+  value->Set("uv_top_left", MathUtil::AsValue(uv_top_left).release());
+  value->Set("uv_bottom_right", MathUtil::AsValue(uv_bottom_right).release());
+  value->SetInteger("background_color", background_color);
+  scoped_ptr<ListValue> vertex_opacity_value(new ListValue);
+  for (size_t i = 0; i < 4; ++i)
+    vertex_opacity_value->AppendDouble(vertex_opacity[i]);
+  value->Set("vertex_opacity", vertex_opacity_value.release());
+  value->SetBoolean("flipped", flipped);
+}
+
 }  // namespace cc
diff --git a/cc/quads/texture_draw_quad.h b/cc/quads/texture_draw_quad.h
index 3db10c6..7f06618 100644
--- a/cc/quads/texture_draw_quad.h
+++ b/cc/quads/texture_draw_quad.h
@@ -57,6 +57,7 @@
 
  private:
   TextureDrawQuad();
+  virtual void ExtendValue(base::DictionaryValue* value) const OVERRIDE;
 };
 
 }  // namespace cc
diff --git a/cc/quads/tile_draw_quad.cc b/cc/quads/tile_draw_quad.cc
index 414b320..3ff9809 100644
--- a/cc/quads/tile_draw_quad.cc
+++ b/cc/quads/tile_draw_quad.cc
@@ -5,6 +5,7 @@
 #include "cc/quads/tile_draw_quad.h"
 
 #include "base/logging.h"
+#include "base/values.h"
 #include "third_party/khronos/GLES2/gl2.h"
 
 namespace cc {
@@ -58,4 +59,9 @@
   return static_cast<const TileDrawQuad*>(quad);
 }
 
+void TileDrawQuad::ExtendValue(base::DictionaryValue* value) const {
+  ContentDrawQuadBase::ExtendValue(value);
+  value->SetInteger("resource_id", resource_id);
+}
+
 }  // namespace cc
diff --git a/cc/quads/tile_draw_quad.h b/cc/quads/tile_draw_quad.h
index 25957f6..6da1e54 100644
--- a/cc/quads/tile_draw_quad.h
+++ b/cc/quads/tile_draw_quad.h
@@ -41,6 +41,7 @@
 
  private:
   TileDrawQuad();
+  virtual void ExtendValue(base::DictionaryValue* value) const OVERRIDE;
 };
 
 }  // namespace cc
diff --git a/cc/quads/yuv_video_draw_quad.cc b/cc/quads/yuv_video_draw_quad.cc
index 2ac75dc..ecdc78f 100644
--- a/cc/quads/yuv_video_draw_quad.cc
+++ b/cc/quads/yuv_video_draw_quad.cc
@@ -5,6 +5,8 @@
 #include "cc/quads/yuv_video_draw_quad.h"
 
 #include "base/logging.h"
+#include "base/values.h"
+#include "cc/base/math_util.h"
 
 namespace cc {
 
@@ -72,4 +74,12 @@
   return static_cast<const YUVVideoDrawQuad*>(quad);
 }
 
+void YUVVideoDrawQuad::ExtendValue(base::DictionaryValue* value) const {
+  value->Set("tex_scale", MathUtil::AsValue(tex_scale).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);
+  value->SetInteger("a_plane_resource_id", a_plane_resource_id);
+}
+
 }  // namespace cc
diff --git a/cc/quads/yuv_video_draw_quad.h b/cc/quads/yuv_video_draw_quad.h
index 34a0612..aa750fa 100644
--- a/cc/quads/yuv_video_draw_quad.h
+++ b/cc/quads/yuv_video_draw_quad.h
@@ -52,6 +52,7 @@
 
  private:
   YUVVideoDrawQuad();
+  virtual void ExtendValue(base::DictionaryValue* value) const OVERRIDE;
 };
 
 }  // namespace cc
diff --git a/cc/resources/pixel_buffer_raster_worker_pool.cc b/cc/resources/pixel_buffer_raster_worker_pool.cc
index 112de14..a03ed81 100644
--- a/cc/resources/pixel_buffer_raster_worker_pool.cc
+++ b/cc/resources/pixel_buffer_raster_worker_pool.cc
@@ -590,10 +590,6 @@
     scoped_refptr<internal::RasterWorkerPoolTask> task,
     bool was_canceled,
     bool needs_upload) {
-  TRACE_EVENT2("cc", "PixelBufferRasterWorkerPool::OnRasterTaskCompleted",
-               "was_canceled", was_canceled,
-               "needs_upload", needs_upload);
-
   DCHECK(pixel_buffer_tasks_.find(task.get()) != pixel_buffer_tasks_.end());
 
   // Balanced with MapPixelBuffer() call in ScheduleMoreTasks().
diff --git a/cc/resources/resource_provider.cc b/cc/resources/resource_provider.cc
index 6d6ac9d..11eaab0 100644
--- a/cc/resources/resource_provider.cc
+++ b/cc/resources/resource_provider.cc
@@ -785,7 +785,6 @@
 void ResourceProvider::PrepareSendToParent(const ResourceIdArray& resources,
                                            TransferableResourceArray* list) {
   DCHECK(thread_checker_.CalledOnValidThread());
-  list->clear();
   WebGraphicsContext3D* context3d = output_surface_->context3d();
   if (!context3d || !context3d->makeContextCurrent()) {
     // TODO(skaslev): Implement this path for software compositing.
@@ -818,7 +817,6 @@
                                           const ResourceIdArray& resources,
                                           TransferableResourceArray* list) {
   DCHECK(thread_checker_.CalledOnValidThread());
-  list->clear();
   WebGraphicsContext3D* context3d = output_surface_->context3d();
   if (!context3d || !context3d->makeContextCurrent()) {
     // TODO(skaslev): Implement this path for software compositing.
diff --git a/cc/resources/video_resource_updater_unittest.cc b/cc/resources/video_resource_updater_unittest.cc
index 95b3124..ff574ff 100644
--- a/cc/resources/video_resource_updater_unittest.cc
+++ b/cc/resources/video_resource_updater_unittest.cc
@@ -36,18 +36,17 @@
 
     return media::VideoFrame::WrapExternalYuvData(
         media::VideoFrame::YV16,  // format
-        size,  // coded_size
-        gfx::Rect(size),  // visible_rect
-        size,  // natural_size
-        size.width(),  // y_stride
-        size.width() / 2,  // u_stride
-        size.width() / 2,  // v_stride
-        y_data,  // y_data
-        u_data,  // u_data
-        v_data,  // v_data
-        base::TimeDelta(),  // timestamp,
-        base::SharedMemory::NULLHandle(),  // shm_handle
-        base::Closure());  // no_longer_needed_cb
+        size,                     // coded_size
+        gfx::Rect(size),          // visible_rect
+        size,                     // natural_size
+        size.width(),             // y_stride
+        size.width() / 2,         // u_stride
+        size.width() / 2,         // v_stride
+        y_data,                   // y_data
+        u_data,                   // u_data
+        v_data,                   // v_data
+        base::TimeDelta(),        // timestamp,
+        base::Closure());         // no_longer_needed_cb
   }
 
   TestWebGraphicsContext3D* context3d_;
diff --git a/cc/resources/worker_pool.cc b/cc/resources/worker_pool.cc
index 812bbeb..dca0c70 100644
--- a/cc/resources/worker_pool.cc
+++ b/cc/resources/worker_pool.cc
@@ -402,7 +402,8 @@
 
 void WorkerPool::ProcessCompletedTasks(
     const TaskVector& completed_tasks) {
-  TRACE_EVENT0("cc", "WorkerPool::ProcessCompletedTasks");
+  TRACE_EVENT1("cc", "WorkerPool::ProcessCompletedTasks",
+               "completed_task_count", completed_tasks.size());
 
   // Worker pool instance is not reentrant while processing completed tasks.
   in_dispatch_completion_callbacks_ = true;
diff --git a/cc/test/fake_delegated_renderer_layer_impl.cc b/cc/test/fake_delegated_renderer_layer_impl.cc
index 8ae1fa5..c6a639e 100644
--- a/cc/test/fake_delegated_renderer_layer_impl.cc
+++ b/cc/test/fake_delegated_renderer_layer_impl.cc
@@ -16,6 +16,12 @@
 
 FakeDelegatedRendererLayerImpl::~FakeDelegatedRendererLayerImpl() {}
 
+scoped_ptr<LayerImpl> FakeDelegatedRendererLayerImpl::CreateLayerImpl(
+    LayerTreeImpl* tree_impl) {
+  return FakeDelegatedRendererLayerImpl::Create(
+      tree_impl, id()).PassAs<LayerImpl>();
+}
+
 static ResourceProvider::ResourceId AddResourceToFrame(
     DelegatedFrameData* frame,
     ResourceProvider::ResourceId resource_id) {
@@ -40,7 +46,8 @@
   }
 
   TransferableResourceArray resources_for_ack;
-  SetFrameData(delegated_frame.Pass(), gfx::RectF(), &resources_for_ack);
+  SetFrameData(delegated_frame.Pass(), gfx::RectF());
+  CollectUnusedResources(&resources_for_ack);
 }
 
 }  // namespace cc
diff --git a/cc/test/fake_delegated_renderer_layer_impl.h b/cc/test/fake_delegated_renderer_layer_impl.h
index b9789f5..a9ca0f9 100644
--- a/cc/test/fake_delegated_renderer_layer_impl.h
+++ b/cc/test/fake_delegated_renderer_layer_impl.h
@@ -17,6 +17,9 @@
   }
   virtual ~FakeDelegatedRendererLayerImpl();
 
+  virtual scoped_ptr<LayerImpl> CreateLayerImpl(LayerTreeImpl* tree_impl)
+      OVERRIDE;
+
   int ChildId() const { return ChildIdForTesting(); }
   const ScopedPtrVector<RenderPass>& RenderPassesInDrawOrder() const {
     return RenderPassesInDrawOrderForTesting();
diff --git a/cc/test/fake_output_surface.cc b/cc/test/fake_output_surface.cc
index 09af44c..9ae7552 100644
--- a/cc/test/fake_output_surface.cc
+++ b/cc/test/fake_output_surface.cc
@@ -61,6 +61,14 @@
   if (frame->software_frame_data || frame->delegated_frame_data ||
       !context3d()) {
     frame->AssignTo(&last_sent_frame_);
+
+    if (last_sent_frame_.delegated_frame_data) {
+      resources_held_by_parent_.insert(
+          resources_held_by_parent_.end(),
+          last_sent_frame_.delegated_frame_data->resource_list.begin(),
+          last_sent_frame_.delegated_frame_data->resource_list.end());
+    }
+
     ++num_sent_frames_;
     PostSwapBuffersComplete();
     DidSwapBuffers();
@@ -116,4 +124,17 @@
   client_->SetTreeActivationCallback(callback);
 }
 
+void FakeOutputSurface::ReturnResource(unsigned id, CompositorFrameAck* ack) {
+  TransferableResourceArray::iterator it;
+  for (it = resources_held_by_parent_.begin();
+       it != resources_held_by_parent_.end();
+       ++it) {
+    if (it->id == id)
+      break;
+  }
+  DCHECK(it != resources_held_by_parent_.end());
+  ack->resources.push_back(*it);
+  resources_held_by_parent_.erase(it);
+}
+
 }  // namespace cc
diff --git a/cc/test/fake_output_surface.h b/cc/test/fake_output_surface.h
index dfd4db5..5091dff 100644
--- a/cc/test/fake_output_surface.h
+++ b/cc/test/fake_output_surface.h
@@ -95,6 +95,12 @@
 
   void SetTreeActivationCallback(const base::Closure& callback);
 
+  const TransferableResourceArray& resources_held_by_parent() {
+    return resources_held_by_parent_;
+  }
+
+  void ReturnResource(unsigned id, CompositorFrameAck* ack);
+
  protected:
   FakeOutputSurface(
       scoped_ptr<WebKit::WebGraphicsContext3D> context3d,
@@ -117,6 +123,7 @@
   bool needs_begin_frame_;
   bool forced_draw_to_software_device_;
   base::WeakPtrFactory<FakeOutputSurface> fake_weak_ptr_factory_;
+  TransferableResourceArray resources_held_by_parent_;
 };
 
 static inline scoped_ptr<cc::OutputSurface> CreateFakeOutputSurface() {
diff --git a/cc/trees/layer_tree_host_impl.cc b/cc/trees/layer_tree_host_impl.cc
index c61e6be..d4a9498 100644
--- a/cc/trees/layer_tree_host_impl.cc
+++ b/cc/trees/layer_tree_host_impl.cc
@@ -7,6 +7,7 @@
 #include <algorithm>
 
 #include "base/basictypes.h"
+#include "base/containers/hash_tables.h"
 #include "base/json/json_writer.h"
 #include "base/metrics/histogram.h"
 #include "base/stl_util.h"
@@ -437,6 +438,25 @@
   }
 }
 
+scoped_ptr<base::Value> LayerTreeHostImpl::FrameData::AsValue() const {
+  scoped_ptr<base::DictionaryValue> value(new base::DictionaryValue());
+  value->SetBoolean("contains_incomplete_tile", contains_incomplete_tile);
+  value->SetBoolean("has_no_damage", has_no_damage);
+
+  // Quad data can be quite large, so only dump render passes if we select
+  // cc.debug.quads.
+  bool quads_enabled;
+  TRACE_EVENT_CATEGORY_GROUP_ENABLED(
+      TRACE_DISABLED_BY_DEFAULT("cc.debug.quads"), &quads_enabled);
+  if (quads_enabled) {
+    scoped_ptr<base::ListValue> render_pass_list(new base::ListValue());
+    for (size_t i = 0; i < render_passes.size(); ++i)
+      render_pass_list->Append(render_passes[i]->AsValue().release());
+    value->Set("render_passes", render_pass_list.release());
+  }
+  return value.PassAs<base::Value>();
+}
+
 void LayerTreeHostImpl::FrameData::AppendRenderPass(
     scoped_ptr<RenderPass> render_pass) {
   render_passes_by_id[render_pass->id] = render_pass.get();
@@ -1257,8 +1277,9 @@
   }
 
   TRACE_EVENT_OBJECT_SNAPSHOT_WITH_ID(
-      TRACE_DISABLED_BY_DEFAULT("cc.debug"), "cc::LayerTreeHostImpl", this,
-      TracedValue::FromValue(AsValue().release()));
+      TRACE_DISABLED_BY_DEFAULT("cc.debug") ","
+      TRACE_DISABLED_BY_DEFAULT("cc.debug.quads"), "cc::LayerTreeHostImpl",
+      this, TracedValue::FromValue(AsValueWithFrame(frame).release()));
 
   // Because the contents of the HUD depend on everything else in the frame, the
   // contents of its texture are updated as the last thing before the frame is
@@ -2136,6 +2157,7 @@
   pinch_gesture_active_ = true;
   previous_pinch_anchor_ = gfx::Point();
   client_->RenewTreePriority();
+  active_tree_->SetCurrentlyScrollingLayer(RootScrollLayer());
 }
 
 void LayerTreeHostImpl::PinchGestureUpdate(float magnify_delta,
@@ -2430,7 +2452,8 @@
   return base::TimeTicks::Now();
 }
 
-scoped_ptr<base::Value> LayerTreeHostImpl::AsValue() const {
+scoped_ptr<base::Value> LayerTreeHostImpl::AsValueWithFrame(
+    FrameData* frame) const {
   scoped_ptr<base::DictionaryValue> state(new base::DictionaryValue());
   if (this->pending_tree_)
       state->Set("activation_state", ActivationStateAsValue().release());
@@ -2441,6 +2464,8 @@
   state->Set("active_tree", active_tree_->AsValue().release());
   if (pending_tree_)
     state->Set("pending_tree", pending_tree_->AsValue().release());
+  if (frame)
+    state->Set("frame", frame->AsValue().release());
   return state.PassAs<base::Value>();
 }
 
diff --git a/cc/trees/layer_tree_host_impl.h b/cc/trees/layer_tree_host_impl.h
index ae6f3c1..31870ac 100644
--- a/cc/trees/layer_tree_host_impl.h
+++ b/cc/trees/layer_tree_host_impl.h
@@ -139,6 +139,7 @@
   struct CC_EXPORT FrameData : public RenderPassSink {
     FrameData();
     virtual ~FrameData();
+    scoped_ptr<base::Value> AsValue() const;
 
     std::vector<gfx::Rect> occluding_screen_space_rects;
     std::vector<gfx::Rect> non_occluding_screen_space_rects;
@@ -371,7 +372,8 @@
 
   virtual base::TimeTicks CurrentPhysicalTimeTicks() const;
 
-  scoped_ptr<base::Value> AsValue() const;
+  scoped_ptr<base::Value> AsValue() const { return AsValueWithFrame(NULL); }
+  scoped_ptr<base::Value> AsValueWithFrame(FrameData* frame) const;
   scoped_ptr<base::Value> ActivationStateAsValue() const;
 
   bool page_scale_animation_active() const { return !!page_scale_animation_; }
diff --git a/cc/trees/layer_tree_host_impl_unittest.cc b/cc/trees/layer_tree_host_impl_unittest.cc
index 72a72b4..ab81c67 100644
--- a/cc/trees/layer_tree_host_impl_unittest.cc
+++ b/cc/trees/layer_tree_host_impl_unittest.cc
@@ -770,9 +770,10 @@
     scroll_layer->SetScrollDelta(gfx::Vector2d());
 
     float page_scale_delta = 2.f;
-    host_impl_->PinchGestureBegin();
+    host_impl_->ScrollBegin(gfx::Point(50, 50), InputHandler::Gesture);
     host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(50, 50));
     host_impl_->PinchGestureEnd();
+    host_impl_->ScrollEnd();
     EXPECT_TRUE(did_request_redraw_);
     EXPECT_TRUE(did_request_commit_);
 
@@ -794,9 +795,11 @@
     scroll_layer->SetScrollDelta(gfx::Vector2d());
 
     float page_scale_delta = 2.f;
+    host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture);
     host_impl_->PinchGestureBegin();
     host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point());
     host_impl_->PinchGestureEnd();
+    host_impl_->ScrollEnd();
 
     gfx::Vector2d scroll_delta(0, 10);
     EXPECT_EQ(InputHandler::ScrollStarted,
@@ -832,9 +835,11 @@
     scroll_layer->SetScrollDelta(gfx::Vector2d());
 
     float page_scale_delta = 2.f;
+    host_impl_->ScrollBegin(gfx::Point(50, 50), InputHandler::Gesture);
     host_impl_->PinchGestureBegin();
     host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(50, 50));
     host_impl_->PinchGestureEnd();
+    host_impl_->ScrollEnd();
     EXPECT_TRUE(did_request_redraw_);
     EXPECT_TRUE(did_request_commit_);
 
@@ -851,9 +856,11 @@
     scroll_layer->SetScrollDelta(gfx::Vector2d());
     float page_scale_delta = 10.f;
 
+    host_impl_->ScrollBegin(gfx::Point(50, 50), InputHandler::Gesture);
     host_impl_->PinchGestureBegin();
     host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(50, 50));
     host_impl_->PinchGestureEnd();
+    host_impl_->ScrollEnd();
 
     scoped_ptr<ScrollAndScaleSet> scroll_info =
         host_impl_->ProcessScrollDeltas();
@@ -869,9 +876,11 @@
     scroll_layer->SetScrollOffset(gfx::Vector2d(50, 50));
 
     float page_scale_delta = 0.1f;
+    host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture);
     host_impl_->PinchGestureBegin();
     host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point());
     host_impl_->PinchGestureEnd();
+    host_impl_->ScrollEnd();
 
     scoped_ptr<ScrollAndScaleSet> scroll_info =
         host_impl_->ProcessScrollDeltas();
@@ -889,10 +898,12 @@
     scroll_layer->SetScrollOffset(gfx::Vector2d(20, 20));
 
     float page_scale_delta = 1.f;
+    host_impl_->ScrollBegin(gfx::Point(10, 10), InputHandler::Gesture);
     host_impl_->PinchGestureBegin();
     host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(10, 10));
     host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(20, 20));
     host_impl_->PinchGestureEnd();
+    host_impl_->ScrollEnd();
 
     scoped_ptr<ScrollAndScaleSet> scroll_info =
         host_impl_->ProcessScrollDeltas();
@@ -909,7 +920,7 @@
     scroll_layer->SetScrollOffset(gfx::Vector2d(20, 20));
 
     float page_scale_delta = 1.f;
-    host_impl_->ScrollBegin(gfx::Point(10, 10), InputHandler::Wheel);
+    host_impl_->ScrollBegin(gfx::Point(10, 10), InputHandler::Gesture);
     host_impl_->PinchGestureBegin();
     host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(10, 10));
     host_impl_->ScrollBy(gfx::Point(10, 10), gfx::Vector2d(-10, -10));
@@ -922,6 +933,30 @@
     EXPECT_EQ(scroll_info->page_scale_delta, page_scale_delta);
     ExpectContains(*scroll_info, scroll_layer->id(), gfx::Vector2d(-10, -10));
   }
+
+  // Two-finger panning should work when starting fully zoomed out.
+  {
+    host_impl_->active_tree()->SetPageScaleFactorAndLimits(0.5f,
+                                                           0.5f,
+                                                           4.f);
+    scroll_layer->SetScrollDelta(gfx::Vector2d());
+    scroll_layer->SetScrollOffset(gfx::Vector2d(0, 0));
+    host_impl_->active_tree()->UpdateMaxScrollOffset();
+
+    host_impl_->ScrollBegin(gfx::Point(0, 0), InputHandler::Gesture);
+    host_impl_->PinchGestureBegin();
+    host_impl_->PinchGestureUpdate(2.f, gfx::Point(0, 0));
+    host_impl_->PinchGestureUpdate(1.f, gfx::Point(0, 0));
+    host_impl_->ScrollBy(gfx::Point(0, 0), gfx::Vector2d(10, 10));
+    host_impl_->PinchGestureUpdate(1.f, gfx::Point(10, 10));
+    host_impl_->PinchGestureEnd();
+    host_impl_->ScrollEnd();
+
+    scoped_ptr<ScrollAndScaleSet> scroll_info =
+        host_impl_->ProcessScrollDeltas();
+    EXPECT_EQ(scroll_info->page_scale_delta, 2.f);
+    ExpectContains(*scroll_info, scroll_layer->id(), gfx::Vector2d(20, 20));
+  }
 }
 
 TEST_F(LayerTreeHostImplTest, PageScaleAnimation) {
@@ -1184,9 +1219,11 @@
   }
 
   // Page scale should update metadata correctly (shrinking only the viewport).
+  host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture);
   host_impl_->PinchGestureBegin();
   host_impl_->PinchGestureUpdate(2.f, gfx::Point());
   host_impl_->PinchGestureEnd();
+  host_impl_->ScrollEnd();
   {
     CompositorFrameMetadata metadata =
         host_impl_->MakeCompositorFrameMetadata();
@@ -1789,9 +1826,11 @@
   host_impl_->ScrollEnd();
 
   // Set new page scale on impl thread by pinching.
+  host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture);
   host_impl_->PinchGestureBegin();
   host_impl_->PinchGestureUpdate(page_scale, gfx::Point());
   host_impl_->PinchGestureEnd();
+  host_impl_->ScrollEnd();
   DrawOneFrame();
 
   // The scroll delta is not scaled because the main thread did not scale.
@@ -1826,9 +1865,11 @@
   LayerImpl* grand_child = child->children()[0];
 
   // Set new page scale on impl thread by pinching.
+  host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture);
   host_impl_->PinchGestureBegin();
   host_impl_->PinchGestureUpdate(new_page_scale, gfx::Point());
   host_impl_->PinchGestureEnd();
+  host_impl_->ScrollEnd();
   DrawOneFrame();
 
   EXPECT_EQ(1.f, root->contents_scale_x());
diff --git a/cc/trees/layer_tree_host_unittest_delegated.cc b/cc/trees/layer_tree_host_unittest_delegated.cc
index 08ba3e0..d489313 100644
--- a/cc/trees/layer_tree_host_unittest_delegated.cc
+++ b/cc/trees/layer_tree_host_unittest_delegated.cc
@@ -4,14 +4,18 @@
 
 #include "cc/trees/layer_tree_host.h"
 
+#include "base/bind.h"
 #include "cc/layers/delegated_renderer_layer.h"
 #include "cc/layers/delegated_renderer_layer_client.h"
 #include "cc/layers/delegated_renderer_layer_impl.h"
+#include "cc/output/compositor_frame.h"
+#include "cc/output/compositor_frame_ack.h"
 #include "cc/output/delegated_frame_data.h"
 #include "cc/quads/shared_quad_state.h"
 #include "cc/quads/texture_draw_quad.h"
 #include "cc/test/fake_delegated_renderer_layer.h"
 #include "cc/test/fake_delegated_renderer_layer_impl.h"
+#include "cc/test/fake_output_surface.h"
 #include "cc/test/layer_tree_test.h"
 #include "cc/trees/layer_tree_impl.h"
 #include "gpu/GLES2/gl2extchromium.h"
@@ -35,6 +39,49 @@
     return frame.Pass();
   }
 
+  scoped_ptr<DelegatedFrameData> CreateInvalidFrameData(
+      gfx::Rect root_output_rect,
+      gfx::Rect root_damage_rect) {
+    scoped_ptr<DelegatedFrameData> frame(new DelegatedFrameData);
+
+    scoped_ptr<RenderPass> root_pass(RenderPass::Create());
+    root_pass->SetNew(RenderPass::Id(1, 1),
+                      root_output_rect,
+                      root_damage_rect,
+                      gfx::Transform());
+
+    scoped_ptr<SharedQuadState> shared_quad_state = SharedQuadState::Create();
+
+    gfx::Rect rect = root_output_rect;
+    gfx::Rect opaque_rect = root_output_rect;
+    // An invalid resource id! The resource isn't part of the frame.
+    unsigned resource_id = 5;
+    bool premultiplied_alpha = false;
+    gfx::PointF uv_top_left = gfx::PointF(0.f, 0.f);
+    gfx::PointF uv_bottom_right = gfx::PointF(1.f, 1.f);
+    SkColor background_color = 0;
+    float vertex_opacity[4] = {1.f, 1.f, 1.f, 1.f};
+    bool flipped = false;
+
+    scoped_ptr<TextureDrawQuad> invalid_draw_quad = TextureDrawQuad::Create();
+    invalid_draw_quad->SetNew(shared_quad_state.get(),
+                              rect,
+                              opaque_rect,
+                              resource_id,
+                              premultiplied_alpha,
+                              uv_top_left,
+                              uv_bottom_right,
+                              background_color,
+                              vertex_opacity,
+                              flipped);
+    root_pass->quad_list.push_back(invalid_draw_quad.PassAs<DrawQuad>());
+
+    root_pass->shared_quad_state_list.push_back(shared_quad_state.Pass());
+
+    frame->render_pass_list.push_back(root_pass.Pass());
+    return frame.Pass();
+  }
+
   void AddTransferableResource(DelegatedFrameData* frame,
                                ResourceProvider::ResourceId resource_id) {
     TransferableResource resource;
@@ -65,6 +112,54 @@
     scoped_ptr<DelegatedFrameData> frame(new DelegatedFrameData);
     return frame.Pass();
   }
+
+
+  static ResourceProvider::ResourceId AppendResourceId(
+      std::vector<ResourceProvider::ResourceId>* resources_in_last_sent_frame,
+      ResourceProvider::ResourceId resource_id) {
+    resources_in_last_sent_frame->push_back(resource_id);
+    return resource_id;
+  }
+
+  void ReturnUnusedResourcesFromParent(LayerTreeHostImpl* host_impl) {
+    DelegatedFrameData* delegated_frame_data =
+        output_surface()->last_sent_frame().delegated_frame_data.get();
+    if (!delegated_frame_data)
+      return;
+
+    std::vector<ResourceProvider::ResourceId> resources_in_last_sent_frame;
+    for (size_t i = 0; i < delegated_frame_data->render_pass_list.size(); ++i) {
+      RenderPass* pass = delegated_frame_data->render_pass_list.at(i);
+      for (size_t j = 0; j < pass->quad_list.size(); ++j) {
+        DrawQuad* quad = pass->quad_list[j];
+        quad->IterateResources(base::Bind(&AppendResourceId,
+                                          &resources_in_last_sent_frame));
+      }
+    }
+
+    std::vector<ResourceProvider::ResourceId> resources_to_return;
+
+    const TransferableResourceArray& resources_held_by_parent =
+        output_surface()->resources_held_by_parent();
+    for (size_t i = 0; i < resources_held_by_parent.size(); ++i) {
+      ResourceProvider::ResourceId resource_in_parent =
+          resources_held_by_parent[i].id;
+      bool resource_in_parent_is_not_part_of_frame =
+          std::find(resources_in_last_sent_frame.begin(),
+                    resources_in_last_sent_frame.end(),
+                    resource_in_parent) == resources_in_last_sent_frame.end();
+      if (resource_in_parent_is_not_part_of_frame)
+        resources_to_return.push_back(resource_in_parent);
+    }
+
+    if (resources_to_return.empty())
+      return;
+
+    CompositorFrameAck ack;
+    for (size_t i = 0; i < resources_to_return.size(); ++i)
+      output_surface()->ReturnResource(resources_to_return[i], &ack);
+    host_impl->OnSwapBuffersComplete(&ack);
+  }
 };
 
 class LayerTreeHostDelegatedTestCaseSingleDelegatedLayer
@@ -267,13 +362,18 @@
                                                  gfx::Rect(5, 5, 1, 1)));
         break;
       case 13:
+        // An invalid frame isn't used, so it should not cause damage.
+        delegated_->SetFrameData(CreateInvalidFrameData(gfx::Rect(0, 0, 10, 10),
+                                                        gfx::Rect(5, 5, 1, 1)));
+        break;
+      case 14:
         // Should create gfx::Rect(1, 1, 2, 2) of damage. The frame size is
         // 5x5 and the display size is now set to 10x10, so this should result
         // in a gfx::Rect(2, 2, 4, 4) damage rect.
         delegated_->SetFrameData(CreateFrameData(gfx::Rect(0, 0, 5, 5),
                                                  gfx::Rect(1, 1, 2, 2)));
         break;
-      case 14:
+      case 15:
         // Should create zero damage.
         layer_tree_host()->SetNeedsCommit();
         break;
@@ -352,10 +452,14 @@
                   damage_rect.ToString());
         break;
       case 13:
-        EXPECT_EQ(gfx::RectF(2.f, 2.f, 4.f, 4.f).ToString(),
+        EXPECT_EQ(gfx::RectF(0.f, 0.f, 0.f, 0.f).ToString(),
                   damage_rect.ToString());
         break;
       case 14:
+        EXPECT_EQ(gfx::RectF(2.f, 2.f, 4.f, 4.f).ToString(),
+                  damage_rect.ToString());
+        break;
+      case 15:
         EXPECT_EQ(gfx::RectF(0.f, 0.f, 0.f, 0.f).ToString(),
                   damage_rect.ToString());
         EndTest();
@@ -479,7 +583,7 @@
     PostSetNeedsCommitToMainThread();
   }
 
-  virtual void DidCommit() OVERRIDE {
+  virtual void DidCommitAndDrawFrame() OVERRIDE {
     scoped_ptr<DelegatedFrameData> frame;
     TransferableResourceArray resources;
 
@@ -495,6 +599,11 @@
         delegated_->SetFrameData(frame.Pass());
         break;
       case 2:
+        // Retrieve unused resources to the main thread.
+        // TODO(danakj): Shouldn't need to commit to get resources.
+        layer_tree_host()->SetNeedsCommit();
+        return;
+      case 3:
         // All of the resources are in use.
         delegated_->TakeUnusedResourcesForChildCompositor(&resources);
         EXPECT_EQ(0u, resources.size());
@@ -506,7 +615,12 @@
         AddTransferableResource(frame.get(), 444);
         delegated_->SetFrameData(frame.Pass());
         break;
-      case 3:
+      case 4:
+        // Retrieve unused resources to the main thread.
+        // TODO(danakj): Shouldn't need to commit to get resources.
+        layer_tree_host()->SetNeedsCommit();
+        return;
+      case 5:
         // 555 is no longer in use.
         delegated_->TakeUnusedResourcesForChildCompositor(&resources);
         EXPECT_EQ(1u, resources.size());
@@ -516,7 +630,12 @@
         frame = CreateFrameData(gfx::Rect(0, 0, 1, 1), gfx::Rect(0, 0, 1, 1));
         delegated_->SetFrameData(frame.Pass());
         break;
-      case 4:
+      case 6:
+        // Postpone collecting resources for a frame. They should still be there
+        // the next frame.
+        layer_tree_host()->SetNeedsCommit();
+        return;
+      case 7:
         // 444 and 999 are no longer in use.
         delegated_->TakeUnusedResourcesForChildCompositor(&resources);
         EXPECT_EQ(2u, resources.size());
@@ -537,11 +656,15 @@
     EXPECT_TRUE(empty_resources.empty());
   }
 
+  virtual void SwapBuffersOnThread(LayerTreeHostImpl* host_impl,
+                                   bool result) OVERRIDE {
+    ReturnUnusedResourcesFromParent(host_impl);
+  }
+
   virtual void AfterTest() OVERRIDE {}
 };
 
-// Enable this for delegating renderer. crbug.com/239290
-SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F(
+SINGLE_AND_MULTI_THREAD_TEST_F(
     LayerTreeHostDelegatedTestReturnUnusedResources);
 
 class LayerTreeHostDelegatedTestReusedResources
@@ -551,7 +674,7 @@
     PostSetNeedsCommitToMainThread();
   }
 
-  virtual void DidCommit() OVERRIDE {
+  virtual void DidCommitAndDrawFrame() OVERRIDE {
     scoped_ptr<DelegatedFrameData> frame;
     TransferableResourceArray resources;
 
@@ -569,6 +692,11 @@
         delegated_->SetFrameData(frame.Pass());
         break;
       case 2:
+        // Retrieve unused resources to the main thread.
+        // TODO(danakj): Shouldn't need to commit to get resources.
+        layer_tree_host()->SetNeedsCommit();
+        return;
+      case 3:
         // All of the resources are in use.
         delegated_->TakeUnusedResourcesForChildCompositor(&resources);
         EXPECT_EQ(0u, resources.size());
@@ -588,7 +716,12 @@
         AddTextureQuad(frame.get(), 444);
         delegated_->SetFrameData(frame.Pass());
         break;
-      case 3:
+      case 4:
+        // Retrieve unused resources to the main thread.
+        // TODO(danakj): Shouldn't need to commit to get resources.
+        layer_tree_host()->SetNeedsCommit();
+        return;
+      case 5:
         // The 999 resource is the only unused one.
         delegated_->TakeUnusedResourcesForChildCompositor(&resources);
         EXPECT_EQ(1u, resources.size());
@@ -598,12 +731,15 @@
     }
   }
 
+  virtual void SwapBuffersOnThread(LayerTreeHostImpl* host_impl,
+                                   bool result) OVERRIDE {
+    ReturnUnusedResourcesFromParent(host_impl);
+  }
+
   virtual void AfterTest() OVERRIDE {}
 };
 
-// Enable this for delegating renderer. crbug.com/239290
-SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F(
-    LayerTreeHostDelegatedTestReusedResources);
+SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostDelegatedTestReusedResources);
 
 class LayerTreeHostDelegatedTestFrameBeforeAck
     : public LayerTreeHostDelegatedTestCaseSingleDelegatedLayer {
@@ -612,7 +748,7 @@
     PostSetNeedsCommitToMainThread();
   }
 
-  virtual void DidCommit() OVERRIDE {
+  virtual void DidCommitAndDrawFrame() OVERRIDE {
     scoped_ptr<DelegatedFrameData> frame;
     TransferableResourceArray resources;
 
@@ -630,6 +766,11 @@
         delegated_->SetFrameData(frame.Pass());
         break;
       case 2:
+        // Retrieve unused resources to the main thread.
+        // TODO(danakj): Shouldn't need to commit to get resources.
+        layer_tree_host()->SetNeedsCommit();
+        return;
+      case 3:
         // All of the resources are in use.
         delegated_->TakeUnusedResourcesForChildCompositor(&resources);
         EXPECT_EQ(0u, resources.size());
@@ -645,7 +786,12 @@
 
         // The parent compositor (this one) does a commit.
         break;
-      case 3:
+      case 4:
+        // Retrieve unused resources to the main thread.
+        // TODO(danakj): Shouldn't need to commit to get resources.
+        layer_tree_host()->SetNeedsCommit();
+        return;
+      case 5:
         delegated_->TakeUnusedResourcesForChildCompositor(&resources);
         EXPECT_EQ(2u, resources.size());
         if (resources[0].id == 555) {
@@ -668,7 +814,7 @@
   }
 
   virtual void DidActivateTreeOnThread(LayerTreeHostImpl* host_impl) OVERRIDE {
-    if (host_impl->active_tree()->source_frame_number() != 3)
+    if (host_impl->active_tree()->source_frame_number() != 5)
       return;
 
     LayerImpl* root_impl = host_impl->active_tree()->root_layer();
@@ -697,12 +843,15 @@
     EndTest();
   }
 
+  virtual void SwapBuffersOnThread(LayerTreeHostImpl* host_impl,
+                                   bool result) OVERRIDE {
+    ReturnUnusedResourcesFromParent(host_impl);
+  }
+
   virtual void AfterTest() OVERRIDE {}
 };
 
-// Enable this for delegating renderer. crbug.com/239290
-SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F(
-    LayerTreeHostDelegatedTestFrameBeforeAck);
+SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostDelegatedTestFrameBeforeAck);
 
 class LayerTreeHostDelegatedTestFrameBeforeTakeResources
     : public LayerTreeHostDelegatedTestCaseSingleDelegatedLayer {
@@ -711,7 +860,7 @@
     PostSetNeedsCommitToMainThread();
   }
 
-  virtual void DidCommit() OVERRIDE {
+  virtual void DidCommitAndDrawFrame() OVERRIDE {
     scoped_ptr<DelegatedFrameData> frame;
     TransferableResourceArray resources;
 
@@ -729,6 +878,11 @@
         delegated_->SetFrameData(frame.Pass());
         break;
       case 2:
+        // Retrieve unused resources to the main thread.
+        // TODO(danakj): Shouldn't need to commit to get resources.
+        layer_tree_host()->SetNeedsCommit();
+        return;
+      case 3:
         // All of the resources are in use.
         delegated_->TakeUnusedResourcesForChildCompositor(&resources);
         EXPECT_EQ(0u, resources.size());
@@ -744,7 +898,12 @@
 
         // The parent compositor (this one) does a commit.
         break;
-      case 3:
+      case 4:
+        // Retrieve unused resources to the main thread.
+        // TODO(danakj): Shouldn't need to commit to get resources.
+        layer_tree_host()->SetNeedsCommit();
+        return;
+      case 5:
         // The child compositor sends a frame before taking resources back
         // from the previous commit. This frame makes use of the resources 555
         // and 444, which were just released during commit.
@@ -758,7 +917,12 @@
         delegated_->TakeUnusedResourcesForChildCompositor(&resources);
         EXPECT_EQ(0u, resources.size());
         break;
-      case 4:
+      case 6:
+        // Retrieve unused resources to the main thread.
+        // TODO(danakj): Shouldn't need to commit to get resources.
+        layer_tree_host()->SetNeedsCommit();
+        return;
+      case 7:
         delegated_->TakeUnusedResourcesForChildCompositor(&resources);
         EXPECT_EQ(0u, resources.size());
         EndTest();
@@ -767,7 +931,7 @@
   }
 
   virtual void DidActivateTreeOnThread(LayerTreeHostImpl* host_impl) OVERRIDE {
-    if (host_impl->active_tree()->source_frame_number() != 3)
+    if (host_impl->active_tree()->source_frame_number() != 5)
       return;
 
     LayerImpl* root_impl = host_impl->active_tree()->root_layer();
@@ -803,11 +967,15 @@
     EXPECT_EQ(map.find(444)->second, quad3->resource_id);
   }
 
+  virtual void SwapBuffersOnThread(LayerTreeHostImpl* host_impl,
+                                   bool result) OVERRIDE {
+    ReturnUnusedResourcesFromParent(host_impl);
+  }
+
   virtual void AfterTest() OVERRIDE {}
 };
 
-// Enable this for delegating renderer. crbug.com/239290
-SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F(
+SINGLE_AND_MULTI_THREAD_TEST_F(
     LayerTreeHostDelegatedTestFrameBeforeTakeResources);
 
 class LayerTreeHostDelegatedTestBadFrame
@@ -817,7 +985,7 @@
     PostSetNeedsCommitToMainThread();
   }
 
-  virtual void DidCommit() OVERRIDE {
+  virtual void DidCommitAndDrawFrame() OVERRIDE {
     scoped_ptr<DelegatedFrameData> frame;
     TransferableResourceArray resources;
 
@@ -833,6 +1001,11 @@
         delegated_->SetFrameData(frame.Pass());
         break;
       case 2:
+        // Retrieve unused resources to the main thread.
+        // TODO(danakj): Shouldn't need to commit to get resources.
+        layer_tree_host()->SetNeedsCommit();
+        return;
+      case 3:
         // All of the resources are in use.
         delegated_->TakeUnusedResourcesForChildCompositor(&resources);
         EXPECT_EQ(0u, resources.size());
@@ -851,7 +1024,12 @@
 
         // The parent compositor (this one) does a commit.
         break;
-      case 3:
+      case 4:
+        // Retrieve unused resources to the main thread.
+        // TODO(danakj): Shouldn't need to commit to get resources.
+        layer_tree_host()->SetNeedsCommit();
+        return;
+      case 5:
         // The bad frame's resource is given back to the child compositor.
         delegated_->TakeUnusedResourcesForChildCompositor(&resources);
         EXPECT_EQ(1u, resources.size());
@@ -862,7 +1040,12 @@
         AddTextureQuad(frame.get(), 999);
         delegated_->SetFrameData(frame.Pass());
         break;
-      case 4:
+      case 6:
+        // Retrieve unused resources to the main thread.
+        // TODO(danakj): Shouldn't need to commit to get resources.
+        layer_tree_host()->SetNeedsCommit();
+        return;
+      case 7:
         // The unused 555 from the last good frame is now released.
         delegated_->TakeUnusedResourcesForChildCompositor(&resources);
         EXPECT_EQ(1u, resources.size());
@@ -873,10 +1056,13 @@
     }
   }
 
-  virtual void DidActivateTreeOnThread(LayerTreeHostImpl* host_impl) OVERRIDE {
+  virtual void SwapBuffersOnThread(LayerTreeHostImpl* host_impl,
+                                   bool result) OVERRIDE {
     if (host_impl->active_tree()->source_frame_number() < 1)
       return;
 
+    ReturnUnusedResourcesFromParent(host_impl);
+
     LayerImpl* root_impl = host_impl->active_tree()->root_layer();
     FakeDelegatedRendererLayerImpl* delegated_impl =
         static_cast<FakeDelegatedRendererLayerImpl*>(root_impl->children()[0]);
@@ -907,7 +1093,7 @@
         EXPECT_EQ(map.find(555)->second, quad2->resource_id);
         break;
       }
-      case 2: {
+      case 3: {
         // We only keep resources from the last valid frame.
         EXPECT_EQ(2u, map.size());
         EXPECT_EQ(1u, map.count(999));
@@ -929,7 +1115,14 @@
         EXPECT_EQ(map.find(555)->second, quad2->resource_id);
         break;
       }
-      case 3: {
+      case 5:
+        // Resources given to our parent compositor will be returned now, but
+        // the DelegatedRendererLayerImpl doesn't know about it until the next
+        // commit.
+        // TODO(danakj): Shouldn't need a commit to return resources to the
+        // DelegatedRendererLayerImpl or to the main thread.
+        break;
+      case 6: {
         // We have the new good frame with just 999 in it.
         EXPECT_EQ(1u, map.size());
         EXPECT_EQ(1u, map.count(999));
@@ -950,9 +1143,7 @@
   virtual void AfterTest() OVERRIDE {}
 };
 
-// Enable this for delegating renderer. crbug.com/239290
-SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F(
-    LayerTreeHostDelegatedTestBadFrame);
+SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostDelegatedTestBadFrame);
 
 class LayerTreeHostDelegatedTestUnnamedResource
     : public LayerTreeHostDelegatedTestCaseSingleDelegatedLayer {
@@ -1077,13 +1268,7 @@
 class LayerTreeHostDelegatedTestResourceSentToParent
     : public LayerTreeHostDelegatedTestCaseSingleDelegatedLayer {
  public:
-  virtual void BeginTest() OVERRIDE {
-    // Prevent drawing with resources that are sent to the grandparent.
-    layer_tree_host()->SetViewportSize(gfx::Size());
-    PostSetNeedsCommitToMainThread();
-  }
-
-  virtual void DidCommit() OVERRIDE {
+  virtual void DidCommitAndDrawFrame() OVERRIDE {
     scoped_ptr<DelegatedFrameData> frame;
     TransferableResourceArray resources;
 
@@ -1113,6 +1298,8 @@
         delegated_->TakeUnusedResourcesForChildCompositor(&resources);
         EXPECT_EQ(0u, resources.size());
 
+        // The impl side will get back the resource at some point.
+        // TODO(danakj): The test should work without this.
         layer_tree_host()->SetNeedsCommit();
         break;
       case 4:
@@ -1148,15 +1335,7 @@
         EXPECT_EQ(1u, delegated_impl->Resources().count(map.find(999)->second));
         EXPECT_EQ(1u, delegated_impl->Resources().count(map.find(555)->second));
 
-        // The 999 resource is sent to a grandparent compositor.
-        ResourceProvider::ResourceIdArray resources_for_parent;
-        resources_for_parent.push_back(map.find(999)->second);
-        TransferableResourceArray transferable_resources;
-        host_impl->resource_provider()->PrepareSendToParent(
-            resources_for_parent, &transferable_resources);
-
-        resource_in_grandparent = transferable_resources[0];
-        EXPECT_EQ(map.find(999)->second, resource_in_grandparent.id);
+        // The 999 resource will be sent to a grandparent compositor.
         break;
       }
       case 2: {
@@ -1164,17 +1343,14 @@
         EXPECT_EQ(1u, map.count(999));
         EXPECT_EQ(1u, map.count(555));
 
-        /// 999 is in the parent, so not held by delegated renderer layer.
+        // 999 is in the parent, so not held by delegated renderer layer.
         EXPECT_EQ(1u, delegated_impl->Resources().size());
         EXPECT_EQ(1u, delegated_impl->Resources().count(map.find(555)->second));
 
         // Receive 999 back from the grandparent.
-        EXPECT_EQ(map.find(999)->second, resource_in_grandparent.id);
-        TransferableResourceArray transferable_resources;
-        transferable_resources.push_back(resource_in_grandparent);
-
-        host_impl->resource_provider()->ReceiveFromParent(
-            transferable_resources);
+        CompositorFrameAck ack;
+        output_surface()->ReturnResource(map.find(999)->second, &ack);
+        host_impl->OnSwapBuffersComplete(&ack);
         break;
       }
       case 3:
@@ -1184,6 +1360,7 @@
 
         EXPECT_EQ(1u, delegated_impl->Resources().size());
         EXPECT_EQ(1u, delegated_impl->Resources().count(map.find(555)->second));
+        break;
     }
   }
 
@@ -1192,7 +1369,8 @@
   TransferableResource resource_in_grandparent;
 };
 
-SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostDelegatedTestResourceSentToParent);
+SINGLE_AND_MULTI_THREAD_DELEGATING_RENDERER_TEST_F(
+    LayerTreeHostDelegatedTestResourceSentToParent);
 
 class LayerTreeHostDelegatedTestCommitWithoutTake
     : public LayerTreeHostDelegatedTestCaseSingleDelegatedLayer {
diff --git a/cc/trees/thread_proxy.cc b/cc/trees/thread_proxy.cc
index 5705788..a0bd4bf 100644
--- a/cc/trees/thread_proxy.cc
+++ b/cc/trees/thread_proxy.cc
@@ -112,7 +112,11 @@
   TRACE_EVENT0("cc", "ThreadProxy::CompositeAndReadback");
   DCHECK(IsMainThread());
   DCHECK(layer_tree_host_);
-  DCHECK(!defer_commits_);
+
+  if (defer_commits_) {
+    TRACE_EVENT0("cc", "CompositeAndReadback_DeferCommit");
+    return false;
+  }
 
   if (!layer_tree_host_->InitializeOutputSurfaceIfNeeded()) {
     TRACE_EVENT0("cc", "CompositeAndReadback_EarlyOut_LR_Uninitialized");
diff --git a/chrome/VERSION b/chrome/VERSION
index 8bdd7b3..5fc8dd7 100644
--- a/chrome/VERSION
+++ b/chrome/VERSION
@@ -1,4 +1,4 @@
 MAJOR=30
 MINOR=0
-BUILD=1591
+BUILD=1595
 PATCH=0
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/FindMatchRectsDetails.java b/chrome/android/java/src/org/chromium/chrome/browser/FindMatchRectsDetails.java
index a0575d3..7b2bd83 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/FindMatchRectsDetails.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/FindMatchRectsDetails.java
@@ -7,8 +7,7 @@
 import android.graphics.RectF;
 
 /**
- * Java equivalent to the C++ FindMatchRectsDetails class
- * defined in chrome/browser/ui/find_bar/find_match_rects_details.h
+ * Holds the result details of a RequestFindMatchRects reply.
  */
 public class FindMatchRectsDetails {
     /** Version of the the rects in this result. */
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/autofill/AutofillDialogControllerAndroid.java b/chrome/android/java/src/org/chromium/chrome/browser/autofill/AutofillDialogControllerAndroid.java
new file mode 100644
index 0000000..e7696d5
--- /dev/null
+++ b/chrome/android/java/src/org/chromium/chrome/browser/autofill/AutofillDialogControllerAndroid.java
@@ -0,0 +1,190 @@
+// 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.
+
+package org.chromium.chrome.browser.autofill;
+
+import org.chromium.base.CalledByNative;
+import org.chromium.base.JNINamespace;
+import org.chromium.ui.WindowAndroid;
+
+/**
+ * Java-side AutofillDialog and AutofillDialogFactory interfaces, and
+ * JNI glue for C++ AutofillDialogControllerAndroid.
+ */
+@JNINamespace("autofill")
+public class AutofillDialogControllerAndroid {
+    private static AutofillDialogFactory mDialogFactory;
+
+    private int mNativeDelegate;  // could be 0 after onDestroy().
+    private AutofillDialog mDialog;
+
+    /**
+     * An interface to the two possible continuations for the dialog.
+     * The dialog is expected to be dismissed when either of the calls is made.
+     */
+    public interface AutofillDialogDelegate {
+        /**
+         * Cancels the requestAutocomplete.
+         */
+        void dialogCancel();
+
+        /**
+         * Submits the data to the web-page and persists the last account/card/address choices.
+         * @param fullWallet Resulting billing/shipping information obtained from the user
+         * @param lastUsedChoiceIsAutofill Whether the last selected data source is Autofill
+         * @param lastUsedAccountName The last selected account name, or null
+         * @param guidLastUsedBilling GUID of the last selected Autofill billing address, or null
+         * @param guidLastUsedShipping GUID of the last selected Autofill shipping address, or null
+         * @param guidLastUsedCard GUID of the last selected Autofill credit card, or null
+         */
+        void dialogContinue(
+                AutofillDialogResult.ResultWallet fullWallet,
+                boolean lastUsedChoiceIsAutofill, String lastUsedAccountName,
+                String guidLastUsedBilling, String guidLastUsedShipping, String guidLastUsedCard);
+    }
+
+    /**
+     * An interface that exposes the necessary functionality for an Autofill dialog.
+     * Note that all information necessary to construct the dialog is passed to the factory.
+     */
+    public interface AutofillDialog {
+        /**
+         * Notifies the dialog that the C++ side is gone.
+         * The dialog needs to clear its reference to the no longer valid AutofillDialogDelegate.
+         */
+        void onDestroy();
+    }
+
+    /**
+     * An interface to the factory that creates Autofill dialogs.
+     */
+    public interface AutofillDialogFactory {
+        /**
+         * Creates the dialog.
+         * Reasonable attempts should be made to respect "initial choices",
+         * Initial choices don't have to be self-consistent or valid.
+         *
+         * @param delegate Continuations for the dialog
+         * @param windowAndroid Context in which the dialog should be shown
+         * @param requestFullBillingAddress Whether the full billing address is required
+         * @param requestShippingAddress Whether the shipping address is required
+         * @param requestPhoneNumbers Whether the phone numbers are required in addresses
+         * @param incognitoMode True if the dialog started from an incognito tab
+         * @param initialChoiceIsAutofill Whether the selected data source should be Autofill
+         * @param initialAccountName Account to be selected, or null
+         * @param initialBillingGuid GUID of the initial billing address selection in Autofill
+         * @param initialShippingGuid GUID of the initial shipping address selection in Autofill
+         * @param initialCardGuid GUID of the initial credit card selection in Autofill
+         * @param merchantDomain Scheme+origin for the originating web page, or null
+         * @return The Autofill dialog that would later call into the delegate, or null
+         */
+        AutofillDialog createDialog(
+                final AutofillDialogDelegate delegate,
+                final WindowAndroid windowAndroid,
+                final boolean requestFullBillingAddress, final boolean requestShippingAddress,
+                final boolean requestPhoneNumbers,
+                final boolean incognitoMode,
+                final boolean initialChoiceIsAutofill, final String initialAccountName,
+                final String initialBillingGuid, final String initialShippingGuid,
+                final String initialCardGuid,
+                final String merchantDomain);
+    }
+
+    /**
+     * Sets the factory to be used.
+     * @param factory An instance of the AutofillDialogFactory that will handle requests.
+     */
+    public static void setDialogFactory(AutofillDialogFactory factory) {
+        mDialogFactory = factory;
+    }
+
+    private AutofillDialogControllerAndroid(
+            final int nativeAutofillDialogControllerAndroid,
+            final WindowAndroid windowAndroid,
+            final boolean requestFullBillingAddress, final boolean requestShippingAddress,
+            final boolean requestPhoneNumbers,
+            final boolean incognitoMode,
+            final boolean initialChoiceIsAutofill, final String initialWalletAccountName,
+            final String initialBillingGuid, final String initialShippingGuid,
+            final String initialCardGuid,
+            final String merchantDomain) {
+        mNativeDelegate = nativeAutofillDialogControllerAndroid;
+
+        if (mDialogFactory == null) {
+            nativeDialogCancel(mNativeDelegate);
+            return;
+        }
+
+        AutofillDialogDelegate delegate = new AutofillDialogDelegate() {
+            @Override
+            public void dialogCancel() {
+                nativeDialogCancel(mNativeDelegate);
+            }
+
+            @Override
+            public void dialogContinue(
+                    AutofillDialogResult.ResultWallet fullWallet,
+                    boolean lastUsedChoiceIsAutofill, String lastUsedAccountName,
+                    String guidLastUsedBilling, String guidLastUsedShipping,
+                    String guidLastUsedCard) {
+                nativeDialogContinue(mNativeDelegate, fullWallet,
+                        lastUsedChoiceIsAutofill, lastUsedAccountName,
+                        guidLastUsedBilling, guidLastUsedShipping, guidLastUsedCard);
+            }
+        };
+
+        mDialog = mDialogFactory.createDialog(
+                delegate,
+                windowAndroid,
+                requestFullBillingAddress, requestShippingAddress,
+                requestPhoneNumbers,
+                incognitoMode,
+                initialChoiceIsAutofill, initialWalletAccountName,
+                initialBillingGuid, initialShippingGuid, initialCardGuid,
+                merchantDomain);
+        if (mDialog == null) {
+            nativeDialogCancel(mNativeDelegate);
+            return;
+        }
+    }
+
+    @CalledByNative
+    private static AutofillDialogControllerAndroid create(
+            final int nativeAutofillDialogControllerAndroid,
+            final WindowAndroid windowAndroid,
+            final boolean requestFullBillingAddress, final boolean requestShippingAddress,
+            final boolean requestPhoneNumbers,
+            final boolean incognitoMode,
+            final boolean initialChoiceIsAutofill, final String initialWalletAccountName,
+            final String initialBillingGuid, final String initialShippingGuid,
+            final String initialCreditCardGuid,
+            final String merchantDomain) {
+        return new AutofillDialogControllerAndroid(
+                nativeAutofillDialogControllerAndroid, windowAndroid,
+                requestFullBillingAddress, requestShippingAddress, requestPhoneNumbers,
+                incognitoMode,
+                initialChoiceIsAutofill, initialWalletAccountName,
+                initialBillingGuid, initialShippingGuid,
+                initialCreditCardGuid,
+                merchantDomain);
+    }
+
+    @CalledByNative
+    private void onDestroy() {
+        if (mNativeDelegate == 0) return;
+
+        if (mDialog != null) mDialog.onDestroy();
+
+        mDialog = null;
+        mNativeDelegate = 0;
+    }
+
+    // Calls from Java to C++ AutofillDialogControllerAndroid:
+
+    private native void nativeDialogCancel(int nativeAutofillDialogControllerAndroid);
+    private native void nativeDialogContinue(int nativeAutofillDialogControllerAndroid,
+            Object fullWallet,
+            boolean lastUsedChoiceIsAutofill, String lastUsedAccountName,
+            String guidLastUsedBilling, String guidLastUsedShipping, String guidLastUsedCard);
+}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/autofill/AutofillDialogResult.java b/chrome/android/java/src/org/chromium/chrome/browser/autofill/AutofillDialogResult.java
new file mode 100644
index 0000000..92f0cd8
--- /dev/null
+++ b/chrome/android/java/src/org/chromium/chrome/browser/autofill/AutofillDialogResult.java
@@ -0,0 +1,246 @@
+// 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.
+
+package org.chromium.chrome.browser.autofill;
+
+import org.chromium.base.CalledByNative;
+import org.chromium.base.JNINamespace;
+
+/**
+ * Java-side result of a non-cancelled AutofillDialog invocation, and
+ * JNI glue for C++ AutofillDialogResult used by AutofillDialogControllerAndroid.
+ */
+@JNINamespace("autofill")
+public class AutofillDialogResult {
+    /**
+     * Information about the credit card in the dialog result.
+     */
+    public static class ResultCard {
+        private final int mExpirationMonth;
+        private final int mExpirationYear;
+        private final String mPan;
+        private final String mCvn;
+
+        /**
+         * Creates a ResultCard.
+         * @param expirationMonth Expiration month
+         * @param expirationYear Expiration year
+         * @param pan Credit card number
+         * @param cvn Credit card verification number
+         */
+        public ResultCard(int expirationMonth, int expirationYear, String pan, String cvn) {
+            mExpirationMonth = expirationMonth;
+            mExpirationYear = expirationYear;
+            mPan = pan;
+            mCvn = cvn;
+        }
+
+        /**
+         * @return Expiration month
+         */
+        @CalledByNative("ResultCard")
+        public int getExpirationMonth() {
+            return mExpirationMonth;
+        }
+
+        /**
+         * @return Expiration year
+         */
+        @CalledByNative("ResultCard")
+        public int getExpirationYear() {
+            return mExpirationYear;
+        }
+
+        /**
+         * @return Credit card number
+         */
+        @CalledByNative("ResultCard")
+        public String getPan() {
+            return mPan;
+        }
+
+        /**
+         * @return Credit card verification number
+         */
+        @CalledByNative("ResultCard")
+        public String getCvn() {
+            return mCvn;
+        }
+    }
+
+    /**
+     * Information about an address in the dialog result.
+     */
+    public static class ResultAddress {
+        private final String mName;
+        private final String mPhoneNumber;
+        private final String mAddress1;
+        private final String mAddress2;
+        private final String mCity;
+        private final String mState;
+        private final String mPostalCode;
+        private final String mCountryCode;
+
+        /**
+         * Creates a ResultAddress.
+         * Any parameter can be empty or null.
+         * @param name Full name
+         * @param phoneNumber Phone number
+         * @param address1 Address line 1
+         * @param address2 Address line 2
+         * @param city City
+         * @param state State
+         * @param postalCode Postal code
+         * @param countryCode Country code
+         */
+        public ResultAddress(
+                String name, String phoneNumber,
+                String address1, String address2,
+                String city, String state, String postalCode,
+                String countryCode) {
+            mName = name;
+            mPhoneNumber = phoneNumber;
+            mAddress1 = address1;
+            mAddress2 = address2;
+            mCity = city;
+            mState = state;
+            mPostalCode = postalCode;
+            mCountryCode = countryCode;
+        }
+
+        /**
+         * @return Full name
+         */
+        @CalledByNative("ResultAddress")
+        public String getName() {
+            return mName;
+        }
+
+        /**
+         * @return Phone number
+         */
+        @CalledByNative("ResultAddress")
+        public String getPhoneNumber() {
+            return mPhoneNumber;
+        }
+
+        /**
+         * @return Address line 1
+         */
+        @CalledByNative("ResultAddress")
+        public String getAddress1() {
+            return mAddress1;
+        }
+
+        /**
+         * @return Address line 2
+         */
+        @CalledByNative("ResultAddress")
+        public String getAddress2() {
+            return mAddress2;
+        }
+
+        /**
+         * @return City
+         */
+        @CalledByNative("ResultAddress")
+        public String getCity() {
+            return mCity;
+        }
+
+        /**
+         * @return State
+         */
+        @CalledByNative("ResultAddress")
+        public String getState() {
+            return mState;
+        }
+
+        /**
+         * @return Postal code
+         */
+        @CalledByNative("ResultAddress")
+        public String getPostalCode() {
+            return mPostalCode;
+        }
+
+        /**
+         * @return Country code
+         */
+        @CalledByNative("ResultAddress")
+        public String getCountryCode() {
+            return mCountryCode;
+        }
+    }
+
+    /**
+     * A response from the dialog.
+     */
+    public static class ResultWallet {
+        private final String mEmail;
+        private final String mGoogleTransactionId;
+        private final ResultCard mCard;
+        private final ResultAddress mBillingAddress;
+        private final ResultAddress mShippingAddress;
+
+        /**
+         * Creates a ResultWallet.
+         * Any fields could be empty or null.
+         * @param email Email address
+         * @param googleTransactionId Google transaction ID if any
+         * @param card Information about the credit card
+         * @param billingAddress Information about the billing address
+         * @param shippingAddress Information about the shipping address
+         */
+        public ResultWallet(
+                String email, String googleTransactionId,
+                ResultCard card, ResultAddress billingAddress, ResultAddress shippingAddress) {
+            mEmail = email;
+            mGoogleTransactionId = googleTransactionId;
+            mCard = card;
+            mBillingAddress = billingAddress;
+            mShippingAddress = shippingAddress;
+        }
+
+        /**
+         * @return Email address
+         */
+        @CalledByNative("ResultWallet")
+        public String getEmail() {
+            return mEmail;
+        }
+
+        /**
+         * @return Google transaction ID if any
+         */
+        @CalledByNative("ResultWallet")
+        public String getGoogleTransactionId() {
+            return mGoogleTransactionId;
+        }
+
+        /**
+         * @return Credit card information, or null
+         */
+        @CalledByNative("ResultWallet")
+        public ResultCard getCard() {
+            return mCard;
+        }
+
+        /**
+         * @return Billing address information, or null
+         */
+        @CalledByNative("ResultWallet")
+        public ResultAddress getBillingAddress() {
+            return mBillingAddress;
+        }
+
+        /**
+         * @return Shipping address information, or null
+         */
+        @CalledByNative("ResultWallet")
+        public ResultAddress getShippingAddress() {
+            return mShippingAddress;
+        }
+    }
+}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/search_engines/TemplateUrlService.java b/chrome/android/java/src/org/chromium/chrome/browser/search_engines/TemplateUrlService.java
index f539e1b..ee26e4c 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/search_engines/TemplateUrlService.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/search_engines/TemplateUrlService.java
@@ -115,7 +115,10 @@
         }
     }
 
-    public int getSearchEngine() {
+    /**
+     * @return The default search engine index (e.g., 0, 1, 2,...).
+     */
+    public int getDefaultSearchEngineIndex() {
         ThreadUtils.assertOnUiThread();
         return nativeGetDefaultSearchProvider(mNativeTemplateUrlServiceAndroid);
     }
@@ -125,7 +128,7 @@
      */
     public TemplateUrl getDefaultSearchEngineTemplateUrl() {
         return nativeGetPrepopulatedTemplateUrlAt(
-                mNativeTemplateUrlServiceAndroid, getSearchEngine());
+                mNativeTemplateUrlServiceAndroid, getDefaultSearchEngineIndex());
     }
 
     public void setSearchEngine(int selectedIndex) {
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/search_engines/TemplateUrlServiceTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/search_engines/TemplateUrlServiceTest.java
index 04c8965..e3b44d8 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/search_engines/TemplateUrlServiceTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/search_engines/TemplateUrlServiceTest.java
@@ -66,7 +66,7 @@
         ThreadUtils.runOnUiThreadBlocking(new Runnable() {
             @Override
             public void run() {
-                searchEngineIndex.set(templateUrlService.getSearchEngine());
+                searchEngineIndex.set(templateUrlService.getDefaultSearchEngineIndex());
             }
         });
         assertEquals(0, searchEngineIndex.get());
@@ -80,7 +80,7 @@
                 assertTrue("There must be more than one search engine to change searchEngines",
                         searchEngines.size() > 1);
                 templateUrlService.setSearchEngine(1);
-                searchEngineIndex.set(templateUrlService.getSearchEngine());
+                searchEngineIndex.set(templateUrlService.getDefaultSearchEngineIndex());
             }
         });
         assertEquals(1, searchEngineIndex.get());
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/test/ModalDialogTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/test/ModalDialogTest.java
index ecefa99..beb56fd 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/test/ModalDialogTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/test/ModalDialogTest.java
@@ -14,6 +14,7 @@
 import android.widget.EditText;
 
 import org.chromium.base.ThreadUtils;
+import org.chromium.base.test.util.DisabledTest;
 import org.chromium.base.test.util.Feature;
 import org.chromium.base.test.util.UrlUtils;
 import org.chromium.chrome.browser.JavascriptAppModalDialog;
@@ -170,8 +171,9 @@
      * Verifies beforeunload dialogs are shown and they block/allow navigation
      * as appropriate.
      */
-    @MediumTest
-    @Feature({"Browser", "Main"})
+    //@MediumTest
+    //@Feature({"Browser", "Main"})
+    @DisabledTest //crbug/270593
     public void testBeforeUnloadDialog()
             throws InterruptedException, TimeoutException, ExecutionException {
         loadUrlWithSanitization(BEFORE_UNLOAD_URL);
diff --git a/chrome/android/testshell/testshell_tab.cc b/chrome/android/testshell/testshell_tab.cc
index 92a35c2..656bc31 100644
--- a/chrome/android/testshell/testshell_tab.cc
+++ b/chrome/android/testshell/testshell_tab.cc
@@ -89,6 +89,10 @@
   return false;
 }
 
+void TestShellTab::OnNewTabPageReady() {
+  NOTIMPLEMENTED();
+}
+
 void TestShellTab::RunExternalProtocolDialog(const GURL& url) {
   NOTIMPLEMENTED();
 }
diff --git a/chrome/android/testshell/testshell_tab.h b/chrome/android/testshell/testshell_tab.h
index 0f79de4..bb06ad9 100644
--- a/chrome/android/testshell/testshell_tab.h
+++ b/chrome/android/testshell/testshell_tab.h
@@ -65,6 +65,7 @@
   virtual void ShowSyncSettings() OVERRIDE;
   virtual void ShowTermsOfService() OVERRIDE;
   virtual bool ShouldWelcomePageLinkToTermsOfService() OVERRIDE;
+  virtual void OnNewTabPageReady() OVERRIDE;
 
   virtual void RunExternalProtocolDialog(const GURL& url) OVERRIDE;
 
diff --git a/chrome/app/chrome_main_delegate.cc b/chrome/app/chrome_main_delegate.cc
index 1daec10..4825c3f 100644
--- a/chrome/app/chrome_main_delegate.cc
+++ b/chrome/app/chrome_main_delegate.cc
@@ -5,6 +5,7 @@
 #include "chrome/app/chrome_main_delegate.h"
 
 #include "base/command_line.h"
+#include "base/files/file_path.h"
 #include "base/lazy_instance.h"
 #include "base/message_loop/message_loop.h"
 #include "base/metrics/stats_counters.h"
diff --git a/chrome/app/chromeos_strings.grdp b/chrome/app/chromeos_strings.grdp
index 027556d..3fc23f4 100644
--- a/chrome/app/chromeos_strings.grdp
+++ b/chrome/app/chromeos_strings.grdp
@@ -471,6 +471,15 @@
   <message name="IDS_CREATE_LOCALLY_MANAGED_USER_NO_MANAGER_TEXT" desc="Text shown when supervised user can be created, but no users that can be manager exist.">
     At least one account must exist on this device before creating a supervised user.
   </message>
+  <message name="IDS_CREATE_LOCALLY_MANAGED_INTRO_TEXT_TITLE" desc="Supervised user dialog, intro page, title">
+    What is a supervised user?
+  </message>
+  <message name="IDS_CREATE_LOCALLY_MANAGED_INTRO_ALTERNATE_TEXT" desc="Supervised user dialog, intro page, first paragraph">
+    A supervised user can explore the web with your guidance. As the manager of a supervised user, you can
+    <ph name="BEGIN_BOLD">&lt;strong&gt;</ph>allow or prohibit<ph name="END_BOLD">&lt;/strong&gt;</ph> certain websites,
+    <ph name="BEGIN_BOLD">&lt;strong&gt;</ph>review<ph name="END_BOLD">&lt;/strong&gt;</ph> websites the supervised user has visited, and
+    <ph name="BEGIN_BOLD">&lt;strong&gt;</ph>manage<ph name="END_BOLD">&lt;/strong&gt;</ph> other settings.
+  </message>
   <message name="IDS_CREATE_LOCALLY_MANAGED_INTRO_TEXT_1" desc="Supervised user dialog, intro page, first paragraph">
     A supervised user can explore the web with your guidance. As the manager of a supervised user in Chrome, you can:
   </message>
@@ -485,8 +494,7 @@
   </message>
   <message name="IDS_CREATE_LOCALLY_MANAGED_INTRO_TEXT_2" desc="Supervised user dialog, intro page, second paragraph">
     Creating a supervised user does not create a Google Account, and their settings
-    and data will not follow them to other devices with Chrome Sync. Currently,
-    a supervised user applies only to this installation of Chrome, on this device.
+    and data will not follow them to other devices with Chrome Sync. A supervised user applies only to this device.
   </message>
   <message name="IDS_CREATE_LOCALLY_MANAGED_INTRO_TEXT_3" desc="Supervised user dialog, intro page, third paragraph">
     After you create a new supervised user, you can manage the settings at any time from any device at <ph name="MANAGEMENT_URL">$1<ex>www.example.com</ex></ph>.
@@ -501,7 +509,7 @@
     Enter password
   </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 an name -
+    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>.
@@ -596,16 +604,19 @@
     Retry
   </message>
   <message name="IDS_CREATE_LOCALLY_MANAGED_USER_CREATION_AUTH_PROGRESS_MESSAGE" desc="Text shown next to progress indicator upon manager authentication.">
-    Authenticating...
+    Authenticating
   </message>
   <message name="IDS_CREATE_LOCALLY_MANAGED_USER_CREATION_CREATION_PROGRESS_MESSAGE" desc="Text shown next to progress indicator upon supervised user creation.">
-    Creating profile...
+    Creating supervised user
   </message>
   <message name="IDS_CREATE_LOCALLY_MANAGED_USER_CREATION_CREATION_TIMEOUT_MESSAGE" desc="Text shown at the place of progess indicator if creation takes too long and should be cancelled.">
     Profile takes too long to create. You may want to cancel process and retry later.
   </message>
   <message name="IDS_USER_IS_LOCALLY_MANAGED_BY_NOTICE" desc="Text for notifications showing that this user is locally managed">
-    This supervised user is managed by <ph name="USER_DISPLAY_NAME">$1<ex>John</ex></ph>. Usage and browsing history can be viewed by the manager.
+    This user is supervised by <ph name="MANAGER_EMAIL">$1<ex>user@example.com</ex></ph>. Usage and history from this user can be reviewed by the manager on chrome.com.
+  </message>
+  <message name="IDS_SUPERVISED_USER_EXPIRED_TOKEN_WARNING" desc="Warning text that is shown on login screen trying to sign in as a supervised user that has expired token">
+    This supervised user may have been deleted or disabled by the manager. Please contact the manager if you would like to continue signing in as this user.
   </message>
   <message name="IDS_LOGIN_POD_USER_REMOVE_WARNING" desc="Text shown as a warning when attempting to remove supervised user.">
     All files and local data associated with the supervised user will be permanently
@@ -975,15 +986,6 @@
   <message name="IDS_OPTIONS_SETTINGS_DISPLAY_OPTIONS_STANDARD_ORIENTATION" desc="The default value of display orientation option item.">
     Standard
   </message>
-  <message name="IDS_OPTIONS_SETTINGS_DISPLAY_OPTIONS_ORIENTATION_90" desc="The value of display orientation option item: 90-degree rotated">
-    90&#x00B0;
-  </message>
-  <message name="IDS_OPTIONS_SETTINGS_DISPLAY_OPTIONS_ORIENTATION_180" desc="The value of display orientation option item: 180-degree rotated">
-    180&#x00B0;
-  </message>
-  <message name="IDS_OPTIONS_SETTINGS_DISPLAY_OPTIONS_ORIENTATION_270" desc="The value of display orientation option item: 270-degree rotated">
-    270&#x00B0;
-  </message>
   <message name="IDS_OPTIONS_SETTINGS_DISPLAY_OPTIONS_START_CALIBRATING_OVERSCAN" desc="Button label to start calibrating the overscan preference.">
     Adjust...
   </message>
@@ -1616,6 +1618,19 @@
     This SIM card is disabled and cannot be used. Please contact your service provider for a replacement.
   </message>
 
+  <message name="IDS_SLOW_DISABLE" desc="The text of the button that disables performance collection for feedback reports">
+    Disable performance data collection
+  </message>
+  <message name="IDS_SLOW_ENABLE" desc="The text of the button that enables performance collection for feedback reports">
+    Enable performance data collection
+  </message>
+  <message name="IDS_SLOW_DESCRIPTION" desc="The description of the performance tracing feature for feedback reports.">
+    Enabling collection of performance data will help Google improve the system over time. No data is sent until you file a feedback report (Alt-Shift-I) and include performance data. You can return to this screen to disable collection at any time.
+  </message>
+  <message name="IDS_SLOW_WARNING" desc="The warning that informs users that enabling this can have a negative effect on their performance">
+    <ph name="BEGIN_BOLD">&lt;strong&gt;</ph>Note:<ph name="END_BOLD">&lt;/strong&gt;</ph> Only enable if you know what you are doing or if you have been asked to do so, as collection of data may reduce performance.
+  </message>
+
   <message name="IDS_EULA_BACK_BUTTON" desc="Back button shown on EULA screen.">
     Back
   </message>
diff --git a/chrome/app/chromium_strings.grd b/chrome/app/chromium_strings.grd
index 8dacb67..9e97135 100644
--- a/chrome/app/chromium_strings.grd
+++ b/chrome/app/chromium_strings.grd
@@ -909,6 +909,9 @@
       <message name="IDS_AUTOFILL_DIALOG_SAVE_LOCALLY_TOOLTIP" desc="Tooltip which explains function of checkbox that controls whether info the user types into the autofill dialog is saved by chrome.">
         Chromium will securely store your information so you don't need to type it in again, but you will still need to verify your card's security code for future payments.
       </message>
+      <message name="IDS_AUTOFILL_NEW_CREDIT_CARD_BUBBLE_TITLE" desc="Title text of the new credit card bubble informing a user their billing information has been saved in chrome.">
+        Your billing details have been saved in Chromium.
+      </message>
 
       <!-- Network Error Pages -->
       <message name="IDS_ERRORPAGES_SUGGESTION_NETWORK_PREDICTION_BODY" desc="When a page fails to load, sometimes we suggest disabling predicting network actions.  These are details below a header.">
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd
index ce595e8..9dfe704 100644
--- a/chrome/app/generated_resources.grd
+++ b/chrome/app/generated_resources.grd
@@ -4786,6 +4786,9 @@
       <message name="IDS_EXTENSION_WARNINGS_CREDENTIALS_CONFLICT" desc="Warning message which indicates that two or more extensions tried to modify a network request in a conflicting way and the modification of this extension was ignored">
         This extension failed to provide credentials to a network request because another extension (<ph name="EXTENSION_NAME">$1<ex>My Cool Extension</ex></ph>) provided different credentials.
       </message>
+      <message name="IDS_EXTENSION_WARNINGS_DOWNLOAD_FILENAME_CONFLICT" desc="Warning message which indicates that two or more extensions tried to determine the filename of a downloaded file in a conflicting way and the modification of this extension was ignored">
+        This extension failed to name the download "<ph name="ATTEMPTED_FILENAME">$1<ex>apple.png</ex></ph>" because another extension (<ph name="EXTENSION_NAME">$2<ex>My Cool Extension</ex></ph>) determined a different filename "<ph name="ACTUAL_FILENAME">$3<ex>banana.png</ex></ph>".
+      </message>
 
       <!-- External extension install alerts -->
       <!-- TODO(mpcomplete): We may need to change Chrome to
@@ -5753,6 +5756,12 @@
       <message name="IDS_FLAGS_ENABLE_PANELS_DESCRIPTION" desc="Description for the flag to enable Panel windows.">
         Enable Panel windows that open outside of the browser frame. Attempts to open a Panel will open a popup instead if not enabled. Panels are always enabled on the dev and canary channels.
       </message>
+      <message name="IDS_FLAGS_ENABLE_HTML_IMPORTS_NAME" desc="Enable HTML Imports.">
+        Enable HTML Imports
+      </message>
+      <message name="IDS_FLAGS_ENABLE_HTML_IMPORTS_DESCRIPTION" desc="Description of 'Enable HTML Imports' flag.">
+        Enabling this option allows web applications to load HTML Imports.
+      </message>
       <message name="IDS_FLAGS_ENABLE_WEBGL_NAME" desc="Name of the 'Enable WebGL' lab.">
         Enable WebGL
       </message>
@@ -7207,6 +7216,9 @@
       <message name="IDS_IMPORT_FROM_SAFARI" desc="browser combo box: Safari">
         Safari
       </message>
+      <message name="IDS_IMPORT_FROM_BOOKMARKS_HTML_FILE" desc="browser combo box: Bookmarks HTML File">
+        Bookmarks HTML File
+      </message>
       <message name="IDS_IMPORT_ITEMS_LABEL" desc="Label before item select checkboxes">
         Select items to import:
       </message>
@@ -7232,6 +7244,9 @@
       <message name="IDS_IMPORT_COMMIT" desc="Text for OK button on dialog">
         Import
       </message>
+      <message name="IDS_IMPORT_CHOOSE_FILE" desc="Text for the Choose File on dialog">
+        Choose File
+      </message>
 
       <message name="IDS_IMPORTER_GOOGLE_LOGIN_TEXT" desc="The message to be displayed on dialog">
         In order to import Toolbar bookmarks into Chrome, you must be signed in to your Google account.  Please sign in and try to import again.
@@ -7239,6 +7254,10 @@
       <message name="IDS_IMPORT_NO_PROFILE_FOUND" desc="Message displayed when we do not find any supported browser to import from.">
         No supported browser found
       </message>
+      <message name="IDS_IMPORT_PASSWORD_KEYCHAIN_WARNING" desc="Message displayed at the bottom of the Import Dialog for Safari on Mac OS">
+        Passwords saved in the Mac OS X Keychain will be used to help you sign in without typing.
+      </message>
+
 
       <!-- Import progress popup -->
       <message name="IDS_IMPORT_PROGRESS_TITLE" desc="Title for the importing progress dialog">
@@ -7333,6 +7352,9 @@
       <message name="IDS_FEEDBACK_SAVED_SCREENSHOTS" desc="Radio button for including the last screen image on the bug report dialog box">
         Send a saved screen shot
       </message>
+      <message name="IDS_FEEDBACK_INCLUDE_PERFORMANCE_TRACE_CHECKBOX" desc="Checkbox for including system information on the bug report dialog box">
+        Send performance trace data
+      </message>
       <message name="IDS_FEEDBACK_INCLUDE_SYSTEM_INFORMATION_CHKBOX" desc="Checkbox for including system information on the bug report dialog box">
         Send system information
       </message>
@@ -7461,6 +7483,9 @@
       <message name="IDS_BLOCK_INTERSTITIAL_MESSAGE" desc="A message for the supervised user when they attempt to visit a site that is not permitted by the manager.">
         Oops, looks like you need permission from <ph name="NAME">$1<ex>John Doe</ex></ph> to access this page.
       </message>
+      <message name="IDS_BLOCK_INTERSTITIAL_MESSAGE_ACCESS_REQUESTS_DISABLED" desc="A message for the supervised user when they attempt to visit a site that is not permitted by the manager (and they can't ask for permission).">
+        Oops, looks like you don't have permission to access this page.
+      </message>
       <message name="IDS_BACK_BUTTON" desc="A button for going back to the last safe url after being blocked.">
         Go back
       </message>
@@ -9762,6 +9787,12 @@
       <message name="IDS_AUTOFILL_DIALOG_PLACEHOLDER_CARD_NUMBER" desc="The placeholder/label text for credit card number in the requestAutocomplete dialog.">
         Card number
       </message>
+      <message name="IDS_AUTOFILL_DIALOG_PLACEHOLDER_EXPIRY_MONTH" desc="The placeholder/label text for credit card expiration month in the requestAutocomplete dialog.">
+        Month
+      </message>
+      <message name="IDS_AUTOFILL_DIALOG_PLACEHOLDER_EXPIRY_YEAR" desc="The placeholder/label text for credit card expiration year in the requestAutocomplete dialog.">
+        Year
+      </message>
       <message name="IDS_AUTOFILL_DIALOG_PLACEHOLDER_CVC" desc="The placeholder/label text for credit card verification code in the requestAutocomplete dialog.">
         CVC
       </message>
@@ -9795,12 +9826,18 @@
       <message name="IDS_AUTOFILL_DIALOG_TITLE" desc="Title for autofill dialog which asks user to input address + payment info.">
         Pay
       </message>
-      <message name="IDS_AUTOFILL_DIALOG_PAY_WITHOUT_WALLET" desc="This text is shown in a payment method chooser when a user is forced to pay without Google Wallet because the service is unavailable.">
-        Chrome Autofill
+      <message name="IDS_AUTOFILL_DIALOG_PAY_WITHOUT_WALLET" desc="This text is shown in a payment method chooser as a way for a user to pay with local Chrome Autofill data instead of using Wallet.">
+        Disable Google Wallet
+      </message>
+      <message name="IDS_AUTOFILL_DIALOG_PAYING_WITHOUT_WALLET" desc="This text is shown as the click target for a dormant payment method chooser when using Chrome Autofill data instead of Wallet.">
+        Google Wallet disabled
       </message>
       <message name="IDS_AUTOFILL_DIALOG_SIGN_IN" desc="This link text is shown when the user is not signed into a GAIA account.">
         Sign in to pay with Google Wallet
       </message>
+      <message name="IDS_AUTOFILL_DIALOG_CANCEL_SIGN_IN" desc="This link text is shown when the user is signing into a GAIA account as a way to cancel sign in.">
+        Back
+      </message>
       <message name="IDS_AUTOFILL_DIALOG_GOOGLE_WALLET" desc="The menu item that allows a user to select Google Wallet as their payment backend.">
         Google Wallet
       </message>
@@ -9861,6 +9898,15 @@
       <message name="IDS_AUTOFILL_WALLET_BUYER_ACCOUNT_ERROR" desc="Text explaining that the user's Wallet account cannot be used.">
         There's something wrong with your Google Wallet account [12].
       </message>
+      <message name="IDS_AUTOFILL_WALLET_BUYER_COUNTRY_NOT_SUPPORTED" desc="Text explaining that the user's Wallet Buyer Legal Address has a country which is unsupported.">
+        lorem ipsum - unsupported buyer bla.
+      </message>
+      <message name="IDS_AUTOFILL_WALLET_UNVERIFIED_KNOW_YOUR_CUSTOMER_STATUS" desc="Text explaining that Google Wallet failed/pending Know Your Customer (KYC) check, and would require user to call Google Wallet.">
+        lorem ipsum - kyc.
+      </message>
+      <message name="IDS_AUTOFILL_WALLET_UNSUPPORTED_MERCHANT" desc="Text explaining that the merchant is blacklisted for Google Wallet Chrome Payments due to compliance violation.">
+        lorem ipsum - unsupported_merchant.
+      </message>
       <message name="IDS_AUTOFILL_WALLET_UPGRADE_CHROME_ERROR" desc="Text explaining that user must upgrade Chrome to use Wallet.">
         You must upgrade Chrome to use Google Wallet [<ph name="ERROR_CODE">$1<ex>54</ex></ph>].
       </message>
@@ -10048,14 +10094,14 @@
         No, Thanks
       </message>
 
-      <!-- Autofill dialog post-submit bubble -->
-      <message name="IDS_AUTOFILL_CREDIT_CARD_BUBBLE_GENERATED_TITLE" desc="Title of a bubble shown directly after a new card has been generated via Online Wallet using the Autofill dialog.">
+      <!-- Autofill dialog post-submit bubbles -->
+      <message name="IDS_AUTOFILL_GENERATED_CREDIT_CARD_BUBBLE_TITLE" desc="Title of a bubble shown directly after a new card has been generated via Online Wallet using the Autofill dialog.">
         Google Wallet is protecting your card
       </message>
-      <message name="IDS_AUTOFILL_CREDIT_CARD_BUBBLE_GENERATED_TEXT" desc="Text in the bubble explaining that a temporary card has been generated for the user's security by Google Wallet.">
+      <message name="IDS_AUTOFILL_GENERATED_CREDIT_CARD_BUBBLE_CONTENTS" desc="Text in the bubble explaining that a temporary card has been generated for the user's security by Google Wallet.">
         Don't worry, this purchase will still be charged to your |$1|. Your card has been protected with the Google Wallet Virtual Online Card (|$2|), this number will appear on your receipt.
       </message>
-      <message name="IDS_AUTOFILL_CREDIT_CARD_BUBBLE_MANAGE_CARDS" desc="The text of a link at the bottom of the autofill dialog bubble that sends users to a Google Wallet billing/card management page.">
+      <message name="IDS_AUTOFILL_NEW_CREDIT_CARD_BUBBLE_LINK" desc="The text of a link at the bottom of the autofill dialog bubble that sends users to a Google Wallet billing/card management page.">
         Manage Saved Cards
       </message>
 
@@ -12001,6 +12047,9 @@
       <message name="IDS_FILE_BROWSER_REMOVE_FOLDER_SHORTCUT_BUTTON_LABEL" desc="Menu item label, unpinning the selected folder from the left nav.">
         Remove shortcut
       </message>
+      <message name="IDS_FILE_BROWSER_SHORTCUT_TARGET_UNAVAILABLE" desc="The message which is shown when the user selects a shortcut to a missing folder and ask whether to remove said shortcut.">
+        The folder referred by this shortcut has been changed or deleted. Do you want to remove it?
+      </message>
       <message name="IDS_FILE_BROWSER_SHARE_BUTTON_LABEL" desc="Menu item label, showing dialog to share the selected file.">
         Share
       </message>
@@ -13060,7 +13109,7 @@
       <message name="IDS_TRANSLATE_INFOBAR_BEFORE_MESSAGE" desc="Message that page is in specified language and ask if should translate">
         This page is in<ph name="original_language">$1<ex>French</ex></ph>Would you like to translate it?
       </message>
-      <if expr="is_android">
+      <if expr="is_android or pp_ifdef('ios')">
         <message name="IDS_TRANSLATE_INFOBAR_BEFORE_MESSAGE_MOBILE" desc="Mobile: Message that page is in specified language and ask if should translate.">
           Translate from <ph name="original_language">$1<ex>French</ex></ph> to <ph name="target_language">$2<ex>English</ex></ph>?
         </message>
@@ -13086,7 +13135,7 @@
       <message name="IDS_TRANSLATE_INFOBAR_AFTER_MESSAGE_AUTODETERMINED_SOURCE_LANGUAGE" desc="Message that page has been translated to another with server side auto language detection">
         This page has been translated to <ph name="target_language">$1<ex>German</ex></ph>
       </message>
-      <if expr="is_android">
+      <if expr="is_android or pp_ifdef('ios')">
       <message name="IDS_TRANSLATE_INFOBAR_AFTER_MESSAGE_MOBILE" desc="Mobile: Message that page has been translated from one language to another">
         This page has been translated to <ph name="target_language">$1<ex>German</ex></ph>
       </message>
@@ -13112,7 +13161,7 @@
       <message name="IDS_TRANSLATE_INFOBAR_UNSUPPORTED_PAGE_LANGUAGE" desc="Error message shown when the translate server translated the page and returned the page was in a language the browser does not know.">
         This page has been translated from an unknown language to <ph name="language_language">$1<ex>English</ex></ph>
       </message>
-      <if expr="is_android">
+      <if expr="is_android or pp_ifdef('ios')">
       <message name="IDS_TRANSLATE_INFOBAR_ERROR_MOBILE" desc="Mobile: Translate Error message">
         The translation to <ph name="target_language">$1<ex>German</ex></ph> failed.
       </message>
@@ -13585,7 +13634,7 @@
       The following sites have been blocked from tracking your location on this page:
     </message>
     <message name="IDS_GEOLOCATION_BUBBLE_REQUIRE_RELOAD_TO_CLEAR" desc="Hint text for the geolocation bubble informing user they must reload the page for the Clear settings command to take effect.">
-      Settings will be cleared on next reload
+      Settings will be cleared on next reload.
     </message>
     <message name="IDS_GEOLOCATION_BUBBLE_CLEAR_LINK" desc="Link on the geolocation bubble that resets the list of allowed and blocked sites.">
       Clear these settings for future visits
@@ -13613,8 +13662,6 @@
     <message name="IDS_MIDI_SYSEX_ASK_RADIO" desc="A radio button in Content Settings dialog to allow a site to query the permision to access MIDI devices with system exclusive messages.">
       Ask me when a site wants to use system exclusive messages to access MIDI devices (recommended)
     </message>
-
-    <!-- Web MIDI messages -->
     <message name="IDS_MIDI_SYSEX_INFOBAR_QUESTION" desc="Question asked on the info bar whenever URL wants to access MIDI devices with system exclusive messages.">
       <ph name="URL">
         $1<ex>www.google.com</ex>
@@ -13626,11 +13673,34 @@
     <message name="IDS_MIDI_SYSEX_DENY_BUTTON" desc="A button in MIDI access infobar for denying full access to MIDI devices for a given domain.">
       Deny
     </message>
+    <message name="IDS_MIDI_SYSEX_ALLOWED_TOOLTIP" desc="Location bar icon tooltip text when a page is allowed to use MIDI system exclusive messages.">
+      This page has full control of MIDI devices.
+    </message>
+    <message name="IDS_MIDI_SYSEX_BLOCKED_TOOLTIP" desc="Location bar icon tooltip text when a page is blocked from using MIDI system exclusive messages.">
+      This page has been blocked from having full control of MIDI devices.
+    </message>
+    <message name="IDS_MIDI_SYSEX_BUBBLE_ALLOWED" desc="Title of the MIDI bubble where system exclusive messages are allowed.">
+      This site has full control of MIDI devices.
+    </message>
+    <message name="IDS_MIDI_SYSEX_BUBBLE_DENIED" desc="Title of the MIDI bubble where system exclusive messages are blocked.">
+      This site has been blocked from having full control of MIDI devices.
+    </message>
+    <message name="IDS_MIDI_SYSEX_BUBBLE_REQUIRE_RELOAD_TO_CLEAR" desc="Hint text for the MIDI bubble informing user they must reload the page for the Clear settings command to take effect.">
+      Settings will be cleared on next reload.
+    </message>
+    <message name="IDS_MIDI_SYSEX_BUBBLE_CLEAR_LINK" desc="Link on the MIDI bubble that resets the list of allowed and blocked sites.">
+      Clear these settings for future visits
+    </message>
+    <message name="IDS_MIDI_SYSEX_BUBBLE_MANAGE_LINK" desc="Link on the MIDI bubble that opens up the Content Settings management dialog.">
+      Manage MIDI settings...
+    </message>
 
+    <!-- Protocol Handler -->
     <message name="IDS_REGISTER_PROTOCOL_HANDLER_TOOLTIP" desc="Location bar icon tooltip text when a page wants to use registerProtocolHandler.">
       This page wants to install a service handler.
     </message>
 
+    <!-- Media Stream -->
     <message name="IDS_MEDIASTREAM_BUBBLE_MANAGE_LINK" desc="Link on the media (camera and microphone) bubble that opens up the Content Settings management dialog for media settings.">
       Manage media settings...
     </message>
@@ -14163,6 +14233,10 @@
     <message name="IDS_PROFILES_CREATE_MANAGED_SIGNED_IN_LABEL" desc="Label for the 'Supervised user' checkbox in the create-profile dialog when the current user is signed in. This will be followed by a 'Learn more' link.">
       This is a supervised user managed by <ph name="CUSTODIAN_EMAIL">$1<ex>user@gmail.com</ex>.</ph>
     </message>
+    <message name="IDS_PROFILES_CREATE_MANAGED_ACCOUNT_DETAILS_OUT_OF_DATE_LABEL" desc="Label for the 'Supervised user' checkbox in the create-profile dialog when the current user is signed in, but their login information is invalid. This will be followed by a 'Sign in again' link.">
+      This is a supervised user managed by <ph name="CUSTODIAN_EMAIL">$1<ex>user@gmail.com</ex>.</ph>
+Your account sign-in details are out of date.
+    </message>
     <message name="IDS_PROFILES_CREATE_MANAGED_NOT_SIGNED_IN_LABEL" desc="Label for the (disabled) 'Supervised user' checkbox in the create-profile dialog when the current user is not signed in. This will be followed by a 'Sign in now' link.">
       This is a supervised user who will be managed by you.
 You need to be signed in to use this feature.
@@ -14170,8 +14244,11 @@
     <message name="IDS_PROFILES_CREATE_MANAGED_NOT_SIGNED_IN_LINK" desc="Text for the sign-in promo link, shown after the (disabled) 'Supervised user' checkbox in the create-profile dialog when the current user is not signed in.">
       Sign in now
     </message>
+    <message name="IDS_PROFILES_CREATE_MANAGED_ACCOUNT_SIGN_IN_AGAIN_LINK" desc="Text for the sign-in promo link, shown after the message telling the user that their sign-in credentials are out of date in the create supervised user dialog.">
+      Sign in again
+    </message>
     <message name="IDS_PROFILES_CREATE_MANAGED_FROM_EXISTING_LABEL" desc="Label for the 'Select an exisiting managed user' checkbox. During managed user creation a custodian will have an option to select an existing managed profile rather creating a new one.">
-      Select an existing managed user: 
+      Select an existing managed user:
     </message>
     <message name="IDS_PROFILES_CREATE_SHORTCUT_CHECKBOX" desc="Create Shortcut checkbox when creating a new profile">
       Create a desktop shortcut for this user
@@ -14217,7 +14294,7 @@
     </message>
 
     <if expr="not is_android and not pp_ifdef('ios') and not pp_ifdef('chromeos')">
-      <!-- User chooser web UI -->
+      <!-- User manager web UI -->
       <if expr="pp_ifdef('use_titlecase')">
         <message name="IDS_ADD_USER_BUTTON" desc="Text shown on an add user button on login/locker screen">
           Add User
@@ -14246,6 +14323,9 @@
           Remove this user
         </message>
       </if>
+      <message name="IDS_USER_MANAGER_SCREEN_TITLE" desc="String to be displayed in the title bar of the user manager page">
+        User Manager
+      </message>
       <message name="IDS_GO_INCOGNITO_BUTTON" desc="Text shown on Chrome OS login screen button that launches guest session. Should be short.">
         Browse as Guest
       </message>
diff --git a/chrome/app/google_chrome_strings.grd b/chrome/app/google_chrome_strings.grd
index 663bc97..10e8dc7 100644
--- a/chrome/app/google_chrome_strings.grd
+++ b/chrome/app/google_chrome_strings.grd
@@ -833,7 +833,9 @@
       <message name="IDS_AUTOFILL_DIALOG_SAVE_LOCALLY_TOOLTIP" desc="Tooltip which explains function of checkbox that controls whether info the user types into the autofill dialog is saved by chrome.">
         Chrome will securely store your information so you don't need to type it in again, but you will still need to verify your card's security code for future payments.
       </message>
-
+      <message name="IDS_AUTOFILL_NEW_CREDIT_CARD_BUBBLE_TITLE" desc="Title text of the new credit card bubble informing a user their billing information has been saved in chrome.">
+        Your billing details have been saved in Chrome.
+      </message>
 
       <!-- Network Error Pages -->
       <message name="IDS_ERRORPAGES_SUGGESTION_NETWORK_PREDICTION_BODY" desc="When a page fails to load, sometimes we suggest disabling predicting network actions.  These are details below a header.">
diff --git a/chrome/app/nibs/ContentBlockedMIDISysEx.xib b/chrome/app/nibs/ContentBlockedMIDISysEx.xib
new file mode 100644
index 0000000..915253a
--- /dev/null
+++ b/chrome/app/nibs/ContentBlockedMIDISysEx.xib
@@ -0,0 +1,848 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<archive type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="7.10">
+	<data>
+		<int key="IBDocument.SystemTarget">1050</int>
+		<string key="IBDocument.SystemVersion">12E55</string>
+		<string key="IBDocument.InterfaceBuilderVersion">3084</string>
+		<string key="IBDocument.AppKitVersion">1187.39</string>
+		<string key="IBDocument.HIToolboxVersion">626.00</string>
+		<object class="NSMutableDictionary" key="IBDocument.PluginVersions">
+			<string key="NS.key.0">com.apple.InterfaceBuilder.CocoaPlugin</string>
+			<string key="NS.object.0">3084</string>
+		</object>
+		<object class="NSArray" key="IBDocument.IntegratedClassDependencies">
+			<bool key="EncodedWithXMLCoder">YES</bool>
+			<string>NSBox</string>
+			<string>NSButton</string>
+			<string>NSButtonCell</string>
+			<string>NSCustomObject</string>
+			<string>NSCustomView</string>
+			<string>NSView</string>
+			<string>NSWindowTemplate</string>
+		</object>
+		<object class="NSArray" key="IBDocument.PluginDependencies">
+			<bool key="EncodedWithXMLCoder">YES</bool>
+			<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+		</object>
+		<object class="NSMutableDictionary" key="IBDocument.Metadata">
+			<string key="NS.key.0">PluginDependencyRecalculationVersion</string>
+			<integer value="1" key="NS.object.0"/>
+		</object>
+		<object class="NSMutableArray" key="IBDocument.RootObjects" id="1000">
+			<bool key="EncodedWithXMLCoder">YES</bool>
+			<object class="NSCustomObject" id="1001">
+				<string key="NSClassName">ContentSettingBubbleController</string>
+			</object>
+			<object class="NSCustomObject" id="1003">
+				<string key="NSClassName">FirstResponder</string>
+			</object>
+			<object class="NSCustomObject" id="1004">
+				<string key="NSClassName">NSApplication</string>
+			</object>
+			<object class="NSWindowTemplate" id="1005">
+				<int key="NSWindowStyleMask">15</int>
+				<int key="NSWindowBacking">2</int>
+				<string key="NSWindowRect">{{196, 422}, {316, 88}}</string>
+				<int key="NSWTFlags">536873984</int>
+				<string key="NSWindowTitle">Window</string>
+				<string key="NSWindowClass">InfoBubbleWindow</string>
+				<nil key="NSViewClass"/>
+				<nil key="NSUserInterfaceItemIdentifier"/>
+				<object class="NSView" key="NSWindowView" id="1006">
+					<reference key="NSNextResponder"/>
+					<int key="NSvFlags">256</int>
+					<object class="NSMutableArray" key="NSSubviews">
+						<bool key="EncodedWithXMLCoder">YES</bool>
+						<object class="NSCustomView" id="301729179">
+							<reference key="NSNextResponder" ref="1006"/>
+							<int key="NSvFlags">274</int>
+							<object class="NSMutableArray" key="NSSubviews">
+								<bool key="EncodedWithXMLCoder">YES</bool>
+								<object class="NSBox" id="913795455">
+									<reference key="NSNextResponder" ref="301729179"/>
+									<int key="NSvFlags">34</int>
+									<string key="NSFrame">{{20, 43}, {276, 5}}</string>
+									<reference key="NSSuperview" ref="301729179"/>
+									<reference key="NSWindow"/>
+									<reference key="NSNextKeyView" ref="730386640"/>
+									<string key="NSOffsets">{0, 0}</string>
+									<object class="NSTextFieldCell" key="NSTitleCell">
+										<int key="NSCellFlags">67108864</int>
+										<int key="NSCellFlags2">0</int>
+										<string key="NSContents">Box</string>
+										<object class="NSFont" key="NSSupport">
+											<string key="NSName">LucidaGrande</string>
+											<double key="NSSize">13</double>
+											<int key="NSfFlags">1044</int>
+										</object>
+										<object class="NSColor" key="NSBackgroundColor">
+											<int key="NSColorSpace">6</int>
+											<string key="NSCatalogName">System</string>
+											<string key="NSColorName">textBackgroundColor</string>
+											<object class="NSColor" key="NSColor">
+												<int key="NSColorSpace">3</int>
+												<bytes key="NSWhite">MQA</bytes>
+											</object>
+										</object>
+										<object class="NSColor" key="NSTextColor">
+											<int key="NSColorSpace">3</int>
+											<bytes key="NSWhite">MCAwLjgwMDAwMDAxAA</bytes>
+										</object>
+									</object>
+									<int key="NSBorderType">3</int>
+									<int key="NSBoxType">2</int>
+									<int key="NSTitlePosition">0</int>
+									<bool key="NSTransparent">NO</bool>
+								</object>
+								<object class="NSCustomView" id="730386640">
+									<reference key="NSNextResponder" ref="301729179"/>
+									<int key="NSvFlags">294</int>
+									<object class="NSMutableArray" key="NSSubviews">
+										<bool key="EncodedWithXMLCoder">YES</bool>
+										<object class="NSButton" id="91589614">
+											<reference key="NSNextResponder" ref="730386640"/>
+											<int key="NSvFlags">292</int>
+											<string key="NSFrame">{{15, 13}, {115, 28}}</string>
+											<reference key="NSSuperview" ref="730386640"/>
+											<reference key="NSWindow"/>
+											<reference key="NSNextKeyView" ref="395762087"/>
+											<bool key="NSEnabled">YES</bool>
+											<object class="NSButtonCell" key="NSCell" id="319182835">
+												<int key="NSCellFlags">67108864</int>
+												<int key="NSCellFlags2">134348800</int>
+												<string key="NSContents">^IDS_MIDI_SYSEX_BUBBLE_MANAGE_LINK</string>
+												<object class="NSFont" key="NSSupport" id="26">
+													<string key="NSName">LucidaGrande</string>
+													<double key="NSSize">11</double>
+													<int key="NSfFlags">3100</int>
+												</object>
+												<reference key="NSControlView" ref="91589614"/>
+												<int key="NSButtonFlags">-2038284288</int>
+												<int key="NSButtonFlags2">129</int>
+												<string key="NSAlternateContents"/>
+												<string key="NSKeyEquivalent"/>
+												<int key="NSPeriodicDelay">200</int>
+												<int key="NSPeriodicInterval">25</int>
+											</object>
+											<bool key="NSAllowsLogicalLayoutDirection">NO</bool>
+										</object>
+									</object>
+									<string key="NSFrameSize">{192, 37}</string>
+									<reference key="NSSuperview" ref="301729179"/>
+									<reference key="NSWindow"/>
+									<reference key="NSNextKeyView" ref="91589614"/>
+									<string key="NSClassName">GTMWidthBasedTweaker</string>
+								</object>
+								<object class="NSCustomView" id="395762087">
+									<reference key="NSNextResponder" ref="301729179"/>
+									<int key="NSvFlags">291</int>
+									<object class="NSMutableArray" key="NSSubviews">
+										<bool key="EncodedWithXMLCoder">YES</bool>
+										<object class="NSButton" id="433059244">
+											<reference key="NSNextResponder" ref="395762087"/>
+											<int key="NSvFlags">289</int>
+											<string key="NSFrame">{{40, 13}, {68, 28}}</string>
+											<reference key="NSSuperview" ref="395762087"/>
+											<reference key="NSWindow"/>
+											<reference key="NSNextKeyView"/>
+											<bool key="NSEnabled">YES</bool>
+											<object class="NSButtonCell" key="NSCell" id="255173005">
+												<int key="NSCellFlags">67108864</int>
+												<int key="NSCellFlags2">134348800</int>
+												<string key="NSContents">^IDS_DONE</string>
+												<reference key="NSSupport" ref="26"/>
+												<reference key="NSControlView" ref="433059244"/>
+												<int key="NSButtonFlags">-2038284288</int>
+												<int key="NSButtonFlags2">129</int>
+												<string key="NSAlternateContents"/>
+												<string type="base64-UTF8" key="NSKeyEquivalent">DQ</string>
+												<int key="NSPeriodicDelay">200</int>
+												<int key="NSPeriodicInterval">25</int>
+											</object>
+											<bool key="NSAllowsLogicalLayoutDirection">NO</bool>
+										</object>
+									</object>
+									<string key="NSFrame">{{193, 0}, {123, 37}}</string>
+									<reference key="NSSuperview" ref="301729179"/>
+									<reference key="NSWindow"/>
+									<reference key="NSNextKeyView" ref="433059244"/>
+									<string key="NSClassName">GTMWidthBasedTweaker</string>
+								</object>
+								<object class="NSCustomView" id="1034822360">
+									<reference key="NSNextResponder" ref="301729179"/>
+									<int key="NSvFlags">290</int>
+									<string key="NSFrame">{{20, 54}, {276, 14}}</string>
+									<reference key="NSSuperview" ref="301729179"/>
+									<reference key="NSWindow"/>
+									<reference key="NSNextKeyView" ref="913795455"/>
+									<string key="NSClassName">NSView</string>
+								</object>
+							</object>
+							<string key="NSFrameSize">{316, 88}</string>
+							<reference key="NSSuperview" ref="1006"/>
+							<reference key="NSWindow"/>
+							<reference key="NSNextKeyView" ref="1034822360"/>
+							<string key="NSClassName">InfoBubbleView</string>
+						</object>
+					</object>
+					<string key="NSFrameSize">{316, 88}</string>
+					<reference key="NSSuperview"/>
+					<reference key="NSWindow"/>
+					<reference key="NSNextKeyView" ref="301729179"/>
+				</object>
+				<string key="NSScreenRect">{{0, 0}, {1680, 1028}}</string>
+				<string key="NSMaxSize">{10000000000000, 10000000000000}</string>
+				<bool key="NSWindowIsRestorable">YES</bool>
+			</object>
+			<object class="NSCustomObject" id="670916757">
+				<string key="NSClassName">ChromeUILocalizer</string>
+			</object>
+			<object class="NSCustomObject" id="684547419">
+				<string key="NSClassName">GTMUILocalizerAndLayoutTweaker</string>
+			</object>
+		</object>
+		<object class="IBObjectContainer" key="IBDocument.Objects">
+			<object class="NSMutableArray" key="connectionRecords">
+				<bool key="EncodedWithXMLCoder">YES</bool>
+				<object class="IBConnectionRecord">
+					<object class="IBOutletConnection" key="connection">
+						<string key="label">window</string>
+						<reference key="source" ref="1001"/>
+						<reference key="destination" ref="1005"/>
+					</object>
+					<int key="connectionID">3</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBOutletConnection" key="connection">
+						<string key="label">bubble_</string>
+						<reference key="source" ref="1001"/>
+						<reference key="destination" ref="301729179"/>
+					</object>
+					<int key="connectionID">5</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBActionConnection" key="connection">
+						<string key="label">manageBlocking:</string>
+						<reference key="source" ref="1001"/>
+						<reference key="destination" ref="91589614"/>
+					</object>
+					<int key="connectionID">25</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBActionConnection" key="connection">
+						<string key="label">closeBubble:</string>
+						<reference key="source" ref="1001"/>
+						<reference key="destination" ref="433059244"/>
+					</object>
+					<int key="connectionID">26</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBOutletConnection" key="connection">
+						<string key="label">contentsContainer_</string>
+						<reference key="source" ref="1001"/>
+						<reference key="destination" ref="1034822360"/>
+					</object>
+					<int key="connectionID">43</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBOutletConnection" key="connection">
+						<string key="label">manageButton_</string>
+						<reference key="source" ref="1001"/>
+						<reference key="destination" ref="91589614"/>
+					</object>
+					<int key="connectionID">45</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBOutletConnection" key="connection">
+						<string key="label">doneButton_</string>
+						<reference key="source" ref="1001"/>
+						<reference key="destination" ref="433059244"/>
+					</object>
+					<int key="connectionID">46</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBOutletConnection" key="connection">
+						<string key="label">delegate</string>
+						<reference key="source" ref="1005"/>
+						<reference key="destination" ref="1001"/>
+					</object>
+					<int key="connectionID">6</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBOutletConnection" key="connection">
+						<string key="label">localizer_</string>
+						<reference key="source" ref="684547419"/>
+						<reference key="destination" ref="670916757"/>
+					</object>
+					<int key="connectionID">22</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBOutletConnection" key="connection">
+						<string key="label">uiObject_</string>
+						<reference key="source" ref="684547419"/>
+						<reference key="destination" ref="1005"/>
+					</object>
+					<int key="connectionID">23</int>
+				</object>
+			</object>
+			<object class="IBMutableOrderedSet" key="objectRecords">
+				<object class="NSArray" key="orderedObjects">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+					<object class="IBObjectRecord">
+						<int key="objectID">0</int>
+						<object class="NSArray" key="object" id="0">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+						</object>
+						<reference key="children" ref="1000"/>
+						<nil key="parent"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">-2</int>
+						<reference key="object" ref="1001"/>
+						<reference key="parent" ref="0"/>
+						<string key="objectName">File's Owner</string>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">-1</int>
+						<reference key="object" ref="1003"/>
+						<reference key="parent" ref="0"/>
+						<string key="objectName">First Responder</string>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">-3</int>
+						<reference key="object" ref="1004"/>
+						<reference key="parent" ref="0"/>
+						<string key="objectName">Application</string>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">1</int>
+						<reference key="object" ref="1005"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="1006"/>
+						</object>
+						<reference key="parent" ref="0"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">2</int>
+						<reference key="object" ref="1006"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="301729179"/>
+						</object>
+						<reference key="parent" ref="1005"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">4</int>
+						<reference key="object" ref="301729179"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="913795455"/>
+							<reference ref="395762087"/>
+							<reference ref="730386640"/>
+							<reference ref="1034822360"/>
+						</object>
+						<reference key="parent" ref="1006"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">20</int>
+						<reference key="object" ref="670916757"/>
+						<reference key="parent" ref="0"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">21</int>
+						<reference key="object" ref="684547419"/>
+						<reference key="parent" ref="0"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">19</int>
+						<reference key="object" ref="913795455"/>
+						<reference key="parent" ref="301729179"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">29</int>
+						<reference key="object" ref="395762087"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="433059244"/>
+						</object>
+						<reference key="parent" ref="301729179"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">17</int>
+						<reference key="object" ref="433059244"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="255173005"/>
+						</object>
+						<reference key="parent" ref="395762087"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">18</int>
+						<reference key="object" ref="255173005"/>
+						<reference key="parent" ref="433059244"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">28</int>
+						<reference key="object" ref="730386640"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="91589614"/>
+						</object>
+						<reference key="parent" ref="301729179"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">15</int>
+						<reference key="object" ref="91589614"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="319182835"/>
+						</object>
+						<reference key="parent" ref="730386640"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">16</int>
+						<reference key="object" ref="319182835"/>
+						<reference key="parent" ref="91589614"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">42</int>
+						<reference key="object" ref="1034822360"/>
+						<reference key="parent" ref="301729179"/>
+					</object>
+				</object>
+			</object>
+			<object class="NSMutableDictionary" key="flattenedProperties">
+				<bool key="EncodedWithXMLCoder">YES</bool>
+				<object class="NSArray" key="dict.sortedKeys">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+					<string>-1.IBPluginDependency</string>
+					<string>-2.IBPluginDependency</string>
+					<string>-3.IBPluginDependency</string>
+					<string>1.IBPluginDependency</string>
+					<string>1.IBWindowTemplateEditedContentRect</string>
+					<string>1.NSWindowTemplate.visibleAtLaunch</string>
+					<string>15.IBPluginDependency</string>
+					<string>16.IBPluginDependency</string>
+					<string>17.IBPluginDependency</string>
+					<string>18.IBPluginDependency</string>
+					<string>19.IBPluginDependency</string>
+					<string>2.IBPluginDependency</string>
+					<string>20.IBPluginDependency</string>
+					<string>21.IBPluginDependency</string>
+					<string>28.IBPluginDependency</string>
+					<string>29.IBPluginDependency</string>
+					<string>4.IBPluginDependency</string>
+					<string>42.IBPluginDependency</string>
+				</object>
+				<object class="NSArray" key="dict.values">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>{{333, 411}, {316, 88}}</string>
+					<boolean value="NO"/>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+				</object>
+			</object>
+			<object class="NSMutableDictionary" key="unlocalizedProperties">
+				<bool key="EncodedWithXMLCoder">YES</bool>
+				<reference key="dict.sortedKeys" ref="0"/>
+				<reference key="dict.values" ref="0"/>
+			</object>
+			<nil key="activeLocalization"/>
+			<object class="NSMutableDictionary" key="localizations">
+				<bool key="EncodedWithXMLCoder">YES</bool>
+				<reference key="dict.sortedKeys" ref="0"/>
+				<reference key="dict.values" ref="0"/>
+			</object>
+			<nil key="sourceID"/>
+			<int key="maxID">46</int>
+		</object>
+		<object class="IBClassDescriber" key="IBDocument.Classes">
+			<object class="NSMutableArray" key="referencedPartialClassDescriptions">
+				<bool key="EncodedWithXMLCoder">YES</bool>
+				<object class="IBPartialClassDescription">
+					<string key="className">BaseBubbleController</string>
+					<string key="superclassName">NSWindowController</string>
+					<object class="NSMutableDictionary" key="outlets">
+						<string key="NS.key.0">bubble_</string>
+						<string key="NS.object.0">InfoBubbleView</string>
+					</object>
+					<object class="NSMutableDictionary" key="toOneOutletInfosByName">
+						<string key="NS.key.0">bubble_</string>
+						<object class="IBToOneOutletInfo" key="NS.object.0">
+							<string key="name">bubble_</string>
+							<string key="candidateClassName">InfoBubbleView</string>
+						</object>
+					</object>
+					<object class="IBClassDescriptionSource" key="sourceIdentifier">
+						<string key="majorKey">IBProjectSource</string>
+						<string key="minorKey">./Classes/BaseBubbleController.h</string>
+					</object>
+				</object>
+				<object class="IBPartialClassDescription">
+					<string key="className">ChromeEventProcessingWindow</string>
+					<string key="superclassName">UnderlayOpenGLHostingWindow</string>
+					<object class="IBClassDescriptionSource" key="sourceIdentifier">
+						<string key="majorKey">IBProjectSource</string>
+						<string key="minorKey">./Classes/ChromeEventProcessingWindow.h</string>
+					</object>
+				</object>
+				<object class="IBPartialClassDescription">
+					<string key="className">ChromeUILocalizer</string>
+					<string key="superclassName">GTMUILocalizer</string>
+					<object class="IBClassDescriptionSource" key="sourceIdentifier">
+						<string key="majorKey">IBProjectSource</string>
+						<string key="minorKey">./Classes/ChromeUILocalizer.h</string>
+					</object>
+				</object>
+				<object class="IBPartialClassDescription">
+					<string key="className">ContentSettingBubbleController</string>
+					<string key="superclassName">BaseBubbleController</string>
+					<object class="NSMutableDictionary" key="actions">
+						<bool key="EncodedWithXMLCoder">YES</bool>
+						<object class="NSArray" key="dict.sortedKeys">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<string>allowBlockToggled:</string>
+							<string>closeBubble:</string>
+							<string>learnMoreLinkClicked:</string>
+							<string>load:</string>
+							<string>loadAllPlugins:</string>
+							<string>manageBlocking:</string>
+							<string>showMoreInfo:</string>
+						</object>
+						<object class="NSArray" key="dict.values">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<string>id</string>
+							<string>id</string>
+							<string>id</string>
+							<string>id</string>
+							<string>id</string>
+							<string>id</string>
+							<string>id</string>
+						</object>
+					</object>
+					<object class="NSMutableDictionary" key="actionInfosByName">
+						<bool key="EncodedWithXMLCoder">YES</bool>
+						<object class="NSArray" key="dict.sortedKeys">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<string>allowBlockToggled:</string>
+							<string>closeBubble:</string>
+							<string>learnMoreLinkClicked:</string>
+							<string>load:</string>
+							<string>loadAllPlugins:</string>
+							<string>manageBlocking:</string>
+							<string>showMoreInfo:</string>
+						</object>
+						<object class="NSArray" key="dict.values">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<object class="IBActionInfo">
+								<string key="name">allowBlockToggled:</string>
+								<string key="candidateClassName">id</string>
+							</object>
+							<object class="IBActionInfo">
+								<string key="name">closeBubble:</string>
+								<string key="candidateClassName">id</string>
+							</object>
+							<object class="IBActionInfo">
+								<string key="name">learnMoreLinkClicked:</string>
+								<string key="candidateClassName">id</string>
+							</object>
+							<object class="IBActionInfo">
+								<string key="name">load:</string>
+								<string key="candidateClassName">id</string>
+							</object>
+							<object class="IBActionInfo">
+								<string key="name">loadAllPlugins:</string>
+								<string key="candidateClassName">id</string>
+							</object>
+							<object class="IBActionInfo">
+								<string key="name">manageBlocking:</string>
+								<string key="candidateClassName">id</string>
+							</object>
+							<object class="IBActionInfo">
+								<string key="name">showMoreInfo:</string>
+								<string key="candidateClassName">id</string>
+							</object>
+						</object>
+					</object>
+					<object class="NSMutableDictionary" key="outlets">
+						<bool key="EncodedWithXMLCoder">YES</bool>
+						<object class="NSArray" key="dict.sortedKeys">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<string>allowBlockRadioGroup_</string>
+							<string>blockedResourcesField_</string>
+							<string>contentsContainer_</string>
+							<string>doneButton_</string>
+							<string>infoButton_</string>
+							<string>loadAllPluginsButton_</string>
+							<string>loadButton_</string>
+							<string>manageButton_</string>
+							<string>titleLabel_</string>
+						</object>
+						<object class="NSArray" key="dict.values">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<string>NSMatrix</string>
+							<string>NSTextField</string>
+							<string>NSView</string>
+							<string>NSButton</string>
+							<string>NSButton</string>
+							<string>NSButton</string>
+							<string>NSButton</string>
+							<string>NSButton</string>
+							<string>NSTextField</string>
+						</object>
+					</object>
+					<object class="NSMutableDictionary" key="toOneOutletInfosByName">
+						<bool key="EncodedWithXMLCoder">YES</bool>
+						<object class="NSArray" key="dict.sortedKeys">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<string>allowBlockRadioGroup_</string>
+							<string>blockedResourcesField_</string>
+							<string>contentsContainer_</string>
+							<string>doneButton_</string>
+							<string>infoButton_</string>
+							<string>loadAllPluginsButton_</string>
+							<string>loadButton_</string>
+							<string>manageButton_</string>
+							<string>titleLabel_</string>
+						</object>
+						<object class="NSArray" key="dict.values">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<object class="IBToOneOutletInfo">
+								<string key="name">allowBlockRadioGroup_</string>
+								<string key="candidateClassName">NSMatrix</string>
+							</object>
+							<object class="IBToOneOutletInfo">
+								<string key="name">blockedResourcesField_</string>
+								<string key="candidateClassName">NSTextField</string>
+							</object>
+							<object class="IBToOneOutletInfo">
+								<string key="name">contentsContainer_</string>
+								<string key="candidateClassName">NSView</string>
+							</object>
+							<object class="IBToOneOutletInfo">
+								<string key="name">doneButton_</string>
+								<string key="candidateClassName">NSButton</string>
+							</object>
+							<object class="IBToOneOutletInfo">
+								<string key="name">infoButton_</string>
+								<string key="candidateClassName">NSButton</string>
+							</object>
+							<object class="IBToOneOutletInfo">
+								<string key="name">loadAllPluginsButton_</string>
+								<string key="candidateClassName">NSButton</string>
+							</object>
+							<object class="IBToOneOutletInfo">
+								<string key="name">loadButton_</string>
+								<string key="candidateClassName">NSButton</string>
+							</object>
+							<object class="IBToOneOutletInfo">
+								<string key="name">manageButton_</string>
+								<string key="candidateClassName">NSButton</string>
+							</object>
+							<object class="IBToOneOutletInfo">
+								<string key="name">titleLabel_</string>
+								<string key="candidateClassName">NSTextField</string>
+							</object>
+						</object>
+					</object>
+					<object class="IBClassDescriptionSource" key="sourceIdentifier">
+						<string key="majorKey">IBProjectSource</string>
+						<string key="minorKey">./Classes/ContentSettingBubbleController.h</string>
+					</object>
+				</object>
+				<object class="IBPartialClassDescription">
+					<string key="className">GTMUILocalizer</string>
+					<string key="superclassName">NSObject</string>
+					<object class="NSMutableDictionary" key="outlets">
+						<bool key="EncodedWithXMLCoder">YES</bool>
+						<object class="NSArray" key="dict.sortedKeys">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<string>otherObjectToLocalize_</string>
+							<string>owner_</string>
+							<string>yetAnotherObjectToLocalize_</string>
+						</object>
+						<object class="NSArray" key="dict.values">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<string>id</string>
+							<string>id</string>
+							<string>id</string>
+						</object>
+					</object>
+					<object class="NSMutableDictionary" key="toOneOutletInfosByName">
+						<bool key="EncodedWithXMLCoder">YES</bool>
+						<object class="NSArray" key="dict.sortedKeys">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<string>otherObjectToLocalize_</string>
+							<string>owner_</string>
+							<string>yetAnotherObjectToLocalize_</string>
+						</object>
+						<object class="NSArray" key="dict.values">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<object class="IBToOneOutletInfo">
+								<string key="name">otherObjectToLocalize_</string>
+								<string key="candidateClassName">id</string>
+							</object>
+							<object class="IBToOneOutletInfo">
+								<string key="name">owner_</string>
+								<string key="candidateClassName">id</string>
+							</object>
+							<object class="IBToOneOutletInfo">
+								<string key="name">yetAnotherObjectToLocalize_</string>
+								<string key="candidateClassName">id</string>
+							</object>
+						</object>
+					</object>
+					<object class="IBClassDescriptionSource" key="sourceIdentifier">
+						<string key="majorKey">IBProjectSource</string>
+						<string key="minorKey">./Classes/GTMUILocalizer.h</string>
+					</object>
+				</object>
+				<object class="IBPartialClassDescription">
+					<string key="className">GTMUILocalizerAndLayoutTweaker</string>
+					<string key="superclassName">NSObject</string>
+					<object class="NSMutableDictionary" key="outlets">
+						<bool key="EncodedWithXMLCoder">YES</bool>
+						<object class="NSArray" key="dict.sortedKeys">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<string>localizerOwner_</string>
+							<string>localizer_</string>
+							<string>uiObject_</string>
+						</object>
+						<object class="NSArray" key="dict.values">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<string>id</string>
+							<string>GTMUILocalizer</string>
+							<string>id</string>
+						</object>
+					</object>
+					<object class="NSMutableDictionary" key="toOneOutletInfosByName">
+						<bool key="EncodedWithXMLCoder">YES</bool>
+						<object class="NSArray" key="dict.sortedKeys">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<string>localizerOwner_</string>
+							<string>localizer_</string>
+							<string>uiObject_</string>
+						</object>
+						<object class="NSArray" key="dict.values">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<object class="IBToOneOutletInfo">
+								<string key="name">localizerOwner_</string>
+								<string key="candidateClassName">id</string>
+							</object>
+							<object class="IBToOneOutletInfo">
+								<string key="name">localizer_</string>
+								<string key="candidateClassName">GTMUILocalizer</string>
+							</object>
+							<object class="IBToOneOutletInfo">
+								<string key="name">uiObject_</string>
+								<string key="candidateClassName">id</string>
+							</object>
+						</object>
+					</object>
+					<object class="IBClassDescriptionSource" key="sourceIdentifier">
+						<string key="majorKey">IBProjectSource</string>
+						<string key="minorKey">./Classes/GTMUILocalizerAndLayoutTweaker.h</string>
+					</object>
+				</object>
+				<object class="IBPartialClassDescription">
+					<string key="className">GTMWidthBasedTweaker</string>
+					<string key="superclassName">NSView</string>
+					<object class="NSMutableDictionary" key="outlets">
+						<bool key="EncodedWithXMLCoder">YES</bool>
+						<object class="NSArray" key="dict.sortedKeys">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<string>viewToResize_</string>
+							<string>viewToSlideAndResize_</string>
+							<string>viewToSlide_</string>
+						</object>
+						<object class="NSArray" key="dict.values">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<string>id</string>
+							<string>NSView</string>
+							<string>NSView</string>
+						</object>
+					</object>
+					<object class="NSMutableDictionary" key="toOneOutletInfosByName">
+						<bool key="EncodedWithXMLCoder">YES</bool>
+						<object class="NSArray" key="dict.sortedKeys">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<string>viewToResize_</string>
+							<string>viewToSlideAndResize_</string>
+							<string>viewToSlide_</string>
+						</object>
+						<object class="NSArray" key="dict.values">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<object class="IBToOneOutletInfo">
+								<string key="name">viewToResize_</string>
+								<string key="candidateClassName">id</string>
+							</object>
+							<object class="IBToOneOutletInfo">
+								<string key="name">viewToSlideAndResize_</string>
+								<string key="candidateClassName">NSView</string>
+							</object>
+							<object class="IBToOneOutletInfo">
+								<string key="name">viewToSlide_</string>
+								<string key="candidateClassName">NSView</string>
+							</object>
+						</object>
+					</object>
+					<object class="IBClassDescriptionSource" key="sourceIdentifier">
+						<string key="majorKey">IBProjectSource</string>
+						<string key="minorKey">./Classes/GTMWidthBasedTweaker.h</string>
+					</object>
+				</object>
+				<object class="IBPartialClassDescription">
+					<string key="className">InfoBubbleView</string>
+					<string key="superclassName">NSView</string>
+					<object class="IBClassDescriptionSource" key="sourceIdentifier">
+						<string key="majorKey">IBProjectSource</string>
+						<string key="minorKey">./Classes/InfoBubbleView.h</string>
+					</object>
+				</object>
+				<object class="IBPartialClassDescription">
+					<string key="className">InfoBubbleWindow</string>
+					<string key="superclassName">ChromeEventProcessingWindow</string>
+					<object class="IBClassDescriptionSource" key="sourceIdentifier">
+						<string key="majorKey">IBProjectSource</string>
+						<string key="minorKey">./Classes/InfoBubbleWindow.h</string>
+					</object>
+				</object>
+				<object class="IBPartialClassDescription">
+					<string key="className">UnderlayOpenGLHostingWindow</string>
+					<string key="superclassName">NSWindow</string>
+					<object class="IBClassDescriptionSource" key="sourceIdentifier">
+						<string key="majorKey">IBProjectSource</string>
+						<string key="minorKey">./Classes/UnderlayOpenGLHostingWindow.h</string>
+					</object>
+				</object>
+			</object>
+		</object>
+		<int key="IBDocument.localizationMode">0</int>
+		<string key="IBDocument.TargetRuntimeIdentifier">IBCocoaFramework</string>
+		<object class="NSMutableDictionary" key="IBDocument.PluginDeclaredDependencies">
+			<string key="NS.key.0">com.apple.InterfaceBuilder.CocoaPlugin.macosx</string>
+			<integer value="1050" key="NS.object.0"/>
+		</object>
+		<object class="NSMutableDictionary" key="IBDocument.PluginDeclaredDevelopmentDependencies">
+			<string key="NS.key.0">com.apple.InterfaceBuilder.CocoaPlugin.InterfaceBuilder3</string>
+			<integer value="3000" key="NS.object.0"/>
+		</object>
+		<bool key="IBDocument.PluginDeclaredDependenciesTrackSystemTargetVersion">YES</bool>
+		<int key="IBDocument.defaultPropertyAccessControl">3</int>
+	</data>
+</archive>
diff --git a/chrome/browser/DEPS b/chrome/browser/DEPS
index a59a81a..09f2cd0 100644
--- a/chrome/browser/DEPS
+++ b/chrome/browser/DEPS
@@ -52,7 +52,6 @@
   # TODO(stuartmorgan): Remove these by refactoring necessary code out of
   # webkit/. See crbug.com/146251
   # DO NOT ADD ANY MORE ITEMS TO THE LIST BELOW!
-  "+webkit/plugins",  # Defines some types that are marshalled over IPC.
 
   # TODO(kinuko): Remove all other webkit/* dependencies after we cleaned
   # up webkit/. crbug.com/239710
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc
index cffd974..71e06a1 100644
--- a/chrome/browser/about_flags.cc
+++ b/chrome/browser/about_flags.cc
@@ -1178,12 +1178,6 @@
     kOsCrOS,
     SINGLE_VALUE_TYPE(chromeos::switches::kUseNewNetworkConfigurationHandlers),
   },
-  { "use-new-network-connection-handler",
-    IDS_FLAGS_CHROMEOS_USE_NEW_NETWORK_CONNECTION_HANDLER_NAME,
-    IDS_FLAGS_CHROMEOS_USE_NEW_NETWORK_CONNECTION_HANDLER_DESCRIPTION,
-    kOsCrOS,
-    SINGLE_VALUE_TYPE(chromeos::switches::kUseNewNetworkConnectionHandler),
-  },
   {
     "ash-audio-device-menu",
     IDS_FLAGS_ASH_AUDIO_DEVICE_MENU_NAME,
@@ -1545,6 +1539,13 @@
     SINGLE_VALUE_TYPE(switches::kEnableWebGLDraftExtensions)
   },
   {
+    "enable-html-imports",
+    IDS_FLAGS_ENABLE_HTML_IMPORTS_NAME,
+    IDS_FLAGS_ENABLE_HTML_IMPORTS_DESCRIPTION,
+    kOsAll,
+    SINGLE_VALUE_TYPE(switches::kEnableHTMLImports)
+  },
+  {
     "high-dpi-support",
     IDS_FLAGS_HIDPI_NAME,
     IDS_FLAGS_HIDPI_DESCRIPTION,
diff --git a/chrome/browser/android/chrome_jni_registrar.cc b/chrome/browser/android/chrome_jni_registrar.cc
index 5b6c457..1675c62 100644
--- a/chrome/browser/android/chrome_jni_registrar.cc
+++ b/chrome/browser/android/chrome_jni_registrar.cc
@@ -27,6 +27,8 @@
 #include "chrome/browser/signin/android_profile_oauth2_token_service.h"
 #include "chrome/browser/speech/tts_android.h"
 #include "chrome/browser/sync/profile_sync_service_android.h"
+#include "chrome/browser/ui/android/autofill/autofill_dialog_controller_android.h"
+#include "chrome/browser/ui/android/autofill/autofill_dialog_result.h"
 #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/javascript_app_modal_dialog_android.h"
@@ -54,6 +56,11 @@
   { "AndroidProfileOAuth2TokenService",
     AndroidProfileOAuth2TokenService::Register },
   { "ApplicationLifetime", RegisterApplicationLifetimeAndroid },
+  { "AutofillDialogControllerAndroid",
+    autofill::AutofillDialogControllerAndroid::
+        RegisterAutofillDialogControllerAndroid },
+  { "AutofillDialogResult",
+    autofill::AutofillDialogResult::RegisterAutofillDialogResult },
   { "AutofillPopup",
     autofill::AutofillPopupViewAndroid::RegisterAutofillPopupViewAndroid },
   { "CertificateViewer", RegisterCertificateViewer },
diff --git a/chrome/browser/android/chrome_web_contents_delegate_android.cc b/chrome/browser/android/chrome_web_contents_delegate_android.cc
index 5b3c747..0eb1157 100644
--- a/chrome/browser/android/chrome_web_contents_delegate_android.cc
+++ b/chrome/browser/android/chrome_web_contents_delegate_android.cc
@@ -9,7 +9,6 @@
 #include "chrome/browser/file_select_helper.h"
 #include "chrome/browser/media/media_capture_devices_dispatcher.h"
 #include "chrome/browser/ui/app_modal_dialogs/javascript_dialog_manager.h"
-#include "chrome/browser/ui/find_bar/find_match_rects_details.h"
 #include "chrome/browser/ui/find_bar/find_notification_details.h"
 #include "chrome/browser/ui/find_bar/find_tab_helper.h"
 #include "content/public/browser/notification_details.h"
@@ -163,12 +162,6 @@
     int version,
     const std::vector<gfx::RectF>& rects,
     const gfx::RectF& active_rect) {
-  FindMatchRectsDetails match_rects(version, rects, active_rect);
-  content::NotificationService::current()->Notify(
-      chrome::NOTIFICATION_FIND_MATCH_RECTS_AVAILABLE,
-      content::Source<WebContents>(web_contents),
-      content::Details<FindMatchRectsDetails>(&match_rects));
-
   JNIEnv* env = base::android::AttachCurrentThread();
   ScopedJavaLocalRef<jobject> obj = GetJavaDelegate(env);
   if (obj.is_null())
@@ -178,17 +171,17 @@
   ScopedJavaLocalRef<jobject> details_object =
       Java_ChromeWebContentsDelegateAndroid_createFindMatchRectsDetails(
           env,
-          match_rects.version(),
-          match_rects.rects().size(),
-          CreateJavaRectF(env, match_rects.active_rect()).obj());
+          version,
+          rects.size(),
+          CreateJavaRectF(env, active_rect).obj());
 
   // Add the rects
-  for (size_t i = 0; i < match_rects.rects().size(); ++i) {
+  for (size_t i = 0; i < rects.size(); ++i) {
       Java_ChromeWebContentsDelegateAndroid_setMatchRectByIndex(
           env,
           details_object.obj(),
           i,
-          CreateJavaRectF(env, match_rects.rects()[i]).obj());
+          CreateJavaRectF(env, rects[i]).obj());
   }
 
   Java_ChromeWebContentsDelegateAndroid_onFindMatchRectsAvailable(
diff --git a/chrome/browser/android/tab_android.h b/chrome/browser/android/tab_android.h
index 3c6f0c1..19d8f25 100644
--- a/chrome/browser/android/tab_android.h
+++ b/chrome/browser/android/tab_android.h
@@ -75,6 +75,9 @@
   // of service and the privacy notice.
   virtual bool ShouldWelcomePageLinkToTermsOfService() = 0;
 
+  // Called to notify that the new tab page has completely rendered.
+  virtual void OnNewTabPageReady() = 0;
+
   // Called when the common ExternalProtocolHandler wants to
   // run the external protocol dialog.
   // TODO(jknotten): Remove this method. Making it non-abstract, so that
diff --git a/chrome/browser/app_controller_mac.h b/chrome/browser/app_controller_mac.h
index 4ea1356..46d8a05 100644
--- a/chrome/browser/app_controller_mac.h
+++ b/chrome/browser/app_controller_mac.h
@@ -81,9 +81,6 @@
 
   scoped_ptr<PrefChangeRegistrar> profilePrefRegistrar_;
   PrefChangeRegistrar localPrefRegistrar_;
-
-  // The main menu item showing the name of a currently focused packaged app.
-  base::scoped_nsobject<NSMenuItem> appMenuItem_;
 }
 
 @property(readonly, nonatomic) BOOL startupComplete;
diff --git a/chrome/browser/app_controller_mac.mm b/chrome/browser/app_controller_mac.mm
index 859a539..b2d30cd 100644
--- a/chrome/browser/app_controller_mac.mm
+++ b/chrome/browser/app_controller_mac.mm
@@ -5,7 +5,7 @@
 #import "chrome/browser/app_controller_mac.h"
 
 #include "apps/app_shim/extension_app_shim_handler_mac.h"
-#include "apps/shell_window.h"
+#include "apps/shell_window_registry.h"
 #include "base/auto_reset.h"
 #include "base/bind.h"
 #include "base/command_line.h"
@@ -28,7 +28,6 @@
 #include "chrome/browser/download/download_service_factory.h"
 #include "chrome/browser/extensions/extension_service.h"
 #include "chrome/browser/extensions/extension_system.h"
-#include "chrome/browser/extensions/shell_window_registry.h"
 #include "chrome/browser/first_run/first_run.h"
 #include "chrome/browser/lifetime/application_lifetime.h"
 #include "chrome/browser/printing/print_dialog_cloud.h"
@@ -73,7 +72,6 @@
 #include "chrome/common/chrome_paths_internal.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/common/cloud_print/cloud_print_class_mac.h"
-#include "chrome/common/extensions/extension.h"
 #include "chrome/common/extensions/extension_constants.h"
 #include "chrome/common/mac/app_mode_common.h"
 #include "chrome/common/pref_names.h"
@@ -199,7 +197,6 @@
 - (BOOL)shouldQuitWithInProgressDownloads;
 - (void)executeApplication:(id)sender;
 - (void)profileWasRemoved:(const base::FilePath&)profilePath;
-- (void)showOrHideMenuItemsForPackagedApp:(NSNotification*)notification;
 @end
 
 class AppControllerProfileObserver : public ProfileInfoCacheObserver {
@@ -315,12 +312,6 @@
   // Set up the command updater for when there are no windows open
   [self initMenuState];
 
-  [[NSNotificationCenter defaultCenter]
-      addObserver:self
-         selector:@selector(showOrHideMenuItemsForPackagedApp:)
-             name:NSWindowDidBecomeMainNotification
-           object:nil];
-
   // Initialize the Profile menu.
   [self initProfileMenu];
 }
@@ -388,7 +379,7 @@
 }
 
 - (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication*)app {
-  using extensions::ShellWindowRegistry;
+  using apps::ShellWindowRegistry;
 
   // If there are no windows, quit immediately.
   if (chrome::BrowserIterator().done() &&
@@ -1345,15 +1336,18 @@
   [item setEnabled:[self validateUserInterfaceItem:item]];
   [dockMenu addItem:item];
 
-  titleStr = l10n_util::GetNSStringWithFixup(IDS_NEW_INCOGNITO_WINDOW_MAC);
-  item.reset(
-      [[NSMenuItem alloc] initWithTitle:titleStr
-                                 action:@selector(commandFromDock:)
-                          keyEquivalent:@""]);
-  [item setTarget:self];
-  [item setTag:IDC_NEW_INCOGNITO_WINDOW];
-  [item setEnabled:[self validateUserInterfaceItem:item]];
-  [dockMenu addItem:item];
+  // |profile| can be NULL during unit tests.
+  if (!profile || !profile->IsManaged()) {
+    titleStr = l10n_util::GetNSStringWithFixup(IDS_NEW_INCOGNITO_WINDOW_MAC);
+    item.reset(
+        [[NSMenuItem alloc] initWithTitle:titleStr
+                                   action:@selector(commandFromDock:)
+                            keyEquivalent:@""]);
+    [item setTarget:self];
+    [item setTag:IDC_NEW_INCOGNITO_WINDOW];
+    [item setEnabled:[self validateUserInterfaceItem:item]];
+    [dockMenu addItem:item];
+  }
 
   // TODO(rickcam): Mock out BackgroundApplicationListModel, then add unit
   // tests which use the mock in place of the profile-initialized model.
@@ -1420,52 +1414,6 @@
       WorkAreaChanged());
 }
 
-// If the window is an app window, show the menu bar for that app, otherwise
-// restore the Chrome menu bar.
-- (void)showOrHideMenuItemsForPackagedApp:(NSNotification*)notification {
-  NSMenu* mainMenu = [NSApp mainMenu];
-  apps::ShellWindow* shellWindow =
-      extensions::ShellWindowRegistry::GetShellWindowForNativeWindowAnyProfile(
-          [notification object]);
-
-  if (!shellWindow) {
-    if (!appMenuItem_)
-      return;
-
-    [mainMenu removeItem:appMenuItem_];
-    appMenuItem_.reset();
-
-    // Restore the Chrome main menu bar.
-    for (NSMenuItem* item in [mainMenu itemArray])
-      [item setHidden:NO];
-
-    return;
-  }
-
-  const extensions::Extension* app = shellWindow->extension();
-  NSString* appId = base::SysUTF8ToNSString(app->id());
-  NSString* title = base::SysUTF8ToNSString(app->name());
-
-  if (appMenuItem_) {
-    if ([[appMenuItem_ title] isEqualToString:appId])
-      return;
-
-    [mainMenu removeItem:appMenuItem_];
-  } else {
-    // Hide everything and add a menu item for the app.
-    for (NSMenuItem* item in [mainMenu itemArray])
-      [item setHidden:YES];
-  }
-
-  appMenuItem_.reset(
-      [[NSMenuItem alloc] initWithTitle:appId
-                                 action:nil
-                          keyEquivalent:@""]);
-  base::scoped_nsobject<NSMenu> appMenu([[NSMenu alloc] initWithTitle:title]);
-  [appMenuItem_ setSubmenu:appMenu];
-  [mainMenu addItem:appMenuItem_];
-}
-
 @end  // @implementation AppController
 
 //---------------------------------------------------------------------------
diff --git a/chrome/browser/app_controller_mac_browsertest.mm b/chrome/browser/app_controller_mac_browsertest.mm
index 02059a5..4e66e35 100644
--- a/chrome/browser/app_controller_mac_browsertest.mm
+++ b/chrome/browser/app_controller_mac_browsertest.mm
@@ -4,20 +4,20 @@
 
 #import <Cocoa/Cocoa.h>
 
+#include "apps/shell_window_registry.h"
 #include "base/command_line.h"
 #include "base/mac/scoped_nsobject.h"
-#include "base/strings/sys_string_conversions.h"
 #include "chrome/app/chrome_command_ids.h"
 #import "chrome/browser/app_controller_mac.h"
 #include "chrome/browser/extensions/extension_test_message_listener.h"
 #include "chrome/browser/extensions/platform_app_browsertest_util.h"
-#include "chrome/browser/extensions/shell_window_registry.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_list.h"
 #include "chrome/browser/ui/browser_window.h"
 #include "chrome/browser/ui/host_desktop.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
 #import "chrome/common/chrome_switches.h"
+#include "chrome/common/extensions/extension.h"
 #include "chrome/test/base/in_process_browser_test.h"
 #include "chrome/test/base/ui_test_utils.h"
 #include "content/public/browser/web_contents.h"
@@ -55,72 +55,6 @@
   EXPECT_EQ(1u, active_browser_list_->size());
 }
 
-// Test that focusing an app window changes the menu bar.
-IN_PROC_BROWSER_TEST_F(AppControllerPlatformAppBrowserTest,
-                       PlatformAppFocusUpdatesMenuBar) {
-  base::scoped_nsobject<AppController> app_controller(
-      [[AppController alloc] init]);
-
-  // Start two apps and wait for them to be launched.
-  ExtensionTestMessageListener listener_1("Launched", false);
-  const extensions::Extension* app_1 =
-      InstallAndLaunchPlatformApp("minimal_id");
-  ASSERT_TRUE(listener_1.WaitUntilSatisfied());
-  ExtensionTestMessageListener listener_2("Launched", false);
-  const extensions::Extension* app_2 =
-      InstallAndLaunchPlatformApp("minimal");
-  ASSERT_TRUE(listener_2.WaitUntilSatisfied());
-
-  NSMenu* main_menu = [NSApp mainMenu];
-  NSUInteger initial_menu_item_count = [[main_menu itemArray] count];
-
-  // When an app is focused, all Chrome menu items should be hidden, and a menu
-  // item for the app should be added.
-  apps::ShellWindow* app_1_shell_window =
-      extensions::ShellWindowRegistry::Get(profile())->
-          GetShellWindowsForApp(app_1->id()).front();
-  [[NSNotificationCenter defaultCenter]
-      postNotificationName:NSWindowDidBecomeMainNotification
-                    object:app_1_shell_window->GetNativeWindow()];
-  NSArray* item_array = [main_menu itemArray];
-  EXPECT_EQ(initial_menu_item_count + 1, [item_array count]);
-  for (NSUInteger i = 0; i < initial_menu_item_count; ++i)
-    EXPECT_TRUE([[item_array objectAtIndex:i] isHidden]);
-  NSMenuItem* last_item = [item_array lastObject];
-  EXPECT_EQ(app_1->id(), base::SysNSStringToUTF8([last_item title]));
-  EXPECT_EQ(app_1->name(),
-            base::SysNSStringToUTF8([[last_item submenu] title]));
-  EXPECT_FALSE([last_item isHidden]);
-
-  // When another app is focused, the menu item for the app should change.
-  apps::ShellWindow* app_2_shell_window =
-      extensions::ShellWindowRegistry::Get(profile())->
-          GetShellWindowsForApp(app_2->id()).front();
-  [[NSNotificationCenter defaultCenter]
-      postNotificationName:NSWindowDidBecomeMainNotification
-                    object:app_2_shell_window->GetNativeWindow()];
-  item_array = [main_menu itemArray];
-  EXPECT_EQ(initial_menu_item_count + 1, [item_array count]);
-  for (NSUInteger i = 0; i < initial_menu_item_count; ++i)
-    EXPECT_TRUE([[item_array objectAtIndex:i] isHidden]);
-  last_item = [item_array lastObject];
-  EXPECT_EQ(app_2->id(), base::SysNSStringToUTF8([last_item title]));
-  EXPECT_EQ(app_2->name(),
-            base::SysNSStringToUTF8([[last_item submenu] title]));
-  EXPECT_FALSE([last_item isHidden]);
-
-  // When Chrome is focused, the menu item for the app should be removed.
-  NSWindow* browser_native_window =
-      active_browser_list_->get(0)->window()->GetNativeWindow();
-  [[NSNotificationCenter defaultCenter]
-      postNotificationName:NSWindowDidBecomeMainNotification
-                    object:browser_native_window];
-  item_array = [main_menu itemArray];
-  EXPECT_EQ(initial_menu_item_count, [item_array count]);
-  for (NSUInteger i = 0; i < initial_menu_item_count; ++i)
-    EXPECT_FALSE([[item_array objectAtIndex:i] isHidden]);
-}
-
 IN_PROC_BROWSER_TEST_F(AppControllerPlatformAppBrowserTest,
                        ActivationFocusesBrowserWindow) {
   base::scoped_nsobject<AppController> app_controller(
@@ -131,7 +65,7 @@
       InstallAndLaunchPlatformApp("minimal");
   ASSERT_TRUE(listener.WaitUntilSatisfied());
 
-  NSWindow* app_window = extensions::ShellWindowRegistry::Get(profile())->
+  NSWindow* app_window = apps::ShellWindowRegistry::Get(profile())->
       GetShellWindowsForApp(app->id()).front()->GetNativeWindow();
   NSWindow* browser_window = browser()->window()->GetNativeWindow();
 
diff --git a/chrome/browser/apps/shortcut_manager.cc b/chrome/browser/apps/shortcut_manager.cc
index 914d1fd..539cf65 100644
--- a/chrome/browser/apps/shortcut_manager.cc
+++ b/chrome/browser/apps/shortcut_manager.cc
@@ -63,9 +63,9 @@
       weak_factory_(this) {
   // Use of g_browser_process requires that we are either on the UI thread, or
   // there are no threads initialized (such as in unit tests).
-  DCHECK(
-      !content::BrowserThread::IsWellKnownThread(content::BrowserThread::UI) ||
-      content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+  DCHECK(!content::BrowserThread::IsThreadInitialized(
+             content::BrowserThread::UI) ||
+         content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
 
   registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_INSTALLED,
                  content::Source<Profile>(profile_));
diff --git a/chrome/browser/autocomplete/autocomplete_controller.cc b/chrome/browser/autocomplete/autocomplete_controller.cc
index ee39845..492533a 100644
--- a/chrome/browser/autocomplete/autocomplete_controller.cc
+++ b/chrome/browser/autocomplete/autocomplete_controller.cc
@@ -543,10 +543,11 @@
       !match.search_terms_args->assisted_query_stats.empty()) {
     TemplateURLRef::SearchTermsArgs search_terms_args(*match.search_terms_args);
     search_terms_args.assisted_query_stats += base::StringPrintf(
-        ".%" PRId64 "j%d",
+        ".%" PRId64 "j%dj%d",
         query_formulation_time.InMilliseconds(),
         search_provider_ &&
-        search_provider_->field_trial_triggered_in_session());
+        search_provider_->field_trial_triggered_in_session(),
+        input_.current_page_classification());
     destination_url = GURL(template_url->url_ref().
                            ReplaceSearchTerms(search_terms_args));
   }
diff --git a/chrome/browser/autocomplete/autocomplete_input.h b/chrome/browser/autocomplete/autocomplete_input.h
index 0ebc17d..3aba2d1 100644
--- a/chrome/browser/autocomplete/autocomplete_input.h
+++ b/chrome/browser/autocomplete/autocomplete_input.h
@@ -8,6 +8,7 @@
 #include <string>
 
 #include "base/basictypes.h"
+#include "base/gtest_prod_util.h"
 #include "base/strings/string16.h"
 #include "url/gurl.h"
 #include "url/url_parse.h"
@@ -68,6 +69,10 @@
     // The new tab page in which this omnibox interaction first started
     // with the user having focus in the fakebox.
     INSTANT_NEW_TAB_PAGE_WITH_FAKEBOX_AS_STARTING_FOCUS = 8,
+    // The user is on a search result page that's not doing search term
+    // replacement, meaning the URL of the page should've appeared in the
+    // omnibox before the user started editing it, not the search terms.
+    SEARCH_RESULT_PAGE_NO_SEARCH_TERM_REPLACEMENT = 9
   };
 
   AutocompleteInput();
@@ -217,6 +222,8 @@
   void Clear();
 
  private:
+  FRIEND_TEST_ALL_PREFIXES(AutocompleteProviderTest, GetDestinationURL);
+
   // NOTE: Whenever adding a new field here, please make sure to update Clear()
   // method.
   string16 text_;
diff --git a/chrome/browser/autocomplete/autocomplete_provider_unittest.cc b/chrome/browser/autocomplete/autocomplete_provider_unittest.cc
index 8b56cbb..7f59752 100644
--- a/chrome/browser/autocomplete/autocomplete_provider_unittest.cc
+++ b/chrome/browser/autocomplete/autocomplete_provider_unittest.cc
@@ -628,7 +628,7 @@
       "chrome.0.69i57j69i58j5l2j0l3j69i59";
   url = controller_->GetDestinationURL(match,
                                        base::TimeDelta::FromMilliseconds(2456));
-  EXPECT_EQ("//aqs=chrome.0.69i57j69i58j5l2j0l3j69i59.2456j0&", url.path());
+  EXPECT_EQ("//aqs=chrome.0.69i57j69i58j5l2j0l3j69i59.2456j0j0&", url.path());
 
   // Test field trial triggered bit set.
   controller_->search_provider_->field_trial_triggered_in_session_ = true;
@@ -636,5 +636,22 @@
       controller_->search_provider_->field_trial_triggered_in_session());
   url = controller_->GetDestinationURL(match,
                                        base::TimeDelta::FromMilliseconds(2456));
-  EXPECT_EQ("//aqs=chrome.0.69i57j69i58j5l2j0l3j69i59.2456j1&", url.path());
+  EXPECT_EQ("//aqs=chrome.0.69i57j69i58j5l2j0l3j69i59.2456j1j0&", url.path());
+
+  // Test page classification set.
+  controller_->input_.current_page_classification_ = AutocompleteInput::OTHER;
+  controller_->search_provider_->field_trial_triggered_in_session_ = false;
+  EXPECT_FALSE(
+      controller_->search_provider_->field_trial_triggered_in_session());
+  url = controller_->GetDestinationURL(match,
+                                       base::TimeDelta::FromMilliseconds(2456));
+  EXPECT_EQ("//aqs=chrome.0.69i57j69i58j5l2j0l3j69i59.2456j0j4&", url.path());
+
+  // Test page classification and field trial triggered set.
+  controller_->search_provider_->field_trial_triggered_in_session_ = true;
+  EXPECT_TRUE(
+      controller_->search_provider_->field_trial_triggered_in_session());
+  url = controller_->GetDestinationURL(match,
+                                       base::TimeDelta::FromMilliseconds(2456));
+  EXPECT_EQ("//aqs=chrome.0.69i57j69i58j5l2j0l3j69i59.2456j1j4&", url.path());
 }
diff --git a/chrome/browser/autocomplete/autocomplete_result.cc b/chrome/browser/autocomplete/autocomplete_result.cc
index 7238c1e..832be73 100644
--- a/chrome/browser/autocomplete/autocomplete_result.cc
+++ b/chrome/browser/autocomplete/autocomplete_result.cc
@@ -11,9 +11,60 @@
 #include "chrome/browser/autocomplete/autocomplete_input.h"
 #include "chrome/browser/autocomplete/autocomplete_match.h"
 #include "chrome/browser/autocomplete/autocomplete_provider.h"
+#include "chrome/browser/omnibox/omnibox_field_trial.h"
 #include "chrome/browser/search/search.h"
 #include "chrome/common/autocomplete_match_type.h"
 
+namespace {
+
+// This class implements a special version of AutocompleteMatch::MoreRelevant
+// that allows matches of particular types to be demoted in AutocompleteResult.
+class CompareWithDemoteByType {
+ public:
+  CompareWithDemoteByType(
+      AutocompleteInput::PageClassification current_page_classification);
+
+  // Returns the relevance score of |match| demoted appropriately by
+  // |demotions_by_type_|.
+  int GetDemotedRelevance(const AutocompleteMatch& match);
+
+  // Comparison function.
+  bool operator()(const AutocompleteMatch& elem1,
+                  const AutocompleteMatch& elem2);
+
+ private:
+  OmniboxFieldTrial::DemotionMultipliers demotions_;
+};
+
+CompareWithDemoteByType::CompareWithDemoteByType(
+    AutocompleteInput::PageClassification current_page_classification) {
+  OmniboxFieldTrial::GetDemotionsByType(current_page_classification,
+                                        &demotions_);
+}
+
+int CompareWithDemoteByType::GetDemotedRelevance(
+    const AutocompleteMatch& match) {
+  OmniboxFieldTrial::DemotionMultipliers::const_iterator demotion_it =
+      demotions_.find(match.type);
+  return (demotion_it == demotions_.end()) ?
+      match.relevance : (match.relevance * demotion_it->second);
+}
+
+bool CompareWithDemoteByType::operator()(const AutocompleteMatch& elem1,
+                                         const AutocompleteMatch& elem2) {
+  // Compute demoted relevance scores for each match.
+  const int demoted_relevance1 = GetDemotedRelevance(elem1);
+  const int demoted_relevance2 = GetDemotedRelevance(elem2);
+  // For equal-relevance matches, we sort alphabetically, so that providers
+  // who return multiple elements at the same priority get a "stable" sort
+  // across multiple updates.
+  return (demoted_relevance1 == demoted_relevance2) ?
+      (elem1.contents < elem2.contents) :
+      (demoted_relevance1 > demoted_relevance2);
+}
+
+};  // namespace
+
 // static
 const size_t AutocompleteResult::kMaxMatches = 6;
 const int AutocompleteResult::kLowestDefaultScore = 1200;
@@ -70,7 +121,8 @@
   old_matches.BuildProviderToMatches(&old_matches_per_provider);
   for (ProviderToMatches::const_iterator i(old_matches_per_provider.begin());
        i != old_matches_per_provider.end(); ++i) {
-    MergeMatchesByProvider(i->second, matches_per_provider[i->first]);
+    MergeMatchesByProvider(input.current_page_classification(),
+                           i->second, matches_per_provider[i->first]);
   }
 
   SortAndCull(input, profile);
@@ -102,9 +154,16 @@
                  matches_.end());
 
   // Sort and trim to the most relevant kMaxMatches matches.
-  const size_t num_matches = std::min(kMaxMatches, matches_.size());
-  std::partial_sort(matches_.begin(), matches_.begin() + num_matches,
-                    matches_.end(), &AutocompleteMatch::MoreRelevant);
+  size_t max_num_matches = std::min(kMaxMatches, matches_.size());
+  CompareWithDemoteByType comparing_object(input.current_page_classification());
+  std::partial_sort(matches_.begin(), matches_.begin() + max_num_matches,
+                    matches_.end(), comparing_object);
+  // In the process of trimming, drop all matches with a demoted relevance
+  // score of 0.
+  size_t num_matches;
+  for (num_matches = 0u; (num_matches < max_num_matches) &&
+       (comparing_object.GetDemotedRelevance(*match_at(num_matches)) > 0);
+       ++num_matches) {}
   matches_.resize(num_matches);
 
   default_match_ = begin();
@@ -221,13 +280,16 @@
   alternate_nav_url_ = rhs.alternate_nav_url_;
 }
 
-void AutocompleteResult::AddMatch(const AutocompleteMatch& match) {
+void AutocompleteResult::AddMatch(
+    AutocompleteInput::PageClassification page_classification,
+    const AutocompleteMatch& match) {
   DCHECK(default_match_ != end());
   DCHECK_EQ(AutocompleteMatch::SanitizeString(match.contents), match.contents);
   DCHECK_EQ(AutocompleteMatch::SanitizeString(match.description),
             match.description);
+  CompareWithDemoteByType comparing_object(page_classification);
   ACMatches::iterator insertion_point =
-      std::upper_bound(begin(), end(), match, &AutocompleteMatch::MoreRelevant);
+      std::upper_bound(begin(), end(), match, comparing_object);
   matches_difference_type default_offset = default_match_ - begin();
   if ((insertion_point - begin()) <= default_offset)
     ++default_offset;
@@ -251,8 +313,10 @@
   return false;
 }
 
-void AutocompleteResult::MergeMatchesByProvider(const ACMatches& old_matches,
-                                                const ACMatches& new_matches) {
+void AutocompleteResult::MergeMatchesByProvider(
+    AutocompleteInput::PageClassification page_classification,
+    const ACMatches& old_matches,
+    const ACMatches& new_matches) {
   if (new_matches.size() >= old_matches.size())
     return;
 
@@ -271,7 +335,7 @@
       AutocompleteMatch match = *i;
       match.relevance = std::min(max_relevance, match.relevance);
       match.from_previous = true;
-      AddMatch(match);
+      AddMatch(page_classification, match);
       delta--;
     }
   }
diff --git a/chrome/browser/autocomplete/autocomplete_result.h b/chrome/browser/autocomplete/autocomplete_result.h
index a622d1b..69bdbed 100644
--- a/chrome/browser/autocomplete/autocomplete_result.h
+++ b/chrome/browser/autocomplete/autocomplete_result.h
@@ -10,6 +10,7 @@
 #include <map>
 
 #include "base/basictypes.h"
+#include "chrome/browser/autocomplete/autocomplete_input.h"
 #include "chrome/browser/autocomplete/autocomplete_match.h"
 #include "url/gurl.h"
 
@@ -166,15 +167,18 @@
   // Adds a single match. The match is inserted at the appropriate position
   // based on relevancy and display order. This is ONLY for use after
   // SortAndCull() has been invoked, and preserves default_match_.
-  void AddMatch(const AutocompleteMatch& match);
+  void AddMatch(AutocompleteInput::PageClassification page_classification,
+                const AutocompleteMatch& match);
 
   // Populates |provider_to_matches| from |matches_|.
   void BuildProviderToMatches(ProviderToMatches* provider_to_matches) const;
 
   // Copies matches into this result. |old_matches| gives the matches from the
   // last result, and |new_matches| the results from this result.
-  void MergeMatchesByProvider(const ACMatches& old_matches,
-                              const ACMatches& new_matches);
+  void MergeMatchesByProvider(
+      AutocompleteInput::PageClassification page_classification,
+      const ACMatches& old_matches,
+      const ACMatches& new_matches);
 
   ACMatches matches_;
 
diff --git a/chrome/browser/autocomplete/autocomplete_result_unittest.cc b/chrome/browser/autocomplete/autocomplete_result_unittest.cc
index 3038c27..1e8900f 100644
--- a/chrome/browser/autocomplete/autocomplete_result_unittest.cc
+++ b/chrome/browser/autocomplete/autocomplete_result_unittest.cc
@@ -4,6 +4,7 @@
 
 #include "chrome/browser/autocomplete/autocomplete_result.h"
 
+#include "base/memory/scoped_ptr.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
@@ -13,6 +14,9 @@
 #include "chrome/browser/search_engines/template_url_prepopulate_data.h"
 #include "chrome/browser/search_engines/template_url_service.h"
 #include "chrome/browser/search_engines/template_url_service_test_util.h"
+#include "chrome/common/autocomplete_match_type.h"
+#include "chrome/common/metrics/entropy_provider.h"
+#include "chrome/common/metrics/variations/variations_util.h"
 #include "chrome/test/base/testing_profile.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
@@ -30,7 +34,14 @@
     int relevance;
   };
 
-  AutocompleteResultTest() {}
+  AutocompleteResultTest() {
+    // Destroy the existing FieldTrialList before creating a new one to avoid
+    // a DCHECK.
+    field_trial_list_.reset();
+    field_trial_list_.reset(new base::FieldTrialList(
+        new metrics::SHA1EntropyProvider("foo")));
+    chrome_variations::testing::ClearAllVariationParams();
+  }
 
   virtual void SetUp() OVERRIDE {
 #if defined(OS_ANDROID)
@@ -69,6 +80,8 @@
   TemplateURLServiceTestUtil test_util_;
 
  private:
+  scoped_ptr<base::FieldTrialList> field_trial_list_;
+
   DISALLOW_COPY_AND_ASSIGN(AutocompleteResultTest);
 };
 
@@ -148,6 +161,7 @@
   // Swap with a single match.
   ACMatches matches;
   AutocompleteMatch match;
+  match.relevance = 1;
   AutocompleteInput input(ASCIIToUTF16("a"), string16::npos, string16(), GURL(),
                           AutocompleteInput::INVALID_SPEC, false, false, false,
                           AutocompleteInput::ALL_MATCHES);
@@ -292,3 +306,69 @@
             result.match_at(2)->destination_url.spec());
   EXPECT_EQ(900, result.match_at(2)->relevance);
 }
+
+TEST_F(AutocompleteResultTest, SortAndCullWithDemotionsByType) {
+  // Add some matches.
+  ACMatches matches;
+  {
+    AutocompleteMatch match;
+    match.destination_url = GURL("http://history-url/");
+    match.relevance = 1400;
+    match.type = AutocompleteMatchType::HISTORY_URL;
+    matches.push_back(match);
+  }
+  {
+    AutocompleteMatch match;
+    match.destination_url = GURL("http://search-what-you-typed/");
+    match.relevance = 1300;
+    match.type = AutocompleteMatchType::SEARCH_WHAT_YOU_TYPED;
+    matches.push_back(match);
+  }
+  {
+    AutocompleteMatch match;
+    match.destination_url = GURL("http://history-title/");
+    match.relevance = 1200;
+    match.type = AutocompleteMatchType::HISTORY_TITLE;
+    matches.push_back(match);
+  }
+  {
+    AutocompleteMatch match;
+    match.destination_url = GURL("http://search-history/");
+    match.relevance = 500;
+    match.type = AutocompleteMatchType::SEARCH_HISTORY;
+    matches.push_back(match);
+  }
+
+  // Add a rule demoting history-url and killing history-title.
+  // Must be the same as kBundledExperimentFieldTrialName
+  // defined in omnibox_field_trial.cc.
+  const std::string kTrialName = "OmniboxBundledExperimentV1";
+  // Must be the same as kDemoteByTypeRule defined in
+  // omnibox_field_trial.cc.
+  const std::string kRuleName = "DemoteByType";
+  {
+    std::map<std::string, std::string> params;
+    params[kRuleName + ":3:*"] = "1:50,7:100,2:0";  // 3 == HOMEPAGE
+    ASSERT_TRUE(chrome_variations::AssociateVariationParams(
+        kTrialName, "A", params));
+  }
+  base::FieldTrialList::CreateFieldTrial(kTrialName, "A");
+
+  AutocompleteResult result;
+  result.AppendMatches(matches);
+  AutocompleteInput input(string16(), string16::npos, string16(), GURL(),
+                          AutocompleteInput::HOMEPAGE, false, false, false,
+                          AutocompleteInput::ALL_MATCHES);
+  result.SortAndCull(input, test_util_.profile());
+
+  // Check the new ordering.  The history-title results should be omitted.
+  // We cannot check relevance scores because the matches are sorted by
+  // demoted relevance but the actual relevance scores are not modified.
+  ASSERT_EQ(3u, result.size());
+  EXPECT_EQ("http://search-what-you-typed/",
+            result.match_at(0)->destination_url.spec());
+  EXPECT_EQ("http://history-url/",
+            result.match_at(1)->destination_url.spec());
+  EXPECT_EQ("http://search-history/",
+            result.match_at(2)->destination_url.spec());
+}
diff --git a/chrome/browser/autocomplete/search_provider.cc b/chrome/browser/autocomplete/search_provider.cc
index d4245fd..b5a6f48 100644
--- a/chrome/browser/autocomplete/search_provider.cc
+++ b/chrome/browser/autocomplete/search_provider.cc
@@ -32,10 +32,13 @@
 #include "chrome/browser/omnibox/omnibox_field_trial.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/search/search.h"
-#include "chrome/browser/search_engines/search_engine_type.h"
 #include "chrome/browser/search_engines/template_url_prepopulate_data.h"
 #include "chrome/browser/search_engines/template_url_service.h"
 #include "chrome/browser/search_engines/template_url_service_factory.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/browser_finder.h"
+#include "chrome/browser/ui/browser_instant_controller.h"
+#include "chrome/browser/ui/search/instant_controller.h"
 #include "chrome/common/net/url_fixer_upper.h"
 #include "chrome/common/pref_names.h"
 #include "chrome/common/url_constants.h"
@@ -250,8 +253,7 @@
       providers_(TemplateURLServiceFactory::GetForProfile(profile)),
       suggest_results_pending_(0),
       field_trial_triggered_(false),
-      field_trial_triggered_in_session_(false),
-      omnibox_start_margin_(-1) {
+      field_trial_triggered_in_session_(false) {
 }
 
 // static
@@ -369,10 +371,6 @@
   field_trial_triggered_in_session_ = false;
 }
 
-void SearchProvider::SetOmniboxStartMargin(int omnibox_start_margin) {
-  omnibox_start_margin_ = omnibox_start_margin;
-}
-
 SearchProvider::~SearchProvider() {
 }
 
@@ -834,6 +832,7 @@
   // Bail if the suggestion URL is invalid with the given replacements.
   TemplateURLRef::SearchTermsArgs search_term_args(input.text());
   search_term_args.cursor_position = input.cursor_position();
+  search_term_args.page_classification = input.current_page_classification();
   GURL suggest_url(template_url->suggestions_url_ref().ReplaceSearchTerms(
       search_term_args));
   if (!suggest_url.is_valid())
@@ -1382,11 +1381,26 @@
                                    int accepted_suggestion,
                                    bool is_keyword,
                                    MatchMap* map) {
+  // On non-mobile, ask the instant controller for the appropriate start margin.
+  // On mobile the start margin is unused, so leave the value as default there.
+  int omnibox_start_margin = chrome::kDisableStartMargin;
+#if !defined(OS_ANDROID) && !defined(IOS)
+  if (chrome::IsInstantExtendedAPIEnabled()) {
+    Browser* browser =
+        chrome::FindBrowserWithProfile(profile_, chrome::GetActiveDesktop());
+    if (browser && browser->instant_controller() &&
+        browser->instant_controller()->instant()) {
+      omnibox_start_margin =
+          browser->instant_controller()->instant()->omnibox_bounds().x();
+    }
+  }
+#endif  // !defined(OS_ANDROID) && !defined(IOS)
+
   const TemplateURL* template_url = is_keyword ?
       providers_.GetKeywordProviderURL() : providers_.GetDefaultProviderURL();
   AutocompleteMatch match = CreateSearchSuggestion(this, relevance, type,
       template_url, query_string, input_text, input_, is_keyword,
-      accepted_suggestion, omnibox_start_margin_,
+      accepted_suggestion, omnibox_start_margin,
       !is_keyword || providers_.default_provider().empty());
   if (!match.destination_url.is_valid())
     return;
diff --git a/chrome/browser/autocomplete/search_provider.h b/chrome/browser/autocomplete/search_provider.h
index 74c5e7e..5f25f35 100644
--- a/chrome/browser/autocomplete/search_provider.h
+++ b/chrome/browser/autocomplete/search_provider.h
@@ -94,9 +94,6 @@
   virtual void AddProviderInfo(ProvidersInfo* provider_info) const OVERRIDE;
   virtual void ResetSession() OVERRIDE;
 
-  // Update the omnibox start margin used to generate search suggestion URLs.
-  void SetOmniboxStartMargin(int omnibox_start_margin);
-
   bool field_trial_triggered_in_session() const {
     return field_trial_triggered_in_session_;
   }
@@ -527,9 +524,6 @@
   // session.
   bool field_trial_triggered_in_session_;
 
-  // Start margin of the omnibox. Used to construct search URLs.
-  int omnibox_start_margin_;
-
   // If true, search history query suggestions will score low enough that
   // they will not be inlined.
   bool prevent_search_history_inlining_;
diff --git a/chrome/browser/autocomplete/shortcuts_provider.cc b/chrome/browser/autocomplete/shortcuts_provider.cc
index cf121be..06f3455 100644
--- a/chrome/browser/autocomplete/shortcuts_provider.cc
+++ b/chrome/browser/autocomplete/shortcuts_provider.cc
@@ -54,8 +54,7 @@
     : AutocompleteProvider(listener, profile,
           AutocompleteProvider::TYPE_SHORTCUTS),
       languages_(profile_->GetPrefs()->GetString(prefs::kAcceptLanguages)),
-      initialized_(false),
-      max_relevance_(AutocompleteResult::kLowestDefaultScore - 1) {
+      initialized_(false) {
   scoped_refptr<history::ShortcutsBackend> backend =
       ShortcutsBackendFactory::GetForProfile(profile_);
   if (backend.get()) {
@@ -63,9 +62,6 @@
     if (backend->initialized())
       initialized_ = true;
   }
-  int max_relevance;
-  if (OmniboxFieldTrial::ShortcutsScoringMaxRelevance(&max_relevance))
-    max_relevance_ = max_relevance;
 }
 
 void ShortcutsProvider::Start(const AutocompleteInput& input,
@@ -157,12 +153,17 @@
   string16 term_string(base::i18n::ToLower(input.text()));
   DCHECK(!term_string.empty());
 
+  int max_relevance;
+  if (!OmniboxFieldTrial::ShortcutsScoringMaxRelevance(
+      input.current_page_classification(), &max_relevance))
+    max_relevance = AutocompleteResult::kLowestDefaultScore - 1;
+
   for (history::ShortcutsBackend::ShortcutMap::const_iterator it =
            FindFirstMatch(term_string, backend.get());
        it != backend->shortcuts_map().end() &&
            StartsWith(it->first, term_string, true); ++it) {
     // Don't return shortcuts with zero relevance.
-    int relevance = CalculateScore(term_string, it->second);
+    int relevance = CalculateScore(term_string, it->second, max_relevance);
     if (relevance)
       matches_.push_back(ShortcutToACMatch(relevance, term_string, it->second));
   }
@@ -177,7 +178,7 @@
   // Reset relevance scores to guarantee no results are given an
   // inlineable score and all scores are decreasing (but not do assign
   // any scores below 1).
-  int max_relevance = AutocompleteResult::kLowestDefaultScore - 1;
+  max_relevance = AutocompleteResult::kLowestDefaultScore - 1;
   for (ACMatches::iterator it = matches_.begin(); it != matches_.end(); ++it) {
     max_relevance = std::min(max_relevance, it->relevance);
     it->relevance = max_relevance;
@@ -338,7 +339,8 @@
 
 int ShortcutsProvider::CalculateScore(
     const string16& terms,
-    const history::ShortcutsBackend::Shortcut& shortcut) {
+    const history::ShortcutsBackend::Shortcut& shortcut,
+    int max_relevance) {
   DCHECK(!terms.empty());
   DCHECK_LE(terms.length(), shortcut.text.length());
 
@@ -348,7 +350,7 @@
   // directly. This makes sense since the first characters typed are much more
   // important for determining how likely it is a user wants a particular
   // shortcut than are the remaining continued characters.
-  double base_score = max_relevance_ *
+  double base_score = max_relevance *
       sqrt(static_cast<double>(terms.length()) / shortcut.text.length());
 
   // Then we decay this by half each week.
diff --git a/chrome/browser/autocomplete/shortcuts_provider.h b/chrome/browser/autocomplete/shortcuts_provider.h
index 11f0b0a..89dcc3c 100644
--- a/chrome/browser/autocomplete/shortcuts_provider.h
+++ b/chrome/browser/autocomplete/shortcuts_provider.h
@@ -96,17 +96,11 @@
 
   int CalculateScore(
       const string16& terms,
-      const history::ShortcutsBackend::Shortcut& shortcut);
+      const history::ShortcutsBackend::Shortcut& shortcut,
+      int max_relevance);
 
   std::string languages_;
   bool initialized_;
-
-  // The maximum relevance that can be assigned in CalculateScore().
-  // Note that if the final assigned relevance is at least
-  // AutocompleteResult::kLowestDefaultScore, the relevance will be
-  // demoted to less than that number because ShortcutsProvider isn't
-  // allowed to inline.
-  int max_relevance_;
 };
 
 #endif  // CHROME_BROWSER_AUTOCOMPLETE_SHORTCUTS_PROVIDER_H_
diff --git a/chrome/browser/autocomplete/shortcuts_provider_unittest.cc b/chrome/browser/autocomplete/shortcuts_provider_unittest.cc
index 73699db..a6fef30 100644
--- a/chrome/browser/autocomplete/shortcuts_provider_unittest.cc
+++ b/chrome/browser/autocomplete/shortcuts_provider_unittest.cc
@@ -21,6 +21,7 @@
 #include "chrome/browser/autocomplete/autocomplete_match.h"
 #include "chrome/browser/autocomplete/autocomplete_provider.h"
 #include "chrome/browser/autocomplete/autocomplete_provider_listener.h"
+#include "chrome/browser/autocomplete/autocomplete_result.h"
 #include "chrome/browser/history/history_service.h"
 #include "chrome/browser/history/in_memory_url_index.h"
 #include "chrome/browser/history/shortcuts_backend.h"
@@ -574,37 +575,38 @@
       spans_description, base::Time::Now(), 1);
 
   // Maximal score.
+  const int max_relevance = AutocompleteResult::kLowestDefaultScore - 1;
   const int kMaxScore = provider_->CalculateScore(
-      ASCIIToUTF16("test"), shortcut);
+      ASCIIToUTF16("test"), shortcut, max_relevance);
 
   // Score decreases as percent of the match is decreased.
   int score_three_quarters =
-      provider_->CalculateScore(ASCIIToUTF16("tes"), shortcut);
+      provider_->CalculateScore(ASCIIToUTF16("tes"), shortcut, max_relevance);
   EXPECT_LT(score_three_quarters, kMaxScore);
   int score_one_half =
-      provider_->CalculateScore(ASCIIToUTF16("te"), shortcut);
+      provider_->CalculateScore(ASCIIToUTF16("te"), shortcut, max_relevance);
   EXPECT_LT(score_one_half, score_three_quarters);
   int score_one_quarter =
-      provider_->CalculateScore(ASCIIToUTF16("t"), shortcut);
+      provider_->CalculateScore(ASCIIToUTF16("t"), shortcut, max_relevance);
   EXPECT_LT(score_one_quarter, score_one_half);
 
   // Should decay with time - one week.
   shortcut.last_access_time = base::Time::Now() - base::TimeDelta::FromDays(7);
   int score_week_old =
-      provider_->CalculateScore(ASCIIToUTF16("test"), shortcut);
+      provider_->CalculateScore(ASCIIToUTF16("test"), shortcut, max_relevance);
   EXPECT_LT(score_week_old, kMaxScore);
 
   // Should decay more in two weeks.
   shortcut.last_access_time = base::Time::Now() - base::TimeDelta::FromDays(14);
   int score_two_weeks_old =
-      provider_->CalculateScore(ASCIIToUTF16("test"), shortcut);
+      provider_->CalculateScore(ASCIIToUTF16("test"), shortcut, max_relevance);
   EXPECT_LT(score_two_weeks_old, score_week_old);
 
   // But not if it was activly clicked on. 2 hits slow decaying power.
   shortcut.number_of_hits = 2;
   shortcut.last_access_time = base::Time::Now() - base::TimeDelta::FromDays(14);
   int score_popular_two_weeks_old =
-      provider_->CalculateScore(ASCIIToUTF16("test"), shortcut);
+      provider_->CalculateScore(ASCIIToUTF16("test"), shortcut, max_relevance);
   EXPECT_LT(score_two_weeks_old, score_popular_two_weeks_old);
   // But still decayed.
   EXPECT_LT(score_popular_two_weeks_old, kMaxScore);
@@ -613,7 +615,7 @@
   shortcut.number_of_hits = 3;
   shortcut.last_access_time = base::Time::Now() - base::TimeDelta::FromDays(14);
   int score_more_popular_two_weeks_old =
-      provider_->CalculateScore(ASCIIToUTF16("test"), shortcut);
+      provider_->CalculateScore(ASCIIToUTF16("test"), shortcut, max_relevance);
   EXPECT_LT(score_two_weeks_old, score_more_popular_two_weeks_old);
   EXPECT_LT(score_popular_two_weeks_old, score_more_popular_two_weeks_old);
   // But still decayed.
diff --git a/chrome/browser/autofill/autofill_browsertest.cc b/chrome/browser/autofill/autofill_browsertest.cc
index b1cda4b..4498d2d 100644
--- a/chrome/browser/autofill/autofill_browsertest.cc
+++ b/chrome/browser/autofill/autofill_browsertest.cc
@@ -20,8 +20,6 @@
 #include "chrome/browser/infobars/confirm_infobar_delegate.h"
 #include "chrome/browser/infobars/infobar_service.h"
 #include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/translate/translate_infobar_delegate.h"
-#include "chrome/browser/translate/translate_manager.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_window.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
@@ -31,9 +29,6 @@
 #include "chrome/test/base/ui_test_utils.h"
 #include "components/autofill/content/browser/autofill_driver_impl.h"
 #include "components/autofill/core/browser/autofill_common_test.h"
-#include "components/autofill/core/browser/autofill_external_delegate.h"
-#include "components/autofill/core/browser/autofill_manager.h"
-#include "components/autofill/core/browser/autofill_manager_test_delegate.h"
 #include "components/autofill/core/browser/autofill_profile.h"
 #include "components/autofill/core/browser/credit_card.h"
 #include "components/autofill/core/browser/personal_data_manager.h"
@@ -55,69 +50,6 @@
 
 namespace autofill {
 
-static const char* kDataURIPrefix = "data:text/html;charset=utf-8,";
-static const char* kTestFormString =
-    "<form action=\"http://www.example.com/\" method=\"POST\">"
-    "<label for=\"firstname\">First name:</label>"
-    " <input type=\"text\" id=\"firstname\""
-    "        onFocus=\"domAutomationController.send(true)\"><br>"
-    "<label for=\"lastname\">Last name:</label>"
-    " <input type=\"text\" id=\"lastname\"><br>"
-    "<label for=\"address1\">Address line 1:</label>"
-    " <input type=\"text\" id=\"address1\"><br>"
-    "<label for=\"address2\">Address line 2:</label>"
-    " <input type=\"text\" id=\"address2\"><br>"
-    "<label for=\"city\">City:</label>"
-    " <input type=\"text\" id=\"city\"><br>"
-    "<label for=\"state\">State:</label>"
-    " <select id=\"state\">"
-    " <option value=\"\" selected=\"yes\">--</option>"
-    " <option value=\"CA\">California</option>"
-    " <option value=\"TX\">Texas</option>"
-    " </select><br>"
-    "<label for=\"zip\">ZIP code:</label>"
-    " <input type=\"text\" id=\"zip\"><br>"
-    "<label for=\"country\">Country:</label>"
-    " <select id=\"country\">"
-    " <option value=\"\" selected=\"yes\">--</option>"
-    " <option value=\"CA\">Canada</option>"
-    " <option value=\"US\">United States</option>"
-    " </select><br>"
-    "<label for=\"phone\">Phone number:</label>"
-    " <input type=\"text\" id=\"phone\"><br>"
-    "</form>";
-
-class AutofillManagerTestDelegateImpl
-    : public autofill::AutofillManagerTestDelegate {
- public:
-  AutofillManagerTestDelegateImpl() {}
-
-  virtual void DidPreviewFormData() OVERRIDE {
-    loop_runner_->Quit();
-  }
-
-  virtual void DidFillFormData() OVERRIDE {
-    loop_runner_->Quit();
-  }
-
-  virtual void DidShowSuggestions() OVERRIDE {
-    loop_runner_->Quit();
-  }
-
-  void Reset() {
-    loop_runner_ = new content::MessageLoopRunner();
-  }
-
-  void Wait() {
-    loop_runner_->Run();
-  }
-
- private:
-  scoped_refptr<content::MessageLoopRunner> loop_runner_;
-
-  DISALLOW_COPY_AND_ASSIGN(AutofillManagerTestDelegateImpl);
-};
-
 class WindowedPersonalDataManagerObserver
     : public PersonalDataManagerObserver,
       public content::NotificationObserver {
@@ -181,39 +113,6 @@
   InfoBarService* infobar_service_;
 };
 
-class TestAutofillExternalDelegate : public AutofillExternalDelegate {
- public:
-  TestAutofillExternalDelegate(content::WebContents* web_contents,
-                               AutofillManager* autofill_manager,
-                               AutofillDriver* autofill_driver)
-      : AutofillExternalDelegate(web_contents, autofill_manager,
-                                 autofill_driver),
-        keyboard_listener_(NULL) {
-  }
-  virtual ~TestAutofillExternalDelegate() {}
-
-  virtual void OnPopupShown(content::KeyboardListener* listener) OVERRIDE {
-    AutofillExternalDelegate::OnPopupShown(listener);
-    keyboard_listener_ = listener;
-  }
-
-  virtual void OnPopupHidden(content::KeyboardListener* listener) OVERRIDE {
-    keyboard_listener_ = NULL;
-    AutofillExternalDelegate::OnPopupHidden(listener);
-  }
-
-  content::KeyboardListener* keyboard_listener() {
-    return keyboard_listener_;
-  }
-
- private:
-  // The popup that is currently registered as a keyboard listener, or NULL if
-  // there is none.
-  content::KeyboardListener* keyboard_listener_;
-
-  DISALLOW_COPY_AND_ASSIGN(TestAutofillExternalDelegate);
-};
-
 class AutofillTest : public InProcessBrowserTest {
  protected:
   AutofillTest() {}
@@ -221,19 +120,6 @@
   virtual void SetUpOnMainThread() OVERRIDE {
     // Don't want Keychain coming up on Mac.
     test::DisableSystemServices(browser()->profile());
-
-    // When testing the native UI, hook up a test external delegate, which
-    // allows us to forward keyboard events to the popup directly.
-    content::WebContents* web_contents =
-        browser()->tab_strip_model()->GetActiveWebContents();
-    AutofillDriverImpl* autofill_driver =
-        AutofillDriverImpl::FromWebContents(web_contents);
-    AutofillManager* autofill_manager = autofill_driver->autofill_manager();
-    scoped_ptr<AutofillExternalDelegate> external_delegate(
-        new TestAutofillExternalDelegate(web_contents, autofill_manager,
-                                         autofill_driver));
-    autofill_driver->SetAutofillExternalDelegate(external_delegate.Pass());
-    autofill_manager->SetTestDelegate(&test_delegate_);
   }
 
   virtual void CleanUpOnMainThread() OVERRIDE {
@@ -249,21 +135,6 @@
     return PersonalDataManagerFactory::GetForProfile(browser()->profile());
   }
 
-  void CreateTestProfile() {
-    AutofillProfile profile;
-    test::SetProfileInfo(
-        &profile, "Milton", "C.", "Waddams",
-        "red.swingline@initech.com", "Initech", "4120 Freidrich Lane",
-        "Basement", "Austin", "Texas", "78744", "US", "5125551234");
-
-    WindowedPersonalDataManagerObserver observer(browser());
-    personal_data_manager()->AddProfile(profile);
-
-    // AddProfile is asynchronous. Wait for it to finish before continuing the
-    // tests.
-    observer.Wait();
-  }
-
   void SetProfiles(std::vector<AutofillProfile>* profiles) {
     WindowedPersonalDataManagerObserver observer(browser());
     personal_data_manager()->SetProfiles(profiles);
@@ -319,18 +190,6 @@
     FillFormAndSubmit("autofill_creditcard_form.html", data);
   }
 
-  // Populates a webpage form using autofill data and keypress events.
-  // This function focuses the specified input field in the form, and then
-  // sends keypress events to the tab to cause the form to be populated.
-  void PopulateForm(const std::string& field_id) {
-    std::string js("document.getElementById('" + field_id + "').focus();");
-    ASSERT_TRUE(content::ExecuteScript(render_view_host(), js));
-
-    SendKeyToPageAndWait(ui::VKEY_DOWN);
-    SendKeyToPopupAndWait(ui::VKEY_DOWN);
-    SendKeyToPopupAndWait(ui::VKEY_RETURN);
-  }
-
   // Aggregate profiles from forms into Autofill preferences. Returns the number
   // of parsed profiles.
   int AggregateProfilesIntoAutofillPrefs(const std::string& filename) {
@@ -387,65 +246,6 @@
         GetRenderViewHost();
   }
 
-  void SimulateURLFetch(bool success) {
-    net::TestURLFetcher* fetcher = url_fetcher_factory_.GetFetcherByID(0);
-    ASSERT_TRUE(fetcher);
-    net::URLRequestStatus status;
-    status.set_status(success ? net::URLRequestStatus::SUCCESS :
-                                net::URLRequestStatus::FAILED);
-
-    std::string script = " var google = {};"
-        "google.translate = (function() {"
-        "  return {"
-        "    TranslateService: function() {"
-        "      return {"
-        "        isAvailable : function() {"
-        "          return true;"
-        "        },"
-        "        restore : function() {"
-        "          return;"
-        "        },"
-        "        getDetectedLanguage : function() {"
-        "          return \"ja\";"
-        "        },"
-        "        translatePage : function(originalLang, targetLang,"
-        "                                 onTranslateProgress) {"
-        "          document.getElementsByTagName(\"body\")[0].innerHTML = '" +
-        std::string(kTestFormString) +
-        "              ';"
-        "          onTranslateProgress(100, true, false);"
-        "        }"
-        "      };"
-        "    }"
-        "  };"
-        "})();";
-
-    fetcher->set_url(fetcher->GetOriginalURL());
-    fetcher->set_status(status);
-    fetcher->set_response_code(success ? 200 : 500);
-    fetcher->SetResponseString(script);
-    fetcher->delegate()->OnURLFetchComplete(fetcher);
-  }
-
-  void FocusFirstNameField() {
-    LOG(WARNING) << "Clicking on the tab.";
-    content::SimulateMouseClick(
-        browser()->tab_strip_model()->GetActiveWebContents(),
-        0,
-        WebKit::WebMouseEvent::ButtonLeft);
-
-    LOG(WARNING) << "Focusing the first name field.";
-    bool result = false;
-    ASSERT_TRUE(content::ExecuteScriptAndExtractBool(
-        render_view_host(),
-        "if (document.readyState === 'complete')"
-        "  document.getElementById('firstname').focus();"
-        "else"
-        "  domAutomationController.send(false);",
-        &result));
-    ASSERT_TRUE(result);
-  }
-
   void ExpectFilledTestForm() {
     ExpectFieldValue("firstname", "Milton");
     ExpectFieldValue("lastname", "Waddams");
@@ -458,528 +258,10 @@
     ExpectFieldValue("phone", "5125551234");
   }
 
-  void SendKeyToPageAndWait(ui::KeyboardCode key) {
-    test_delegate_.Reset();
-    content::SimulateKeyPress(
-        browser()->tab_strip_model()->GetActiveWebContents(),
-        key, false, false, false, false);
-    test_delegate_.Wait();
-  }
-
-  void SendKeyToPopupAndWait(ui::KeyboardCode key) {
-    // When testing the native UI, route popup-targeted key presses via the
-    // external delegate.
-    content::NativeWebKeyboardEvent event;
-    event.windowsKeyCode = key;
-    test_delegate_.Reset();
-    external_delegate()->keyboard_listener()->HandleKeyPressEvent(event);
-    test_delegate_.Wait();
-  }
-
-  void TryBasicFormFill() {
-    FocusFirstNameField();
-
-    // Start filling the first name field with "M" and wait for the popup to be
-    // shown.
-    LOG(WARNING) << "Typing 'M' to bring up the Autofill popup.";
-    SendKeyToPageAndWait(ui::VKEY_M);
-
-    // Press the down arrow to select the suggestion and preview the autofilled
-    // form.
-    LOG(WARNING) << "Simulating down arrow press to initiate Autofill preview.";
-    SendKeyToPopupAndWait(ui::VKEY_DOWN);
-
-    // The previewed values should not be accessible to JavaScript.
-    ExpectFieldValue("firstname", "M");
-    ExpectFieldValue("lastname", std::string());
-    ExpectFieldValue("address1", std::string());
-    ExpectFieldValue("address2", std::string());
-    ExpectFieldValue("city", std::string());
-    ExpectFieldValue("state", std::string());
-    ExpectFieldValue("zip", std::string());
-    ExpectFieldValue("country", std::string());
-    ExpectFieldValue("phone", std::string());
-    // TODO(isherman): It would be nice to test that the previewed values are
-    // displayed: http://crbug.com/57220
-
-    // Press Enter to accept the autofill suggestions.
-    LOG(WARNING) << "Simulating Return press to fill the form.";
-    SendKeyToPopupAndWait(ui::VKEY_RETURN);
-
-    // The form should be filled.
-    ExpectFilledTestForm();
-  }
-
-  TestAutofillExternalDelegate* external_delegate() {
-    content::WebContents* web_contents =
-        browser()->tab_strip_model()->GetActiveWebContents();
-    AutofillDriverImpl* autofill_driver =
-        AutofillDriverImpl::FromWebContents(web_contents);
-    return static_cast<TestAutofillExternalDelegate*>(
-        autofill_driver->autofill_external_delegate());
-  }
-
-  AutofillManagerTestDelegateImpl test_delegate_;
-
  private:
   net::TestURLFetcherFactory url_fetcher_factory_;
 };
 
-// http://crbug.com/150084
-#if defined(OS_MACOSX)
-#define MAYBE_BasicFormFill BasicFormFill
-#else
-#define MAYBE_BasicFormFill DISABLED_BasicFormFill
-#endif
-// Test that basic form fill is working.
-IN_PROC_BROWSER_TEST_F(AutofillTest, MAYBE_BasicFormFill) {
-  CreateTestProfile();
-
-  // Load the test page.
-  ASSERT_NO_FATAL_FAILURE(ui_test_utils::NavigateToURL(browser(),
-      GURL(std::string(kDataURIPrefix) + kTestFormString)));
-
-  // Invoke Autofill.
-  TryBasicFormFill();
-}
-
-// http://crbug.com/150084
-#if defined(OS_MACOSX)
-#define MAYBE_AutofillViaDownArrow AutofillViaDownArrow
-#else
-#define MAYBE_AutofillViaDownArrow DISABLED_AutofillViaDownArrow
-#endif
-// Test that form filling can be initiated by pressing the down arrow.
-IN_PROC_BROWSER_TEST_F(AutofillTest, MAYBE_AutofillViaDownArrow) {
-  CreateTestProfile();
-
-  // Load the test page.
-  ASSERT_NO_FATAL_FAILURE(ui_test_utils::NavigateToURL(browser(),
-      GURL(std::string(kDataURIPrefix) + kTestFormString)));
-
-  // Focus a fillable field.
-  FocusFirstNameField();
-
-  // Press the down arrow to initiate Autofill and wait for the popup to be
-  // shown.
-  SendKeyToPageAndWait(ui::VKEY_DOWN);
-
-  // Press the down arrow to select the suggestion and preview the autofilled
-  // form.
-  SendKeyToPopupAndWait(ui::VKEY_DOWN);
-
-  // Press Enter to accept the autofill suggestions.
-  SendKeyToPopupAndWait(ui::VKEY_RETURN);
-
-  // The form should be filled.
-  ExpectFilledTestForm();
-}
-
-// http://crbug.com/150084
-#if defined(OS_MACOSX)
-#define MAYBE_OnChangeAfterAutofill OnChangeAfterAutofill
-#else
-#define MAYBE_OnChangeAfterAutofill DISABLED_OnChangeAfterAutofill
-#endif
-// Test that a JavaScript onchange event is fired after auto-filling a form.
-IN_PROC_BROWSER_TEST_F(AutofillTest, MAYBE_OnChangeAfterAutofill) {
-  CreateTestProfile();
-
-  const char* kOnChangeScript =
-      "<script>"
-      "focused_fired = false;"
-      "unfocused_fired = false;"
-      "changed_select_fired = false;"
-      "unchanged_select_fired = false;"
-      "document.getElementById('firstname').onchange = function() {"
-      "  focused_fired = true;"
-      "};"
-      "document.getElementById('lastname').onchange = function() {"
-      "  unfocused_fired = true;"
-      "};"
-      "document.getElementById('state').onchange = function() {"
-      "  changed_select_fired = true;"
-      "};"
-      "document.getElementById('country').onchange = function() {"
-      "  unchanged_select_fired = true;"
-      "};"
-      "document.getElementById('country').value = 'US';"
-      "</script>";
-
-  // Load the test page.
-  ASSERT_NO_FATAL_FAILURE(ui_test_utils::NavigateToURL(browser(),
-      GURL(std::string(kDataURIPrefix) + kTestFormString + kOnChangeScript)));
-
-  // Invoke Autofill.
-  FocusFirstNameField();
-
-  // Start filling the first name field with "M" and wait for the popup to be
-  // shown.
-  SendKeyToPageAndWait(ui::VKEY_M);
-
-  // Press the down arrow to select the suggestion and preview the autofilled
-  // form.
-  SendKeyToPopupAndWait(ui::VKEY_DOWN);
-
-  // Press Enter to accept the autofill suggestions.
-  SendKeyToPopupAndWait(ui::VKEY_RETURN);
-
-  // The form should be filled.
-  ExpectFilledTestForm();
-
-  // The change event should have already fired for unfocused fields, both of
-  // <input> and of <select> type. However, it should not yet have fired for the
-  // focused field.
-  bool focused_fired = false;
-  bool unfocused_fired = false;
-  bool changed_select_fired = false;
-  bool unchanged_select_fired = false;
-  ASSERT_TRUE(content::ExecuteScriptAndExtractBool(
-      render_view_host(),
-      "domAutomationController.send(focused_fired);",
-      &focused_fired));
-  ASSERT_TRUE(content::ExecuteScriptAndExtractBool(
-      render_view_host(),
-      "domAutomationController.send(unfocused_fired);",
-      &unfocused_fired));
-  ASSERT_TRUE(content::ExecuteScriptAndExtractBool(
-      render_view_host(),
-      "domAutomationController.send(changed_select_fired);",
-      &changed_select_fired));
-  ASSERT_TRUE(content::ExecuteScriptAndExtractBool(
-      render_view_host(),
-      "domAutomationController.send(unchanged_select_fired);",
-      &unchanged_select_fired));
-  EXPECT_FALSE(focused_fired);
-  EXPECT_TRUE(unfocused_fired);
-  EXPECT_TRUE(changed_select_fired);
-  EXPECT_FALSE(unchanged_select_fired);
-
-  // Unfocus the first name field. Its change event should fire.
-  ASSERT_TRUE(content::ExecuteScriptAndExtractBool(
-      render_view_host(),
-      "document.getElementById('firstname').blur();"
-      "domAutomationController.send(focused_fired);", &focused_fired));
-  EXPECT_TRUE(focused_fired);
-}
-
-// Test that we can autofill forms distinguished only by their |id| attribute.
-// DISABLED: http://crbug.com/150084
-IN_PROC_BROWSER_TEST_F(AutofillTest, DISABLED_AutofillFormsDistinguishedById) {
-  CreateTestProfile();
-
-  // Load the test page.
-  const std::string kURL =
-      std::string(kDataURIPrefix) + kTestFormString +
-      "<script>"
-      "var mainForm = document.forms[0];"
-      "mainForm.id = 'mainForm';"
-      "var newForm = document.createElement('form');"
-      "newForm.action = mainForm.action;"
-      "newForm.method = mainForm.method;"
-      "newForm.id = 'newForm';"
-      "mainForm.parentNode.insertBefore(newForm, mainForm);"
-      "</script>";
-  ASSERT_NO_FATAL_FAILURE(ui_test_utils::NavigateToURL(browser(), GURL(kURL)));
-
-  // Invoke Autofill.
-  TryBasicFormFill();
-}
-
-// Test that we properly autofill forms with repeated fields.
-// In the wild, the repeated fields are typically either email fields
-// (duplicated for "confirmation"); or variants that are hot-swapped via
-// JavaScript, with only one actually visible at any given time.
-// DISABLED: http://crbug.com/150084
-IN_PROC_BROWSER_TEST_F(AutofillTest, DISABLED_AutofillFormWithRepeatedField) {
-  CreateTestProfile();
-
-  // Load the test page.
-  ASSERT_NO_FATAL_FAILURE(ui_test_utils::NavigateToURL(browser(),
-      GURL(std::string(kDataURIPrefix) +
-           "<form action=\"http://www.example.com/\" method=\"POST\">"
-           "<label for=\"firstname\">First name:</label>"
-           " <input type=\"text\" id=\"firstname\""
-           "        onFocus=\"domAutomationController.send(true)\"><br>"
-           "<label for=\"lastname\">Last name:</label>"
-           " <input type=\"text\" id=\"lastname\"><br>"
-           "<label for=\"address1\">Address line 1:</label>"
-           " <input type=\"text\" id=\"address1\"><br>"
-           "<label for=\"address2\">Address line 2:</label>"
-           " <input type=\"text\" id=\"address2\"><br>"
-           "<label for=\"city\">City:</label>"
-           " <input type=\"text\" id=\"city\"><br>"
-           "<label for=\"state\">State:</label>"
-           " <select id=\"state\">"
-           " <option value=\"\" selected=\"yes\">--</option>"
-           " <option value=\"CA\">California</option>"
-           " <option value=\"TX\">Texas</option>"
-           " </select><br>"
-           "<label for=\"state_freeform\" style=\"display:none\">State:</label>"
-           " <input type=\"text\" id=\"state_freeform\""
-           "        style=\"display:none\"><br>"
-           "<label for=\"zip\">ZIP code:</label>"
-           " <input type=\"text\" id=\"zip\"><br>"
-           "<label for=\"country\">Country:</label>"
-           " <select id=\"country\">"
-           " <option value=\"\" selected=\"yes\">--</option>"
-           " <option value=\"CA\">Canada</option>"
-           " <option value=\"US\">United States</option>"
-           " </select><br>"
-           "<label for=\"phone\">Phone number:</label>"
-           " <input type=\"text\" id=\"phone\"><br>"
-           "</form>")));
-
-  // Invoke Autofill.
-  TryBasicFormFill();
-  ExpectFieldValue("state_freeform", std::string());
-}
-
-// http://crbug.com/150084
-#if defined(OS_MACOSX)
-#define MAYBE_AutofillFormWithNonAutofillableField \
-    AutofillFormWithNonAutofillableField
-#else
-#define MAYBE_AutofillFormWithNonAutofillableField \
-    DISABLED_AutofillFormWithNonAutofillableField
-#endif
-
-// Test that we properly autofill forms with non-autofillable fields.
-IN_PROC_BROWSER_TEST_F(AutofillTest,
-                       MAYBE_AutofillFormWithNonAutofillableField) {
-  CreateTestProfile();
-
-  // Load the test page.
-  ASSERT_NO_FATAL_FAILURE(ui_test_utils::NavigateToURL(browser(),
-      GURL(std::string(kDataURIPrefix) +
-           "<form action=\"http://www.example.com/\" method=\"POST\">"
-           "<label for=\"firstname\">First name:</label>"
-           " <input type=\"text\" id=\"firstname\""
-           "        onFocus=\"domAutomationController.send(true)\"><br>"
-           "<label for=\"middlename\">Middle name:</label>"
-           " <input type=\"text\" id=\"middlename\" autocomplete=\"off\" /><br>"
-           "<label for=\"lastname\">Last name:</label>"
-           " <input type=\"text\" id=\"lastname\"><br>"
-           "<label for=\"address1\">Address line 1:</label>"
-           " <input type=\"text\" id=\"address1\"><br>"
-           "<label for=\"address2\">Address line 2:</label>"
-           " <input type=\"text\" id=\"address2\"><br>"
-           "<label for=\"city\">City:</label>"
-           " <input type=\"text\" id=\"city\"><br>"
-           "<label for=\"state\">State:</label>"
-           " <select id=\"state\">"
-           " <option value=\"\" selected=\"yes\">--</option>"
-           " <option value=\"CA\">California</option>"
-           " <option value=\"TX\">Texas</option>"
-           " </select><br>"
-           "<label for=\"zip\">ZIP code:</label>"
-           " <input type=\"text\" id=\"zip\"><br>"
-           "<label for=\"country\">Country:</label>"
-           " <select id=\"country\">"
-           " <option value=\"\" selected=\"yes\">--</option>"
-           " <option value=\"CA\">Canada</option>"
-           " <option value=\"US\">United States</option>"
-           " </select><br>"
-           "<label for=\"phone\">Phone number:</label>"
-           " <input type=\"text\" id=\"phone\"><br>"
-           "</form>")));
-
-  // Invoke Autofill.
-  TryBasicFormFill();
-}
-
-// Test that we can Autofill dynamically generated forms.
-// DISABLED: http://crbug.com/150084
-IN_PROC_BROWSER_TEST_F(AutofillTest, DISABLED_DynamicFormFill) {
-  CreateTestProfile();
-
-  // Load the test page.
-  ASSERT_NO_FATAL_FAILURE(ui_test_utils::NavigateToURL(browser(),
-      GURL(std::string(kDataURIPrefix) +
-           "<form id=\"form\" action=\"http://www.example.com/\""
-           "      method=\"POST\"></form>"
-           "<script>"
-           "function AddElement(name, label) {"
-           "  var form = document.getElementById('form');"
-           ""
-           "  var label_text = document.createTextNode(label);"
-           "  var label_element = document.createElement('label');"
-           "  label_element.setAttribute('for', name);"
-           "  label_element.appendChild(label_text);"
-           "  form.appendChild(label_element);"
-           ""
-           "  if (name === 'state' || name === 'country') {"
-           "    var select_element = document.createElement('select');"
-           "    select_element.setAttribute('id', name);"
-           "    select_element.setAttribute('name', name);"
-           ""
-           "    /* Add an empty selected option. */"
-           "    var default_option = new Option('--', '', true);"
-           "    select_element.appendChild(default_option);"
-           ""
-           "    /* Add the other options. */"
-           "    if (name == 'state') {"
-           "      var option1 = new Option('California', 'CA');"
-           "      select_element.appendChild(option1);"
-           "      var option2 = new Option('Texas', 'TX');"
-           "      select_element.appendChild(option2);"
-           "    } else {"
-           "      var option1 = new Option('Canada', 'CA');"
-           "      select_element.appendChild(option1);"
-           "      var option2 = new Option('United States', 'US');"
-           "      select_element.appendChild(option2);"
-           "    }"
-           ""
-           "    form.appendChild(select_element);"
-           "  } else {"
-           "    var input_element = document.createElement('input');"
-           "    input_element.setAttribute('id', name);"
-           "    input_element.setAttribute('name', name);"
-           ""
-           "    /* Add the onFocus listener to the 'firstname' field. */"
-           "    if (name === 'firstname') {"
-           "      input_element.setAttribute("
-           "          'onFocus', 'domAutomationController.send(true)');"
-           "    }"
-           ""
-           "    form.appendChild(input_element);"
-           "  }"
-           ""
-           "  form.appendChild(document.createElement('br'));"
-           "};"
-           ""
-           "function BuildForm() {"
-           "  var elements = ["
-           "    ['firstname', 'First name:'],"
-           "    ['lastname', 'Last name:'],"
-           "    ['address1', 'Address line 1:'],"
-           "    ['address2', 'Address line 2:'],"
-           "    ['city', 'City:'],"
-           "    ['state', 'State:'],"
-           "    ['zip', 'ZIP code:'],"
-           "    ['country', 'Country:'],"
-           "    ['phone', 'Phone number:'],"
-           "  ];"
-           ""
-           "  for (var i = 0; i < elements.length; i++) {"
-           "    var name = elements[i][0];"
-           "    var label = elements[i][1];"
-           "    AddElement(name, label);"
-           "  }"
-           "};"
-           "</script>")));
-
-  // Dynamically construct the form.
-  ASSERT_TRUE(content::ExecuteScript(render_view_host(), "BuildForm();"));
-
-  // Invoke Autofill.
-  TryBasicFormFill();
-}
-
-// Test that form filling works after reloading the current page.
-// This test brought to you by http://crbug.com/69204
-#if defined(OS_MACOSX)
-// Now flaky on everything but mac.
-// http://crbug.com/150084
-#define MAYBE_AutofillAfterReload AutofillAfterReload
-#else
-#define MAYBE_AutofillAfterReload DISABLED_AutofillAfterReload
-#endif
-IN_PROC_BROWSER_TEST_F(AutofillTest, MAYBE_AutofillAfterReload) {
-  LOG(WARNING) << "Creating test profile.";
-  CreateTestProfile();
-
-  // Load the test page.
-  LOG(WARNING) << "Bringing browser window to front.";
-  LOG(WARNING) << "Navigating to URL.";
-  ASSERT_NO_FATAL_FAILURE(ui_test_utils::NavigateToURL(browser(),
-      GURL(std::string(kDataURIPrefix) + kTestFormString)));
-
-  // Reload the page.
-  LOG(WARNING) << "Reloading the page.";
-  content::WebContents* web_contents =
-      browser()->tab_strip_model()->GetActiveWebContents();
-  web_contents->GetController().Reload(false);
-  content::WaitForLoadStop(web_contents);
-
-  // Invoke Autofill.
-  LOG(WARNING) << "Trying to fill the form.";
-  TryBasicFormFill();
-}
-
-// DISABLED: http://crbug.com/150084
-IN_PROC_BROWSER_TEST_F(AutofillTest, DISABLED_AutofillAfterTranslate) {
-  CreateTestProfile();
-
-  GURL url(std::string(kDataURIPrefix) +
-               "<form action=\"http://www.example.com/\" method=\"POST\">"
-               "<label for=\"fn\">なまえ</label>"
-               " <input type=\"text\" id=\"fn\""
-               "        onFocus=\"domAutomationController.send(true)\""
-               "><br>"
-               "<label for=\"ln\">みょうじ</label>"
-               " <input type=\"text\" id=\"ln\"><br>"
-               "<label for=\"a1\">Address line 1:</label>"
-               " <input type=\"text\" id=\"a1\"><br>"
-               "<label for=\"a2\">Address line 2:</label>"
-               " <input type=\"text\" id=\"a2\"><br>"
-               "<label for=\"ci\">City:</label>"
-               " <input type=\"text\" id=\"ci\"><br>"
-               "<label for=\"st\">State:</label>"
-               " <select id=\"st\">"
-               " <option value=\"\" selected=\"yes\">--</option>"
-               " <option value=\"CA\">California</option>"
-               " <option value=\"TX\">Texas</option>"
-               " </select><br>"
-               "<label for=\"z\">ZIP code:</label>"
-               " <input type=\"text\" id=\"z\"><br>"
-               "<label for=\"co\">Country:</label>"
-               " <select id=\"co\">"
-               " <option value=\"\" selected=\"yes\">--</option>"
-               " <option value=\"CA\">Canada</option>"
-               " <option value=\"US\">United States</option>"
-               " </select><br>"
-               "<label for=\"ph\">Phone number:</label>"
-               " <input type=\"text\" id=\"ph\"><br>"
-               "</form>");
-  ASSERT_NO_FATAL_FAILURE(ui_test_utils::NavigateToURL(browser(), url));
-
-  // Get translation bar.
-  LanguageDetectionDetails details;
-  details.adopted_language = "ja";
-  content::RenderViewHostTester::TestOnMessageReceived(
-      render_view_host(),
-      ChromeViewHostMsg_TranslateLanguageDetermined(0, details, true));
-  TranslateInfoBarDelegate* delegate = InfoBarService::FromWebContents(
-      browser()->tab_strip_model()->GetActiveWebContents())->infobar_at(0)->
-          AsTranslateInfoBarDelegate();
-  ASSERT_TRUE(delegate);
-  EXPECT_EQ(TranslateInfoBarDelegate::BEFORE_TRANSLATE,
-            delegate->infobar_type());
-
-  // Simulate translation button press.
-  delegate->Translate();
-
-  // Simulate the translate script being retrieved.
-  // Pass fake google.translate lib as the translate script.
-  SimulateURLFetch(true);
-
-  content::WindowedNotificationObserver translation_observer(
-      chrome::NOTIFICATION_PAGE_TRANSLATED,
-      content::NotificationService::AllSources());
-
-  // Simulate translation to kick onTranslateElementLoad.
-  // But right now, the call stucks here.
-  // Once click the text field, it starts again.
-  ASSERT_TRUE(content::ExecuteScript(
-      render_view_host(), "cr.googleTranslate.onTranslateElementLoad();"));
-
-  // Simulate the render notifying the translation has been done.
-  translation_observer.Wait();
-
-  TryBasicFormFill();
-}
-
 // Test filling profiles with unicode strings and crazy characters.
 // TODO(isherman): rewrite as unit test under PersonalDataManagerTest.
 IN_PROC_BROWSER_TEST_F(AutofillTest, FillProfileCrazyCharacters) {
@@ -1273,52 +555,6 @@
   ASSERT_TRUE(personal_data_manager()->GetProfiles().empty());
 }
 
-// http://crbug.com/150084
-#if defined(OS_MACOSX)
-#define MAYBE_ComparePhoneNumbers ComparePhoneNumbers
-#else
-#define MAYBE_ComparePhoneNumbers DISABLED_ComparePhoneNumbers
-#endif
-// Test phone fields parse correctly from a given profile.
-// The high level key presses execute the following: Select the first text
-// field, invoke the autofill popup list, select the first profile within the
-// list, and commit to the profile to populate the form.
-IN_PROC_BROWSER_TEST_F(AutofillTest, MAYBE_ComparePhoneNumbers) {
-  ASSERT_TRUE(test_server()->Start());
-
-  AutofillProfile profile;
-  profile.SetRawInfo(NAME_FIRST, ASCIIToUTF16("Bob"));
-  profile.SetRawInfo(NAME_LAST, ASCIIToUTF16("Smith"));
-  profile.SetRawInfo(ADDRESS_HOME_LINE1, ASCIIToUTF16("1234 H St."));
-  profile.SetRawInfo(ADDRESS_HOME_CITY, ASCIIToUTF16("San Jose"));
-  profile.SetRawInfo(ADDRESS_HOME_STATE, ASCIIToUTF16("CA"));
-  profile.SetRawInfo(ADDRESS_HOME_ZIP, ASCIIToUTF16("95110"));
-  profile.SetRawInfo(PHONE_HOME_WHOLE_NUMBER, ASCIIToUTF16("1-408-555-4567"));
-  SetProfile(profile);
-
-  GURL url = test_server()->GetURL("files/autofill/form_phones.html");
-  ui_test_utils::NavigateToURL(browser(), url);
-  PopulateForm("NAME_FIRST");
-
-  ExpectFieldValue("NAME_FIRST", "Bob");
-  ExpectFieldValue("NAME_LAST", "Smith");
-  ExpectFieldValue("ADDRESS_HOME_LINE1", "1234 H St.");
-  ExpectFieldValue("ADDRESS_HOME_CITY", "San Jose");
-  ExpectFieldValue("ADDRESS_HOME_STATE", "CA");
-  ExpectFieldValue("ADDRESS_HOME_ZIP", "95110");
-  ExpectFieldValue("PHONE_HOME_WHOLE_NUMBER", "14085554567");
-  ExpectFieldValue("PHONE_HOME_CITY_CODE-1", "408");
-  ExpectFieldValue("PHONE_HOME_CITY_CODE-2", "408");
-  ExpectFieldValue("PHONE_HOME_NUMBER", "5554567");
-  ExpectFieldValue("PHONE_HOME_NUMBER_3-1", "555");
-  ExpectFieldValue("PHONE_HOME_NUMBER_3-2", "555");
-  ExpectFieldValue("PHONE_HOME_NUMBER_4-1", "4567");
-  ExpectFieldValue("PHONE_HOME_NUMBER_4-2", "4567");
-  ExpectFieldValue("PHONE_HOME_EXT-1", std::string());
-  ExpectFieldValue("PHONE_HOME_EXT-2", std::string());
-  ExpectFieldValue("PHONE_HOME_COUNTRY_CODE-1", "1");
-}
-
 // Test profile is saved if phone number is valid in selected country.
 // The data file contains two profiles with valid phone numbers and two
 // profiles with invalid phone numbers from their respective country.
@@ -1432,129 +668,6 @@
                     infobar_count());
 }
 
-// http://crbug.com/150084
-#if defined(OS_MACOSX)
-#define MAYBE_NoAutofillForReadOnlyFields NoAutofillForReadOnlyFields
-#else
-#define MAYBE_NoAutofillForReadOnlyFields DISABLED_NoAutofillForReadOnlyFields
-#endif
-// Test that Autofill does not fill in read-only fields.
-IN_PROC_BROWSER_TEST_F(AutofillTest, MAYBE_NoAutofillForReadOnlyFields) {
-  ASSERT_TRUE(test_server()->Start());
-
-  std::string addr_line1("1234 H St.");
-
-  AutofillProfile profile;
-  profile.SetRawInfo(NAME_FIRST, ASCIIToUTF16("Bob"));
-  profile.SetRawInfo(NAME_LAST, ASCIIToUTF16("Smith"));
-  profile.SetRawInfo(EMAIL_ADDRESS, ASCIIToUTF16("bsmith@gmail.com"));
-  profile.SetRawInfo(ADDRESS_HOME_LINE1, ASCIIToUTF16(addr_line1));
-  profile.SetRawInfo(ADDRESS_HOME_CITY, ASCIIToUTF16("San Jose"));
-  profile.SetRawInfo(ADDRESS_HOME_STATE, ASCIIToUTF16("CA"));
-  profile.SetRawInfo(ADDRESS_HOME_ZIP, ASCIIToUTF16("95110"));
-  profile.SetRawInfo(COMPANY_NAME, ASCIIToUTF16("Company X"));
-  profile.SetRawInfo(PHONE_HOME_WHOLE_NUMBER, ASCIIToUTF16("408-871-4567"));
-  SetProfile(profile);
-
-  GURL url = test_server()->GetURL("files/autofill/read_only_field_test.html");
-  ui_test_utils::NavigateToURL(browser(), url);
-  PopulateForm("firstname");
-
-  ExpectFieldValue("email", std::string());
-  ExpectFieldValue("address", addr_line1);
-}
-
-// http://crbug.com/150084
-#if defined(OS_MACOSX)
-#define MAYBE_FormFillableOnReset FormFillableOnReset
-#else
-#define MAYBE_FormFillableOnReset DISABLED_FormFillableOnReset
-#endif
-// Test form is fillable from a profile after form was reset.
-// Steps:
-//   1. Fill form using a saved profile.
-//   2. Reset the form.
-//   3. Fill form using a saved profile.
-IN_PROC_BROWSER_TEST_F(AutofillTest, MAYBE_FormFillableOnReset) {
-  ASSERT_TRUE(test_server()->Start());
-
-  CreateTestProfile();
-
-  GURL url = test_server()->GetURL("files/autofill/autofill_test_form.html");
-  ui_test_utils::NavigateToURL(browser(), url);
-  PopulateForm("NAME_FIRST");
-
-  ASSERT_TRUE(content::ExecuteScript(
-      browser()->tab_strip_model()->GetActiveWebContents(),
-      "document.getElementById('testform').reset()"));
-
-  PopulateForm("NAME_FIRST");
-
-  ExpectFieldValue("NAME_FIRST", "Milton");
-  ExpectFieldValue("NAME_LAST", "Waddams");
-  ExpectFieldValue("EMAIL_ADDRESS", "red.swingline@initech.com");
-  ExpectFieldValue("ADDRESS_HOME_LINE1", "4120 Freidrich Lane");
-  ExpectFieldValue("ADDRESS_HOME_CITY", "Austin");
-  ExpectFieldValue("ADDRESS_HOME_STATE", "Texas");
-  ExpectFieldValue("ADDRESS_HOME_ZIP", "78744");
-  ExpectFieldValue("ADDRESS_HOME_COUNTRY", "United States");
-  ExpectFieldValue("PHONE_HOME_WHOLE_NUMBER", "5125551234");
-}
-
-// http://crbug.com/150084
-#if defined(OS_MACOSX)
-#define MAYBE_DistinguishMiddleInitialWithinName \
-    DistinguishMiddleInitialWithinName
-#else
-#define MAYBE_DistinguishMiddleInitialWithinName \
-    DISABLED_DistinguishMiddleInitialWithinName
-#endif
-// Test Autofill distinguishes a middle initial in a name.
-IN_PROC_BROWSER_TEST_F(AutofillTest, MAYBE_DistinguishMiddleInitialWithinName) {
-  ASSERT_TRUE(test_server()->Start());
-
-  CreateTestProfile();
-
-  GURL url = test_server()->GetURL(
-      "files/autofill/autofill_middleinit_form.html");
-  ui_test_utils::NavigateToURL(browser(), url);
-  PopulateForm("NAME_FIRST");
-
-  ExpectFieldValue("NAME_MIDDLE", "C");
-}
-
-// http://crbug.com/150084
-#if defined(OS_MACOSX)
-#define MAYBE_MultipleEmailFilledByOneUserGesture \
-    MultipleEmailFilledByOneUserGesture
-#else
-#define MAYBE_MultipleEmailFilledByOneUserGesture \
-    DISABLED_MultipleEmailFilledByOneUserGesture
-#endif
-// Test forms with multiple email addresses are filled properly.
-// Entire form should be filled with one user gesture.
-IN_PROC_BROWSER_TEST_F(AutofillTest,
-                       MAYBE_MultipleEmailFilledByOneUserGesture) {
-  ASSERT_TRUE(test_server()->Start());
-
-  std::string email("bsmith@gmail.com");
-
-  AutofillProfile profile;
-  profile.SetRawInfo(NAME_FIRST, ASCIIToUTF16("Bob"));
-  profile.SetRawInfo(NAME_LAST, ASCIIToUTF16("Smith"));
-  profile.SetRawInfo(EMAIL_ADDRESS, ASCIIToUTF16(email));
-  profile.SetRawInfo(PHONE_HOME_WHOLE_NUMBER, ASCIIToUTF16("4088714567"));
-  SetProfile(profile);
-
-  GURL url = test_server()->GetURL(
-      "files/autofill/autofill_confirmemail_form.html");
-  ui_test_utils::NavigateToURL(browser(), url);
-  PopulateForm("NAME_FIRST");
-
-  ExpectFieldValue("EMAIL_CONFIRM", email);
-  // TODO(isherman): verify entire form.
-}
-
 // Test profile not aggregated if email found in non-email field.
 IN_PROC_BROWSER_TEST_F(AutofillTest, ProfileWithEmailInOtherFieldNotSaved) {
   ASSERT_TRUE(test_server()->Start());
@@ -1573,123 +686,6 @@
   ASSERT_EQ(0u, personal_data_manager()->GetProfiles().size());
 }
 
-// http://crbug.com/150084
-#if defined(OS_MACOSX)
-#define MAYBE_FormFillLatencyAfterSubmit FormFillLatencyAfterSubmit
-#else
-#define MAYBE_FormFillLatencyAfterSubmit DISABLED_FormFillLatencyAfterSubmit
-#endif
-// Test latency time on form submit with lots of stored Autofill profiles.
-// This test verifies when a profile is selected from the Autofill dictionary
-// that consists of thousands of profiles, the form does not hang after being
-// submitted.
-IN_PROC_BROWSER_TEST_F(AutofillTest, MAYBE_FormFillLatencyAfterSubmit) {
-  ASSERT_TRUE(test_server()->Start());
-
-  std::vector<std::string> cities;
-  cities.push_back("San Jose");
-  cities.push_back("San Francisco");
-  cities.push_back("Sacramento");
-  cities.push_back("Los Angeles");
-
-  std::vector<std::string> streets;
-  streets.push_back("St");
-  streets.push_back("Ave");
-  streets.push_back("Ln");
-  streets.push_back("Ct");
-
-  const int kNumProfiles = 1500;
-  base::Time start_time = base::Time::Now();
-  std::vector<AutofillProfile> profiles;
-  for (int i = 0; i < kNumProfiles; i++) {
-    AutofillProfile profile;
-    string16 name(base::IntToString16(i));
-    string16 email(name + ASCIIToUTF16("@example.com"));
-    string16 street = ASCIIToUTF16(
-        base::IntToString(base::RandInt(0, 10000)) + " " +
-        streets[base::RandInt(0, streets.size() - 1)]);
-    string16 city = ASCIIToUTF16(cities[base::RandInt(0, cities.size() - 1)]);
-    string16 zip(base::IntToString16(base::RandInt(0, 10000)));
-    profile.SetRawInfo(NAME_FIRST, name);
-    profile.SetRawInfo(EMAIL_ADDRESS, email);
-    profile.SetRawInfo(ADDRESS_HOME_LINE1, street);
-    profile.SetRawInfo(ADDRESS_HOME_CITY, city);
-    profile.SetRawInfo(ADDRESS_HOME_STATE, WideToUTF16(L"CA"));
-    profile.SetRawInfo(ADDRESS_HOME_ZIP, zip);
-    profile.SetRawInfo(ADDRESS_HOME_COUNTRY, WideToUTF16(L"US"));
-    profiles.push_back(profile);
-  }
-  SetProfiles(&profiles);
-  // TODO(isherman): once we're sure this test doesn't timeout on any bots, this
-  // can be removd.
-  LOG(INFO) << "Created " << kNumProfiles << " profiles in " <<
-               (base::Time::Now() - start_time).InSeconds() << " seconds.";
-
-  GURL url = test_server()->GetURL(
-      "files/autofill/latency_after_submit_test.html");
-  ui_test_utils::NavigateToURL(browser(), url);
-  PopulateForm("NAME_FIRST");
-
-  content::WindowedNotificationObserver load_stop_observer(
-      content::NOTIFICATION_LOAD_STOP,
-      content::Source<content::NavigationController>(
-          &browser()->tab_strip_model()->GetActiveWebContents()->
-              GetController()));
-
-  ASSERT_TRUE(content::ExecuteScript(
-      render_view_host(),
-      "document.getElementById('testform').submit();"));
-  // This will ensure the test didn't hang.
-  load_stop_observer.Wait();
-}
-
-// http://crbug.com/150084
-#if defined(OS_MACOSX)
-#define MAYBE_DisableAutocompleteWhileFilling DisableAutocompleteWhileFilling
-#else
-#define MAYBE_DisableAutocompleteWhileFilling \
-    DISABLED_DisableAutocompleteWhileFilling
-#endif
-// Test that Chrome doesn't crash when autocomplete is disabled while the user
-// is interacting with the form.  This is a regression test for
-// http://crbug.com/160476
-IN_PROC_BROWSER_TEST_F(AutofillTest, MAYBE_DisableAutocompleteWhileFilling) {
-  CreateTestProfile();
-
-  // Load the test page.
-  ASSERT_NO_FATAL_FAILURE(ui_test_utils::NavigateToURL(browser(),
-      GURL(std::string(kDataURIPrefix) + kTestFormString)));
-
-  // Invoke Autofill: Start filling the first name field with "M" and wait for
-  // the popup to be shown.
-  FocusFirstNameField();
-  SendKeyToPageAndWait(ui::VKEY_M);
-
-  // Now that the popup with suggestions is showing, disable autocomplete for
-  // the active field.
-  ASSERT_TRUE(content::ExecuteScript(
-      render_view_host(),
-      "document.querySelector('input').autocomplete = 'off';"));
-
-  // Press the down arrow to select the suggestion and attempt to preview the
-  // autofilled form.
-  content::NativeWebKeyboardEvent event;
-  event.windowsKeyCode = ui::VKEY_DOWN;
-  external_delegate()->keyboard_listener()->HandleKeyPressEvent(event);
-
-  // Wait for any IPCs to complete by performing an action that generates an
-  // IPC that's easy to wait for.  Chrome shouldn't crash.
-  bool result = false;
-  ASSERT_TRUE(content::ExecuteScriptAndExtractBool(
-      render_view_host(),
-      "var city = document.getElementById('city');"
-      "city.onfocus = function() { domAutomationController.send(true); };"
-      "city.focus()",
-      &result));
-  ASSERT_TRUE(result);
-  SendKeyToPageAndWait(ui::VKEY_A);
-}
-
 // Test that profiles merge for aggregated data with same address.
 // The criterion for when two profiles are expected to be merged is when their
 // 'Address Line 1' and 'City' data match. When two profiles are merged, any
diff --git a/chrome/browser/autofill/autofill_interactive_uitest.cc b/chrome/browser/autofill/autofill_interactive_uitest.cc
index 8f4f6e6..50e84ae 100644
--- a/chrome/browser/autofill/autofill_interactive_uitest.cc
+++ b/chrome/browser/autofill/autofill_interactive_uitest.cc
@@ -2,16 +2,32 @@
 // 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 <string>
+
+#include "base/basictypes.h"
+#include "base/command_line.h"
+#include "base/file_util.h"
 #include "base/memory/ref_counted.h"
 #include "base/memory/scoped_ptr.h"
+#include "base/rand_util.h"
+#include "base/strings/string16.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/strings/string_split.h"
+#include "base/strings/utf_string_conversions.h"
+#include "base/time/time.h"
 #include "chrome/browser/autofill/personal_data_manager_factory.h"
 #include "chrome/browser/chrome_notification_types.h"
 #include "chrome/browser/infobars/confirm_infobar_delegate.h"
+#include "chrome/browser/infobars/infobar_service.h"
 #include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/translate/translate_infobar_delegate.h"
+#include "chrome/browser/translate/translate_manager.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/common/render_messages.h"
 #include "chrome/test/base/in_process_browser_test.h"
+#include "chrome/test/base/test_switches.h"
 #include "chrome/test/base/ui_test_utils.h"
 #include "components/autofill/content/browser/autofill_driver_impl.h"
 #include "components/autofill/core/browser/autofill_common_test.h"
@@ -21,22 +37,56 @@
 #include "components/autofill/core/browser/autofill_profile.h"
 #include "components/autofill/core/browser/personal_data_manager.h"
 #include "components/autofill/core/browser/personal_data_manager_observer.h"
+#include "components/autofill/core/browser/validation.h"
+#include "content/public/browser/navigation_controller.h"
 #include "content/public/browser/notification_observer.h"
 #include "content/public/browser/notification_registrar.h"
 #include "content/public/browser/notification_service.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 "content/public/test/test_renderer_host.h"
 #include "content/public/test/test_utils.h"
+#include "net/url_request/test_url_fetcher_factory.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
 #include "ui/base/keycodes/keyboard_codes.h"
 
 
-// TODO(csharp): Most of this file was just copied from autofill_browsertests.cc
-// The repeated code should be moved into a helper file, instead of being
-// repeated.
-
 namespace autofill {
 
+static const char* kDataURIPrefix = "data:text/html;charset=utf-8,";
+static const char* kTestFormString =
+    "<form action=\"http://www.example.com/\" method=\"POST\">"
+    "<label for=\"firstname\">First name:</label>"
+    " <input type=\"text\" id=\"firstname\""
+    "        onFocus=\"domAutomationController.send(true)\"><br>"
+    "<label for=\"lastname\">Last name:</label>"
+    " <input type=\"text\" id=\"lastname\"><br>"
+    "<label for=\"address1\">Address line 1:</label>"
+    " <input type=\"text\" id=\"address1\"><br>"
+    "<label for=\"address2\">Address line 2:</label>"
+    " <input type=\"text\" id=\"address2\"><br>"
+    "<label for=\"city\">City:</label>"
+    " <input type=\"text\" id=\"city\"><br>"
+    "<label for=\"state\">State:</label>"
+    " <select id=\"state\">"
+    " <option value=\"\" selected=\"yes\">--</option>"
+    " <option value=\"CA\">California</option>"
+    " <option value=\"TX\">Texas</option>"
+    " </select><br>"
+    "<label for=\"zip\">ZIP code:</label>"
+    " <input type=\"text\" id=\"zip\"><br>"
+    "<label for=\"country\">Country:</label>"
+    " <select id=\"country\">"
+    " <option value=\"\" selected=\"yes\">--</option>"
+    " <option value=\"CA\">Canada</option>"
+    " <option value=\"US\">United States</option>"
+    " </select><br>"
+    "<label for=\"phone\">Phone number:</label>"
+    " <input type=\"text\" id=\"phone\"><br>"
+    "</form>";
+
 
 // AutofillManagerTestDelegateImpl --------------------------------------------
 
@@ -48,17 +98,14 @@
 
   // autofill::AutofillManagerTestDelegate:
   virtual void DidPreviewFormData() OVERRIDE {
-    LOG(INFO) << "DidPreviewFormData";
     loop_runner_->Quit();
   }
 
   virtual void DidFillFormData() OVERRIDE {
-    LOG(INFO) << "DidFillFormData";
     loop_runner_->Quit();
   }
 
   virtual void DidShowSuggestions() OVERRIDE {
-    LOG(INFO) << "DidShowSuggestions";
     loop_runner_->Quit();
   }
 
@@ -67,7 +114,6 @@
   }
 
   void Wait() {
-    LOG(INFO) << "Wait";
     loop_runner_->Run();
   }
 
@@ -251,6 +297,30 @@
     observer.Wait();
   }
 
+  void SetProfiles(std::vector<AutofillProfile>* profiles) {
+    WindowedPersonalDataManagerObserver observer(browser());
+    GetPersonalDataManager()->SetProfiles(profiles);
+    observer.Wait();
+  }
+
+  void SetProfile(const AutofillProfile& profile) {
+    std::vector<AutofillProfile> profiles;
+    profiles.push_back(profile);
+    SetProfiles(&profiles);
+  }
+
+  // Populates a webpage form using autofill data and keypress events.
+  // This function focuses the specified input field in the form, and then
+  // sends keypress events to the tab to cause the form to be populated.
+  void PopulateForm(const std::string& field_id) {
+    std::string js("document.getElementById('" + field_id + "').focus();");
+    ASSERT_TRUE(content::ExecuteScript(GetRenderViewHost(), js));
+
+    SendKeyToPageAndWait(ui::VKEY_DOWN);
+    SendKeyToPopupAndWait(ui::VKEY_DOWN);
+    SendKeyToPopupAndWait(ui::VKEY_RETURN);
+  }
+
   void ExpectFieldValue(const std::string& field_name,
                         const std::string& expected_value) {
     std::string value;
@@ -262,8 +332,47 @@
     EXPECT_EQ(expected_value, value);
   }
 
+  void SimulateURLFetch(bool success) {
+    net::TestURLFetcher* fetcher = url_fetcher_factory_.GetFetcherByID(0);
+    ASSERT_TRUE(fetcher);
+    net::URLRequestStatus status;
+    status.set_status(success ? net::URLRequestStatus::SUCCESS :
+                                net::URLRequestStatus::FAILED);
+
+    std::string script = " var google = {};"
+        "google.translate = (function() {"
+        "  return {"
+        "    TranslateService: function() {"
+        "      return {"
+        "        isAvailable : function() {"
+        "          return true;"
+        "        },"
+        "        restore : function() {"
+        "          return;"
+        "        },"
+        "        getDetectedLanguage : function() {"
+        "          return \"ja\";"
+        "        },"
+        "        translatePage : function(originalLang, targetLang,"
+        "                                 onTranslateProgress) {"
+        "          document.getElementsByTagName(\"body\")[0].innerHTML = '" +
+        std::string(kTestFormString) +
+        "              ';"
+        "          onTranslateProgress(100, true, false);"
+        "        }"
+        "      };"
+        "    }"
+        "  };"
+        "})();";
+
+    fetcher->set_url(fetcher->GetOriginalURL());
+    fetcher->set_status(status);
+    fetcher->set_response_code(success ? 200 : 500);
+    fetcher->SetResponseString(script);
+    fetcher->delegate()->OnURLFetchComplete(fetcher);
+  }
+
   void FocusFirstNameField() {
-    LOG(WARNING) << "Focusing the first name field.";
     bool result = false;
     ASSERT_TRUE(content::ExecuteScriptAndExtractBool(
         GetRenderViewHost(),
@@ -288,8 +397,6 @@
   }
 
   void SendKeyToPageAndWait(ui::KeyboardCode key) {
-    LOG(INFO) << "SendKeyToPageAndWait";
-
     test_delegate_.Reset();
     content::SimulateKeyPress(
         browser()->tab_strip_model()->GetActiveWebContents(),
@@ -307,60 +414,92 @@
     test_delegate_.Wait();
   }
 
+  void TryBasicFormFill() {
+    FocusFirstNameField();
+
+    // Start filling the first name field with "M" and wait for the popup to be
+    // shown.
+    SendKeyToPageAndWait(ui::VKEY_M);
+
+    // Press the down arrow to select the suggestion and preview the autofilled
+    // form.
+    SendKeyToPopupAndWait(ui::VKEY_DOWN);
+
+    // The previewed values should not be accessible to JavaScript.
+    ExpectFieldValue("firstname", "M");
+    ExpectFieldValue("lastname", std::string());
+    ExpectFieldValue("address1", std::string());
+    ExpectFieldValue("address2", std::string());
+    ExpectFieldValue("city", std::string());
+    ExpectFieldValue("state", std::string());
+    ExpectFieldValue("zip", std::string());
+    ExpectFieldValue("country", std::string());
+    ExpectFieldValue("phone", std::string());
+    // TODO(isherman): It would be nice to test that the previewed values are
+    // displayed: http://crbug.com/57220
+
+    // Press Enter to accept the autofill suggestions.
+    SendKeyToPopupAndWait(ui::VKEY_RETURN);
+
+    // The form should be filled.
+    ExpectFilledTestForm();
+  }
+
  private:
   AutofillManagerTestDelegateImpl test_delegate_;
 
+  net::TestURLFetcherFactory url_fetcher_factory_;
+
   DISALLOW_COPY_AND_ASSIGN(AutofillInteractiveTest);
 };
 
-
-// Actual tests ---------------------------------------------------------------
-
-// Potentially flaky, see http://crbug.com/150084
-IN_PROC_BROWSER_TEST_F(AutofillInteractiveTest, DISABLED_AutofillSelectViaTab) {
+// Test that basic form fill is working.
+IN_PROC_BROWSER_TEST_F(AutofillInteractiveTest, BasicFormFill) {
   CreateTestProfile();
 
   // Load the test page.
-  const char kDataURIPrefix[] = "data:text/html;charset=utf-8,";
-  const char kTestFormString[] =
-      "<form action=\"http://www.example.com/\" method=\"POST\">"
-      "<label for=\"firstname\">First name:</label>"
-      " <input type=\"text\" id=\"firstname\""
-      "        onFocus=\"domAutomationController.send(true)\"><br>"
-      "<label for=\"lastname\">Last name:</label>"
-      " <input type=\"text\" id=\"lastname\"><br>"
-      "<label for=\"address1\">Address line 1:</label>"
-      " <input type=\"text\" id=\"address1\"><br>"
-      "<label for=\"address2\">Address line 2:</label>"
-      " <input type=\"text\" id=\"address2\"><br>"
-      "<label for=\"city\">City:</label>"
-      " <input type=\"text\" id=\"city\"><br>"
-      "<label for=\"state\">State:</label>"
-      " <select id=\"state\">"
-      " <option value=\"\" selected=\"yes\">--</option>"
-      " <option value=\"CA\">California</option>"
-      " <option value=\"TX\">Texas</option>"
-      " </select><br>"
-      "<label for=\"zip\">ZIP code:</label>"
-      " <input type=\"text\" id=\"zip\"><br>"
-      "<label for=\"country\">Country:</label>"
-      " <select id=\"country\">"
-      " <option value=\"\" selected=\"yes\">--</option>"
-      " <option value=\"CA\">Canada</option>"
-      " <option value=\"US\">United States</option>"
-      " </select><br>"
-      "<label for=\"phone\">Phone number:</label>"
-      " <input type=\"text\" id=\"phone\"><br>"
-      "</form>";
+  ASSERT_NO_FATAL_FAILURE(ui_test_utils::NavigateToURL(browser(),
+      GURL(std::string(kDataURIPrefix) + kTestFormString)));
+
+  // Invoke Autofill.
+  TryBasicFormFill();
+}
+
+// Test that form filling can be initiated by pressing the down arrow.
+IN_PROC_BROWSER_TEST_F(AutofillInteractiveTest, AutofillViaDownArrow) {
+  CreateTestProfile();
+
+  // Load the test page.
   ASSERT_NO_FATAL_FAILURE(ui_test_utils::NavigateToURL(browser(),
       GURL(std::string(kDataURIPrefix) + kTestFormString)));
 
   // Focus a fillable field.
   FocusFirstNameField();
 
-  // Enable all logging to help track down the flakiness.
-  // TODO(csharp): Remove once this flakiness is fixed.
-  logging::SetMinLogLevel(0);
+  // Press the down arrow to initiate Autofill and wait for the popup to be
+  // shown.
+  SendKeyToPageAndWait(ui::VKEY_DOWN);
+
+  // Press the down arrow to select the suggestion and preview the autofilled
+  // form.
+  SendKeyToPopupAndWait(ui::VKEY_DOWN);
+
+  // Press Enter to accept the autofill suggestions.
+  SendKeyToPopupAndWait(ui::VKEY_RETURN);
+
+  // The form should be filled.
+  ExpectFilledTestForm();
+}
+
+IN_PROC_BROWSER_TEST_F(AutofillInteractiveTest, AutofillSelectViaTab) {
+  CreateTestProfile();
+
+  // Load the test page.
+  ASSERT_NO_FATAL_FAILURE(ui_test_utils::NavigateToURL(browser(),
+      GURL(std::string(kDataURIPrefix) + kTestFormString)));
+
+  // Focus a fillable field.
+  FocusFirstNameField();
 
   // Press the down arrow to initiate Autofill and wait for the popup to be
   // shown.
@@ -377,4 +516,631 @@
   ExpectFilledTestForm();
 }
 
+// Test that a JavaScript onchange event is fired after auto-filling a form.
+IN_PROC_BROWSER_TEST_F(AutofillInteractiveTest, OnChangeAfterAutofill) {
+  CreateTestProfile();
+
+  const char* kOnChangeScript =
+      "<script>"
+      "focused_fired = false;"
+      "unfocused_fired = false;"
+      "changed_select_fired = false;"
+      "unchanged_select_fired = false;"
+      "document.getElementById('firstname').onchange = function() {"
+      "  focused_fired = true;"
+      "};"
+      "document.getElementById('lastname').onchange = function() {"
+      "  unfocused_fired = true;"
+      "};"
+      "document.getElementById('state').onchange = function() {"
+      "  changed_select_fired = true;"
+      "};"
+      "document.getElementById('country').onchange = function() {"
+      "  unchanged_select_fired = true;"
+      "};"
+      "document.getElementById('country').value = 'US';"
+      "</script>";
+
+  // Load the test page.
+  ASSERT_NO_FATAL_FAILURE(ui_test_utils::NavigateToURL(browser(),
+      GURL(std::string(kDataURIPrefix) + kTestFormString + kOnChangeScript)));
+
+  // Invoke Autofill.
+  FocusFirstNameField();
+
+  // Start filling the first name field with "M" and wait for the popup to be
+  // shown.
+  SendKeyToPageAndWait(ui::VKEY_M);
+
+  // Press the down arrow to select the suggestion and preview the autofilled
+  // form.
+  SendKeyToPopupAndWait(ui::VKEY_DOWN);
+
+  // Press Enter to accept the autofill suggestions.
+  SendKeyToPopupAndWait(ui::VKEY_RETURN);
+
+  // The form should be filled.
+  ExpectFilledTestForm();
+
+  // The change event should have already fired for unfocused fields, both of
+  // <input> and of <select> type. However, it should not yet have fired for the
+  // focused field.
+  bool focused_fired = false;
+  bool unfocused_fired = false;
+  bool changed_select_fired = false;
+  bool unchanged_select_fired = false;
+  ASSERT_TRUE(content::ExecuteScriptAndExtractBool(
+      GetRenderViewHost(),
+      "domAutomationController.send(focused_fired);",
+      &focused_fired));
+  ASSERT_TRUE(content::ExecuteScriptAndExtractBool(
+      GetRenderViewHost(),
+      "domAutomationController.send(unfocused_fired);",
+      &unfocused_fired));
+  ASSERT_TRUE(content::ExecuteScriptAndExtractBool(
+      GetRenderViewHost(),
+      "domAutomationController.send(changed_select_fired);",
+      &changed_select_fired));
+  ASSERT_TRUE(content::ExecuteScriptAndExtractBool(
+      GetRenderViewHost(),
+      "domAutomationController.send(unchanged_select_fired);",
+      &unchanged_select_fired));
+  EXPECT_FALSE(focused_fired);
+  EXPECT_TRUE(unfocused_fired);
+  EXPECT_TRUE(changed_select_fired);
+  EXPECT_FALSE(unchanged_select_fired);
+
+  // Unfocus the first name field. Its change event should fire.
+  ASSERT_TRUE(content::ExecuteScriptAndExtractBool(
+      GetRenderViewHost(),
+      "document.getElementById('firstname').blur();"
+      "domAutomationController.send(focused_fired);", &focused_fired));
+  EXPECT_TRUE(focused_fired);
+}
+
+// Test that we can autofill forms distinguished only by their |id| attribute.
+IN_PROC_BROWSER_TEST_F(AutofillInteractiveTest,
+                       AutofillFormsDistinguishedById) {
+  CreateTestProfile();
+
+  // Load the test page.
+  const std::string kURL =
+      std::string(kDataURIPrefix) + kTestFormString +
+      "<script>"
+      "var mainForm = document.forms[0];"
+      "mainForm.id = 'mainForm';"
+      "var newForm = document.createElement('form');"
+      "newForm.action = mainForm.action;"
+      "newForm.method = mainForm.method;"
+      "newForm.id = 'newForm';"
+      "mainForm.parentNode.insertBefore(newForm, mainForm);"
+      "</script>";
+  ASSERT_NO_FATAL_FAILURE(ui_test_utils::NavigateToURL(browser(), GURL(kURL)));
+
+  // Invoke Autofill.
+  TryBasicFormFill();
+}
+
+// Test that we properly autofill forms with repeated fields.
+// In the wild, the repeated fields are typically either email fields
+// (duplicated for "confirmation"); or variants that are hot-swapped via
+// JavaScript, with only one actually visible at any given time.
+IN_PROC_BROWSER_TEST_F(AutofillInteractiveTest, AutofillFormWithRepeatedField) {
+  CreateTestProfile();
+
+  // Load the test page.
+  ASSERT_NO_FATAL_FAILURE(ui_test_utils::NavigateToURL(browser(),
+      GURL(std::string(kDataURIPrefix) +
+           "<form action=\"http://www.example.com/\" method=\"POST\">"
+           "<label for=\"firstname\">First name:</label>"
+           " <input type=\"text\" id=\"firstname\""
+           "        onFocus=\"domAutomationController.send(true)\"><br>"
+           "<label for=\"lastname\">Last name:</label>"
+           " <input type=\"text\" id=\"lastname\"><br>"
+           "<label for=\"address1\">Address line 1:</label>"
+           " <input type=\"text\" id=\"address1\"><br>"
+           "<label for=\"address2\">Address line 2:</label>"
+           " <input type=\"text\" id=\"address2\"><br>"
+           "<label for=\"city\">City:</label>"
+           " <input type=\"text\" id=\"city\"><br>"
+           "<label for=\"state\">State:</label>"
+           " <select id=\"state\">"
+           " <option value=\"\" selected=\"yes\">--</option>"
+           " <option value=\"CA\">California</option>"
+           " <option value=\"TX\">Texas</option>"
+           " </select><br>"
+           "<label for=\"state_freeform\" style=\"display:none\">State:</label>"
+           " <input type=\"text\" id=\"state_freeform\""
+           "        style=\"display:none\"><br>"
+           "<label for=\"zip\">ZIP code:</label>"
+           " <input type=\"text\" id=\"zip\"><br>"
+           "<label for=\"country\">Country:</label>"
+           " <select id=\"country\">"
+           " <option value=\"\" selected=\"yes\">--</option>"
+           " <option value=\"CA\">Canada</option>"
+           " <option value=\"US\">United States</option>"
+           " </select><br>"
+           "<label for=\"phone\">Phone number:</label>"
+           " <input type=\"text\" id=\"phone\"><br>"
+           "</form>")));
+
+  // Invoke Autofill.
+  TryBasicFormFill();
+  ExpectFieldValue("state_freeform", std::string());
+}
+
+// Test that we properly autofill forms with non-autofillable fields.
+IN_PROC_BROWSER_TEST_F(AutofillInteractiveTest,
+                       AutofillFormWithNonAutofillableField) {
+  CreateTestProfile();
+
+  // Load the test page.
+  ASSERT_NO_FATAL_FAILURE(ui_test_utils::NavigateToURL(browser(),
+      GURL(std::string(kDataURIPrefix) +
+           "<form action=\"http://www.example.com/\" method=\"POST\">"
+           "<label for=\"firstname\">First name:</label>"
+           " <input type=\"text\" id=\"firstname\""
+           "        onFocus=\"domAutomationController.send(true)\"><br>"
+           "<label for=\"middlename\">Middle name:</label>"
+           " <input type=\"text\" id=\"middlename\" autocomplete=\"off\" /><br>"
+           "<label for=\"lastname\">Last name:</label>"
+           " <input type=\"text\" id=\"lastname\"><br>"
+           "<label for=\"address1\">Address line 1:</label>"
+           " <input type=\"text\" id=\"address1\"><br>"
+           "<label for=\"address2\">Address line 2:</label>"
+           " <input type=\"text\" id=\"address2\"><br>"
+           "<label for=\"city\">City:</label>"
+           " <input type=\"text\" id=\"city\"><br>"
+           "<label for=\"state\">State:</label>"
+           " <select id=\"state\">"
+           " <option value=\"\" selected=\"yes\">--</option>"
+           " <option value=\"CA\">California</option>"
+           " <option value=\"TX\">Texas</option>"
+           " </select><br>"
+           "<label for=\"zip\">ZIP code:</label>"
+           " <input type=\"text\" id=\"zip\"><br>"
+           "<label for=\"country\">Country:</label>"
+           " <select id=\"country\">"
+           " <option value=\"\" selected=\"yes\">--</option>"
+           " <option value=\"CA\">Canada</option>"
+           " <option value=\"US\">United States</option>"
+           " </select><br>"
+           "<label for=\"phone\">Phone number:</label>"
+           " <input type=\"text\" id=\"phone\"><br>"
+           "</form>")));
+
+  // Invoke Autofill.
+  TryBasicFormFill();
+}
+
+// Test that we can Autofill dynamically generated forms.
+IN_PROC_BROWSER_TEST_F(AutofillInteractiveTest, DynamicFormFill) {
+  CreateTestProfile();
+
+  // Load the test page.
+  ASSERT_NO_FATAL_FAILURE(ui_test_utils::NavigateToURL(browser(),
+      GURL(std::string(kDataURIPrefix) +
+           "<form id=\"form\" action=\"http://www.example.com/\""
+           "      method=\"POST\"></form>"
+           "<script>"
+           "function AddElement(name, label) {"
+           "  var form = document.getElementById('form');"
+           ""
+           "  var label_text = document.createTextNode(label);"
+           "  var label_element = document.createElement('label');"
+           "  label_element.setAttribute('for', name);"
+           "  label_element.appendChild(label_text);"
+           "  form.appendChild(label_element);"
+           ""
+           "  if (name === 'state' || name === 'country') {"
+           "    var select_element = document.createElement('select');"
+           "    select_element.setAttribute('id', name);"
+           "    select_element.setAttribute('name', name);"
+           ""
+           "    /* Add an empty selected option. */"
+           "    var default_option = new Option('--', '', true);"
+           "    select_element.appendChild(default_option);"
+           ""
+           "    /* Add the other options. */"
+           "    if (name == 'state') {"
+           "      var option1 = new Option('California', 'CA');"
+           "      select_element.appendChild(option1);"
+           "      var option2 = new Option('Texas', 'TX');"
+           "      select_element.appendChild(option2);"
+           "    } else {"
+           "      var option1 = new Option('Canada', 'CA');"
+           "      select_element.appendChild(option1);"
+           "      var option2 = new Option('United States', 'US');"
+           "      select_element.appendChild(option2);"
+           "    }"
+           ""
+           "    form.appendChild(select_element);"
+           "  } else {"
+           "    var input_element = document.createElement('input');"
+           "    input_element.setAttribute('id', name);"
+           "    input_element.setAttribute('name', name);"
+           ""
+           "    /* Add the onFocus listener to the 'firstname' field. */"
+           "    if (name === 'firstname') {"
+           "      input_element.setAttribute("
+           "          'onFocus', 'domAutomationController.send(true)');"
+           "    }"
+           ""
+           "    form.appendChild(input_element);"
+           "  }"
+           ""
+           "  form.appendChild(document.createElement('br'));"
+           "};"
+           ""
+           "function BuildForm() {"
+           "  var elements = ["
+           "    ['firstname', 'First name:'],"
+           "    ['lastname', 'Last name:'],"
+           "    ['address1', 'Address line 1:'],"
+           "    ['address2', 'Address line 2:'],"
+           "    ['city', 'City:'],"
+           "    ['state', 'State:'],"
+           "    ['zip', 'ZIP code:'],"
+           "    ['country', 'Country:'],"
+           "    ['phone', 'Phone number:'],"
+           "  ];"
+           ""
+           "  for (var i = 0; i < elements.length; i++) {"
+           "    var name = elements[i][0];"
+           "    var label = elements[i][1];"
+           "    AddElement(name, label);"
+           "  }"
+           "};"
+           "</script>")));
+
+  // Dynamically construct the form.
+  ASSERT_TRUE(content::ExecuteScript(GetRenderViewHost(), "BuildForm();"));
+
+  // Invoke Autofill.
+  TryBasicFormFill();
+}
+
+// Test that form filling works after reloading the current page.
+IN_PROC_BROWSER_TEST_F(AutofillInteractiveTest, AutofillAfterReload) {
+  CreateTestProfile();
+
+  // Load the test page.
+  ASSERT_NO_FATAL_FAILURE(ui_test_utils::NavigateToURL(browser(),
+      GURL(std::string(kDataURIPrefix) + kTestFormString)));
+
+  // Reload the page.
+  content::WebContents* web_contents =
+      browser()->tab_strip_model()->GetActiveWebContents();
+  web_contents->GetController().Reload(false);
+  content::WaitForLoadStop(web_contents);
+
+  // Invoke Autofill.
+  TryBasicFormFill();
+}
+
+// DISABLED: http://crbug.com/150084
+IN_PROC_BROWSER_TEST_F(AutofillInteractiveTest,
+                       DISABLED_AutofillAfterTranslate) {
+  CreateTestProfile();
+
+  GURL url(std::string(kDataURIPrefix) +
+               "<form action=\"http://www.example.com/\" method=\"POST\">"
+               "<label for=\"fn\">なまえ</label>"
+               " <input type=\"text\" id=\"fn\""
+               "        onFocus=\"domAutomationController.send(true)\""
+               "><br>"
+               "<label for=\"ln\">みょうじ</label>"
+               " <input type=\"text\" id=\"ln\"><br>"
+               "<label for=\"a1\">Address line 1:</label>"
+               " <input type=\"text\" id=\"a1\"><br>"
+               "<label for=\"a2\">Address line 2:</label>"
+               " <input type=\"text\" id=\"a2\"><br>"
+               "<label for=\"ci\">City:</label>"
+               " <input type=\"text\" id=\"ci\"><br>"
+               "<label for=\"st\">State:</label>"
+               " <select id=\"st\">"
+               " <option value=\"\" selected=\"yes\">--</option>"
+               " <option value=\"CA\">California</option>"
+               " <option value=\"TX\">Texas</option>"
+               " </select><br>"
+               "<label for=\"z\">ZIP code:</label>"
+               " <input type=\"text\" id=\"z\"><br>"
+               "<label for=\"co\">Country:</label>"
+               " <select id=\"co\">"
+               " <option value=\"\" selected=\"yes\">--</option>"
+               " <option value=\"CA\">Canada</option>"
+               " <option value=\"US\">United States</option>"
+               " </select><br>"
+               "<label for=\"ph\">Phone number:</label>"
+               " <input type=\"text\" id=\"ph\"><br>"
+               "</form>");
+  ASSERT_NO_FATAL_FAILURE(ui_test_utils::NavigateToURL(browser(), url));
+
+  // Get translation bar.
+  LanguageDetectionDetails details;
+  details.adopted_language = "ja";
+  content::RenderViewHostTester::TestOnMessageReceived(
+      GetRenderViewHost(),
+      ChromeViewHostMsg_TranslateLanguageDetermined(0, details, true));
+  TranslateInfoBarDelegate* delegate = InfoBarService::FromWebContents(
+      browser()->tab_strip_model()->GetActiveWebContents())->infobar_at(0)->
+          AsTranslateInfoBarDelegate();
+  ASSERT_TRUE(delegate);
+  EXPECT_EQ(TranslateInfoBarDelegate::BEFORE_TRANSLATE,
+            delegate->infobar_type());
+
+  // Simulate translation button press.
+  delegate->Translate();
+
+  // Simulate the translate script being retrieved.
+  // Pass fake google.translate lib as the translate script.
+  SimulateURLFetch(true);
+
+  content::WindowedNotificationObserver translation_observer(
+      chrome::NOTIFICATION_PAGE_TRANSLATED,
+      content::NotificationService::AllSources());
+
+  // Simulate translation to kick onTranslateElementLoad.
+  // But right now, the call stucks here.
+  // Once click the text field, it starts again.
+  ASSERT_TRUE(content::ExecuteScript(
+      GetRenderViewHost(), "cr.googleTranslate.onTranslateElementLoad();"));
+
+  // Simulate the render notifying the translation has been done.
+  translation_observer.Wait();
+
+  TryBasicFormFill();
+}
+
+// Test phone fields parse correctly from a given profile.
+// The high level key presses execute the following: Select the first text
+// field, invoke the autofill popup list, select the first profile within the
+// list, and commit to the profile to populate the form.
+IN_PROC_BROWSER_TEST_F(AutofillInteractiveTest, ComparePhoneNumbers) {
+  ASSERT_TRUE(test_server()->Start());
+
+  AutofillProfile profile;
+  profile.SetRawInfo(NAME_FIRST, ASCIIToUTF16("Bob"));
+  profile.SetRawInfo(NAME_LAST, ASCIIToUTF16("Smith"));
+  profile.SetRawInfo(ADDRESS_HOME_LINE1, ASCIIToUTF16("1234 H St."));
+  profile.SetRawInfo(ADDRESS_HOME_CITY, ASCIIToUTF16("San Jose"));
+  profile.SetRawInfo(ADDRESS_HOME_STATE, ASCIIToUTF16("CA"));
+  profile.SetRawInfo(ADDRESS_HOME_ZIP, ASCIIToUTF16("95110"));
+  profile.SetRawInfo(PHONE_HOME_WHOLE_NUMBER, ASCIIToUTF16("1-408-555-4567"));
+  SetProfile(profile);
+
+  GURL url = test_server()->GetURL("files/autofill/form_phones.html");
+  ui_test_utils::NavigateToURL(browser(), url);
+  PopulateForm("NAME_FIRST");
+
+  ExpectFieldValue("NAME_FIRST", "Bob");
+  ExpectFieldValue("NAME_LAST", "Smith");
+  ExpectFieldValue("ADDRESS_HOME_LINE1", "1234 H St.");
+  ExpectFieldValue("ADDRESS_HOME_CITY", "San Jose");
+  ExpectFieldValue("ADDRESS_HOME_STATE", "CA");
+  ExpectFieldValue("ADDRESS_HOME_ZIP", "95110");
+  ExpectFieldValue("PHONE_HOME_WHOLE_NUMBER", "14085554567");
+  ExpectFieldValue("PHONE_HOME_CITY_CODE-1", "408");
+  ExpectFieldValue("PHONE_HOME_CITY_CODE-2", "408");
+  ExpectFieldValue("PHONE_HOME_NUMBER", "5554567");
+  ExpectFieldValue("PHONE_HOME_NUMBER_3-1", "555");
+  ExpectFieldValue("PHONE_HOME_NUMBER_3-2", "555");
+  ExpectFieldValue("PHONE_HOME_NUMBER_4-1", "4567");
+  ExpectFieldValue("PHONE_HOME_NUMBER_4-2", "4567");
+  ExpectFieldValue("PHONE_HOME_EXT-1", std::string());
+  ExpectFieldValue("PHONE_HOME_EXT-2", std::string());
+  ExpectFieldValue("PHONE_HOME_COUNTRY_CODE-1", "1");
+}
+
+// Test that Autofill does not fill in read-only fields.
+IN_PROC_BROWSER_TEST_F(AutofillInteractiveTest, NoAutofillForReadOnlyFields) {
+  ASSERT_TRUE(test_server()->Start());
+
+  std::string addr_line1("1234 H St.");
+
+  AutofillProfile profile;
+  profile.SetRawInfo(NAME_FIRST, ASCIIToUTF16("Bob"));
+  profile.SetRawInfo(NAME_LAST, ASCIIToUTF16("Smith"));
+  profile.SetRawInfo(EMAIL_ADDRESS, ASCIIToUTF16("bsmith@gmail.com"));
+  profile.SetRawInfo(ADDRESS_HOME_LINE1, ASCIIToUTF16(addr_line1));
+  profile.SetRawInfo(ADDRESS_HOME_CITY, ASCIIToUTF16("San Jose"));
+  profile.SetRawInfo(ADDRESS_HOME_STATE, ASCIIToUTF16("CA"));
+  profile.SetRawInfo(ADDRESS_HOME_ZIP, ASCIIToUTF16("95110"));
+  profile.SetRawInfo(COMPANY_NAME, ASCIIToUTF16("Company X"));
+  profile.SetRawInfo(PHONE_HOME_WHOLE_NUMBER, ASCIIToUTF16("408-871-4567"));
+  SetProfile(profile);
+
+  GURL url = test_server()->GetURL("files/autofill/read_only_field_test.html");
+  ui_test_utils::NavigateToURL(browser(), url);
+  PopulateForm("firstname");
+
+  ExpectFieldValue("email", std::string());
+  ExpectFieldValue("address", addr_line1);
+}
+
+// Test form is fillable from a profile after form was reset.
+// Steps:
+//   1. Fill form using a saved profile.
+//   2. Reset the form.
+//   3. Fill form using a saved profile.
+// Flakily times out: http://crbug.com/270341
+IN_PROC_BROWSER_TEST_F(AutofillInteractiveTest, DISABLED_FormFillableOnReset) {
+  ASSERT_TRUE(test_server()->Start());
+
+  CreateTestProfile();
+
+  GURL url = test_server()->GetURL("files/autofill/autofill_test_form.html");
+  ui_test_utils::NavigateToURL(browser(), url);
+  PopulateForm("NAME_FIRST");
+
+  ASSERT_TRUE(content::ExecuteScript(
+      browser()->tab_strip_model()->GetActiveWebContents(),
+      "document.getElementById('testform').reset()"));
+
+  PopulateForm("NAME_FIRST");
+
+  ExpectFieldValue("NAME_FIRST", "Milton");
+  ExpectFieldValue("NAME_LAST", "Waddams");
+  ExpectFieldValue("EMAIL_ADDRESS", "red.swingline@initech.com");
+  ExpectFieldValue("ADDRESS_HOME_LINE1", "4120 Freidrich Lane");
+  ExpectFieldValue("ADDRESS_HOME_CITY", "Austin");
+  ExpectFieldValue("ADDRESS_HOME_STATE", "Texas");
+  ExpectFieldValue("ADDRESS_HOME_ZIP", "78744");
+  ExpectFieldValue("ADDRESS_HOME_COUNTRY", "United States");
+  ExpectFieldValue("PHONE_HOME_WHOLE_NUMBER", "5125551234");
+}
+
+// Test Autofill distinguishes a middle initial in a name.
+// Flakily times out: http://crbug.com/270341
+IN_PROC_BROWSER_TEST_F(AutofillInteractiveTest,
+                       DISABLED_DistinguishMiddleInitialWithinName) {
+  ASSERT_TRUE(test_server()->Start());
+
+  CreateTestProfile();
+
+  GURL url = test_server()->GetURL(
+      "files/autofill/autofill_middleinit_form.html");
+  ui_test_utils::NavigateToURL(browser(), url);
+  PopulateForm("NAME_FIRST");
+
+  ExpectFieldValue("NAME_MIDDLE", "C");
+}
+
+// Test forms with multiple email addresses are filled properly.
+// Entire form should be filled with one user gesture.
+// Flakily times out: http://crbug.com/270341
+IN_PROC_BROWSER_TEST_F(AutofillInteractiveTest,
+                       DISABLED_MultipleEmailFilledByOneUserGesture) {
+  ASSERT_TRUE(test_server()->Start());
+
+  std::string email("bsmith@gmail.com");
+
+  AutofillProfile profile;
+  profile.SetRawInfo(NAME_FIRST, ASCIIToUTF16("Bob"));
+  profile.SetRawInfo(NAME_LAST, ASCIIToUTF16("Smith"));
+  profile.SetRawInfo(EMAIL_ADDRESS, ASCIIToUTF16(email));
+  profile.SetRawInfo(PHONE_HOME_WHOLE_NUMBER, ASCIIToUTF16("4088714567"));
+  SetProfile(profile);
+
+  GURL url = test_server()->GetURL(
+      "files/autofill/autofill_confirmemail_form.html");
+  ui_test_utils::NavigateToURL(browser(), url);
+  PopulateForm("NAME_FIRST");
+
+  ExpectFieldValue("EMAIL_CONFIRM", email);
+  // TODO(isherman): verify entire form.
+}
+
+// http://crbug.com/150084
+#if defined(OS_MACOSX)
+#define MAYBE_FormFillLatencyAfterSubmit FormFillLatencyAfterSubmit
+#else
+#define MAYBE_FormFillLatencyAfterSubmit DISABLED_FormFillLatencyAfterSubmit
+#endif
+// Test latency time on form submit with lots of stored Autofill profiles.
+// This test verifies when a profile is selected from the Autofill dictionary
+// that consists of thousands of profiles, the form does not hang after being
+// submitted.
+IN_PROC_BROWSER_TEST_F(AutofillInteractiveTest,
+                       MAYBE_FormFillLatencyAfterSubmit) {
+  ASSERT_TRUE(test_server()->Start());
+
+  std::vector<std::string> cities;
+  cities.push_back("San Jose");
+  cities.push_back("San Francisco");
+  cities.push_back("Sacramento");
+  cities.push_back("Los Angeles");
+
+  std::vector<std::string> streets;
+  streets.push_back("St");
+  streets.push_back("Ave");
+  streets.push_back("Ln");
+  streets.push_back("Ct");
+
+  const int kNumProfiles = 1500;
+  base::Time start_time = base::Time::Now();
+  std::vector<AutofillProfile> profiles;
+  for (int i = 0; i < kNumProfiles; i++) {
+    AutofillProfile profile;
+    string16 name(base::IntToString16(i));
+    string16 email(name + ASCIIToUTF16("@example.com"));
+    string16 street = ASCIIToUTF16(
+        base::IntToString(base::RandInt(0, 10000)) + " " +
+        streets[base::RandInt(0, streets.size() - 1)]);
+    string16 city = ASCIIToUTF16(cities[base::RandInt(0, cities.size() - 1)]);
+    string16 zip(base::IntToString16(base::RandInt(0, 10000)));
+    profile.SetRawInfo(NAME_FIRST, name);
+    profile.SetRawInfo(EMAIL_ADDRESS, email);
+    profile.SetRawInfo(ADDRESS_HOME_LINE1, street);
+    profile.SetRawInfo(ADDRESS_HOME_CITY, city);
+    profile.SetRawInfo(ADDRESS_HOME_STATE, WideToUTF16(L"CA"));
+    profile.SetRawInfo(ADDRESS_HOME_ZIP, zip);
+    profile.SetRawInfo(ADDRESS_HOME_COUNTRY, WideToUTF16(L"US"));
+    profiles.push_back(profile);
+  }
+  SetProfiles(&profiles);
+  // TODO(isherman): once we're sure this test doesn't timeout on any bots, this
+  // can be removd.
+  LOG(INFO) << "Created " << kNumProfiles << " profiles in " <<
+               (base::Time::Now() - start_time).InSeconds() << " seconds.";
+
+  GURL url = test_server()->GetURL(
+      "files/autofill/latency_after_submit_test.html");
+  ui_test_utils::NavigateToURL(browser(), url);
+  PopulateForm("NAME_FIRST");
+
+  content::WindowedNotificationObserver load_stop_observer(
+      content::NOTIFICATION_LOAD_STOP,
+      content::Source<content::NavigationController>(
+          &browser()->tab_strip_model()->GetActiveWebContents()->
+              GetController()));
+
+  ASSERT_TRUE(content::ExecuteScript(
+      GetRenderViewHost(),
+      "document.getElementById('testform').submit();"));
+  // This will ensure the test didn't hang.
+  load_stop_observer.Wait();
+}
+
+// Test that Chrome doesn't crash when autocomplete is disabled while the user
+// is interacting with the form.  This is a regression test for
+// http://crbug.com/160476
+IN_PROC_BROWSER_TEST_F(AutofillInteractiveTest,
+                       DisableAutocompleteWhileFilling) {
+  CreateTestProfile();
+
+  // Load the test page.
+  ASSERT_NO_FATAL_FAILURE(ui_test_utils::NavigateToURL(browser(),
+      GURL(std::string(kDataURIPrefix) + kTestFormString)));
+
+  // Invoke Autofill: Start filling the first name field with "M" and wait for
+  // the popup to be shown.
+  FocusFirstNameField();
+  SendKeyToPageAndWait(ui::VKEY_M);
+
+  // Now that the popup with suggestions is showing, disable autocomplete for
+  // the active field.
+  ASSERT_TRUE(content::ExecuteScript(
+      GetRenderViewHost(),
+      "document.querySelector('input').autocomplete = 'off';"));
+
+  // Press the down arrow to select the suggestion and attempt to preview the
+  // autofilled form.
+  content::NativeWebKeyboardEvent event;
+  event.windowsKeyCode = ui::VKEY_DOWN;
+  GetExternalDelegate()->keyboard_listener()->HandleKeyPressEvent(event);
+
+  // Wait for any IPCs to complete by performing an action that generates an
+  // IPC that's easy to wait for.  Chrome shouldn't crash.
+  bool result = false;
+  ASSERT_TRUE(content::ExecuteScriptAndExtractBool(
+      GetRenderViewHost(),
+      "var city = document.getElementById('city');"
+      "city.onfocus = function() { domAutomationController.send(true); };"
+      "city.focus()",
+      &result));
+  ASSERT_TRUE(result);
+  SendKeyToPageAndWait(ui::VKEY_A);
+}
+
 }  // namespace autofill
diff --git a/chrome/browser/automation/testing_automation_provider.cc b/chrome/browser/automation/testing_automation_provider.cc
index a6a3aa6..6bf6afa 100644
--- a/chrome/browser/automation/testing_automation_provider.cc
+++ b/chrome/browser/automation/testing_automation_provider.cc
@@ -3500,11 +3500,10 @@
     // If the given path has a 'crx' extension, assume it is a packed extension
     // and install it. Otherwise load it as an unpacked extension.
     if (extension_path.MatchesExtension(FILE_PATH_LITERAL(".crx"))) {
-      ExtensionInstallPrompt* client = (with_ui ?
-          new ExtensionInstallPrompt(tab) :
-          NULL);
+      scoped_ptr<ExtensionInstallPrompt> client(
+          with_ui ? new ExtensionInstallPrompt(tab) : NULL);
       scoped_refptr<extensions::CrxInstaller> installer(
-          extensions::CrxInstaller::Create(service, client));
+          extensions::CrxInstaller::Create(service, client.Pass()));
       if (!with_ui)
         installer->set_allow_silent_install(true);
       installer->set_install_cause(extension_misc::INSTALL_CAUSE_AUTOMATION);
diff --git a/chrome/browser/bookmarks/bookmark_model_test_utils.cc b/chrome/browser/bookmarks/bookmark_model_test_utils.cc
index f04a6b5..485872e 100644
--- a/chrome/browser/bookmarks/bookmark_model_test_utils.cc
+++ b/chrome/browser/bookmarks/bookmark_model_test_utils.cc
@@ -115,7 +115,6 @@
     const BookmarkNode* node,
     const std::string& model_string) {
   DCHECK(node);
-  const std::string folder_tell(":[");
   std::string::size_type start_pos = 0;
   std::string::size_type end_pos =
       AddNodesFromString(model, node, model_string, start_pos);
diff --git a/chrome/browser/browser_process_impl.cc b/chrome/browser/browser_process_impl.cc
index 82aa66b..1f9c3fd 100644
--- a/chrome/browser/browser_process_impl.cc
+++ b/chrome/browser/browser_process_impl.cc
@@ -70,10 +70,8 @@
 #include "chrome/common/chrome_constants.h"
 #include "chrome/common/chrome_paths.h"
 #include "chrome/common/chrome_switches.h"
-#include "chrome/common/extensions/chrome_manifest_handlers.h"
+#include "chrome/common/extensions/chrome_extensions_client.h"
 #include "chrome/common/extensions/extension_l10n_util.h"
-#include "chrome/common/extensions/permissions/chrome_api_permissions.h"
-#include "chrome/common/extensions/permissions/permissions_info.h"
 #include "chrome/common/pref_names.h"
 #include "chrome/common/switch_utils.h"
 #include "chrome/common/url_constants.h"
@@ -184,9 +182,8 @@
   InitIdleMonitor();
 #endif
 
-  extensions::PermissionsInfo::GetInstance()->InitializeWithDelegate(
-      extensions::ChromeAPIPermissions());
-  extensions::RegisterChromeManifestHandlers();
+  extensions::ExtensionsClient::Set(
+      extensions::ChromeExtensionsClient::GetInstance());
   extension_event_router_forwarder_ = new extensions::EventRouterForwarder;
   ExtensionRendererState::GetInstance()->Init();
 
diff --git a/chrome/browser/browser_resources.grd b/chrome/browser/browser_resources.grd
index d6e5804..6d6a0b9 100644
--- a/chrome/browser/browser_resources.grd
+++ b/chrome/browser/browser_resources.grd
@@ -318,6 +318,8 @@
         <include name="IDR_SIM_UNLOCK_HTML" file="resources\chromeos\sim_unlock.html" flattenhtml="true" type="BINDATA" />
         <include name="IDR_WRENCH_MENU_CSS" file="resources\chromeos\wrench_menu.css" flattenhtml="true" type="BINDATA" />
         <include name="IDR_WRENCH_MENU_JS" file="resources\chromeos\wrench_menu.js" flattenhtml="true" type="BINDATA" />
+        <include name="IDR_SLOW_HTML" file="resources\chromeos\slow.html" flattenhtml="true" type="BINDATA" />
+        <include name="IDR_SLOW_JS" file="resources\chromeos\slow.js" type="BINDATA" />
       </if>
       <if expr="pp_ifdef('file_manager_extension')">
         <include name="IDR_FILEMANAGER_MANIFEST" file="resources\file_manager\manifest.json" type="BINDATA" />
@@ -355,8 +357,8 @@
         <include name="IDR_SET_AS_DEFAULT_BROWSER_HTML" file="resources\set_as_default_browser.html" flattenhtml="true" allowexternalscript="true" type="BINDATA" />
       </if>
       <if expr="not is_android and not pp_ifdef('ios') and not pp_ifdef('chromeos')">
-        <include name="IDR_USER_CHOOSER_JS" file="resources\user_chooser\user_chooser.js" flattenhtml="true" type="BINDATA" />
-        <include name="IDR_USER_CHOOSER_HTML" file="resources\user_chooser\user_chooser.html" flattenhtml="true" allowexternalscript="true" type="BINDATA" />
+        <include name="IDR_USER_MANAGER_JS" file="resources\user_manager\user_manager.js" flattenhtml="true" type="BINDATA" />
+        <include name="IDR_USER_MANAGER_HTML" file="resources\user_manager\user_manager.html" flattenhtml="true" allowexternalscript="true" type="BINDATA" />
       </if>
       <include name="IDR_MANAGED_MODE_BLOCK_INTERSTITIAL_HTML" file="resources\managed_mode_block_interstitial.html" flattenhtml="true" type="BINDATA" />
       <include name="IDR_PROFILE_SIGNIN_CONFIRMATION_HTML" file="resources\profile_signin_confirmation.html" type="BINDATA" />
diff --git a/chrome/browser/browsing_data/browsing_data_helper_unittest.cc b/chrome/browser/browsing_data/browsing_data_helper_unittest.cc
index 2186b44..5fe25ce 100644
--- a/chrome/browser/browsing_data/browsing_data_helper_unittest.cc
+++ b/chrome/browser/browsing_data/browsing_data_helper_unittest.cc
@@ -75,8 +75,8 @@
   EXPECT_FALSE(IsWebScheme(chrome::kChromeInternalScheme));
   EXPECT_FALSE(IsWebScheme(chrome::kChromeUIScheme));
   EXPECT_FALSE(IsWebScheme(chrome::kJavaScriptScheme));
-  EXPECT_FALSE(IsWebScheme(chrome::kMailToScheme));
-  EXPECT_FALSE(IsWebScheme(chrome::kMetadataScheme));
+  EXPECT_FALSE(IsWebScheme(content::kMailToScheme));
+  EXPECT_FALSE(IsWebScheme(content::kMetadataScheme));
   EXPECT_FALSE(IsWebScheme(content::kSwappedOutScheme));
   EXPECT_FALSE(IsWebScheme(content::kViewSourceScheme));
 }
@@ -100,8 +100,8 @@
   EXPECT_FALSE(IsExtensionScheme(chrome::kChromeInternalScheme));
   EXPECT_FALSE(IsExtensionScheme(chrome::kChromeUIScheme));
   EXPECT_FALSE(IsExtensionScheme(chrome::kJavaScriptScheme));
-  EXPECT_FALSE(IsExtensionScheme(chrome::kMailToScheme));
-  EXPECT_FALSE(IsExtensionScheme(chrome::kMetadataScheme));
+  EXPECT_FALSE(IsExtensionScheme(content::kMailToScheme));
+  EXPECT_FALSE(IsExtensionScheme(content::kMetadataScheme));
   EXPECT_FALSE(IsExtensionScheme(content::kSwappedOutScheme));
   EXPECT_FALSE(IsExtensionScheme(content::kViewSourceScheme));
 }
diff --git a/chrome/browser/browsing_data/browsing_data_remover.cc b/chrome/browser/browsing_data/browsing_data_remover.cc
index 008d5cf..0512a67 100644
--- a/chrome/browser/browsing_data/browsing_data_remover.cc
+++ b/chrome/browser/browsing_data/browsing_data_remover.cc
@@ -25,6 +25,7 @@
 #include "chrome/browser/history/history_service_factory.h"
 #include "chrome/browser/io_thread.h"
 #include "chrome/browser/nacl_host/nacl_browser.h"
+#include "chrome/browser/nacl_host/pnacl_host.h"
 #include "chrome/browser/net/chrome_url_request_context.h"
 #include "chrome/browser/net/predictor.h"
 #include "chrome/browser/password_manager/password_store.h"
@@ -169,10 +170,12 @@
       waiting_for_clear_network_predictor_(false),
       waiting_for_clear_networking_history_(false),
       waiting_for_clear_plugin_data_(false),
+      waiting_for_clear_pnacl_cache_(false),
       waiting_for_clear_quota_managed_data_(false),
       waiting_for_clear_server_bound_certs_(false),
       waiting_for_clear_session_storage_(false),
       waiting_for_clear_shader_cache_(false),
+      waiting_for_clear_webrtc_identity_store_(false),
       remove_mask_(0),
       remove_origin_(GURL()),
       origin_set_mask_(0) {
@@ -529,6 +532,12 @@
         BrowserThread::IO, FROM_HERE,
         base::Bind(&BrowsingDataRemover::ClearNaClCacheOnIOThread,
                    base::Unretained(this)));
+
+    waiting_for_clear_pnacl_cache_ = true;
+    BrowserThread::PostTask(
+        BrowserThread::IO, FROM_HERE,
+        base::Bind(&BrowsingDataRemover::ClearPnaclCacheOnIOThread,
+                   base::Unretained(this), delete_begin_, delete_end_));
 #endif
 
     // The PrerenderManager may have a page actively being prerendered, which
@@ -545,6 +554,15 @@
     content::RecordAction(UserMetricsAction("ClearBrowsingData_ShaderCache"));
 
     ClearShaderCacheOnUIThread();
+
+    waiting_for_clear_webrtc_identity_store_ = true;
+    BrowserContext::GetDefaultStoragePartition(profile_)->ClearDataForRange(
+        content::StoragePartition::REMOVE_DATA_MASK_WEBRTC_IDENTITY,
+        content::StoragePartition::QUOTA_MANAGED_STORAGE_MASK_ALL,
+        delete_begin_,
+        delete_end_,
+        base::Bind(&BrowsingDataRemover::OnClearWebRTCIdentityStore,
+                   base::Unretained(this)));
   }
 
 #if defined(ENABLE_PLUGINS)
@@ -617,24 +635,22 @@
 }
 
 bool BrowsingDataRemover::AllDone() {
-  return registrar_.IsEmpty() &&
-      !waiting_for_clear_autofill_origin_urls_ &&
-      !waiting_for_clear_cache_ &&
-      !waiting_for_clear_nacl_cache_ &&
-      !waiting_for_clear_cookies_count_&&
-      !waiting_for_clear_history_ &&
-      !waiting_for_clear_local_storage_ &&
-      !waiting_for_clear_logged_in_predictor_ &&
-      !waiting_for_clear_session_storage_ &&
-      !waiting_for_clear_networking_history_ &&
-      !waiting_for_clear_server_bound_certs_ &&
-      !waiting_for_clear_plugin_data_ &&
-      !waiting_for_clear_quota_managed_data_ &&
-      !waiting_for_clear_content_licenses_ &&
-      !waiting_for_clear_form_ &&
-      !waiting_for_clear_hostname_resolution_cache_ &&
-      !waiting_for_clear_network_predictor_ &&
-      !waiting_for_clear_shader_cache_;
+  return registrar_.IsEmpty() && !waiting_for_clear_autofill_origin_urls_ &&
+         !waiting_for_clear_cache_ && !waiting_for_clear_nacl_cache_ &&
+         !waiting_for_clear_cookies_count_ && !waiting_for_clear_history_ &&
+         !waiting_for_clear_local_storage_ &&
+         !waiting_for_clear_logged_in_predictor_ &&
+         !waiting_for_clear_session_storage_ &&
+         !waiting_for_clear_networking_history_ &&
+         !waiting_for_clear_server_bound_certs_ &&
+         !waiting_for_clear_plugin_data_ &&
+         !waiting_for_clear_pnacl_cache_ &&
+         !waiting_for_clear_quota_managed_data_ &&
+         !waiting_for_clear_content_licenses_ && !waiting_for_clear_form_ &&
+         !waiting_for_clear_hostname_resolution_cache_ &&
+         !waiting_for_clear_network_predictor_ &&
+         !waiting_for_clear_shader_cache_ &&
+         !waiting_for_clear_webrtc_identity_store_;
 }
 
 void BrowsingDataRemover::Observe(int type,
@@ -886,6 +902,36 @@
       base::Bind(&BrowsingDataRemover::ClearedNaClCacheOnIOThread,
                  base::Unretained(this)));
 }
+
+void BrowsingDataRemover::ClearedPnaclCache() {
+  // This function should be called on the UI thread.
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+
+  waiting_for_clear_pnacl_cache_ = false;
+
+  NotifyAndDeleteIfDone();
+}
+
+void BrowsingDataRemover::ClearedPnaclCacheOnIOThread() {
+  // This function should be called on the IO thread.
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+
+  // Notify the UI thread that we are done.
+  BrowserThread::PostTask(
+      BrowserThread::UI, FROM_HERE,
+      base::Bind(&BrowsingDataRemover::ClearedPnaclCache,
+                 base::Unretained(this)));
+}
+
+void BrowsingDataRemover::ClearPnaclCacheOnIOThread(base::Time begin,
+                                                    base::Time end) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+
+  PnaclHost::GetInstance()->ClearTranslationCacheEntriesBetween(
+      begin, end,
+      base::Bind(&BrowsingDataRemover::ClearedPnaclCacheOnIOThread,
+                 base::Unretained(this)));
+}
 #endif
 
 void BrowsingDataRemover::ClearLocalStorageOnUIThread() {
@@ -1123,3 +1169,9 @@
   waiting_for_clear_autofill_origin_urls_ = false;
   NotifyAndDeleteIfDone();
 }
+
+void BrowsingDataRemover::OnClearWebRTCIdentityStore() {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  waiting_for_clear_webrtc_identity_store_ = false;
+  NotifyAndDeleteIfDone();
+}
diff --git a/chrome/browser/browsing_data/browsing_data_remover.h b/chrome/browser/browsing_data/browsing_data_remover.h
index af1b441..be29059 100644
--- a/chrome/browser/browsing_data/browsing_data_remover.h
+++ b/chrome/browser/browsing_data/browsing_data_remover.h
@@ -288,6 +288,16 @@
 
   // Invoked on the IO thread to delete the NaCl cache.
   void ClearNaClCacheOnIOThread();
+
+  // Callback for when the PNaCl translation cache has been deleted. Invokes
+  // NotifyAndDeleteIfDone.
+  void ClearedPnaclCache();
+
+  // Invokes ClearedPnaclCacheOn on the UI thread.
+  void ClearedPnaclCacheOnIOThread();
+
+  // Invoked on the IO thread to delete entries in the PNaCl translation cache.
+  void ClearPnaclCacheOnIOThread(base::Time begin, base::Time end);
 #endif
 
   // Invoked on the UI thread to delete local storage.
@@ -361,6 +371,9 @@
   // Invoked on the IO thread to delete from the shader cache.
   void ClearShaderCacheOnUIThread();
 
+  // Callback on UI thread when the WebRTC identities are cleared.
+  void OnClearWebRTCIdentityStore();
+
   // Returns true if we're all done.
   bool AllDone();
 
@@ -421,10 +434,12 @@
   bool waiting_for_clear_network_predictor_;
   bool waiting_for_clear_networking_history_;
   bool waiting_for_clear_plugin_data_;
+  bool waiting_for_clear_pnacl_cache_;
   bool waiting_for_clear_quota_managed_data_;
   bool waiting_for_clear_server_bound_certs_;
   bool waiting_for_clear_session_storage_;
   bool waiting_for_clear_shader_cache_;
+  bool waiting_for_clear_webrtc_identity_store_;
 
   // Tracking how many origins need to be deleted, and whether we're finished
   // gathering origins.
diff --git a/chrome/browser/chrome_browser_main.cc b/chrome/browser/chrome_browser_main.cc
index bc285f0..26155b1 100644
--- a/chrome/browser/chrome_browser_main.cc
+++ b/chrome/browser/chrome_browser_main.cc
@@ -91,7 +91,6 @@
 #include "chrome/browser/profiles/profile_manager.h"
 #include "chrome/browser/profiles/profiles_state.h"
 #include "chrome/browser/renderer_host/chrome_render_view_host_observer.h"
-#include "chrome/browser/search_engines/search_engine_type.h"
 #include "chrome/browser/service/service_process_control.h"
 #include "chrome/browser/shell_integration.h"
 #include "chrome/browser/three_d_api_observer.h"
@@ -689,17 +688,17 @@
 
   bool is_first_run = first_run::IsChromeFirstRun();
 
-// CurrentProcessInfo::CreationTime() is currently only implemented on Mac and
-// Windows.
-#if defined(OS_MACOSX) || defined(OS_WIN)
-  const base::Time* process_creation_time =
+// CurrentProcessInfo::CreationTime() is currently only implemented on some
+// platforms.
+#if defined(OS_MACOSX) || defined(OS_WIN) || defined(OS_LINUX)
+  const base::Time process_creation_time =
       base::CurrentProcessInfo::CreationTime();
 
-  if (!is_first_run && process_creation_time) {
+  if (!is_first_run && !process_creation_time.is_null()) {
     RecordPreReadExperimentTime("Startup.BrowserMessageLoopStartTime",
-        base::Time::Now() - *process_creation_time);
+        base::Time::Now() - process_creation_time);
   }
-#endif  // defined(OS_MACOSX) || defined(OS_WIN)
+#endif  // defined(OS_MACOSX) || defined(OS_WIN) || defined(OS_LINUX)
 
   // Record collected startup metrics.
   startup_metric_utils::OnBrowserStartupComplete(is_first_run);
diff --git a/chrome/browser/chrome_browser_main_linux.cc b/chrome/browser/chrome_browser_main_linux.cc
index 299154d..2e6ad60 100644
--- a/chrome/browser/chrome_browser_main_linux.cc
+++ b/chrome/browser/chrome_browser_main_linux.cc
@@ -23,6 +23,7 @@
 #include "chromeos/chromeos_switches.h"
 #else
 #include "chrome/browser/storage_monitor/storage_monitor_linux.h"
+#include "chrome/browser/sxs_linux.h"
 #include "content/public/browser/browser_thread.h"
 #endif
 
@@ -113,6 +114,11 @@
   content::BrowserThread::PostTask(content::BrowserThread::FILE,
                                    FROM_HERE,
                                    base::Bind(&GetLinuxDistroCallback));
+
+  content::BrowserThread::PostTask(
+      content::BrowserThread::FILE,
+      FROM_HERE,
+      base::Bind(&sxs_linux::AddChannelMarkToUserDataDir));
 #endif
 
   if (IsCrashReportingEnabled(local_state()))
diff --git a/chrome/browser/chrome_browser_main_mac.mm b/chrome/browser/chrome_browser_main_mac.mm
index 3d41c65..07f250c 100644
--- a/chrome/browser/chrome_browser_main_mac.mm
+++ b/chrome/browser/chrome_browser_main_mac.mm
@@ -229,7 +229,7 @@
   [[KeystoneGlue defaultKeystoneGlue] registerWithKeystone];
 
   // Disk image installation is sort of a first-run task, so it shares the
-  // kNoFirstRun switch.
+  // no first run switches.
   //
   // This needs to be done after the resource bundle is initialized (for
   // access to localizations in the UI) and after Keystone is initialized
@@ -240,7 +240,7 @@
   // anyone tries doing anything silly like firing off an import job, and
   // before anything creating preferences like Local State in order for the
   // relaunched installed application to still consider itself as first-run.
-  if (!parsed_command_line().HasSwitch(switches::kNoFirstRun)) {
+  if (!first_run::IsFirstRunSuppressed(parsed_command_line())) {
     if (MaybeInstallFromDiskImage()) {
       // The application was installed and the installed copy has been
       // launched.  This process is now obsolete.  Exit.
diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/chrome_content_browser_client.cc
index 22947f0..4700b5a 100644
--- a/chrome/browser/chrome_content_browser_client.cc
+++ b/chrome/browser/chrome_content_browser_client.cc
@@ -140,7 +140,6 @@
 #include "ui/message_center/message_center_util.h"
 #include "webkit/browser/fileapi/external_mount_points.h"
 #include "webkit/common/webpreferences.h"
-#include "webkit/plugins/plugin_switches.h"
 
 #if defined(OS_WIN)
 #include "chrome/browser/chrome_browser_main_win.h"
diff --git a/chrome/browser/chrome_notification_types.h b/chrome/browser/chrome_notification_types.h
index a4b5adc..f6ecc44 100644
--- a/chrome/browser/chrome_notification_types.h
+++ b/chrome/browser/chrome_notification_types.h
@@ -150,17 +150,6 @@
   // starting and finishing all painting.
   NOTIFICATION_INITIAL_NEW_TAB_UI_LOAD,
 
-#if defined(OS_ANDROID)
-  // Indicates that the new tab page is ready.  This is different than
-  // NOTIFICATION_INITIAL_NEW_TAB_UI_LOAD as the NTP might do some more in-page
-  // navigations after it's done loading, potentially causing flakyness in tests
-  // that would navigate as soon as the NTP is done loading.
-  // When this notification happen, it guarantees the page is not going to do
-  // any further navigation.
-  // The source is the WebContents containing the NTP.
-  NOTIFICATION_NEW_TAB_READY,
-#endif
-
   // Used to fire notifications about how long various events took to
   // complete.  E.g., this is used to get more fine grained timings from the
   // new tab page.  The source is a WebContents and the details is a
@@ -204,14 +193,6 @@
   // match was found or not found.
   NOTIFICATION_FIND_RESULT_AVAILABLE,
 
-#if defined(OS_ANDROID)
-  // This notification is sent when the match rects of a find-in-page search
-  // are available. The source is a Source<WebContents>. Details encompass a
-  // FindMatchRectsDetails object that contains the result version and the
-  // rects information.
-  NOTIFICATION_FIND_MATCH_RECTS_AVAILABLE,
-#endif
-
   // BackgroundContents ------------------------------------------------------
 
   // A new background contents was opened by script. The source is the parent
@@ -355,9 +336,6 @@
 
   // Task Manager ------------------------------------------------------------
 
-  // Sent when WebUI TaskManager opens and is ready for showing tasks.
-  NOTIFICATION_TASK_MANAGER_WINDOW_READY,
-
   // The TaskManagerChildProcessResourceProvider collects the list of child
   // processes when StartUpdating is called. This data is collected on the IO
   // thread and passed back to the UI thread. Once all entries are added to the
@@ -493,9 +471,6 @@
   // UpdatedExtensionPermissionsInfo, and the source is a Profile.
   NOTIFICATION_EXTENSION_PERMISSIONS_UPDATED,
 
-  // Sent when an extension install turns out to not be a theme.
-  NOTIFICATION_NO_THEME_DETECTED,
-
   // Sent when new extensions are installed, or existing extensions are updated.
   // The details are an InstalledExtensionInfo, and the source is a Profile.
   NOTIFICATION_EXTENSION_INSTALLED,
@@ -657,31 +632,6 @@
   // found update.
   NOTIFICATION_EXTENSION_UPDATE_FOUND,
 
-  // Component Updater -------------------------------------------------------
-  //
-  // The component updater notifications are deprecated and they will be
-  // removed soon.
-  //
-  // Sent when the component updater starts doing update checks. If no
-  // component has been registered for update this notification is not
-  // generated. The source is the component updater itself and there are
-  // no details.
-  NOTIFICATION_COMPONENT_UPDATER_STARTED,
-
-  // Sent when the component updater is going to take a long nap. The
-  // source is the component updater itself and there are no details.
-  NOTIFICATION_COMPONENT_UPDATER_SLEEPING,
-
-  // Sent when there is a new version of a registered component. After
-  // the notification is send the component will be downloaded. The source
-  // is the id of the component and there are no details.
-  NOTIFICATION_COMPONENT_UPDATE_FOUND,
-
-  // Send when the new component has been downloaded and an installation
-  // or upgrade is about to be attempted. The source is the id of the
-  // component and there are no details.
-  NOTIFICATION_COMPONENT_UPDATE_READY,
-
   // Desktop Notifications ---------------------------------------------------
 
   // This notification is sent when a balloon is connected to a renderer
@@ -923,39 +873,19 @@
   // notification.
   NOTIFICATION_LOGIN_WEBUI_LOADED,
 
-  // Sent when the login screen has loaded in retail mode. The first paint event
-  // after this fires NOTIFICATION_LOGIN_OR_LOCK_WEBUI_VISIBLE.
-  NOTIFICATION_DEMO_WEBUI_LOADED,
-
-  // Sent when the user images on the WebUI login screen have all been loaded.
-  // "Normal boot" i.e. for the device with at least one user would generate
-  // this one on boot. First paint event after this fires
-  // NOTIFICATION_LOGIN_OR_LOCK_WEBUI_VISIBLE.
-  NOTIFICATION_LOGIN_USER_IMAGES_LOADED,
-
   // Sent when a network error message is displayed on the WebUI login screen.
   // First paint event of this fires NOTIFICATION_LOGIN_OR_LOCK_WEBUI_VISIBLE.
   NOTIFICATION_LOGIN_NETWORK_ERROR_SHOWN,
 
-  // Sent when the first OOBE screen has been displayed. Note that the screen
-  // may not be fully rendered at this point. First paint event after this fires
-  // NOTIFICATION_LOGIN_OR_LOCK_WEBUI_VISIBLE.
-  NOTIFICATION_WIZARD_FIRST_SCREEN_SHOWN,
-
   // Sent when the specific part of login/lock WebUI is considered to be
   // visible. That moment is tracked as the first paint event after one of the:
-  // 1. NOTIFICATION_LOGIN_USER_IMAGES_LOADED
-  // 2. NOTIFICATION_LOGIN_WEBUI_LOADED
-  // 3. NOTIFICATION_LOGIN_NETWORK_ERROR_SHOWN
-  // 4. NOTIFICATION_WIZARD_FIRST_SCREEN_SHOWN
-  // 5. NOTIFICATION_DEMO_WEBUI_LOADED
+  // 1. NOTIFICATION_LOGIN_WEBUI_LOADED
+  // 2. NOTIFICATION_LOGIN_NETWORK_ERROR_SHOWN
   //
   // Possible series of notifications:
   // 1. Boot into fresh OOBE
-  //    NOTIFICATION_WIZARD_FIRST_SCREEN_SHOWN
   //    NOTIFICATION_LOGIN_OR_LOCK_WEBUI_VISIBLE
   // 2. Boot into user pods list (normal boot). Same for lock screen.
-  //    NOTIFICATION_LOGIN_USER_IMAGES_LOADED
   //    NOTIFICATION_LOGIN_OR_LOCK_WEBUI_VISIBLE
   // 3. Boot into GAIA sign in UI (user pods display disabled or no users):
   //    if no network is connected or flaky network
@@ -964,7 +894,6 @@
   //    NOTIFICATION_LOGIN_WEBUI_LOADED
   //    NOTIFICATION_LOGIN_OR_LOCK_WEBUI_VISIBLE
   // 4. Boot into retail mode
-  //    NOTIFICATION_DEMO_WEBUI_LOADED
   //    NOTIFICATION_LOGIN_OR_LOCK_WEBUI_VISIBLE
   // 5. Boot into kiosk mode
   //    NOTIFICATION_KIOSK_APP_LAUNCHED
@@ -1055,9 +984,6 @@
   // menu has been created and shown.
   NOTIFICATION_RENDER_VIEW_CONTEXT_MENU_SHOWN,
 
-  // Send when a context menu is closed.
-  NOTIFICATION_RENDER_VIEW_CONTEXT_MENU_CLOSED,
-
   // Sent when the Instant Controller determines whether an Instant tab supports
   // the Instant API or not.
   NOTIFICATION_INSTANT_TAB_SUPPORT_DETERMINED,
@@ -1111,9 +1037,6 @@
   NOTIFICATION_ASH_SESSION_ENDED,
 #endif
 
-  // Sent when a new web store promo has been loaded.
-  NOTIFICATION_WEB_STORE_PROMO_LOADED,
-
   // Protocol Handler Registry -----------------------------------------------
   // Sent when a ProtocolHandlerRegistry is changed. The source is the profile.
   NOTIFICATION_PROTOCOL_HANDLER_REGISTRY_CHANGED,
diff --git a/chrome/browser/chrome_plugin_browsertest.cc b/chrome/browser/chrome_plugin_browsertest.cc
index 5386e42..e9f3be6 100644
--- a/chrome/browser/chrome_plugin_browsertest.cc
+++ b/chrome/browser/chrome_plugin_browsertest.cc
@@ -21,13 +21,13 @@
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/child_process_data.h"
 #include "content/public/browser/plugin_service.h"
+#include "content/public/common/content_constants.h"
 #include "content/public/common/content_paths.h"
 #include "content/public/common/process_type.h"
 #include "content/public/common/webplugininfo.h"
 #include "content/public/test/browser_test_utils.h"
 #include "content/public/test/test_utils.h"
 #include "net/base/net_util.h"
-#include "webkit/plugins/plugin_constants.h"
 
 using content::BrowserThread;
 
@@ -109,7 +109,7 @@
     std::vector<content::WebPluginInfo> plugins = GetPlugins();
     for (std::vector<content::WebPluginInfo>::const_iterator it =
              plugins.begin(); it != plugins.end(); ++it) {
-      if (it->name == ASCIIToUTF16(kFlashPluginName))
+      if (it->name == ASCIIToUTF16(content::kFlashPluginName))
         paths->push_back(it->path);
     }
   }
diff --git a/chrome/browser/chrome_process_finder_win.cc b/chrome/browser/chrome_process_finder_win.cc
index e1d66ee..da0f7ae 100644
--- a/chrome/browser/chrome_process_finder_win.cc
+++ b/chrome/browser/chrome_process_finder_win.cc
@@ -149,7 +149,7 @@
   command_line.AppendSwitchASCII(
       switches::kOriginalProcessStartTime,
       base::Int64ToString(
-          base::CurrentProcessInfo::CreationTime()->ToInternalValue()));
+          base::CurrentProcessInfo::CreationTime().ToInternalValue()));
 
   if (fast_start)
     command_line.AppendSwitch(switches::kFastStart);
diff --git a/chrome/browser/chromeos/app_mode/app_session_lifetime.cc b/chrome/browser/chromeos/app_mode/app_session_lifetime.cc
index 48514f0..e140e88 100644
--- a/chrome/browser/chromeos/app_mode/app_session_lifetime.cc
+++ b/chrome/browser/chromeos/app_mode/app_session_lifetime.cc
@@ -4,17 +4,17 @@
 
 #include "chrome/browser/chromeos/app_mode/app_session_lifetime.h"
 
+#include "apps/shell_window_registry.h"
 #include "base/basictypes.h"
 #include "base/lazy_instance.h"
 #include "base/prefs/pref_service.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/chromeos/app_mode/kiosk_app_update_service.h"
-#include "chrome/browser/extensions/shell_window_registry.h"
 #include "chrome/browser/lifetime/application_lifetime.h"
 #include "chrome/browser/policy/browser_policy_connector.h"
 #include "chrome/common/pref_names.h"
 
-using extensions::ShellWindowRegistry;
+using apps::ShellWindowRegistry;
 
 namespace chromeos {
 
@@ -35,7 +35,7 @@
   }
 
  private:
-  // extensions::ShellWindowRegistry::Observer overrides:
+  // apps::ShellWindowRegistry::Observer overrides:
   virtual void OnShellWindowAdded(apps::ShellWindow* shell_window) OVERRIDE {}
   virtual void OnShellWindowIconChanged(apps::ShellWindow* shell_window)
     OVERRIDE {}
@@ -46,7 +46,7 @@
     }
   }
 
-  extensions::ShellWindowRegistry* window_registry_;
+  apps::ShellWindowRegistry* window_registry_;
 
   DISALLOW_COPY_AND_ASSIGN(AppWindowWatcher);
 };
diff --git a/chrome/browser/chromeos/background/ash_user_wallpaper_delegate.cc b/chrome/browser/chromeos/background/ash_user_wallpaper_delegate.cc
index 16709fb..f931995 100644
--- a/chrome/browser/chromeos/background/ash_user_wallpaper_delegate.cc
+++ b/chrome/browser/chromeos/background/ash_user_wallpaper_delegate.cc
@@ -28,7 +28,8 @@
 
 bool IsNormalWallpaperChange() {
   if (chromeos::LoginState::Get()->IsUserLoggedIn() ||
-      !CommandLine::ForCurrentProcess()->HasSwitch(switches::kFirstBoot) ||
+      !CommandLine::ForCurrentProcess()->HasSwitch(
+          switches::kFirstExecAfterBoot) ||
       WizardController::IsZeroDelayEnabled() ||
       !CommandLine::ForCurrentProcess()->HasSwitch(switches::kLoginManager)) {
     return true;
diff --git a/chrome/browser/chromeos/chrome_browser_main_chromeos.cc b/chrome/browser/chromeos/chrome_browser_main_chromeos.cc
index e87caf6..d6a251e 100644
--- a/chrome/browser/chromeos/chrome_browser_main_chromeos.cc
+++ b/chrome/browser/chromeos/chrome_browser_main_chromeos.cc
@@ -32,6 +32,7 @@
 #include "chrome/browser/chromeos/boot_times_loader.h"
 #include "chrome/browser/chromeos/contacts/contact_manager.h"
 #include "chrome/browser/chromeos/cros/cert_library.h"
+#include "chrome/browser/chromeos/cros/network_library.h"
 #include "chrome/browser/chromeos/dbus/cros_dbus_service.h"
 #include "chrome/browser/chromeos/display/display_configuration_observer.h"
 #include "chrome/browser/chromeos/extensions/default_app_order.h"
@@ -51,9 +52,6 @@
 #include "chrome/browser/chromeos/login/wallpaper_manager.h"
 #include "chrome/browser/chromeos/login/wizard_controller.h"
 #include "chrome/browser/chromeos/memory/oom_priority_manager.h"
-#include "chrome/browser/chromeos/net/connectivity_state_helper.h"
-#include "chrome/browser/chromeos/net/cros_network_change_notifier_factory.h"
-#include "chrome/browser/chromeos/net/network_change_notifier_network_library.h"
 #include "chrome/browser/chromeos/net/network_portal_detector.h"
 #include "chrome/browser/chromeos/power/brightness_observer.h"
 #include "chrome/browser/chromeos/power/idle_action_warning_observer.h"
@@ -303,12 +301,7 @@
     // Initialize the network change notifier for Chrome OS. The network
     // change notifier starts to monitor changes from the power manager and
     // the network manager.
-    if (!CommandLine::ForCurrentProcess()->HasSwitch(
-            chromeos::switches::kDisableNewNetworkChangeNotifier)) {
-      NetworkChangeNotifierFactoryChromeos::GetInstance()->Initialize();
-    } else {
-      CrosNetworkChangeNotifierFactory::GetInstance()->Init();
-    }
+    NetworkChangeNotifierFactoryChromeos::GetInstance()->Initialize();
 
     // Likewise, initialize the upgrade detector for Chrome OS. The upgrade
     // detector starts to monitor changes from the update engine.
@@ -327,12 +320,9 @@
     DeviceSettingsService::Get()->SetSessionManager(
         DBusThreadManager::Get()->GetSessionManagerClient(),
         OwnerKeyUtil::Create());
-    ConnectivityStateHelper::Initialize();
   }
 
   ~DBusServices() {
-    ConnectivityStateHelper::Shutdown();
-
     CertLibrary::Shutdown();
     NetworkHandler::Shutdown();
     if (network_library_initialized_)
@@ -418,18 +408,8 @@
   // Replace the default NetworkChangeNotifierFactory with ChromeOS specific
   // implementation. This must be done before BrowserMainLoop calls
   // net::NetworkChangeNotifier::Create() in MainMessageLoopStart().
-  net::NetworkChangeNotifierFactory* network_change_factory;
-  // Note: At the time this is called, we have not processed about:flags
-  // so this requires that the network handler flag was passed in at the command
-  // line.
-  if (!CommandLine::ForCurrentProcess()->HasSwitch(
-          chromeos::switches::kDisableNewNetworkChangeNotifier)) {
-    LOG(WARNING) << "Using new connection change notifier.";
-    network_change_factory = new NetworkChangeNotifierFactoryChromeos();
-  } else {
-    network_change_factory = new CrosNetworkChangeNotifierFactory();
-  }
-  net::NetworkChangeNotifier::SetFactory(network_change_factory);
+  net::NetworkChangeNotifier::SetFactory(
+      new NetworkChangeNotifierFactoryChromeos());
   ChromeBrowserMainPartsLinux::PreMainMessageLoopStart();
 }
 
@@ -740,8 +720,6 @@
   // Shutdown the network change notifier for Chrome OS. The network
   // change notifier stops monitoring changes from the power manager and
   // the network manager.
-  if (CrosNetworkChangeNotifierFactory::GetInstance())
-    CrosNetworkChangeNotifierFactory::GetInstance()->Shutdown();
   if (NetworkChangeNotifierFactoryChromeos::GetInstance())
     NetworkChangeNotifierFactoryChromeos::GetInstance()->Shutdown();
 
diff --git a/chrome/browser/chromeos/cros/network_library.cc b/chrome/browser/chromeos/cros/network_library.cc
index c84eaaa..9943d9e 100644
--- a/chrome/browser/chromeos/cros/network_library.cc
+++ b/chrome/browser/chromeos/cros/network_library.cc
@@ -15,6 +15,7 @@
 #include "chrome/browser/chromeos/cros/native_network_parser.h"
 #include "chrome/browser/chromeos/cros/network_library_impl_cros.h"
 #include "chrome/browser/chromeos/cros/network_library_impl_stub.h"
+#include "chrome/browser/chromeos/enrollment_dialog_view.h"
 #include "chrome/common/net/x509_certificate_model.h"
 #include "chromeos/network/certificate_pattern.h"
 #include "chromeos/network/certificate_pattern_matcher.h"
@@ -331,6 +332,10 @@
 void Network::CopyCredentialsFromRemembered(Network* remembered) {
 }
 
+void Network::SetEnrollmentDelegate(EnrollmentDelegate* delegate) {
+  enrollment_delegate_.reset(delegate);
+}
+
 void Network::SetValueProperty(const char* prop, const base::Value& value) {
   DCHECK(prop);
   if (!EnsureRunningOnChromeOS())
@@ -419,11 +424,6 @@
 
 void Network::set_connecting() {
   state_ = STATE_CONNECT_REQUESTED;
-  // Set the connecting network in NetworkStateHandler for the status area UI.
-  if (NetworkHandler::IsInitialized()) {
-    NetworkHandler::Get()->network_state_handler()->
-        SetConnectingNetwork(service_path());
-  }
 }
 
 void Network::SetProfilePath(const std::string& profile_path) {
diff --git a/chrome/browser/chromeos/cros/network_library.h b/chrome/browser/chromeos/cros/network_library.h
index ba7a6d3..e4ebbb0 100644
--- a/chrome/browser/chromeos/cros/network_library.h
+++ b/chrome/browser/chromeos/cros/network_library.h
@@ -27,9 +27,10 @@
 
 namespace chromeos {
 
+class CertificatePattern;
+class EnrollmentDelegate;
 class NetworkDeviceParser;
 class NetworkParser;
-class CertificatePattern;
 
 // This is the list of all implementation classes that are allowed
 // access to the internals of the network library classes.
@@ -296,25 +297,6 @@
   DISALLOW_COPY_AND_ASSIGN(NetworkDevice);
 };
 
-// A virtual class that can be used to handle certificate enrollment URIs when
-// encountered.  Also used by unit tests to avoid opening browser windows
-// when testing.
-class EnrollmentDelegate {
- public:
-  EnrollmentDelegate() {}
-  virtual ~EnrollmentDelegate() {}
-
-  // Implemented to handle a given certificate enrollment URI.  Returns false
-  // if the enrollment URI doesn't use a scheme that we can handle, and in
-  // that case, this will be called for any remaining enrollment URIs.
-  // If enrollment succeeds, then the enrollment handler must run
-  // |post_action| to finish connecting.
-  virtual void Enroll(const std::vector<std::string>& uri_list,
-                      const base::Closure& post_action) = 0;
- private:
-  DISALLOW_COPY_AND_ASSIGN(EnrollmentDelegate);
-};
-
 // Contains data common to all network service types.
 class Network {
  public:
@@ -436,9 +418,7 @@
 
   // Adopts the given enrollment handler to handle any certificate enrollment
   // URIs encountered during network connection.
-  void SetEnrollmentDelegate(EnrollmentDelegate* delegate) {
-    enrollment_delegate_.reset(delegate);
-  }
+  void SetEnrollmentDelegate(EnrollmentDelegate* delegate);
 
   virtual bool UpdateStatus(const std::string& key,
                             const base::Value& value,
diff --git a/chrome/browser/chromeos/cros/network_library_unittest.cc b/chrome/browser/chromeos/cros/network_library_unittest.cc
index 06223fc..41ff24c 100644
--- a/chrome/browser/chromeos/cros/network_library_unittest.cc
+++ b/chrome/browser/chromeos/cros/network_library_unittest.cc
@@ -16,6 +16,7 @@
 #include "base/path_service.h"
 #include "chrome/browser/chromeos/cros/network_library.h"
 #include "chrome/browser/chromeos/cros/network_library_impl_stub.h"
+#include "chrome/browser/chromeos/enrollment_dialog_view.h"
 #include "chrome/browser/chromeos/login/mock_user_manager.h"
 #include "chrome/browser/chromeos/login/user_manager.h"
 #include "chrome/browser/google_apis/test_util.h"
@@ -43,7 +44,7 @@
       : did_enroll(false),
         correct_args(false) {}
 
-  virtual void Enroll(const std::vector<std::string>& uri_list,
+  virtual bool Enroll(const std::vector<std::string>& uri_list,
                       const base::Closure& closure) OVERRIDE {
     std::vector<std::string> expected_uri_list;
     expected_uri_list.push_back("http://youtu.be/dQw4w9WgXcQ");
@@ -53,6 +54,7 @@
 
     did_enroll = true;
     closure.Run();
+    return true;
   }
 
   bool did_enroll;
diff --git a/chrome/browser/chromeos/display/display_preferences.cc b/chrome/browser/chromeos/display/display_preferences.cc
index 168404c..14c18ff 100644
--- a/chrome/browser/chromeos/display/display_preferences.cc
+++ b/chrome/browser/chromeos/display/display_preferences.cc
@@ -8,6 +8,7 @@
 #include "ash/display/display_layout_store.h"
 #include "ash/display/display_manager.h"
 #include "ash/display/display_pref_util.h"
+#include "ash/display/resolution_notification_controller.h"
 #include "ash/shell.h"
 #include "base/prefs/pref_registry_simple.h"
 #include "base/prefs/pref_service.h"
@@ -258,8 +259,12 @@
 }
 
 void StoreDisplayPrefs() {
-  if (!IsValidUser())
+  // Do not store prefs when the confirmation dialog is shown.
+  if (!IsValidUser() ||
+      ash::Shell::GetInstance()->resolution_notification_controller()->
+          DoesNotificationTimeout()) {
     return;
+  }
   StoreCurrentDisplayLayoutPrefs();
   StoreCurrentDisplayProperties();
   StoreCurrentDisplayPowerState();
diff --git a/chrome/browser/chromeos/display/display_preferences_unittest.cc b/chrome/browser/chromeos/display/display_preferences_unittest.cc
index a319c5b..8299957 100644
--- a/chrome/browser/chromeos/display/display_preferences_unittest.cc
+++ b/chrome/browser/chromeos/display/display_preferences_unittest.cc
@@ -7,6 +7,7 @@
 #include "ash/display/display_controller.h"
 #include "ash/display/display_layout_store.h"
 #include "ash/display/display_manager.h"
+#include "ash/display/resolution_notification_controller.h"
 #include "ash/screen_ash.h"
 #include "ash/shell.h"
 #include "ash/test/ash_test_base.h"
@@ -20,6 +21,9 @@
 #include "chrome/common/pref_names.h"
 #include "chrome/test/base/testing_browser_process.h"
 #include "chromeos/display/output_configurator.h"
+#include "ui/message_center/message_center.h"
+
+using ash::internal::ResolutionNotificationController;
 
 namespace chromeos {
 namespace {
@@ -40,6 +44,7 @@
   virtual void SetUp() OVERRIDE {
     EXPECT_CALL(*mock_user_manager_, IsUserLoggedIn())
         .WillRepeatedly(testing::Return(false));
+    EXPECT_CALL(*mock_user_manager_, Shutdown());
     ash::test::AshTestBase::SetUp();
     RegisterDisplayLocalStatePrefs(local_state_.registry());
     TestingBrowserProcess::GetGlobal()->SetLocalState(&local_state_);
@@ -146,6 +151,8 @@
   DISALLOW_COPY_AND_ASSIGN(DisplayPreferencesTest);
 };
 
+}  // namespace
+
 TEST_F(DisplayPreferencesTest, PairedLayoutOverrides) {
   UpdateDisplay("100x100,200x200");
   int64 id1 = gfx::Screen::GetNativeScreen()->GetPrimaryDisplay().id();
@@ -352,6 +359,47 @@
   EXPECT_EQ(400, height);
 }
 
+TEST_F(DisplayPreferencesTest, PreventStore) {
+  ResolutionNotificationController::SuppressTimerForTest();
+  LoggedInAsUser();
+  UpdateDisplay("400x300");
+  int64 id = ash::Shell::GetScreen()->GetPrimaryDisplay().id();
+  // Set display's resolution in single display. It creates the notification and
+  // display preferences should not stored meanwhile.
+  ash::Shell::GetInstance()->resolution_notification_controller()->
+      SetDisplayResolutionAndNotify(
+          id, gfx::Size(400, 300), gfx::Size(500, 400), base::Closure());
+  UpdateDisplay("500x400");
+
+  const base::DictionaryValue* properties =
+      local_state()->GetDictionary(prefs::kDisplayProperties);
+  const base::DictionaryValue* property = NULL;
+  EXPECT_TRUE(properties->GetDictionary(base::Int64ToString(id), &property));
+  int width = 0, height = 0;
+  EXPECT_FALSE(property->GetInteger("width", &width));
+  EXPECT_FALSE(property->GetInteger("height", &height));
+
+  // Revert the change. When timeout, 2nd button is revert.
+  message_center::MessageCenter::Get()->ClickOnNotificationButton(
+      ResolutionNotificationController::kNotificationId, 1);
+  RunAllPendingInMessageLoop();
+  EXPECT_FALSE(message_center::MessageCenter::Get()->HasNotification(
+      ResolutionNotificationController::kNotificationId));
+
+  // Once the notification is removed, the specified resolution will be stored
+  // by SetDisplayResolution.
+  ash::Shell::GetInstance()->display_manager()->SetDisplayResolution(
+      id, gfx::Size(300, 200));
+  UpdateDisplay("300x200");
+
+  property = NULL;
+  EXPECT_TRUE(properties->GetDictionary(base::Int64ToString(id), &property));
+  EXPECT_TRUE(property->GetInteger("width", &width));
+  EXPECT_TRUE(property->GetInteger("height", &height));
+  EXPECT_EQ(300, width);
+  EXPECT_EQ(200, height);
+}
+
 TEST_F(DisplayPreferencesTest, StoreForSwappedDisplay) {
   UpdateDisplay("100x100,200x200");
   int64 id1 = gfx::Screen::GetNativeScreen()->GetPrimaryDisplay().id();
@@ -445,5 +493,4 @@
       ash::Shell::GetInstance()->output_configurator()->power_state());
 }
 
-}  // namespace
 }  // namespace chromeos
diff --git a/chrome/browser/chromeos/drive/dummy_file_system.h b/chrome/browser/chromeos/drive/dummy_file_system.h
index 191be66..c0fe931 100644
--- a/chrome/browser/chromeos/drive/dummy_file_system.h
+++ b/chrome/browser/chromeos/drive/dummy_file_system.h
@@ -58,6 +58,9 @@
                      const FileOperationCallback& callback) OVERRIDE {}
   virtual void GetFileByPath(const base::FilePath& file_path,
                              const GetFileCallback& callback) OVERRIDE {}
+  virtual void GetFileByPathForSaving(
+      const base::FilePath& file_path,
+      const GetFileCallback& callback) OVERRIDE {}
   virtual void GetFileContentByPath(
       const base::FilePath& file_path,
       const GetFileContentInitializedCallback& initialized_callback,
diff --git a/chrome/browser/chromeos/drive/fake_file_system.cc b/chrome/browser/chromeos/drive/fake_file_system.cc
index 4b6f6e4..6211872 100644
--- a/chrome/browser/chromeos/drive/fake_file_system.cc
+++ b/chrome/browser/chromeos/drive/fake_file_system.cc
@@ -134,6 +134,11 @@
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
 }
 
+void FakeFileSystem::GetFileByPathForSaving(const base::FilePath& file_path,
+                                            const GetFileCallback& callback) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+}
+
 void FakeFileSystem::GetFileContentByPath(
     const base::FilePath& file_path,
     const GetFileContentInitializedCallback& initialized_callback,
diff --git a/chrome/browser/chromeos/drive/fake_file_system.h b/chrome/browser/chromeos/drive/fake_file_system.h
index da005db..6b20d34 100644
--- a/chrome/browser/chromeos/drive/fake_file_system.h
+++ b/chrome/browser/chromeos/drive/fake_file_system.h
@@ -91,6 +91,8 @@
                      const FileOperationCallback& callback) OVERRIDE;
   virtual void GetFileByPath(const base::FilePath& file_path,
                              const GetFileCallback& callback) OVERRIDE;
+  virtual void GetFileByPathForSaving(const base::FilePath& file_path,
+                                      const GetFileCallback& callback) OVERRIDE;
   virtual void GetFileContentByPath(
       const base::FilePath& file_path,
       const GetFileContentInitializedCallback& initialized_callback,
diff --git a/chrome/browser/chromeos/drive/file_errors.cc b/chrome/browser/chromeos/drive/file_errors.cc
index 05d76f9..3778eae 100644
--- a/chrome/browser/chromeos/drive/file_errors.cc
+++ b/chrome/browser/chromeos/drive/file_errors.cc
@@ -63,6 +63,9 @@
 
     case FILE_ERROR_NO_LOCAL_SPACE:
       return "FILE_ERROR_NO_LOCAL_SPACE";
+
+    case FILE_ERROR_SERVICE_UNAVAILABLE:
+      return "FILE_ERROR_SERVICE_UNAVAILABLE";
   }
 
   NOTREACHED();
@@ -124,6 +127,9 @@
 
     case FILE_ERROR_NO_LOCAL_SPACE:
       return base::PLATFORM_FILE_ERROR_FAILED;
+
+    case FILE_ERROR_SERVICE_UNAVAILABLE:
+      return base::PLATFORM_FILE_ERROR_FAILED;
   }
 
   NOTREACHED();
@@ -141,6 +147,9 @@
       return FILE_ERROR_ACCESS_DENIED;
     case google_apis::HTTP_NOT_FOUND:
       return FILE_ERROR_NOT_FOUND;
+    case google_apis::HTTP_INTERNAL_SERVER_ERROR:
+    case google_apis::HTTP_SERVICE_UNAVAILABLE:
+      return FILE_ERROR_SERVICE_UNAVAILABLE;
     case google_apis::HTTP_NOT_IMPLEMENTED:
       return FILE_ERROR_INVALID_OPERATION;
     case google_apis::GDATA_CANCELLED:
diff --git a/chrome/browser/chromeos/drive/file_errors.h b/chrome/browser/chromeos/drive/file_errors.h
index 08cf5a1..4b7bc67 100644
--- a/chrome/browser/chromeos/drive/file_errors.h
+++ b/chrome/browser/chromeos/drive/file_errors.h
@@ -30,6 +30,7 @@
   FILE_ERROR_INVALID_URL = -15,
   FILE_ERROR_NO_CONNECTION = -16,
   FILE_ERROR_NO_LOCAL_SPACE = -17,
+  FILE_ERROR_SERVICE_UNAVAILABLE = -18,
 };
 
 // Used as callbacks for file operations.
diff --git a/chrome/browser/chromeos/drive/file_system.cc b/chrome/browser/chromeos/drive/file_system.cc
index 6b89008..b6f4e93 100644
--- a/chrome/browser/chromeos/drive/file_system.cc
+++ b/chrome/browser/chromeos/drive/file_system.cc
@@ -20,6 +20,7 @@
 #include "chrome/browser/chromeos/drive/file_system/create_directory_operation.h"
 #include "chrome/browser/chromeos/drive/file_system/create_file_operation.h"
 #include "chrome/browser/chromeos/drive/file_system/download_operation.h"
+#include "chrome/browser/chromeos/drive/file_system/get_file_for_saving_operation.h"
 #include "chrome/browser/chromeos/drive/file_system/move_operation.h"
 #include "chrome/browser/chromeos/drive/file_system/open_file_operation.h"
 #include "chrome/browser/chromeos/drive/file_system/remove_operation.h"
@@ -208,13 +209,20 @@
                                        cache_));
   search_operation_.reset(new file_system::SearchOperation(
       blocking_task_runner_.get(), scheduler_, resource_metadata_));
+  get_file_for_saving_operation_.reset(
+      new file_system::GetFileForSavingOperation(blocking_task_runner_.get(),
+                                                 observer,
+                                                 scheduler_,
+                                                 resource_metadata_,
+                                                 cache_,
+                                                 temporary_file_directory_));
+
   sync_client_.reset(new internal::SyncClient(blocking_task_runner_.get(),
                                               observer,
                                               scheduler_,
                                               resource_metadata_,
                                               cache_,
                                               temporary_file_directory_));
-
   hide_hosted_docs_ =
       pref_service_->GetBoolean(prefs::kDisableDriveHostedFiles);
 
@@ -491,6 +499,14 @@
       callback);
 }
 
+void FileSystem::GetFileByPathForSaving(const base::FilePath& file_path,
+                                        const GetFileCallback& callback) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK(!callback.is_null());
+
+  get_file_for_saving_operation_->GetFileForSaving(file_path, callback);
+}
+
 void FileSystem::GetFileContentByPath(
     const base::FilePath& file_path,
     const GetFileContentInitializedCallback& initialized_callback,
diff --git a/chrome/browser/chromeos/drive/file_system.h b/chrome/browser/chromeos/drive/file_system.h
index 5bb1ca8..dacc522 100644
--- a/chrome/browser/chromeos/drive/file_system.h
+++ b/chrome/browser/chromeos/drive/file_system.h
@@ -46,6 +46,7 @@
 class CreateDirectoryOperation;
 class CreateFileOperation;
 class DownloadOperation;
+class GetFileForSavingOperation;
 class MoveOperation;
 class OpenFileOperation;
 class OperationObserver;
@@ -122,6 +123,8 @@
                      const FileOperationCallback& callback) OVERRIDE;
   virtual void GetFileByPath(const base::FilePath& file_path,
                              const GetFileCallback& callback) OVERRIDE;
+  virtual void GetFileByPathForSaving(const base::FilePath& file_path,
+                                      const GetFileCallback& callback) OVERRIDE;
   virtual void GetFileContentByPath(
       const base::FilePath& file_path,
       const GetFileContentInitializedCallback& initialized_callback,
@@ -319,6 +322,8 @@
   scoped_ptr<file_system::DownloadOperation> download_operation_;
   scoped_ptr<file_system::UpdateOperation> update_operation_;
   scoped_ptr<file_system::SearchOperation> search_operation_;
+  scoped_ptr<file_system::GetFileForSavingOperation>
+      get_file_for_saving_operation_;
 
   // 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/file_system/copy_operation.cc b/chrome/browser/chromeos/drive/file_system/copy_operation.cc
index b0d007c..a38adb5 100644
--- a/chrome/browser/chromeos/drive/file_system/copy_operation.cc
+++ b/chrome/browser/chromeos/drive/file_system/copy_operation.cc
@@ -49,6 +49,23 @@
   return cache->MarkDirty(resource_id);
 }
 
+// Gets the file size of the |local_path|, and the ResourceEntry for the parent
+// of |remote_path| to prepare the necessary information for transfer.
+FileError PrepareTransferFileFromLocalToRemote(
+    internal::ResourceMetadata* metadata,
+    const base::FilePath& local_path,
+    const base::FilePath& remote_path,
+    int64* local_file_size,
+    ResourceEntry* parent_entry) {
+  DCHECK(metadata);
+  DCHECK(local_file_size);
+  DCHECK(parent_entry);
+
+  if (!file_util::GetFileSize(local_path, local_file_size))
+      return FILE_ERROR_NOT_FOUND;
+  return metadata->GetResourceEntryByPath(remote_path.DirName(), parent_entry);
+}
+
 }  // namespace
 
 CopyOperation::CopyOperation(base::SequencedTaskRunner* blocking_task_runner,
@@ -149,15 +166,25 @@
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
   DCHECK(!callback.is_null());
 
-  // Make sure the destination directory exists.
-  metadata_->GetResourceEntryByPathOnUIThread(
-      remote_dest_file_path.DirName(),
+  int64* local_file_size = new int64(-1);
+  ResourceEntry* parent_entry = new ResourceEntry;
+  base::PostTaskAndReplyWithResult(
+      blocking_task_runner_.get(),
+      FROM_HERE,
+      base::Bind(&PrepareTransferFileFromLocalToRemote,
+                 metadata_,
+                 local_src_file_path,
+                 remote_dest_file_path,
+                 local_file_size,
+                 parent_entry),
       base::Bind(
-          &CopyOperation::TransferFileFromLocalToRemoteAfterGetResourceEntry,
+          &CopyOperation::TransferFileFromLocalToRemoteAfterPrepare,
           weak_ptr_factory_.GetWeakPtr(),
           local_src_file_path,
           remote_dest_file_path,
-          callback));
+          callback,
+          base::Owned(local_file_size),
+          base::Owned(parent_entry)));
 }
 
 void CopyOperation::ScheduleTransferRegularFile(
@@ -287,8 +314,6 @@
     const base::FilePath& file_path) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
   DCHECK(!callback.is_null());
-  DCHECK_EQ(util::GetDriveMyDriveRootPath().value(),
-            file_path.DirName().value());
 
   // Return if there is an error or |dir_path| is the root directory.
   if (error != FILE_ERROR_OK ||
@@ -297,6 +322,9 @@
     return;
   }
 
+  DCHECK_EQ(util::GetDriveMyDriveRootPath().value(),
+            file_path.DirName().value()) << file_path.value();
+
   move_operation_->Move(file_path,
                         directory_path.Append(file_path.BaseName()),
                         callback);
@@ -424,22 +452,24 @@
   ScheduleTransferRegularFile(local_file_path, remote_dest_file_path, callback);
 }
 
-void CopyOperation::TransferFileFromLocalToRemoteAfterGetResourceEntry(
+void CopyOperation::TransferFileFromLocalToRemoteAfterPrepare(
     const base::FilePath& local_src_file_path,
     const base::FilePath& remote_dest_file_path,
     const FileOperationCallback& callback,
-    FileError error,
-    scoped_ptr<ResourceEntry> entry) {
+    int64* local_file_size,
+    ResourceEntry* parent_entry,
+    FileError error) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
   DCHECK(!callback.is_null());
+  DCHECK(parent_entry);
+  DCHECK(local_file_size);
 
   if (error != FILE_ERROR_OK) {
     callback.Run(error);
     return;
   }
 
-  DCHECK(entry.get());
-  if (!entry->file_info().is_directory()) {
+  if (!parent_entry->file_info().is_directory()) {
     // The parent of |remote_dest_file_path| is not a directory.
     callback.Run(FILE_ERROR_NOT_A_DIRECTORY);
     return;
@@ -456,11 +486,45 @@
                    remote_dest_file_path,
                    callback));
   } else {
-    ScheduleTransferRegularFile(local_src_file_path, remote_dest_file_path,
-                                callback);
+    // For regular files, check the server-side quota whether sufficient space
+    // is available for the file to be uploaded.
+    scheduler_->GetAboutResource(
+        base::Bind(&CopyOperation::TransferFileFromLocalToRemoteAfterGetQuota,
+                   weak_ptr_factory_.GetWeakPtr(),
+                   local_src_file_path,
+                   remote_dest_file_path,
+                   callback,
+                   *local_file_size));
   }
 }
 
+void CopyOperation::TransferFileFromLocalToRemoteAfterGetQuota(
+    const base::FilePath& local_src_file_path,
+    const base::FilePath& remote_dest_file_path,
+    const FileOperationCallback& callback,
+    int64 local_file_size,
+    google_apis::GDataErrorCode status,
+    scoped_ptr<google_apis::AboutResource> about_resource) {
+  DCHECK(!callback.is_null());
+
+  FileError error = GDataToFileError(status);
+  if (error != FILE_ERROR_OK) {
+    callback.Run(error);
+    return;
+  }
+
+  DCHECK(about_resource);
+  const int64 space =
+      about_resource->quota_bytes_total() - about_resource->quota_bytes_used();
+  if (space < local_file_size) {
+    callback.Run(FILE_ERROR_NO_SERVER_SPACE);
+    return;
+  }
+
+  ScheduleTransferRegularFile(local_src_file_path, remote_dest_file_path,
+                              callback);
+}
+
 void CopyOperation::TransferFileForResourceId(
     const base::FilePath& local_file_path,
     const base::FilePath& remote_dest_file_path,
diff --git a/chrome/browser/chromeos/drive/file_system/copy_operation.h b/chrome/browser/chromeos/drive/file_system/copy_operation.h
index 9ba481d..41be0cf 100644
--- a/chrome/browser/chromeos/drive/file_system/copy_operation.h
+++ b/chrome/browser/chromeos/drive/file_system/copy_operation.h
@@ -10,6 +10,7 @@
 #include "base/memory/scoped_ptr.h"
 #include "base/memory/weak_ptr.h"
 #include "chrome/browser/chromeos/drive/resource_metadata.h"
+#include "chrome/browser/google_apis/drive_api_parser.h"
 #include "chrome/browser/google_apis/gdata_errorcode.h"
 
 namespace base {
@@ -154,14 +155,25 @@
                                 const base::FilePath& local_file_path,
                                 scoped_ptr<ResourceEntry> entry);
 
-  // Part of TransferFileFromLocalToRemote(). Called after
-  // GetResourceEntryByPath() is complete.
-  void TransferFileFromLocalToRemoteAfterGetResourceEntry(
+  // Part of TransferFileFromLocalToRemote(). Called after |parent_entry| and
+  // |local_file_size| are retrieved in the blocking pool.
+  void TransferFileFromLocalToRemoteAfterPrepare(
       const base::FilePath& local_src_file_path,
       const base::FilePath& remote_dest_file_path,
       const FileOperationCallback& callback,
-      FileError error,
-      scoped_ptr<ResourceEntry> entry);
+      int64* local_file_size,
+      ResourceEntry* parent_entry,
+      FileError error);
+
+  // Part of TransferFileFromLocalToRemote(). Called after the result of
+  // GetAboutResource() is avaiable.
+  void TransferFileFromLocalToRemoteAfterGetQuota(
+      const base::FilePath& local_src_file_path,
+      const base::FilePath& remote_dest_file_path,
+      const FileOperationCallback& callback,
+      int64 local_file_size,
+      google_apis::GDataErrorCode status,
+      scoped_ptr<google_apis::AboutResource> about_resource);
 
   // Initiates transfer of |local_file_path| with |resource_id| to
   // |remote_dest_file_path|. |local_file_path| must be a file from the local
diff --git a/chrome/browser/chromeos/drive/file_system/copy_operation_unittest.cc b/chrome/browser/chromeos/drive/file_system/copy_operation_unittest.cc
index 3451b3a..433c57d 100644
--- a/chrome/browser/chromeos/drive/file_system/copy_operation_unittest.cc
+++ b/chrome/browser/chromeos/drive/file_system/copy_operation_unittest.cc
@@ -72,6 +72,43 @@
       remote_dest_path.DirName()));
 }
 
+TEST_F(CopyOperationTest, TransferFileFromLocalToRemote_QuotaCheck) {
+  const base::FilePath local_src_path = temp_dir().AppendASCII("local.txt");
+  const base::FilePath remote_dest_path(
+      FILE_PATH_LITERAL("drive/root/remote.txt"));
+
+  const size_t kFileSize = 10;
+
+  // Prepare a local file.
+  ASSERT_TRUE(
+      google_apis::test_util::WriteStringToFile(local_src_path,
+                                                std::string(kFileSize, 'a')));
+
+  // Set insufficient quota.
+  fake_service()->SetQuotaValue(100, 100 + kFileSize - 1);
+
+  // Transfer the local file to Drive.
+  FileError error = FILE_ERROR_FAILED;
+  operation_->TransferFileFromLocalToRemote(
+      local_src_path,
+      remote_dest_path,
+      google_apis::test_util::CreateCopyResultCallback(&error));
+  test_util::RunBlockingPoolTask();
+  EXPECT_EQ(FILE_ERROR_NO_SERVER_SPACE, error);
+
+  // Set sufficient quota.
+  fake_service()->SetQuotaValue(100, 100 + kFileSize);
+
+  // Transfer the local file to Drive.
+  error = FILE_ERROR_FAILED;
+  operation_->TransferFileFromLocalToRemote(
+      local_src_path,
+      remote_dest_path,
+      google_apis::test_util::CreateCopyResultCallback(&error));
+  test_util::RunBlockingPoolTask();
+  EXPECT_EQ(FILE_ERROR_OK, error);
+}
+
 TEST_F(CopyOperationTest, TransferFileFromLocalToRemote_HostedDocument) {
   const base::FilePath local_src_path = temp_dir().AppendASCII("local.gdoc");
   const base::FilePath remote_dest_path(FILE_PATH_LITERAL(
diff --git a/chrome/browser/chromeos/drive/file_system/get_file_for_saving_operation.cc b/chrome/browser/chromeos/drive/file_system/get_file_for_saving_operation.cc
new file mode 100644
index 0000000..7964876
--- /dev/null
+++ b/chrome/browser/chromeos/drive/file_system/get_file_for_saving_operation.cc
@@ -0,0 +1,146 @@
+// 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/drive/file_system/get_file_for_saving_operation.h"
+
+#include "base/bind.h"
+#include "chrome/browser/chromeos/drive/file_system/create_file_operation.h"
+#include "chrome/browser/chromeos/drive/file_system/download_operation.h"
+#include "chrome/browser/chromeos/drive/file_write_watcher.h"
+#include "content/public/browser/browser_thread.h"
+
+using content::BrowserThread;
+
+namespace drive {
+namespace file_system {
+
+GetFileForSavingOperation::GetFileForSavingOperation(
+    base::SequencedTaskRunner* blocking_task_runner,
+    OperationObserver* observer,
+    JobScheduler* scheduler,
+    internal::ResourceMetadata* metadata,
+    internal::FileCache* cache,
+    const base::FilePath& temporary_file_directory)
+    : create_file_operation_(new CreateFileOperation(blocking_task_runner,
+                                                     observer,
+                                                     scheduler,
+                                                     metadata,
+                                                     cache)),
+      download_operation_(new DownloadOperation(blocking_task_runner,
+                                                observer,
+                                                scheduler,
+                                                metadata,
+                                                cache,
+                                                temporary_file_directory)),
+      file_write_watcher_(new internal::FileWriteWatcher(observer)),
+      cache_(cache),
+      weak_ptr_factory_(this) {
+}
+
+GetFileForSavingOperation::~GetFileForSavingOperation() {
+}
+
+void GetFileForSavingOperation::GetFileForSaving(
+    const base::FilePath& file_path,
+    const GetFileCallback& callback) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK(!callback.is_null());
+
+  create_file_operation_->CreateFile(
+      file_path,
+      false,  // error_if_already_exists
+      base::Bind(&GetFileForSavingOperation::GetFileForSavingAfterCreate,
+                 weak_ptr_factory_.GetWeakPtr(),
+                 file_path,
+                 callback));
+}
+
+void GetFileForSavingOperation::GetFileForSavingAfterCreate(
+    const base::FilePath& file_path,
+    const GetFileCallback& callback,
+    FileError error) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK(!callback.is_null());
+
+  if (error != FILE_ERROR_OK) {
+    callback.Run(error, base::FilePath(), scoped_ptr<ResourceEntry>());
+    return;
+  }
+
+  download_operation_->EnsureFileDownloadedByPath(
+      file_path,
+      ClientContext(USER_INITIATED),
+      GetFileContentInitializedCallback(),
+      google_apis::GetContentCallback(),
+      base::Bind(&GetFileForSavingOperation::GetFileForSavingAfterDownload,
+                 weak_ptr_factory_.GetWeakPtr(),
+                 callback));
+}
+
+void GetFileForSavingOperation::GetFileForSavingAfterDownload(
+    const GetFileCallback& callback,
+    FileError error,
+    const base::FilePath& cache_path,
+    scoped_ptr<ResourceEntry> entry) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK(!callback.is_null());
+
+  if (error != FILE_ERROR_OK) {
+    callback.Run(error, base::FilePath(), scoped_ptr<ResourceEntry>());
+    return;
+  }
+
+  const std::string& resource_id = entry->resource_id();
+  cache_->MarkDirtyOnUIThread(
+      resource_id,
+      base::Bind(&GetFileForSavingOperation::GetFileForSavingAfterMarkDirty,
+                 weak_ptr_factory_.GetWeakPtr(),
+                 callback,
+                 cache_path,
+                 base::Passed(&entry)));
+}
+
+void GetFileForSavingOperation::GetFileForSavingAfterMarkDirty(
+    const GetFileCallback& callback,
+    const base::FilePath& cache_path,
+    scoped_ptr<ResourceEntry> entry,
+    FileError error) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK(!callback.is_null());
+
+  if (error != FILE_ERROR_OK) {
+    callback.Run(error, base::FilePath(), scoped_ptr<ResourceEntry>());
+    return;
+  }
+
+  const std::string& resource_id = entry->resource_id();
+  file_write_watcher_->StartWatch(
+      cache_path,
+      resource_id,
+      base::Bind(&GetFileForSavingOperation::GetFileForSavingAfterWatch,
+                 weak_ptr_factory_.GetWeakPtr(),
+                 callback,
+                 cache_path,
+                 base::Passed(&entry)));
+}
+
+void GetFileForSavingOperation::GetFileForSavingAfterWatch(
+    const GetFileCallback& callback,
+    const base::FilePath& cache_path,
+    scoped_ptr<ResourceEntry> entry,
+    bool success) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK(!callback.is_null());
+
+  if (!success) {
+    callback.Run(FILE_ERROR_FAILED,
+                 base::FilePath(), scoped_ptr<ResourceEntry>());
+    return;
+  }
+
+  callback.Run(FILE_ERROR_OK, cache_path, entry.Pass());
+}
+
+}  // namespace file_system
+}  // namespace drive
diff --git a/chrome/browser/chromeos/drive/file_system/get_file_for_saving_operation.h b/chrome/browser/chromeos/drive/file_system/get_file_for_saving_operation.h
new file mode 100644
index 0000000..3215cc2
--- /dev/null
+++ b/chrome/browser/chromeos/drive/file_system/get_file_for_saving_operation.h
@@ -0,0 +1,92 @@
+// 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_DRIVE_FILE_SYSTEM_GET_FILE_FOR_SAVING_OPERATION_H_
+#define CHROME_BROWSER_CHROMEOS_DRIVE_FILE_SYSTEM_GET_FILE_FOR_SAVING_OPERATION_H_
+
+#include "base/basictypes.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/memory/weak_ptr.h"
+#include "chrome/browser/chromeos/drive/file_errors.h"
+#include "chrome/browser/chromeos/drive/file_system_interface.h"
+
+namespace base {
+class FilePath;
+class SequencedTaskRunner;
+}  // namespace base
+
+namespace drive {
+namespace internal {
+class FileCache;
+class FileWriteWatcher;
+class ResourceMetadata;
+}  // namespace internal
+
+class JobScheduler;
+class ResourceEntry;
+
+namespace file_system {
+
+class CreateFileOperation;
+class DownloadOperation;
+class OperationObserver;
+
+// Implements GetFileForSaving() operation that prepares a local cache for
+// a Drive file whose next modification is monitored and notified to the
+// OperationObserver.
+// TODO(kinaba): crbug.com/269424: we might want to monitor all the changes
+// to the cache directory, not just the one immediately after the save dialog.
+class GetFileForSavingOperation {
+ public:
+  GetFileForSavingOperation(base::SequencedTaskRunner* blocking_task_runner,
+                            OperationObserver* observer,
+                            JobScheduler* scheduler,
+                            internal::ResourceMetadata* metadata,
+                            internal::FileCache* cache,
+                            const base::FilePath& temporary_file_directory);
+  ~GetFileForSavingOperation();
+
+  // Makes sure that |file_path| in the file system is available in the local
+  // cache, and marks it as dirty. The next modification to the cache file is
+  // watched and is automatically notified to the observer. If the entry is not
+  // present in the file system, it is created.
+  void GetFileForSaving(const base::FilePath& file_path,
+                        const GetFileCallback& callback);
+
+  internal::FileWriteWatcher* file_write_watcher_for_testing() {
+    return file_write_watcher_.get();
+  }
+
+ private:
+  void GetFileForSavingAfterCreate(const base::FilePath& file_path,
+                                   const GetFileCallback& callback,
+                                   FileError error);
+  void GetFileForSavingAfterDownload(const GetFileCallback& callback,
+                                     FileError error,
+                                     const base::FilePath& cache_path,
+                                     scoped_ptr<ResourceEntry> entry);
+  void GetFileForSavingAfterMarkDirty(const GetFileCallback& callback,
+                                      const base::FilePath& cache_path,
+                                      scoped_ptr<ResourceEntry> entry,
+                                      FileError error);
+  void GetFileForSavingAfterWatch(const GetFileCallback& callback,
+                                  const base::FilePath& cache_path,
+                                  scoped_ptr<ResourceEntry> entry,
+                                  bool success);
+
+  scoped_ptr<CreateFileOperation> create_file_operation_;
+  scoped_ptr<DownloadOperation> download_operation_;
+  scoped_ptr<internal::FileWriteWatcher> file_write_watcher_;
+  internal::FileCache* cache_;
+
+  // Note: This should remain the last member so it'll be destroyed and
+  // invalidate the weak pointers before any other members are destroyed.
+  base::WeakPtrFactory<GetFileForSavingOperation> weak_ptr_factory_;
+  DISALLOW_COPY_AND_ASSIGN(GetFileForSavingOperation);
+};
+
+}  // namespace file_system
+}  // namespace drive
+
+#endif  // CHROME_BROWSER_CHROMEOS_DRIVE_FILE_SYSTEM_GET_FILE_FOR_SAVING_OPERATION_H_
diff --git a/chrome/browser/chromeos/drive/file_system/get_file_for_saving_operation_unittest.cc b/chrome/browser/chromeos/drive/file_system/get_file_for_saving_operation_unittest.cc
new file mode 100644
index 0000000..08918e6
--- /dev/null
+++ b/chrome/browser/chromeos/drive/file_system/get_file_for_saving_operation_unittest.cc
@@ -0,0 +1,158 @@
+// 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/drive/file_system/get_file_for_saving_operation.h"
+
+#include "base/callback.h"
+#include "base/file_util.h"
+#include "base/files/file_path.h"
+#include "base/run_loop.h"
+#include "chrome/browser/chromeos/drive/drive.pb.h"
+#include "chrome/browser/chromeos/drive/file_errors.h"
+#include "chrome/browser/chromeos/drive/file_system/operation_test_base.h"
+#include "chrome/browser/chromeos/drive/file_write_watcher.h"
+#include "chrome/browser/google_apis/test_util.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace drive {
+namespace file_system {
+
+namespace {
+
+// If OnCacheFileUploadNeededByOperation is called, records the resource ID and
+// calls |quit_closure|.
+class TestObserver : public OperationObserver {
+ public:
+  void set_quit_closure(const base::Closure& quit_closure) {
+    quit_closure_ = quit_closure;
+  }
+
+  const std::string& observerd_resource_id() const {
+    return observed_resource_id_;
+  }
+
+  // OperationObserver overrides.
+  virtual void OnDirectoryChangedByOperation(
+      const base::FilePath& path) OVERRIDE {}
+
+  virtual void OnCacheFileUploadNeededByOperation(
+      const std::string& resource_id) OVERRIDE {
+    observed_resource_id_ = resource_id;
+    quit_closure_.Run();
+  }
+
+ private:
+  std::string observed_resource_id_;
+  base::Closure quit_closure_;
+};
+
+}  // namespace
+
+class GetFileForSavingOperationTest : public OperationTestBase {
+ protected:
+  // FileWriteWatcher requires TYPE_IO message loop to run.
+  GetFileForSavingOperationTest()
+      : OperationTestBase(content::TestBrowserThreadBundle::IO_MAINLOOP) {
+  }
+
+  virtual void SetUp() OVERRIDE {
+    OperationTestBase::SetUp();
+
+    operation_.reset(new GetFileForSavingOperation(
+        blocking_task_runner(), &observer_, scheduler(), metadata(), cache(),
+        temp_dir()));
+    operation_->file_write_watcher_for_testing()->DisableDelayForTesting();
+  }
+
+  TestObserver observer_;
+  scoped_ptr<GetFileForSavingOperation> operation_;
+};
+
+TEST_F(GetFileForSavingOperationTest, GetFileForSaving_Exist) {
+  base::FilePath drive_path(FILE_PATH_LITERAL("drive/root/File 1.txt"));
+  ResourceEntry src_entry;
+  ASSERT_EQ(FILE_ERROR_OK, GetLocalResourceEntry(drive_path, &src_entry));
+
+  // Run the operation.
+  FileError error = FILE_ERROR_FAILED;
+  scoped_ptr<ResourceEntry> entry;
+  base::FilePath local_path;
+  operation_->GetFileForSaving(
+      drive_path,
+      google_apis::test_util::CreateCopyResultCallback(
+          &error, &local_path, &entry));
+  test_util::RunBlockingPoolTask();
+
+  // Checks that the file is retrieved.
+  EXPECT_EQ(FILE_ERROR_OK, error);
+  ASSERT_TRUE(entry);
+  EXPECT_EQ(src_entry.resource_id(), entry->resource_id());
+
+  // Checks that it presents in cache and marked dirty.
+  bool success = false;
+  FileCacheEntry cache_entry;
+  cache()->GetCacheEntryOnUIThread(
+      src_entry.resource_id(),
+      google_apis::test_util::CreateCopyResultCallback(&success, &cache_entry));
+  test_util::RunBlockingPoolTask();
+  EXPECT_TRUE(success);
+  EXPECT_TRUE(cache_entry.is_present());
+  EXPECT_TRUE(cache_entry.is_dirty());
+
+  // Write something to the cache and checks that the event is reported.
+  {
+    base::RunLoop run_loop;
+    observer_.set_quit_closure(run_loop.QuitClosure());
+    google_apis::test_util::WriteStringToFile(local_path, "hello");
+    run_loop.Run();
+    EXPECT_EQ(entry->resource_id(), observer_.observerd_resource_id());
+  }
+}
+
+TEST_F(GetFileForSavingOperationTest, GetFileForSaving_NotExist) {
+  base::FilePath drive_path(FILE_PATH_LITERAL("drive/root/NotExist.txt"));
+  ResourceEntry src_entry;
+  ASSERT_EQ(FILE_ERROR_NOT_FOUND,
+            GetLocalResourceEntry(drive_path, &src_entry));
+
+  // Run the operation.
+  FileError error = FILE_ERROR_FAILED;
+  scoped_ptr<ResourceEntry> entry;
+  base::FilePath local_path;
+  operation_->GetFileForSaving(
+      drive_path,
+      google_apis::test_util::CreateCopyResultCallback(
+          &error, &local_path, &entry));
+  test_util::RunBlockingPoolTask();
+
+  // Checks that the file is created and retrieved.
+  EXPECT_EQ(FILE_ERROR_OK, error);
+  EXPECT_EQ(FILE_ERROR_OK, GetLocalResourceEntry(drive_path, &src_entry));
+  int64 size = -1;
+  EXPECT_TRUE(file_util::GetFileSize(local_path, &size));
+  EXPECT_EQ(0, size);
+}
+
+TEST_F(GetFileForSavingOperationTest, GetFileForSaving_Directory) {
+  base::FilePath drive_path(FILE_PATH_LITERAL("drive/root/Directory 1"));
+  ResourceEntry src_entry;
+  ASSERT_EQ(FILE_ERROR_OK, GetLocalResourceEntry(drive_path, &src_entry));
+  ASSERT_TRUE(src_entry.file_info().is_directory());
+
+  // Run the operation.
+  FileError error = FILE_ERROR_FAILED;
+  scoped_ptr<ResourceEntry> entry;
+  base::FilePath local_path;
+  operation_->GetFileForSaving(
+      drive_path,
+      google_apis::test_util::CreateCopyResultCallback(
+          &error, &local_path, &entry));
+  test_util::RunBlockingPoolTask();
+
+  // Checks that an error is returned.
+  EXPECT_EQ(FILE_ERROR_EXISTS, error);
+}
+
+}  // namespace file_system
+}  // namespace drive
diff --git a/chrome/browser/chromeos/drive/file_system/operation_test_base.cc b/chrome/browser/chromeos/drive/file_system/operation_test_base.cc
index ad1fb09..324858d 100644
--- a/chrome/browser/chromeos/drive/file_system/operation_test_base.cc
+++ b/chrome/browser/chromeos/drive/file_system/operation_test_base.cc
@@ -39,6 +39,10 @@
 OperationTestBase::OperationTestBase() {
 }
 
+OperationTestBase::OperationTestBase(int test_thread_bundle_options)
+    : thread_bundle_(test_thread_bundle_options) {
+}
+
 OperationTestBase::~OperationTestBase() {
 }
 
diff --git a/chrome/browser/chromeos/drive/file_system/operation_test_base.h b/chrome/browser/chromeos/drive/file_system/operation_test_base.h
index b8b26cc..4056455 100644
--- a/chrome/browser/chromeos/drive/file_system/operation_test_base.h
+++ b/chrome/browser/chromeos/drive/file_system/operation_test_base.h
@@ -67,6 +67,7 @@
   };
 
   OperationTestBase();
+  explicit OperationTestBase(int test_thread_bundle_options);
   virtual ~OperationTestBase();
 
   // testing::Test overrides.
diff --git a/chrome/browser/chromeos/drive/file_system_interface.h b/chrome/browser/chromeos/drive/file_system_interface.h
index 1c5865e..4df3c8f 100644
--- a/chrome/browser/chromeos/drive/file_system_interface.h
+++ b/chrome/browser/chromeos/drive/file_system_interface.h
@@ -318,15 +318,23 @@
   virtual void Unpin(const base::FilePath& file_path,
                      const FileOperationCallback& callback) = 0;
 
-  // Gets |file_path| from the file system. The file entry represented by
-  // |file_path| needs to be present in in-memory representation of the file
-  // system in order to be retrieved. If the file is not cached, the file
-  // will be downloaded through GData API or Drive V2 API.
+  // Makes sure that |file_path| in the file system is available in the local
+  // cache. If the file is not cached, the file will be downloaded. The entry
+  // needs to be present in the file system.
   //
-  // |callback| must not be null.
+  // Returns the cache path and entry info to |callback|. It must not be null.
   virtual void GetFileByPath(const base::FilePath& file_path,
                              const GetFileCallback& callback) = 0;
 
+  // Makes sure that |file_path| in the file system is available in the local
+  // cache, and mark it as dirty. The next modification to the cache file is
+  // watched and is automatically uploaded to the server. If the entry is not
+  // present in the file system, it is created.
+  //
+  // Returns the cache path and entry info to |callback|. It must not be null.
+  virtual void GetFileByPathForSaving(const base::FilePath& file_path,
+                                      const GetFileCallback& callback) = 0;
+
   // Gets a file by the given |file_path|.
   // Calls |initialized_callback| when either:
   //   1) The cached file (or JSON file for hosted file) is found, or
diff --git a/chrome/browser/chromeos/drive/file_task_executor.h b/chrome/browser/chromeos/drive/file_task_executor.h
index ce9c459..69e7dad 100644
--- a/chrome/browser/chromeos/drive/file_task_executor.h
+++ b/chrome/browser/chromeos/drive/file_task_executor.h
@@ -8,6 +8,7 @@
 #include <string>
 #include <vector>
 
+#include "base/callback.h"
 #include "base/memory/weak_ptr.h"
 #include "chrome/browser/chromeos/drive/file_errors.h"
 #include "chrome/browser/chromeos/extensions/file_manager/file_tasks.h"
diff --git a/chrome/browser/chromeos/drive/file_write_watcher.h b/chrome/browser/chromeos/drive/file_write_watcher.h
index 91c947d..13523df 100644
--- a/chrome/browser/chromeos/drive/file_write_watcher.h
+++ b/chrome/browser/chromeos/drive/file_write_watcher.h
@@ -46,7 +46,7 @@
   // 5 seconds has passed after the last write operation is detected.
   //
   // TODO(kinaba): investigate the possibility to continuously watch the whole
-  // cache directory.
+  // cache directory. http://crbug.com/269424
   void StartWatch(const base::FilePath& path,
                   const std::string& resource_id,
                   const StartWatchCallback& callback);
diff --git a/chrome/browser/chromeos/drive/job_scheduler.cc b/chrome/browser/chromeos/drive/job_scheduler.cc
index d9c0d61..682b3c1 100644
--- a/chrome/browser/chromeos/drive/job_scheduler.cc
+++ b/chrome/browser/chromeos/drive/job_scheduler.cc
@@ -22,9 +22,13 @@
 
 namespace {
 
-const int kMaxThrottleCount = 5;
+const int kMaxThrottleCount = 4;
 
-const int kMaxRetryCount = kMaxThrottleCount - 1;
+// According to the API documentation, this should be the same as
+// kMaxThrottleCount (https://developers.google.com/drive/handle-errors).
+// But currently multiplied by 2 to ensure upload related jobs retried for a
+// sufficient number of times. crbug.com/269918
+const int kMaxRetryCount = 2*kMaxThrottleCount;
 
 // Parameter struct for RunUploadNewFile.
 struct UploadNewFileParams {
diff --git a/chrome/browser/chromeos/drive/resource_metadata_storage.h b/chrome/browser/chromeos/drive/resource_metadata_storage.h
index 0ad61ef..9c4621a 100644
--- a/chrome/browser/chromeos/drive/resource_metadata_storage.h
+++ b/chrome/browser/chromeos/drive/resource_metadata_storage.h
@@ -36,7 +36,10 @@
  public:
   // This should be incremented when incompatibility change is made to DB
   // format.
-  static const int kDBVersion = 7;
+  //
+  // Note: Skip '7' when incrementing this value next time. '7' has been used
+  // in the period between r208686 and r213797.
+  static const int kDBVersion = 6;
 
   // Object to iterate over entries stored in this storage.
   class Iterator {
diff --git a/chrome/browser/chromeos/drive/sync_client.cc b/chrome/browser/chromeos/drive/sync_client.cc
index c1f487b..31771d6 100644
--- a/chrome/browser/chromeos/drive/sync_client.cc
+++ b/chrome/browser/chromeos/drive/sync_client.cc
@@ -38,6 +38,9 @@
 // and shorten the delay. crbug.com/134774
 const int kDelaySeconds = 5;
 
+// The delay constant is used to delay retrying a sync task on server errors.
+const int kLongDelaySeconds = 600;
+
 // Appends |resource_id| to |to_fetch| if the file is pinned but not fetched
 // (not present locally), or to |to_upload| if the file is dirty but not
 // uploaded.
@@ -78,6 +81,7 @@
                                                          metadata,
                                                          cache)),
       delay_(base::TimeDelta::FromSeconds(kDelaySeconds)),
+      long_delay_(base::TimeDelta::FromSeconds(kLongDelaySeconds)),
       weak_ptr_factory_(this) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
 }
@@ -110,7 +114,7 @@
 void SyncClient::AddFetchTask(const std::string& resource_id) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
 
-  AddTaskToQueue(FETCH, resource_id);
+  AddTaskToQueue(FETCH, resource_id, delay_);
 }
 
 void SyncClient::RemoveFetchTask(const std::string& resource_id) {
@@ -123,11 +127,12 @@
 void SyncClient::AddUploadTask(const std::string& resource_id) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
 
-  AddTaskToQueue(UPLOAD, resource_id);
+  AddTaskToQueue(UPLOAD, resource_id, delay_);
 }
 
 void SyncClient::AddTaskToQueue(SyncType type,
-                                const std::string& resource_id) {
+                                const std::string& resource_id,
+                                const base::TimeDelta& delay) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
 
   // If the same task is already queued, ignore this task.
@@ -156,7 +161,7 @@
                  weak_ptr_factory_.GetWeakPtr(),
                  type,
                  resource_id),
-      delay_);
+      delay);
 }
 
 void SyncClient::StartTask(SyncType type, const std::string& resource_id) {
@@ -205,13 +210,13 @@
   for (size_t i = 0; i < to_upload->size(); ++i) {
     const std::string& resource_id = (*to_upload)[i];
     DVLOG(1) << "Queuing to upload: " << resource_id;
-    AddTaskToQueue(UPLOAD_NO_CONTENT_CHECK, resource_id);
+    AddTaskToQueue(UPLOAD_NO_CONTENT_CHECK, resource_id, delay_);
   }
 
   for (size_t i = 0; i < to_fetch->size(); ++i) {
     const std::string& resource_id = (*to_fetch)[i];
     DVLOG(1) << "Queuing to fetch: " << resource_id;
-    AddTaskToQueue(FETCH, resource_id);
+    AddTaskToQueue(FETCH, resource_id, delay_);
   }
 }
 
@@ -284,7 +289,7 @@
   }
 
   // Finally, adding to the queue.
-  AddTaskToQueue(FETCH, resource_id);
+  AddTaskToQueue(FETCH, resource_id, delay_);
 }
 
 void SyncClient::OnFetchFileComplete(const std::string& resource_id,
@@ -308,7 +313,11 @@
         break;
       case FILE_ERROR_NO_CONNECTION:
         // Re-queue the task so that we'll retry once the connection is back.
-        AddTaskToQueue(FETCH, resource_id);
+        AddTaskToQueue(FETCH, resource_id, delay_);
+        break;
+      case FILE_ERROR_SERVICE_UNAVAILABLE:
+        // Re-queue the task so that we'll retry once the service is back.
+        AddTaskToQueue(FETCH, resource_id, long_delay_);
         break;
       default:
         LOG(WARNING) << "Failed to fetch " << resource_id
@@ -329,7 +338,11 @@
     switch (error) {
       case FILE_ERROR_NO_CONNECTION:
         // Re-queue the task so that we'll retry once the connection is back.
-        AddTaskToQueue(UPLOAD_NO_CONTENT_CHECK, resource_id);
+        AddTaskToQueue(UPLOAD_NO_CONTENT_CHECK, resource_id, delay_);
+        break;
+      case FILE_ERROR_SERVICE_UNAVAILABLE:
+        // Re-queue the task so that we'll retry once the service is back.
+        AddTaskToQueue(UPLOAD_NO_CONTENT_CHECK, resource_id, long_delay_);
         break;
       default:
         LOG(WARNING) << "Failed to upload " << resource_id << ": "
diff --git a/chrome/browser/chromeos/drive/sync_client.h b/chrome/browser/chromeos/drive/sync_client.h
index f5c6734..3178f5b 100644
--- a/chrome/browser/chromeos/drive/sync_client.h
+++ b/chrome/browser/chromeos/drive/sync_client.h
@@ -91,7 +91,9 @@
  private:
   // Adds the given task to the queue. If the same task is queued, remove the
   // existing one, and adds a new one to the end of the queue.
-  void AddTaskToQueue(SyncType type, const std::string& resource_id);
+  void AddTaskToQueue(SyncType type,
+                      const std::string& resource_id,
+                      const base::TimeDelta& delay);
 
   // Called when a task is ready to be added to the queue.
   void StartTask(SyncType type, const std::string& resource_id);
@@ -153,9 +155,12 @@
   // removed before starting, they will be cancelled.
   std::set<std::string> pending_fetch_list_;
 
-  // The delay is used for delaying processing SyncTasks in DoSyncLoop().
+  // The delay is used for delaying processing tasks in AddTaskToQueue().
   base::TimeDelta delay_;
 
+  // The delay is used for delaying retry of tasks on server errors.
+  base::TimeDelta long_delay_;
+
   // 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<SyncClient> weak_ptr_factory_;
diff --git a/chrome/browser/chromeos/enrollment_dialog_view.cc b/chrome/browser/chromeos/enrollment_dialog_view.cc
index 31e3762..29cff16 100644
--- a/chrome/browser/chromeos/enrollment_dialog_view.cc
+++ b/chrome/browser/chromeos/enrollment_dialog_view.cc
@@ -10,6 +10,7 @@
 #include "chrome/browser/extensions/extension_host.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/browser_navigator.h"
+#include "chromeos/network/network_event_log.h"
 #include "content/public/common/page_transition_types.h"
 #include "extensions/common/constants.h"
 #include "grit/generated_resources.h"
@@ -192,7 +193,7 @@
   virtual ~DialogEnrollmentDelegate();
 
   // EnrollmentDelegate overrides
-  virtual void Enroll(const std::vector<std::string>& uri_list,
+  virtual bool Enroll(const std::vector<std::string>& uri_list,
                       const base::Closure& connect) OVERRIDE;
 
  private:
@@ -212,8 +213,8 @@
 
 DialogEnrollmentDelegate::~DialogEnrollmentDelegate() {}
 
-void DialogEnrollmentDelegate::Enroll(const std::vector<std::string>& uri_list,
-                                      const base::Closure& connect) {
+bool DialogEnrollmentDelegate::Enroll(const std::vector<std::string>& uri_list,
+                                      const base::Closure& post_action) {
   // Keep the closure for later activation if we notice that
   // a certificate has been added.
 
@@ -229,16 +230,14 @@
       EnrollmentDialogView::ShowDialog(owning_window_,
                                        network_name_,
                                        profile_,
-                                       uri, connect);
-      return;
+                                       uri, post_action);
+      return true;
     }
   }
 
-  // If we didn't find a scheme we could handle, then don't continue connecting.
-  // TODO(gspencer): provide a path to display this failure to the user. (but
-  // for the most part they won't know what it means, since it's probably coming
-  // from a policy-pushed ONC file).
-  VLOG(1) << "Couldn't find usable scheme in enrollment URI(s)";
+  // No appropriate scheme was found.
+  NET_LOG_EVENT("No usable enrollment URI", network_name_);
+  return false;
 }
 
 }  // namespace
diff --git a/chrome/browser/chromeos/enrollment_dialog_view.h b/chrome/browser/chromeos/enrollment_dialog_view.h
index a3cd8f0..b855cac 100644
--- a/chrome/browser/chromeos/enrollment_dialog_view.h
+++ b/chrome/browser/chromeos/enrollment_dialog_view.h
@@ -6,14 +6,31 @@
 #define CHROME_BROWSER_CHROMEOS_ENROLLMENT_DIALOG_VIEW_H_
 
 #include <string>
+#include <vector>
 
+#include "base/callback_forward.h"
 #include "ui/gfx/native_widget_types.h"
 
 class Profile;
 
 namespace chromeos {
 
-class EnrollmentDelegate;
+// An interface that can be used to handle certificate enrollment URIs when
+// encountered.  Also used by unit tests to avoid opening browser windows
+// when testing.
+class EnrollmentDelegate {
+ public:
+  EnrollmentDelegate() {}
+  virtual ~EnrollmentDelegate() {}
+
+  // Implemented to handle a given certificate enrollment URI.  Returns false
+  // if the enrollment URI doesn't use a scheme that we can handle.
+  // |post_action| is called when enrollment completes.
+  virtual bool Enroll(const std::vector<std::string>& uri_list,
+                      const base::Closure& post_action) = 0;
+ private:
+  DISALLOW_COPY_AND_ASSIGN(EnrollmentDelegate);
+};
 
 EnrollmentDelegate* CreateEnrollmentDelegate(gfx::NativeWindow owning_window,
                                              const std::string& network_name,
diff --git a/chrome/browser/chromeos/extensions/external_cache.cc b/chrome/browser/chromeos/extensions/external_cache.cc
index 86c0f19..8174772 100644
--- a/chrome/browser/chromeos/extensions/external_cache.cc
+++ b/chrome/browser/chromeos/extensions/external_cache.cc
@@ -34,10 +34,12 @@
 
 ExternalCache::ExternalCache(const std::string& cache_dir,
                              net::URLRequestContextGetter* request_context,
-                             Delegate* delegate)
+                             Delegate* delegate,
+                             bool always_check_updates)
     : cache_dir_(cache_dir),
       request_context_(request_context),
       delegate_(delegate),
+      always_check_updates_(always_check_updates),
       cached_extensions_(new base::DictionaryValue()),
       weak_ptr_factory_(this),
       worker_pool_token_(
@@ -54,7 +56,17 @@
 void ExternalCache::UpdateExtensionsList(
     scoped_ptr<base::DictionaryValue> prefs) {
   extensions_ = prefs.Pass();
-  CheckCacheNow();
+  if (extensions_->empty()) {
+    // Don't check cache and clear it if there are no extensions in the list.
+    // It is important case because login to supervised user shouldn't clear
+    // cache for normal users.
+    // TODO(dpolukhin): introduce reference counting to preserve cache elements
+    // when they are not needed for current user but needed for other users.
+    cached_extensions_->Clear();
+    UpdateExtensionLoader();
+  } else {
+    CheckCacheNow();
+  }
 }
 
 void ExternalCache::OnDamagedFileDetected(const base::FilePath& path) {
@@ -78,9 +90,12 @@
       UpdateExtensionLoader();
 
       // The file will be downloaded again on the next restart.
-      content::BrowserThread::PostTask(
-          content::BrowserThread::FILE, FROM_HERE,
-          base::Bind(base::IgnoreResult(base::DeleteFile), path, true));
+      if (base::FilePath(cache_dir_).IsParent(path)) {
+        // Don't delete files out of cache_dir_.
+        content::BrowserThread::PostTask(
+            content::BrowserThread::FILE, FROM_HERE,
+            base::Bind(base::IgnoreResult(base::DeleteFile), path, true));
+      }
 
       // Don't try to DownloadMissingExtensions() from here,
       // since it can cause a fail/retry loop.
@@ -202,10 +217,10 @@
     if (!file_util::CreateDirectory(dir)) {
       LOG(ERROR) << "Failed to create ExternalCache directory at "
                  << dir.value();
-
-      // Nothing else to do. Cache won't be used.
-      return;
     }
+
+    // Nothing else to do. Cache won't be used.
+    return;
   }
 
   // Enumerate all the files in the cache |dir|, including directories
@@ -271,27 +286,35 @@
       entry->SetString(extensions::ExternalProviderImpl::kExternalVersion,
                        version);
       entry->SetString(extensions::ExternalProviderImpl::kExternalCrx,
-                        path.value());
+                       path.value());
       if (extension_urls::IsWebstoreUpdateUrl(GURL(update_url))) {
         entry->SetBoolean(extensions::ExternalProviderImpl::kIsFromWebstore,
-                         true);
+                          true);
       }
     } else if (
         entry->GetString(extensions::ExternalProviderImpl::kExternalVersion,
                          &prev_version_string) &&
         entry->GetString(extensions::ExternalProviderImpl::kExternalCrx,
                          &prev_crx)) {
-      LOG(ERROR) << "Found two ExternalCache files for the same extension, "
-                    "will erase the oldest version";
       Version prev_version(prev_version_string);
       Version curr_version(version);
       DCHECK(prev_version.IsValid());
       DCHECK(curr_version.IsValid());
-      if (prev_version.CompareTo(curr_version) < 0) {
-        base::DeleteFile(base::FilePath(prev_crx), true /* recursive */);
+      if (prev_version.CompareTo(curr_version) <= 0) {
+        VLOG(1) << "ExternalCache found old cached version "
+                << prev_version_string << " path: " << prev_crx;
+        base::FilePath prev_crx_file(prev_crx);
+        if (dir.IsParent(prev_crx_file)) {
+          // Only delete old cached files under cache_dir_ folder.
+          base::DeleteFile(base::FilePath(prev_crx), true /* recursive */);
+        }
+        entry->SetString(extensions::ExternalProviderImpl::kExternalVersion,
+                         version);
         entry->SetString(extensions::ExternalProviderImpl::kExternalCrx,
                          path.value());
       } else {
+        VLOG(1) << "ExternalCache found old cached version "
+                << version << " path: " << path.value();
         base::DeleteFile(path, true /* recursive */);
       }
     } else {
@@ -322,12 +345,18 @@
 
     // Check for updates for all extensions configured except for extensions
     // marked as keep_if_present.
-    std::string update_url;
     if (downloader_ &&
-        !entry->HasKey(extensions::ExternalProviderImpl::kKeepIfPresent) &&
-        entry->GetString(extensions::ExternalProviderImpl::kExternalUpdateUrl,
-                         &update_url)) {
-      downloader_->AddPendingExtension(it.key(), GURL(update_url), 0);
+        !entry->HasKey(extensions::ExternalProviderImpl::kKeepIfPresent)) {
+      GURL update_url;
+      std::string external_update_url;
+      if (entry->GetString(extensions::ExternalProviderImpl::kExternalUpdateUrl,
+                           &external_update_url)) {
+        update_url = GURL(external_update_url);
+      } else if (always_check_updates_) {
+        update_url = extension_urls::GetWebstoreUpdateUrl();
+      }
+      if (update_url.is_valid())
+        downloader_->AddPendingExtension(it.key(), update_url, 0);
     }
 
     base::DictionaryValue* cached_entry = NULL;
@@ -410,9 +439,7 @@
 
   base::DictionaryValue* entry = NULL;
   std::string update_url;
-  if (!extensions_->GetDictionary(id, &entry) ||
-      !entry->GetString(extensions::ExternalProviderImpl::kExternalUpdateUrl,
-                        &update_url)) {
+  if (!extensions_->GetDictionary(id, &entry)) {
     LOG(ERROR) << "ExternalCache cannot find entry for extension " << id;
     return;
   }
diff --git a/chrome/browser/chromeos/extensions/external_cache.h b/chrome/browser/chromeos/extensions/external_cache.h
index 2b4b4bf..07f2252 100644
--- a/chrome/browser/chromeos/extensions/external_cache.h
+++ b/chrome/browser/chromeos/extensions/external_cache.h
@@ -47,9 +47,12 @@
   };
 
   // The |request_context| is used for the update checks.
+  // By default updates are checked for the extensions with external_update_url.
+  // If |always_check_webstore| set, updates will be check for external_crx too.
   ExternalCache(const std::string& cache_dir,
                 net::URLRequestContextGetter* request_context,
-                Delegate* delegate);
+                Delegate* delegate,
+                bool always_check_updates);
   virtual ~ExternalCache();
 
   // Returns already cached extensions.
@@ -150,6 +153,9 @@
   // Delegate that would like to get notifications about cache updates.
   Delegate* delegate_;
 
+  // Updates needs to be check for the extensions with external_crx too.
+  bool always_check_updates_;
+
   // This is the list of extensions currently configured.
   scoped_ptr<base::DictionaryValue> extensions_;
 
diff --git a/chrome/browser/chromeos/extensions/external_pref_cache_loader.cc b/chrome/browser/chromeos/extensions/external_pref_cache_loader.cc
index cd02dae..470b743 100644
--- a/chrome/browser/chromeos/extensions/external_pref_cache_loader.cc
+++ b/chrome/browser/chromeos/extensions/external_pref_cache_loader.cc
@@ -38,7 +38,7 @@
   if (!external_cache_.get()) {
     external_cache_.reset(new ExternalCache(kPreinstalledAppsCacheDir,
         g_browser_process->system_request_context(),
-        this));
+        this, true));
   }
 
   external_cache_->UpdateExtensionsList(prefs_.Pass());
diff --git a/chrome/browser/chromeos/extensions/file_manager/event_router.cc b/chrome/browser/chromeos/extensions/file_manager/event_router.cc
index 58296be..df5ef07 100644
--- a/chrome/browser/chromeos/extensions/file_manager/event_router.cc
+++ b/chrome/browser/chromeos/extensions/file_manager/event_router.cc
@@ -21,7 +21,6 @@
 #include "chrome/browser/chromeos/extensions/file_manager/mounted_disk_monitor.h"
 #include "chrome/browser/chromeos/login/login_display_host_impl.h"
 #include "chrome/browser/chromeos/login/screen_locker.h"
-#include "chrome/browser/chromeos/net/connectivity_state_helper.h"
 #include "chrome/browser/drive/drive_service_interface.h"
 #include "chrome/browser/extensions/event_names.h"
 #include "chrome/browser/extensions/event_router.h"
@@ -30,12 +29,15 @@
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/common/pref_names.h"
 #include "chromeos/login/login_state.h"
+#include "chromeos/network/network_handler.h"
+#include "chromeos/network/network_state_handler.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/notification_source.h"
 #include "webkit/common/fileapi/file_system_types.h"
 #include "webkit/common/fileapi/file_system_util.h"
 
 using chromeos::disks::DiskMountManager;
+using chromeos::NetworkHandler;
 using content::BrowserThread;
 using drive::DriveIntegrationService;
 using drive::DriveIntegrationServiceFactory;
@@ -254,9 +256,9 @@
     integration_service->job_list()->RemoveObserver(this);
   }
 
-  if (chromeos::ConnectivityStateHelper::IsInitialized()) {
-    chromeos::ConnectivityStateHelper::Get()->
-        RemoveNetworkManagerObserver(this);
+  if (NetworkHandler::IsInitialized()) {
+    NetworkHandler::Get()->network_state_handler()->RemoveObserver(this,
+                                                                   FROM_HERE);
   }
   profile_ = NULL;
 }
@@ -288,9 +290,9 @@
     integration_service->job_list()->AddObserver(this);
   }
 
-  if (chromeos::ConnectivityStateHelper::IsInitialized()) {
-    chromeos::ConnectivityStateHelper::Get()->
-        AddNetworkManagerObserver(this);
+  if (NetworkHandler::IsInitialized()) {
+    NetworkHandler::Get()->network_state_handler()->AddObserver(this,
+                                                                FROM_HERE);
   }
 
   mounted_disk_monitor_.reset(new MountedDiskMonitor());
@@ -476,7 +478,7 @@
       BroadcastEvent(event.Pass());
 }
 
-void EventRouter::DefaultNetworkChanged() {
+void EventRouter::DefaultNetworkChanged(const chromeos::NetworkState* network) {
   NetworkManagerChanged();
 }
 
diff --git a/chrome/browser/chromeos/extensions/file_manager/event_router.h b/chrome/browser/chromeos/extensions/file_manager/event_router.h
index e10e30b..ae4cc86 100644
--- a/chrome/browser/chromeos/extensions/file_manager/event_router.h
+++ b/chrome/browser/chromeos/extensions/file_manager/event_router.h
@@ -14,13 +14,17 @@
 #include "chrome/browser/chromeos/drive/file_system_observer.h"
 #include "chrome/browser/chromeos/drive/job_list.h"
 #include "chrome/browser/chromeos/extensions/file_manager/file_watcher.h"
-#include "chrome/browser/chromeos/net/connectivity_state_helper_observer.h"
 #include "chrome/browser/drive/drive_service_interface.h"
 #include "chromeos/disks/disk_mount_manager.h"
+#include "chromeos/network/network_state_handler_observer.h"
 
 class PrefChangeRegistrar;
 class Profile;
 
+namespace chromeos {
+class NetworkState;
+}
+
 namespace file_manager {
 
 class DesktopNotifications;
@@ -30,7 +34,7 @@
 // affecting File Manager. Dispatches appropriate File Browser events.
 class EventRouter
     : public chromeos::disks::DiskMountManager::Observer,
-      public chromeos::ConnectivityStateHelperObserver,
+      public chromeos::NetworkStateHandlerObserver,
       public drive::DriveIntegrationServiceObserver,
       public drive::FileSystemObserver,
       public drive::JobListObserver,
@@ -77,9 +81,10 @@
       chromeos::FormatError error_code,
       const std::string& device_path) OVERRIDE;
 
-  // chromeos::ConnectivityStateHelperObserver override.
+  // chromeos::NetworkStateHandlerObserver overrides.
   virtual void NetworkManagerChanged() OVERRIDE;
-  virtual void DefaultNetworkChanged() OVERRIDE;
+  virtual void DefaultNetworkChanged(
+      const chromeos::NetworkState* network) OVERRIDE;
 
   // drive::JobListObserver overrides.
   virtual void OnJobAdded(const drive::JobInfo& job_info) OVERRIDE;
diff --git a/chrome/browser/chromeos/extensions/file_manager/file_browser_handlers.cc b/chrome/browser/chromeos/extensions/file_manager/file_browser_handlers.cc
new file mode 100644
index 0000000..771a5ac
--- /dev/null
+++ b/chrome/browser/chromeos/extensions/file_manager/file_browser_handlers.cc
@@ -0,0 +1,615 @@
+// 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/chromeos/extensions/file_manager/file_browser_handlers.h"
+
+#include "base/bind.h"
+#include "base/file_util.h"
+#include "base/i18n/case_conversion.h"
+#include "base/strings/utf_string_conversions.h"
+#include "chrome/browser/chromeos/drive/file_system_util.h"
+#include "chrome/browser/chromeos/extensions/file_manager/file_manager_util.h"
+#include "chrome/browser/chromeos/extensions/file_manager/fileapi_util.h"
+#include "chrome/browser/chromeos/fileapi/file_system_backend.h"
+#include "chrome/browser/extensions/event_router.h"
+#include "chrome/browser/extensions/extension_host.h"
+#include "chrome/browser/extensions/extension_service.h"
+#include "chrome/browser/extensions/extension_system.h"
+#include "chrome/browser/extensions/lazy_background_task_queue.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/common/extensions/api/file_browser_handlers/file_browser_handler.h"
+#include "chrome/common/extensions/background_info.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/child_process_security_policy.h"
+#include "content/public/browser/render_process_host.h"
+#include "content/public/browser/site_instance.h"
+#include "content/public/browser/web_contents.h"
+#include "net/base/escape.h"
+#include "webkit/browser/fileapi/file_system_context.h"
+#include "webkit/browser/fileapi/file_system_url.h"
+
+using content::BrowserThread;
+using content::ChildProcessSecurityPolicy;
+using content::SiteInstance;
+using content::WebContents;
+using extensions::Extension;
+using fileapi::FileSystemURL;
+
+namespace file_manager {
+namespace file_browser_handlers {
+namespace {
+
+// Returns process id of the process the extension is running in.
+int ExtractProcessFromExtensionId(Profile* profile,
+                                  const std::string& extension_id) {
+  GURL extension_url =
+      Extension::GetBaseURLFromExtensionId(extension_id);
+  ExtensionProcessManager* manager =
+    extensions::ExtensionSystem::Get(profile)->process_manager();
+
+  SiteInstance* site_instance = manager->GetSiteInstanceForURL(extension_url);
+  if (!site_instance || !site_instance->HasProcess())
+    return -1;
+  content::RenderProcessHost* process = site_instance->GetProcess();
+
+  return process->GetID();
+}
+
+// Finds a file browser handler that matches |action_id|. Returns NULL if not
+// found.
+const FileBrowserHandler* FindFileBrowserHandlerForActionId(
+    const Extension* extension,
+    const std::string& action_id) {
+  FileBrowserHandler::List* handler_list =
+      FileBrowserHandler::GetHandlers(extension);
+  for (FileBrowserHandler::List::const_iterator handler_iter =
+           handler_list->begin();
+       handler_iter != handler_list->end();
+       ++handler_iter) {
+    if (handler_iter->get()->id() == action_id)
+      return handler_iter->get();
+  }
+  return NULL;
+}
+
+std::string EscapedUtf8ToLower(const std::string& str) {
+  string16 utf16 = UTF8ToUTF16(
+      net::UnescapeURLComponent(str, net::UnescapeRule::NORMAL));
+  return net::EscapeUrlEncodedData(
+      UTF16ToUTF8(base::i18n::ToLower(utf16)),
+      false /* do not replace space with plus */);
+}
+
+// Finds file browser handlers that can handle the |selected_file_url|.
+FileBrowserHandlerList FindFileBrowserHandlersForURL(
+    Profile* profile,
+    const GURL& selected_file_url) {
+  ExtensionService* service =
+      extensions::ExtensionSystem::Get(profile)->extension_service();
+  // In unit-tests, we may not have an ExtensionService.
+  if (!service)
+    return FileBrowserHandlerList();
+
+  // We need case-insensitive matching, and pattern in the handler is already
+  // in lower case.
+  const GURL lowercase_url(EscapedUtf8ToLower(selected_file_url.spec()));
+
+  FileBrowserHandlerList results;
+  for (ExtensionSet::const_iterator iter = service->extensions()->begin();
+       iter != service->extensions()->end();
+       ++iter) {
+    const Extension* extension = iter->get();
+    if (profile->IsOffTheRecord() &&
+        !service->IsIncognitoEnabled(extension->id()))
+      continue;
+
+    FileBrowserHandler::List* handler_list =
+        FileBrowserHandler::GetHandlers(extension);
+    if (!handler_list)
+      continue;
+    for (FileBrowserHandler::List::const_iterator handler_iter =
+             handler_list->begin();
+         handler_iter != handler_list->end();
+         ++handler_iter) {
+      const FileBrowserHandler* handler = handler_iter->get();
+      if (!handler->MatchesURL(lowercase_url))
+        continue;
+
+      results.push_back(handler_iter->get());
+    }
+  }
+  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:
+//
+// 1) Open the "external" file system
+// 2) Set up permissions for the target files on the external file system.
+// 3) Raise onExecute event with the action ID and entries of the target
+//    files. The event will launch the file browser handler if not active.
+// 4) In the file browser handler, onExecute event is handled and executes the
+//    task in JavaScript.
+//
+// That said, the class itself does not execute a task. The task will be
+// executed in JavaScript.
+class FileBrowserHandlerExecutor {
+ public:
+  FileBrowserHandlerExecutor(Profile* profile,
+                             const Extension* extension,
+                             int32 tab_id,
+                             const std::string& action_id);
+
+  // Executes the task for each file. |done| will be run with the result.
+  void Execute(const std::vector<FileSystemURL>& file_urls,
+               const file_tasks::FileTaskFinishedCallback& done);
+
+ private:
+  // This object is responsible to delete itself.
+  virtual ~FileBrowserHandlerExecutor();
+
+  struct FileDefinition {
+    FileDefinition();
+    ~FileDefinition();
+
+    base::FilePath virtual_path;
+    base::FilePath absolute_path;
+    bool is_directory;
+  };
+
+  typedef std::vector<FileDefinition> FileDefinitionList;
+
+  // Checks legitimacy of file url and grants file RO access permissions from
+  // handler (target) extension and its renderer process.
+  static FileDefinitionList SetupFileAccessPermissions(
+      scoped_refptr<fileapi::FileSystemContext> file_system_context_handler,
+      const scoped_refptr<const Extension>& handler_extension,
+      const std::vector<FileSystemURL>& file_urls);
+
+  void DidOpenFileSystem(const std::vector<FileSystemURL>& file_urls,
+                         base::PlatformFileError result,
+                         const std::string& file_system_name,
+                         const GURL& file_system_root);
+
+  void ExecuteDoneOnUIThread(bool success);
+  void ExecuteFileActionsOnUIThread(const std::string& file_system_name,
+                                    const GURL& file_system_root,
+                                    const FileDefinitionList& file_list);
+  void SetupPermissionsAndDispatchEvent(const std::string& file_system_name,
+                                        const GURL& file_system_root,
+                                        const FileDefinitionList& file_list,
+                                        int handler_pid_in,
+                                        extensions::ExtensionHost* host);
+
+  // Registers file permissions from |handler_host_permissions_| with
+  // ChildProcessSecurityPolicy for process with id |handler_pid|.
+  void SetupHandlerHostFileAccessPermissions(
+      const FileDefinitionList& file_list,
+      const Extension* extension,
+      int handler_pid);
+
+  Profile* profile_;
+  scoped_refptr<const Extension> extension_;
+  int32 tab_id_;
+  const std::string action_id_;
+  file_tasks::FileTaskFinishedCallback done_;
+  base::WeakPtrFactory<FileBrowserHandlerExecutor> weak_ptr_factory_;
+
+  DISALLOW_COPY_AND_ASSIGN(FileBrowserHandlerExecutor);
+};
+
+FileBrowserHandlerExecutor::FileDefinition::FileDefinition()
+    : is_directory(false) {
+}
+
+FileBrowserHandlerExecutor::FileDefinition::~FileDefinition() {
+}
+
+// static
+FileBrowserHandlerExecutor::FileDefinitionList
+FileBrowserHandlerExecutor::SetupFileAccessPermissions(
+    scoped_refptr<fileapi::FileSystemContext> file_system_context_handler,
+    const scoped_refptr<const Extension>& handler_extension,
+    const std::vector<FileSystemURL>& file_urls) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+  DCHECK(handler_extension.get());
+
+  fileapi::ExternalFileSystemBackend* backend =
+      file_system_context_handler->external_backend();
+
+  FileDefinitionList file_list;
+  for (size_t i = 0; i < file_urls.size(); ++i) {
+    const FileSystemURL& url = file_urls[i];
+
+    // Check if this file system entry exists first.
+    base::PlatformFileInfo file_info;
+
+    base::FilePath local_path = url.path();
+    base::FilePath virtual_path = url.virtual_path();
+
+    bool is_drive_file = url.type() == fileapi::kFileSystemTypeDrive;
+    DCHECK(!is_drive_file || drive::util::IsUnderDriveMountPoint(local_path));
+
+    // If the file is under drive mount point, there is no actual file to be
+    // found on the url.path().
+    if (!is_drive_file) {
+      if (!base::PathExists(local_path) ||
+          file_util::IsLink(local_path) ||
+          !file_util::GetFileInfo(local_path, &file_info)) {
+        continue;
+      }
+    }
+
+    // Grant access to this particular file to target extension. This will
+    // ensure that the target extension can access only this FS entry and
+    // prevent from traversing FS hierarchy upward.
+    backend->GrantFileAccessToExtension(
+        handler_extension->id(), virtual_path);
+
+    // Output values.
+    FileDefinition file;
+    file.virtual_path = virtual_path;
+    file.is_directory = file_info.is_directory;
+    file.absolute_path = local_path;
+    file_list.push_back(file);
+  }
+  return file_list;
+}
+
+FileBrowserHandlerExecutor::FileBrowserHandlerExecutor(
+    Profile* profile,
+    const Extension* extension,
+    int32 tab_id,
+    const std::string& action_id)
+    : profile_(profile),
+      extension_(extension),
+      tab_id_(tab_id),
+      action_id_(action_id),
+      weak_ptr_factory_(this) {
+}
+
+FileBrowserHandlerExecutor::~FileBrowserHandlerExecutor() {}
+
+void FileBrowserHandlerExecutor::Execute(
+    const std::vector<FileSystemURL>& file_urls,
+    const file_tasks::FileTaskFinishedCallback& done) {
+  done_ = done;
+
+  // Get file system context for the extension to which onExecute event will be
+  // sent. The file access permissions will be granted to the extension in the
+  // file system context for the files in |file_urls|.
+  fileapi_util::GetFileSystemContextForExtensionId(
+      profile_, extension_->id())->OpenFileSystem(
+          Extension::GetBaseURLFromExtensionId(extension_->id()).GetOrigin(),
+          fileapi::kFileSystemTypeExternal,
+          fileapi::OPEN_FILE_SYSTEM_FAIL_IF_NONEXISTENT,
+          base::Bind(&FileBrowserHandlerExecutor::DidOpenFileSystem,
+                     weak_ptr_factory_.GetWeakPtr(),
+                     file_urls));
+}
+
+void FileBrowserHandlerExecutor::DidOpenFileSystem(
+    const std::vector<FileSystemURL>& file_urls,
+    base::PlatformFileError result,
+    const std::string& file_system_name,
+    const GURL& file_system_root) {
+  if (result != base::PLATFORM_FILE_OK) {
+    ExecuteDoneOnUIThread(false);
+    return;
+  }
+
+  scoped_refptr<fileapi::FileSystemContext> file_system_context(
+      fileapi_util::GetFileSystemContextForExtensionId(
+          profile_, extension_->id()));
+  BrowserThread::PostTaskAndReplyWithResult(
+      BrowserThread::FILE,
+      FROM_HERE,
+      base::Bind(&SetupFileAccessPermissions,
+                 file_system_context,
+                 extension_,
+                 file_urls),
+      base::Bind(&FileBrowserHandlerExecutor::ExecuteFileActionsOnUIThread,
+                 weak_ptr_factory_.GetWeakPtr(),
+                 file_system_name,
+                 file_system_root));
+}
+
+void FileBrowserHandlerExecutor::ExecuteDoneOnUIThread(bool success) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  if (!done_.is_null())
+    done_.Run(success);
+  delete this;
+}
+
+void FileBrowserHandlerExecutor::ExecuteFileActionsOnUIThread(
+    const std::string& file_system_name,
+    const GURL& file_system_root,
+    const FileDefinitionList& file_list) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+
+  if (file_list.empty()) {
+    ExecuteDoneOnUIThread(false);
+    return;
+  }
+
+  int handler_pid = ExtractProcessFromExtensionId(profile_, extension_->id());
+  if (handler_pid <= 0 &&
+      !extensions::BackgroundInfo::HasLazyBackgroundPage(extension_.get())) {
+    ExecuteDoneOnUIThread(false);
+    return;
+  }
+
+  if (handler_pid > 0) {
+    SetupPermissionsAndDispatchEvent(file_system_name, file_system_root,
+                                     file_list, handler_pid, NULL);
+  } else {
+    // We have to wake the handler background page before we proceed.
+    extensions::LazyBackgroundTaskQueue* queue =
+        extensions::ExtensionSystem::Get(profile_)->
+        lazy_background_task_queue();
+    if (!queue->ShouldEnqueueTask(profile_, extension_.get())) {
+      ExecuteDoneOnUIThread(false);
+      return;
+    }
+    queue->AddPendingTask(
+        profile_, extension_->id(),
+        base::Bind(
+            &FileBrowserHandlerExecutor::SetupPermissionsAndDispatchEvent,
+            weak_ptr_factory_.GetWeakPtr(),
+            file_system_name,
+            file_system_root,
+            file_list,
+            handler_pid));
+  }
+}
+
+void FileBrowserHandlerExecutor::SetupPermissionsAndDispatchEvent(
+    const std::string& file_system_name,
+    const GURL& file_system_root,
+    const FileDefinitionList& file_list,
+    int handler_pid_in,
+    extensions::ExtensionHost* host) {
+  int handler_pid = host ? host->render_process_host()->GetID() :
+      handler_pid_in;
+
+  if (handler_pid <= 0) {
+    ExecuteDoneOnUIThread(false);
+    return;
+  }
+
+  extensions::EventRouter* event_router =
+      extensions::ExtensionSystem::Get(profile_)->event_router();
+  if (!event_router) {
+    ExecuteDoneOnUIThread(false);
+    return;
+  }
+
+  SetupHandlerHostFileAccessPermissions(
+      file_list, extension_.get(), handler_pid);
+
+  scoped_ptr<ListValue> event_args(new ListValue());
+  event_args->Append(new base::StringValue(action_id_));
+  DictionaryValue* details = new DictionaryValue();
+  event_args->Append(details);
+  // Get file definitions. These will be replaced with Entry instances by
+  // dispatchEvent() method from event_binding.js.
+  ListValue* file_entries = new ListValue();
+  details->Set("entries", file_entries);
+  for (FileDefinitionList::const_iterator iter = file_list.begin();
+       iter != file_list.end();
+       ++iter) {
+    DictionaryValue* file_def = new DictionaryValue();
+    file_entries->Append(file_def);
+    file_def->SetString("fileSystemName", file_system_name);
+    file_def->SetString("fileSystemRoot", file_system_root.spec());
+    base::FilePath root(FILE_PATH_LITERAL("/"));
+    base::FilePath full_path = root.Append(iter->virtual_path);
+    file_def->SetString("fileFullPath", full_path.value());
+    file_def->SetBoolean("fileIsDirectory", iter->is_directory);
+  }
+
+  details->SetInteger("tab_id", tab_id_);
+
+  scoped_ptr<extensions::Event> event(new extensions::Event(
+      "fileBrowserHandler.onExecute", event_args.Pass()));
+  event->restrict_to_profile = profile_;
+  event_router->DispatchEventToExtension(extension_->id(), event.Pass());
+
+  ExecuteDoneOnUIThread(true);
+}
+
+void FileBrowserHandlerExecutor::SetupHandlerHostFileAccessPermissions(
+    const FileDefinitionList& file_list,
+    const Extension* extension,
+    int handler_pid) {
+  const FileBrowserHandler* action = FindFileBrowserHandlerForActionId(
+      extension_, action_id_);
+  for (FileDefinitionList::const_iterator iter = file_list.begin();
+       iter != file_list.end();
+       ++iter) {
+    if (!action)
+      continue;
+    if (action->CanRead()) {
+      content::ChildProcessSecurityPolicy::GetInstance()->GrantReadFile(
+          handler_pid, iter->absolute_path);
+    }
+    if (action->CanWrite()) {
+      content::ChildProcessSecurityPolicy::GetInstance()->
+          GrantCreateReadWriteFile(handler_pid, iter->absolute_path);
+    }
+  }
+}
+
+}  // namespace
+
+bool ExecuteFileBrowserHandler(
+    Profile* profile,
+    const Extension* extension,
+    int32 tab_id,
+    const std::string& action_id,
+    const std::vector<FileSystemURL>& file_urls,
+    const file_tasks::FileTaskFinishedCallback& done) {
+  // Forbid calling undeclared handlers.
+  if (!FindFileBrowserHandlerForActionId(extension, action_id))
+    return false;
+
+  // The executor object will be self deleted on completion.
+  (new FileBrowserHandlerExecutor(
+      profile, extension, tab_id, action_id))->Execute(file_urls, done);
+  return true;
+}
+
+bool IsFallbackFileBrowserHandler(const FileBrowserHandler* handler) {
+  const std::string& extension_id = handler->extension_id();
+  return (extension_id == kFileBrowserDomain ||
+          extension_id == extension_misc::kQuickOfficeComponentExtensionId ||
+          extension_id == extension_misc::kQuickOfficeDevExtensionId ||
+          extension_id == extension_misc::kQuickOfficeExtensionId);
+}
+
+FileBrowserHandlerList FindDefaultFileBrowserHandlers(
+    Profile* profile,
+    const std::vector<base::FilePath>& file_list,
+    const FileBrowserHandlerList& common_handlers) {
+  FileBrowserHandlerList default_handlers;
+
+  std::set<std::string> default_ids;
+  for (std::vector<base::FilePath>::const_iterator it = file_list.begin();
+       it != file_list.end(); ++it) {
+    std::string task_id = file_tasks::GetDefaultTaskIdFromPrefs(
+        profile, "", it->Extension());
+    if (!task_id.empty())
+      default_ids.insert(task_id);
+  }
+
+  const FileBrowserHandler* fallback_handler = NULL;
+  // Convert the default task IDs collected above to one of the handler pointers
+  // from common_handlers.
+  for (size_t i = 0; i < common_handlers.size(); ++i) {
+    const FileBrowserHandler* handler = common_handlers[i];
+    std::string task_id = file_tasks::MakeTaskID(
+        handler->extension_id(),
+        file_tasks::kFileBrowserHandlerTaskType,
+        handler->id());
+    std::set<std::string>::iterator default_iter = default_ids.find(task_id);
+    if (default_iter != default_ids.end()) {
+      default_handlers.push_back(handler);
+      continue;
+    }
+
+    // Remember the first fallback handler.
+    if (!fallback_handler && IsFallbackFileBrowserHandler(handler))
+      fallback_handler = handler;
+  }
+
+  // If there are no default handlers found, use fallback as default.
+  if (fallback_handler && default_handlers.empty())
+    default_handlers.push_back(fallback_handler);
+
+  return default_handlers;
+}
+
+FileBrowserHandlerList FindCommonFileBrowserHandlers(
+    Profile* profile,
+    const std::vector<GURL>& file_list) {
+  FileBrowserHandlerList common_handlers;
+  for (std::vector<GURL>::const_iterator it = file_list.begin();
+       it != file_list.end(); ++it) {
+    FileBrowserHandlerList handlers =
+        FindFileBrowserHandlersForURL(profile, *it);
+    // If there is nothing to do for one file, the intersection of handlers
+    // for all files will be empty at the end, so no need to check further.
+    if (handlers.empty())
+      return FileBrowserHandlerList();
+
+    // For the very first file, just copy all the elements.
+    if (it == file_list.begin()) {
+      common_handlers = handlers;
+    } else {
+      // For all additional files, find intersection between the accumulated and
+      // file specific set.
+      FileBrowserHandlerList intersection;
+      std::set_intersection(common_handlers.begin(), common_handlers.end(),
+                            handlers.begin(), handlers.end(),
+                            std::back_inserter(intersection));
+      common_handlers = intersection;
+      if (common_handlers.empty())
+        return FileBrowserHandlerList();
+    }
+  }
+
+  FileBrowserHandlerList::iterator watch_iter =
+      FindFileBrowserHandlerForExtensionIdAndActionId(
+          &common_handlers, kFileBrowserDomain, kFileBrowserWatchTaskId);
+  FileBrowserHandlerList::iterator gallery_iter =
+      FindFileBrowserHandlerForExtensionIdAndActionId(
+          &common_handlers, kFileBrowserDomain, kFileBrowserGalleryTaskId);
+  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;
+}
+
+const FileBrowserHandler* FindFileBrowserHandlerForURLAndPath(
+    Profile* profile,
+    const GURL& url,
+    const base::FilePath& file_path) {
+  std::vector<GURL> file_urls;
+  file_urls.push_back(url);
+
+  FileBrowserHandlerList common_handlers =
+      FindCommonFileBrowserHandlers(profile, file_urls);
+  if (common_handlers.empty())
+    return NULL;
+
+  std::vector<base::FilePath> file_paths;
+  file_paths.push_back(file_path);
+
+  FileBrowserHandlerList default_handlers =
+      FindDefaultFileBrowserHandlers(profile, file_paths, common_handlers);
+
+  // If there's none, or more than one, then we don't have a canonical default.
+  if (!default_handlers.empty()) {
+    // There should not be multiple default handlers for a single URL.
+    DCHECK_EQ(1u, default_handlers.size());
+
+    return *default_handlers.begin();
+  }
+
+  // If there are no default handlers, use first handler in the list (file
+  // manager does the same in this situation).  TODO(tbarzic): This is not so
+  // optimal behaviour.
+  return *common_handlers.begin();
+}
+
+}  // namespace file_browser_handlers
+}  // namespace file_manager
diff --git a/chrome/browser/chromeos/extensions/file_manager/file_browser_handlers.h b/chrome/browser/chromeos/extensions/file_manager/file_browser_handlers.h
new file mode 100644
index 0000000..87b5c92
--- /dev/null
+++ b/chrome/browser/chromeos/extensions/file_manager/file_browser_handlers.h
@@ -0,0 +1,84 @@
+// 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 provides utility functions for file browser handlers.
+// https://developer.chrome.com/extensions/fileBrowserHandler.html
+
+#ifndef CHROME_BROWSER_CHROMEOS_EXTENSIONS_FILE_MANAGER_FILE_BROWSER_HANDLERS_H_
+#define CHROME_BROWSER_CHROMEOS_EXTENSIONS_FILE_MANAGER_FILE_BROWSER_HANDLERS_H_
+
+#include <string>
+#include <vector>
+
+#include "base/basictypes.h"
+#include "base/callback_forward.h"
+#include "chrome/browser/chromeos/extensions/file_manager/file_tasks.h"
+
+class FileBrowserHandler;
+class GURL;
+class Profile;
+
+namespace base {
+class FilePath;
+}
+
+namespace extensions {
+class Extension;
+}
+
+namespace fileapi {
+class FileSystemURL;
+}
+
+namespace file_manager {
+namespace file_browser_handlers {
+
+// Tasks are stored as a vector in order of priorities.
+typedef std::vector<const FileBrowserHandler*> FileBrowserHandlerList;
+
+// Returns true if the given file browser handler should be used as a
+// fallback. Such handlers are Files.app's internal handlers as well as quick
+// office extensions.
+bool IsFallbackFileBrowserHandler(const FileBrowserHandler* handler);
+
+// Finds file browser handlers set as default from |common_tasks| for
+// |file_list|. If no handlers are set as default, choose the the firstly
+// found fallback handler as default.
+FileBrowserHandlerList FindDefaultFileBrowserHandlers(
+    Profile* profile,
+    const std::vector<base::FilePath>& file_list,
+    const FileBrowserHandlerList& common_tasks);
+
+// Returns the list of file browser handlers that can open all files in
+// |file_list|.
+FileBrowserHandlerList FindCommonFileBrowserHandlers(
+    Profile* profile,
+    const std::vector<GURL>& file_list);
+
+// Finds a file browser handler for a file whose URL is |url| and whose path
+// is |path|. Returns the default handler if one is defined (The default
+// handler is the one that is assigned to the file manager task button by
+// default). If the default handler is not found, tries to match the url with
+// one of the file browser handlers.
+const FileBrowserHandler* FindFileBrowserHandlerForURLAndPath(
+    Profile* profile,
+    const GURL& url,
+    const base::FilePath& path);
+
+// Executes a file browser handler specified by |extension| of the given
+// action ID for |file_urls|. Returns false if undeclared handlers are
+// found. |done| is on completion. See also the comment at ExecuteFileTask()
+// for other parameters.
+bool ExecuteFileBrowserHandler(
+    Profile* profile,
+    const extensions::Extension* extension,
+    int32 tab_id,
+    const std::string& action_id,
+    const std::vector<fileapi::FileSystemURL>& file_urls,
+    const file_tasks::FileTaskFinishedCallback& done);
+
+}  // namespace file_browser_handlers
+}  // namespace file_manager
+
+#endif  // CHROME_BROWSER_CHROMEOS_EXTENSIONS_FILE_MANAGER_FILE_BROWSER_HANDLERS_H_
diff --git a/chrome/browser/chromeos/extensions/file_manager/file_manager_util.cc b/chrome/browser/chromeos/extensions/file_manager/file_manager_util.cc
index e38c55b..9e9d34a 100644
--- a/chrome/browser/chromeos/extensions/file_manager/file_manager_util.cc
+++ b/chrome/browser/chromeos/extensions/file_manager/file_manager_util.cc
@@ -18,7 +18,9 @@
 #include "chrome/browser/chromeos/drive/drive_integration_service.h"
 #include "chrome/browser/chromeos/drive/file_system.h"
 #include "chrome/browser/chromeos/drive/file_system_util.h"
+#include "chrome/browser/chromeos/extensions/file_manager/file_browser_handlers.h"
 #include "chrome/browser/chromeos/extensions/file_manager/file_tasks.h"
+#include "chrome/browser/chromeos/extensions/file_manager/fileapi_util.h"
 #include "chrome/browser/chromeos/media/media_player.h"
 #include "chrome/browser/extensions/api/file_handlers/app_file_handler_util.h"
 #include "chrome/browser/extensions/crx_installer.h"
@@ -98,15 +100,6 @@
     ".mhtml", ".mht", ".svg"
 };
 
-// List of all extensions we want to be shown in histogram that keep track of
-// files that were unsuccessfully tried to be opened.
-// The list has to be synced with histogram values.
-const char* kUMATrackingExtensions[] = {
-  "other", ".doc", ".docx", ".odt", ".rtf", ".pdf", ".ppt", ".pptx", ".odp",
-  ".xls", ".xlsx", ".ods", ".csv", ".odf", ".rar", ".asf", ".wma", ".wmv",
-  ".mov", ".mpg", ".log"
-};
-
 // Returns a file manager URL for the given |path|.
 GURL GetFileManagerUrl(const char* path) {
   return GURL(std::string("chrome-extension://") + kFileBrowserDomain + path);
@@ -154,19 +147,6 @@
   return IsPepperPluginEnabled(profile, plugin_path);
 }
 
-// Returns index |ext| has in the |array|. If there is no |ext| in |array|, last
-// element's index is return (last element should have irrelevant value).
-int UMAExtensionIndex(const char *file_extension,
-                      const char** array,
-                      size_t array_size) {
-  for (size_t i = 0; i < array_size; i++) {
-    if (base::strcasecmp(file_extension, array[i]) == 0) {
-      return i;
-    }
-  }
-  return 0;
-}
-
 // Convert numeric dialog type to a string.
 std::string GetDialogTypeAsString(
     ui::SelectFileDialog::Type dialog_type) {
@@ -238,7 +218,8 @@
   scoped_refptr<extensions::CrxInstaller> installer(
       extensions::CrxInstaller::Create(
           service,
-          new ExtensionInstallPrompt(browser->profile(), NULL, NULL)));
+          scoped_ptr<ExtensionInstallPrompt>(new ExtensionInstallPrompt(
+              browser->profile(), NULL, NULL))));
   installer->set_error_on_unsupported_requirements(true);
   installer->set_is_gallery_install(false);
   installer->set_allow_silent_install(false);
@@ -270,22 +251,18 @@
   return true;
 }
 
-// Executes handler specified with |extension_id| and |action_id| for |url|.
+// Executes handler specified with |task| for |url|.
 void ExecuteHandler(Profile* profile,
-                    std::string extension_id,
-                    std::string action_id,
-                    const GURL& url,
-                    const std::string& task_type) {
+                    const file_tasks::TaskDescriptor& task,
+                    const GURL& url) {
   // If File Browser has not been open yet then it did not request access
   // to the file system. Do it now.
   if (!GrantFileSystemAccessToFileBrowser(profile))
     return;
 
-  GURL site = extensions::ExtensionSystem::Get(profile)->extension_service()->
-      GetSiteForExtensionId(kFileBrowserDomain);
   fileapi::FileSystemContext* file_system_context =
-      BrowserContext::GetStoragePartitionForSite(profile, site)->
-          GetFileSystemContext();
+      fileapi_util::GetFileSystemContextForExtensionId(
+          profile, kFileBrowserDomain);
 
   // We are executing the task on behalf of File Browser extension.
   const GURL source_url = GetFileBrowserUrl();
@@ -297,9 +274,7 @@
       source_url,
       kFileBrowserDomain,
       0, // no tab id
-      extension_id,
-      task_type,
-      action_id,
+      task,
       urls,
       file_tasks::FileTaskFinishedCallback());
 }
@@ -313,10 +288,10 @@
   if (!ConvertFileToFileSystemUrl(profile, path, kFileBrowserDomain, &url))
     return;
 
-  // Some values of |action_id| are not listed in the manifest and are used
-  // to parameterize the behavior when opening the Files app window.
-  ExecuteHandler(profile, kFileBrowserDomain, action_id, url,
-                 file_tasks::kTaskFile);
+  file_tasks::TaskDescriptor task(kFileBrowserDomain,
+                                  file_tasks::kFileBrowserHandlerTaskType,
+                                  action_id);
+  ExecuteHandler(profile, task, url);
 }
 
 Browser* GetBrowserForUrl(GURL target_url) {
@@ -370,11 +345,15 @@
     for (FileHandlerList::iterator i = file_handlers.begin();
          i != file_handlers.end(); ++i) {
       const extensions::FileHandlerInfo* handler = *i;
-      std::string task_id = file_tasks::MakeTaskID(extension->id(),
-          file_tasks::kTaskApp, handler->id);
+      std::string task_id = file_tasks::MakeTaskID(
+          extension->id(),
+          file_tasks::kFileHandlerTaskType,
+          handler->id);
       if (task_id == default_task_id) {
-        ExecuteHandler(profile, extension->id(), handler->id, url,
-                       file_tasks::kTaskApp);
+        file_tasks::TaskDescriptor task(extension->id(),
+                                        file_tasks::kFileHandlerTaskType,
+                                        handler->id);
+        ExecuteHandler(profile, task, url);
         return true;
 
       } else if (!first_handler) {
@@ -384,8 +363,10 @@
     }
   }
   if (first_handler) {
-    ExecuteHandler(profile, extension_for_first_handler->id(),
-                   first_handler->id, url, file_tasks::kTaskApp);
+    file_tasks::TaskDescriptor task(extension_for_first_handler->id(),
+                                    file_tasks::kFileHandlerTaskType,
+                                    first_handler->id);
+    ExecuteHandler(profile, task, url);
     return true;
   }
   return false;
@@ -410,15 +391,19 @@
         action_id == kFileBrowserMountArchiveTaskId ||
         action_id == kFileBrowserPlayTaskId ||
         action_id == kFileBrowserWatchTaskId) {
-      ExecuteHandler(profile, extension_id, action_id, url,
-                     file_tasks::kTaskFile);
+      file_tasks::TaskDescriptor task(extension_id,
+                                      file_tasks::kFileBrowserHandlerTaskType,
+                                      action_id);
+      ExecuteHandler(profile, task, url);
       return true;
     }
     return ExecuteBuiltinHandler(browser, path);
   }
 
-  ExecuteHandler(profile, extension_id, action_id, url,
-                 file_tasks::kTaskFile);
+  file_tasks::TaskDescriptor task(extension_id,
+                                  file_tasks::kFileBrowserHandlerTaskType,
+                                  action_id);
+  ExecuteHandler(profile, task, url);
   return true;
 }
 
@@ -430,7 +415,6 @@
   std::string mime_type = GetMimeTypeForPath(path);
   std::string default_task_id = file_tasks::GetDefaultTaskIdFromPrefs(
       profile, mime_type, path.Extension());
-  const FileBrowserHandler* handler;
 
   // We choose the file handler from the following in decreasing priority or
   // fail if none support the file type:
@@ -440,15 +424,20 @@
   // 4. non-default app
   // 5. non-default extension
   // Note that there can be at most one of default extension and default app.
-  if (!file_tasks::GetTaskForURLAndPath(profile, url, path, &handler)) {
+  const FileBrowserHandler* handler =
+      file_browser_handlers::FindFileBrowserHandlerForURLAndPath(
+          profile, url, path);
+  if (!handler) {
     return ExecuteDefaultAppHandler(
         profile, path, url, mime_type, default_task_id);
   }
 
   std::string handler_task_id = file_tasks::MakeTaskID(
-        handler->extension_id(), file_tasks::kTaskFile, handler->id());
+        handler->extension_id(),
+        file_tasks::kFileBrowserHandlerTaskType,
+        handler->id());
   if (handler_task_id != default_task_id &&
-      !file_tasks::IsFallbackTask(handler) &&
+      !file_browser_handlers::IsFallbackFileBrowserHandler(handler) &&
       ExecuteDefaultAppHandler(
           profile, path, url, mime_type, default_task_id)) {
     return true;
@@ -740,11 +729,9 @@
     return;
   }
 
-  GURL site = extensions::ExtensionSystem::Get(profile)->extension_service()->
-      GetSiteForExtensionId(kFileBrowserDomain);
   scoped_refptr<fileapi::FileSystemContext> file_system_context =
-      BrowserContext::GetStoragePartitionForSite(profile, site)->
-      GetFileSystemContext();
+      fileapi_util::GetFileSystemContextForExtensionId(
+          profile, kFileBrowserDomain);
 
   CheckIfDirectoryExists(file_system_context, url,
                          base::Bind(&ContinueViewItem, profile, path));
@@ -807,13 +794,8 @@
     return true;
   }
 
-  // Unknown file type. Record UMA and show an error message.
-  size_t extension_index = UMAExtensionIndex(file_extension.data(),
-                                             kUMATrackingExtensions,
-                                             arraysize(kUMATrackingExtensions));
-  UMA_HISTOGRAM_ENUMERATION("FileBrowser.OpeningFileType",
-                            extension_index,
-                            arraysize(kUMATrackingExtensions) - 1);
+  // Failed to open the file of unknown type.
+  LOG(WARNING) << "Unknown file type: " << path.value();
   return false;
 }
 
diff --git a/chrome/browser/chromeos/extensions/file_manager/file_tasks.cc b/chrome/browser/chromeos/extensions/file_manager/file_tasks.cc
index 609cf4c..00f1cd1 100644
--- a/chrome/browser/chromeos/extensions/file_manager/file_tasks.cc
+++ b/chrome/browser/chromeos/extensions/file_manager/file_tasks.cc
@@ -6,55 +6,36 @@
 
 #include "apps/launcher.h"
 #include "base/bind.h"
-#include "base/file_util.h"
-#include "base/i18n/case_conversion.h"
-#include "base/strings/string_util.h"
 #include "base/strings/stringprintf.h"
-#include "base/strings/utf_string_conversions.h"
-#include "chrome/browser/chromeos/drive/file_system_util.h"
 #include "chrome/browser/chromeos/drive/file_task_executor.h"
+#include "chrome/browser/chromeos/extensions/file_manager/file_browser_handlers.h"
 #include "chrome/browser/chromeos/extensions/file_manager/file_manager_util.h"
+#include "chrome/browser/chromeos/extensions/file_manager/fileapi_util.h"
 #include "chrome/browser/chromeos/fileapi/file_system_backend.h"
-#include "chrome/browser/extensions/event_router.h"
 #include "chrome/browser/extensions/extension_host.h"
 #include "chrome/browser/extensions/extension_service.h"
 #include "chrome/browser/extensions/extension_system.h"
 #include "chrome/browser/extensions/extension_tab_util.h"
-#include "chrome/browser/extensions/lazy_background_task_queue.h"
-#include "chrome/browser/prefs/scoped_user_pref_update.h"
 #include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/ui/browser.h"
-#include "chrome/browser/ui/browser_tabstrip.h"
-#include "chrome/browser/ui/host_desktop.h"
-#include "chrome/common/extensions/api/file_browser_handlers/file_browser_handler.h"
-#include "chrome/common/extensions/background_info.h"
 #include "chrome/common/pref_names.h"
-#include "content/public/browser/browser_thread.h"
-#include "content/public/browser/child_process_security_policy.h"
-#include "content/public/browser/render_process_host.h"
-#include "content/public/browser/site_instance.h"
-#include "content/public/browser/storage_partition.h"
-#include "content/public/browser/web_contents.h"
-#include "net/base/escape.h"
 #include "webkit/browser/fileapi/file_system_context.h"
 #include "webkit/browser/fileapi/file_system_url.h"
-#include "webkit/browser/fileapi/isolated_context.h"
-#include "webkit/common/fileapi/file_system_util.h"
 
-using content::BrowserContext;
-using content::BrowserThread;
-using content::ChildProcessSecurityPolicy;
-using content::SiteInstance;
-using content::WebContents;
 using extensions::Extension;
 using fileapi::FileSystemURL;
 
 namespace file_manager {
 namespace file_tasks {
 
-const char kTaskFile[] = "file";
-const char kTaskDrive[] = "drive";
-const char kTaskApp[] = "app";
+// The values "file" and "app" are confusing, but cannot be changed easily as
+// these are used in default task IDs stored in preferences.
+//
+// TODO(satorux): We should rename them to "file_browser_handler" and
+// "file_handler" respectively when switching from preferences to
+// chrome.storage crbug.com/267359
+const char kFileBrowserHandlerTaskType[] = "file";
+const char kFileHandlerTaskType[] = "app";
+const char kDriveTaskType[] = "drive";
 
 namespace {
 
@@ -63,91 +44,6 @@
 const size_t kDriveTaskExtensionPrefixLength =
     arraysize(kDriveTaskExtensionPrefix) - 1;
 
-// Returns process id of the process the extension is running in.
-int ExtractProcessFromExtensionId(Profile* profile,
-                                  const std::string& extension_id) {
-  GURL extension_url =
-      Extension::GetBaseURLFromExtensionId(extension_id);
-  ExtensionProcessManager* manager =
-    extensions::ExtensionSystem::Get(profile)->process_manager();
-
-  SiteInstance* site_instance = manager->GetSiteInstanceForURL(extension_url);
-  if (!site_instance || !site_instance->HasProcess())
-    return -1;
-  content::RenderProcessHost* process = site_instance->GetProcess();
-
-  return process->GetID();
-}
-
-const FileBrowserHandler* FindFileBrowserHandler(const Extension* extension,
-                                                 const std::string& action_id) {
-  FileBrowserHandler::List* handler_list =
-      FileBrowserHandler::GetHandlers(extension);
-  for (FileBrowserHandler::List::const_iterator action_iter =
-           handler_list->begin();
-       action_iter != handler_list->end();
-       ++action_iter) {
-    if (action_iter->get()->id() == action_id)
-      return action_iter->get();
-  }
-  return NULL;
-}
-
-std::string EscapedUtf8ToLower(const std::string& str) {
-  string16 utf16 = UTF8ToUTF16(
-      net::UnescapeURLComponent(str, net::UnescapeRule::NORMAL));
-  return net::EscapeUrlEncodedData(
-      UTF16ToUTF8(base::i18n::ToLower(utf16)),
-      false /* do not replace space with plus */);
-}
-
-bool GetFileBrowserHandlers(Profile* profile,
-                            const GURL& selected_file_url,
-                            FileBrowserHandlerList* results) {
-  ExtensionService* service =
-      extensions::ExtensionSystem::Get(profile)->extension_service();
-  if (!service)
-    return false;  // In unit-tests, we may not have an ExtensionService.
-
-  // We need case-insensitive matching, and pattern in the handler is already
-  // in lower case.
-  const GURL lowercase_url(EscapedUtf8ToLower(selected_file_url.spec()));
-
-  for (ExtensionSet::const_iterator iter = service->extensions()->begin();
-       iter != service->extensions()->end();
-       ++iter) {
-    const Extension* extension = iter->get();
-    if (profile->IsOffTheRecord() &&
-        !service->IsIncognitoEnabled(extension->id()))
-      continue;
-
-    FileBrowserHandler::List* handler_list =
-        FileBrowserHandler::GetHandlers(extension);
-    if (!handler_list)
-      continue;
-    for (FileBrowserHandler::List::const_iterator action_iter =
-             handler_list->begin();
-         action_iter != handler_list->end();
-         ++action_iter) {
-      const FileBrowserHandler* action = action_iter->get();
-      if (!action->MatchesURL(lowercase_url))
-        continue;
-
-      results->push_back(action_iter->get());
-    }
-  }
-  return true;
-}
-
-fileapi::FileSystemContext* GetFileSystemContextForExtension(
-    Profile* profile,
-    const std::string& extension_id) {
-  GURL site = extensions::ExtensionSystem::Get(profile)->
-      extension_service()->GetSiteForExtensionId(extension_id);
-  return BrowserContext::GetStoragePartitionForSite(profile, site)->
-      GetFileSystemContext();
-}
-
 // Checks if the file browser extension has permissions for the files in its
 // file system context.
 bool FileBrowserHasAccessPermissionForFiles(
@@ -156,8 +52,8 @@
     const std::string& file_browser_id,
     const std::vector<FileSystemURL>& files) {
   fileapi::ExternalFileSystemBackend* backend =
-      GetFileSystemContextForExtension(profile, file_browser_id)->
-      external_backend();
+      fileapi_util::GetFileSystemContextForExtensionId(
+          profile, file_browser_id)->external_backend();
   if (!backend)
     return false;
 
@@ -177,14 +73,6 @@
 
 }  // namespace
 
-bool IsFallbackTask(const FileBrowserHandler* task) {
-  return (task->extension_id() == kFileBrowserDomain ||
-          task->extension_id() ==
-              extension_misc::kQuickOfficeComponentExtensionId ||
-          task->extension_id() == extension_misc::kQuickOfficeDevExtensionId ||
-          task->extension_id() == extension_misc::kQuickOfficeExtensionId);
-}
-
 void UpdateDefaultTask(Profile* profile,
                        const std::string& task_id,
                        const std::set<std::string>& suffixes,
@@ -247,41 +135,39 @@
 std::string MakeTaskID(const std::string& extension_id,
                        const std::string& task_type,
                        const std::string& action_id) {
-  DCHECK(task_type == kTaskFile ||
-         task_type == kTaskDrive ||
-         task_type == kTaskApp);
+  DCHECK(task_type == kFileBrowserHandlerTaskType ||
+         task_type == kDriveTaskType ||
+         task_type == kFileHandlerTaskType);
   return base::StringPrintf("%s|%s|%s",
                             extension_id.c_str(),
                             task_type.c_str(),
                             action_id.c_str());
 }
 
-bool CrackTaskID(const std::string& task_id,
-                 std::string* extension_id,
-                 std::string* task_type,
-                 std::string* action_id) {
+std::string MakeDriveAppTaskId(const std::string& app_id) {
+  return MakeTaskID(app_id, kDriveTaskType, "open-with");
+}
+
+bool ParseTaskID(const std::string& task_id, TaskDescriptor* task) {
+  DCHECK(task);
+
   std::vector<std::string> result;
   int count = Tokenize(task_id, std::string("|"), &result);
 
-  // Parse historic task_id parameters that only contain two parts. Drive tasks
-  // are identified by a prefix "drive-app:" on the extension ID.
+  // Parse a legacy task ID that only contain two parts. Drive tasks are
+  // identified by a prefix "drive-app:" on the extension ID. The legacy task
+  // IDs can be stored in preferences.
+  // TODO(satorux): We should get rid of this code: crbug.com/267359.
   if (count == 2) {
     if (StartsWithASCII(result[0], kDriveTaskExtensionPrefix, true)) {
-      if (task_type)
-        *task_type = kTaskDrive;
-
-      if (extension_id)
-        *extension_id = result[0].substr(kDriveTaskExtensionPrefixLength);
+      task->task_type = kDriveTaskType;
+      task->app_id = result[0].substr(kDriveTaskExtensionPrefixLength);
     } else {
-      if (task_type)
-        *task_type = kTaskFile;
-
-      if (extension_id)
-        *extension_id = result[0];
+      task->task_type = kFileBrowserHandlerTaskType;
+      task->app_id = result[0];
     }
 
-    if (action_id)
-      *action_id = result[1];
+    task->action_id = result[1];
 
     return true;
   }
@@ -289,242 +175,21 @@
   if (count != 3)
     return false;
 
-  if (extension_id)
-    *extension_id = result[0];
-
-  if (task_type) {
-    *task_type = result[1];
-    DCHECK(*task_type == kTaskFile ||
-           *task_type == kTaskDrive ||
-           *task_type == kTaskApp);
-  }
-
-  if (action_id)
-    *action_id = result[2];
+ task->app_id = result[0];
+ task->task_type = result[1];
+ DCHECK(task->task_type == kFileBrowserHandlerTaskType ||
+        task->task_type == kDriveTaskType ||
+        task->task_type == kFileHandlerTaskType);
+ task->action_id = result[2];
 
   return true;
 }
 
-// Find a specific handler in the handler list.
-FileBrowserHandlerList::iterator FindHandler(
-    FileBrowserHandlerList* handler_list,
-    const std::string& extension_id,
-    const std::string& id) {
-  FileBrowserHandlerList::iterator iter = handler_list->begin();
-  while (iter != handler_list->end() &&
-         !((*iter)->extension_id() == extension_id &&
-           (*iter)->id() == id)) {
-    ++iter;
-  }
-  return iter;
-}
-
-// Given the list of selected files, returns array of file action tasks
-// that are shared between them.
-void FindDefaultTasks(Profile* profile,
-                      const std::vector<base::FilePath>& files_list,
-                      const FileBrowserHandlerList& common_tasks,
-                      FileBrowserHandlerList* default_tasks) {
-  DCHECK(default_tasks);
-  default_tasks->clear();
-
-  std::set<std::string> default_ids;
-  for (std::vector<base::FilePath>::const_iterator it = files_list.begin();
-       it != files_list.end(); ++it) {
-    std::string task_id = file_tasks::GetDefaultTaskIdFromPrefs(
-        profile, "", it->Extension());
-    if (!task_id.empty())
-      default_ids.insert(task_id);
-  }
-
-  const FileBrowserHandler* fallback_task = NULL;
-  // Convert the default task IDs collected above to one of the handler pointers
-  // from common_tasks.
-  for (FileBrowserHandlerList::const_iterator task_iter = common_tasks.begin();
-       task_iter != common_tasks.end(); ++task_iter) {
-    std::string task_id = MakeTaskID((*task_iter)->extension_id(), kTaskFile,
-                                     (*task_iter)->id());
-    std::set<std::string>::iterator default_iter = default_ids.find(task_id);
-    if (default_iter != default_ids.end()) {
-      default_tasks->push_back(*task_iter);
-      continue;
-    }
-
-    // Remember the first fallback task.
-    if (!fallback_task && IsFallbackTask(*task_iter))
-      fallback_task = *task_iter;
-  }
-
-  // If there are no default tasks found, use fallback as default.
-  if (fallback_task && default_tasks->empty())
-    default_tasks->push_back(fallback_task);
-}
-
-// Given the list of selected files, returns array of context menu tasks
-// that are shared
-bool FindCommonTasks(Profile* profile,
-                     const std::vector<GURL>& files_list,
-                     FileBrowserHandlerList* common_tasks) {
-  DCHECK(common_tasks);
-  common_tasks->clear();
-
-  FileBrowserHandlerList common_task_list;
-  std::set<std::string> default_task_ids;
-  for (std::vector<GURL>::const_iterator it = files_list.begin();
-       it != files_list.end(); ++it) {
-    FileBrowserHandlerList file_actions;
-    if (!GetFileBrowserHandlers(profile, *it, &file_actions))
-      return false;
-    // If there is nothing to do for one file, the intersection of tasks for all
-    // files will be empty at the end, and so will the default tasks.
-    if (file_actions.empty())
-      return true;
-
-    // For the very first file, just copy all the elements.
-    if (it == files_list.begin()) {
-      common_task_list = file_actions;
-    } else {
-      // For all additional files, find intersection between the accumulated and
-      // file specific set.
-      FileBrowserHandlerList intersection;
-      std::set_intersection(common_task_list.begin(), common_task_list.end(),
-                            file_actions.begin(), file_actions.end(),
-                            std::back_inserter(intersection));
-      common_task_list = intersection;
-      if (common_task_list.empty())
-        return true;
-    }
-  }
-
-  FileBrowserHandlerList::iterator watch_iter = FindHandler(
-      &common_task_list, kFileBrowserDomain, kFileBrowserWatchTaskId);
-  FileBrowserHandlerList::iterator gallery_iter = FindHandler(
-      &common_task_list, kFileBrowserDomain, kFileBrowserGalleryTaskId);
-  if (watch_iter != common_task_list.end() &&
-      gallery_iter != common_task_list.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 (files_list.size() == 1)
-      common_task_list.erase(gallery_iter);
-    else
-      common_task_list.erase(watch_iter);
-  }
-
-  common_tasks->swap(common_task_list);
-  return true;
-}
-
-bool GetTaskForURLAndPath(Profile* profile,
-                   const GURL& url,
-                   const base::FilePath& file_path,
-                   const FileBrowserHandler** handler) {
-  std::vector<GURL> file_urls;
-  file_urls.push_back(url);
-
-  FileBrowserHandlerList default_tasks;
-  FileBrowserHandlerList common_tasks;
-  if (!FindCommonTasks(profile, file_urls, &common_tasks))
-    return false;
-
-  if (common_tasks.empty())
-    return false;
-
-  std::vector<base::FilePath> file_paths;
-  file_paths.push_back(file_path);
-
-  FindDefaultTasks(profile, file_paths, common_tasks, &default_tasks);
-
-  // If there's none, or more than one, then we don't have a canonical default.
-  if (!default_tasks.empty()) {
-    // There should not be multiple default tasks for a single URL.
-    DCHECK_EQ(1u, default_tasks.size());
-
-    *handler = *default_tasks.begin();
-    return true;
-  }
-
-  // If there are no default tasks, use first task in the list (file manager
-  // does the same in this situation).
-  // TODO(tbarzic): This is so not optimal behaviour.
-  *handler = *common_tasks.begin();
-  return true;
-}
-
-// ExtensionTaskExecutor executes tasks with kTaskFile type.
-class ExtensionTaskExecutor {
- public:
-  ExtensionTaskExecutor(Profile* profile,
-                        const Extension* extension,
-                        int32 tab_id,
-                        const std::string& action_id);
-
-  // Executes the task for each file. |done| will be run with the result.
-  void Execute(const std::vector<FileSystemURL>& file_urls,
-               const FileTaskFinishedCallback& done);
-
- private:
-  // This object is responsible to delete itself.
-  virtual ~ExtensionTaskExecutor();
-
-  struct FileDefinition {
-    FileDefinition();
-    ~FileDefinition();
-
-    base::FilePath virtual_path;
-    base::FilePath absolute_path;
-    bool is_directory;
-  };
-
-  typedef std::vector<FileDefinition> FileDefinitionList;
-
-  // Checks legitimacy of file url and grants file RO access permissions from
-  // handler (target) extension and its renderer process.
-  static FileDefinitionList SetupFileAccessPermissions(
-      scoped_refptr<fileapi::FileSystemContext> file_system_context_handler,
-      const scoped_refptr<const Extension>& handler_extension,
-      const std::vector<FileSystemURL>& file_urls);
-
-  void DidOpenFileSystem(const std::vector<FileSystemURL>& file_urls,
-                         base::PlatformFileError result,
-                         const std::string& file_system_name,
-                         const GURL& file_system_root);
-
-  void ExecuteDoneOnUIThread(bool success);
-  void ExecuteFileActionsOnUIThread(const std::string& file_system_name,
-                                    const GURL& file_system_root,
-                                    const FileDefinitionList& file_list);
-  void SetupPermissionsAndDispatchEvent(const std::string& file_system_name,
-                                        const GURL& file_system_root,
-                                        const FileDefinitionList& file_list,
-                                        int handler_pid_in,
-                                        extensions::ExtensionHost* host);
-
-  // Registers file permissions from |handler_host_permissions_| with
-  // ChildProcessSecurityPolicy for process with id |handler_pid|.
-  void SetupHandlerHostFileAccessPermissions(
-      const FileDefinitionList& file_list,
-      const Extension* extension,
-      int handler_pid);
-
-  Profile* profile_;
-  scoped_refptr<const Extension> extension_;
-  int32 tab_id_;
-  const std::string action_id_;
-  FileTaskFinishedCallback done_;
-  base::WeakPtrFactory<ExtensionTaskExecutor> weak_ptr_factory_;
-
-  DISALLOW_COPY_AND_ASSIGN(ExtensionTaskExecutor);
-};
-
 bool ExecuteFileTask(Profile* profile,
                      const GURL& source_url,
                      const std::string& file_browser_id,
                      int32 tab_id,
-                     const std::string& extension_id,
-                     const std::string& task_type,
-                     const std::string& action_id,
+                     const TaskDescriptor& task,
                      const std::vector<FileSystemURL>& file_urls,
                      const FileTaskFinishedCallback& done) {
   if (!FileBrowserHasAccessPermissionForFiles(profile, source_url,
@@ -532,10 +197,10 @@
     return false;
 
   // drive::FileTaskExecutor is responsible to handle drive tasks.
-  if (task_type == kTaskDrive) {
-    DCHECK_EQ("open-with", action_id);
+  if (task.task_type == kDriveTaskType) {
+    DCHECK_EQ("open-with", task.action_id);
     drive::FileTaskExecutor* executor =
-        new drive::FileTaskExecutor(profile, extension_id);
+        new drive::FileTaskExecutor(profile, task.app_id);
     executor->Execute(file_urls, done);
     return true;
   }
@@ -544,23 +209,23 @@
   ExtensionService* service =
       extensions::ExtensionSystem::Get(profile)->extension_service();
   const Extension* extension = service ?
-      service->GetExtensionById(extension_id, false) : NULL;
+      service->GetExtensionById(task.app_id, false) : NULL;
   if (!extension)
     return false;
 
   // Execute the task.
-  if (task_type == kTaskFile) {
-    // Forbid calling undeclared handlers.
-    if (!FindFileBrowserHandler(extension, action_id))
-      return false;
-
-    (new ExtensionTaskExecutor(
-        profile, extension, tab_id, action_id))->Execute(file_urls, done);
-    return true;
-  } else if (task_type == kTaskApp) {
+  if (task.task_type == kFileBrowserHandlerTaskType) {
+    return file_browser_handlers::ExecuteFileBrowserHandler(
+        profile,
+        extension,
+        tab_id,
+        task.action_id,
+        file_urls,
+        done);
+  } else if (task.task_type == kFileHandlerTaskType) {
     for (size_t i = 0; i != file_urls.size(); ++i) {
       apps::LaunchPlatformAppWithFileHandler(
-          profile, extension, action_id, file_urls[i].path());
+          profile, extension, task.action_id, file_urls[i].path());
     }
 
     if (!done.is_null())
@@ -571,242 +236,5 @@
   return false;
 }
 
-ExtensionTaskExecutor::FileDefinition::FileDefinition() : is_directory(false) {
-}
-
-ExtensionTaskExecutor::FileDefinition::~FileDefinition() {
-}
-
-// static
-ExtensionTaskExecutor::FileDefinitionList
-ExtensionTaskExecutor::SetupFileAccessPermissions(
-    scoped_refptr<fileapi::FileSystemContext> file_system_context_handler,
-    const scoped_refptr<const Extension>& handler_extension,
-    const std::vector<FileSystemURL>& file_urls) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
-  DCHECK(handler_extension.get());
-
-  fileapi::ExternalFileSystemBackend* backend =
-      file_system_context_handler->external_backend();
-
-  FileDefinitionList file_list;
-  for (size_t i = 0; i < file_urls.size(); ++i) {
-    const FileSystemURL& url = file_urls[i];
-
-    // Check if this file system entry exists first.
-    base::PlatformFileInfo file_info;
-
-    base::FilePath local_path = url.path();
-    base::FilePath virtual_path = url.virtual_path();
-
-    bool is_drive_file = url.type() == fileapi::kFileSystemTypeDrive;
-    DCHECK(!is_drive_file || drive::util::IsUnderDriveMountPoint(local_path));
-
-    // If the file is under drive mount point, there is no actual file to be
-    // found on the url.path().
-    if (!is_drive_file) {
-      if (!base::PathExists(local_path) ||
-          file_util::IsLink(local_path) ||
-          !file_util::GetFileInfo(local_path, &file_info)) {
-        continue;
-      }
-    }
-
-    // Grant access to this particular file to target extension. This will
-    // ensure that the target extension can access only this FS entry and
-    // prevent from traversing FS hierarchy upward.
-    backend->GrantFileAccessToExtension(
-        handler_extension->id(), virtual_path);
-
-    // Output values.
-    FileDefinition file;
-    file.virtual_path = virtual_path;
-    file.is_directory = file_info.is_directory;
-    file.absolute_path = local_path;
-    file_list.push_back(file);
-  }
-  return file_list;
-}
-
-ExtensionTaskExecutor::ExtensionTaskExecutor(
-    Profile* profile,
-    const Extension* extension,
-    int32 tab_id,
-    const std::string& action_id)
-    : profile_(profile),
-      extension_(extension),
-      tab_id_(tab_id),
-      action_id_(action_id),
-      weak_ptr_factory_(this) {
-}
-
-ExtensionTaskExecutor::~ExtensionTaskExecutor() {}
-
-void ExtensionTaskExecutor::Execute(const std::vector<FileSystemURL>& file_urls,
-                                    const FileTaskFinishedCallback& done) {
-  done_ = done;
-
-  // Get file system context for the extension to which onExecute event will be
-  // sent. The file access permissions will be granted to the extension in the
-  // file system context for the files in |file_urls|.
-  GetFileSystemContextForExtension(profile_, extension_->id())->OpenFileSystem(
-      Extension::GetBaseURLFromExtensionId(extension_->id()).GetOrigin(),
-      fileapi::kFileSystemTypeExternal,
-      fileapi::OPEN_FILE_SYSTEM_FAIL_IF_NONEXISTENT,
-      base::Bind(&ExtensionTaskExecutor::DidOpenFileSystem,
-                 weak_ptr_factory_.GetWeakPtr(),
-                 file_urls));
-}
-
-void ExtensionTaskExecutor::DidOpenFileSystem(
-    const std::vector<FileSystemURL>& file_urls,
-    base::PlatformFileError result,
-    const std::string& file_system_name,
-    const GURL& file_system_root) {
-  if (result != base::PLATFORM_FILE_OK) {
-    ExecuteDoneOnUIThread(false);
-    return;
-  }
-
-  scoped_refptr<fileapi::FileSystemContext> file_system_context(
-      GetFileSystemContextForExtension(profile_, extension_->id()));
-  BrowserThread::PostTaskAndReplyWithResult(
-      BrowserThread::FILE,
-      FROM_HERE,
-      base::Bind(&SetupFileAccessPermissions,
-                 file_system_context,
-                 extension_,
-                 file_urls),
-      base::Bind(&ExtensionTaskExecutor::ExecuteFileActionsOnUIThread,
-                 weak_ptr_factory_.GetWeakPtr(),
-                 file_system_name,
-                 file_system_root));
-}
-
-void ExtensionTaskExecutor::ExecuteDoneOnUIThread(bool success) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-  if (!done_.is_null())
-    done_.Run(success);
-  delete this;
-}
-
-void ExtensionTaskExecutor::ExecuteFileActionsOnUIThread(
-    const std::string& file_system_name,
-    const GURL& file_system_root,
-    const FileDefinitionList& file_list) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-
-  if (file_list.empty()) {
-    ExecuteDoneOnUIThread(false);
-    return;
-  }
-
-  int handler_pid = ExtractProcessFromExtensionId(profile_, extension_->id());
-  if (handler_pid <= 0 &&
-      !extensions::BackgroundInfo::HasLazyBackgroundPage(extension_.get())) {
-    ExecuteDoneOnUIThread(false);
-    return;
-  }
-
-  if (handler_pid > 0) {
-    SetupPermissionsAndDispatchEvent(file_system_name, file_system_root,
-        file_list, handler_pid, NULL);
-  } else {
-    // We have to wake the handler background page before we proceed.
-    extensions::LazyBackgroundTaskQueue* queue =
-        extensions::ExtensionSystem::Get(profile_)->
-        lazy_background_task_queue();
-    if (!queue->ShouldEnqueueTask(profile_, extension_.get())) {
-      ExecuteDoneOnUIThread(false);
-      return;
-    }
-    queue->AddPendingTask(
-        profile_, extension_->id(),
-        base::Bind(&ExtensionTaskExecutor::SetupPermissionsAndDispatchEvent,
-                   weak_ptr_factory_.GetWeakPtr(),
-                   file_system_name,
-                   file_system_root,
-                   file_list,
-                   handler_pid));
-  }
-}
-
-void ExtensionTaskExecutor::SetupPermissionsAndDispatchEvent(
-    const std::string& file_system_name,
-    const GURL& file_system_root,
-    const FileDefinitionList& file_list,
-    int handler_pid_in,
-    extensions::ExtensionHost* host) {
-  int handler_pid = host ? host->render_process_host()->GetID() :
-                           handler_pid_in;
-
-  if (handler_pid <= 0) {
-    ExecuteDoneOnUIThread(false);
-    return;
-  }
-
-  extensions::EventRouter* event_router =
-      extensions::ExtensionSystem::Get(profile_)->event_router();
-  if (!event_router) {
-    ExecuteDoneOnUIThread(false);
-    return;
-  }
-
-  SetupHandlerHostFileAccessPermissions(
-      file_list, extension_.get(), handler_pid);
-
-  scoped_ptr<ListValue> event_args(new ListValue());
-  event_args->Append(new base::StringValue(action_id_));
-  DictionaryValue* details = new DictionaryValue();
-  event_args->Append(details);
-  // Get file definitions. These will be replaced with Entry instances by
-  // dispatchEvent() method from event_binding.js.
-  ListValue* files_urls = new ListValue();
-  details->Set("entries", files_urls);
-  for (FileDefinitionList::const_iterator iter = file_list.begin();
-       iter != file_list.end();
-       ++iter) {
-    DictionaryValue* file_def = new DictionaryValue();
-    files_urls->Append(file_def);
-    file_def->SetString("fileSystemName", file_system_name);
-    file_def->SetString("fileSystemRoot", file_system_root.spec());
-    base::FilePath root(FILE_PATH_LITERAL("/"));
-    base::FilePath full_path = root.Append(iter->virtual_path);
-    file_def->SetString("fileFullPath", full_path.value());
-    file_def->SetBoolean("fileIsDirectory", iter->is_directory);
-  }
-
-  details->SetInteger("tab_id", tab_id_);
-
-  scoped_ptr<extensions::Event> event(new extensions::Event(
-      "fileBrowserHandler.onExecute", event_args.Pass()));
-  event->restrict_to_profile = profile_;
-  event_router->DispatchEventToExtension(extension_->id(), event.Pass());
-
-  ExecuteDoneOnUIThread(true);
-}
-
-void ExtensionTaskExecutor::SetupHandlerHostFileAccessPermissions(
-    const FileDefinitionList& file_list,
-    const Extension* extension,
-    int handler_pid) {
-  const FileBrowserHandler* action = FindFileBrowserHandler(extension_,
-                                                            action_id_);
-  for (FileDefinitionList::const_iterator iter = file_list.begin();
-       iter != file_list.end();
-       ++iter) {
-    if (!action)
-      continue;
-    if (action->CanRead()) {
-      content::ChildProcessSecurityPolicy::GetInstance()->GrantReadFile(
-          handler_pid, iter->absolute_path);
-    }
-    if (action->CanWrite()) {
-      content::ChildProcessSecurityPolicy::GetInstance()->
-          GrantCreateReadWriteFile(handler_pid, iter->absolute_path);
-    }
-  }
-}
-
 }  // namespace file_tasks
 }  // namespace file_manager
diff --git a/chrome/browser/chromeos/extensions/file_manager/file_tasks.h b/chrome/browser/chromeos/extensions/file_manager/file_tasks.h
index 9c05fa5..50a3e13 100644
--- a/chrome/browser/chromeos/extensions/file_manager/file_tasks.h
+++ b/chrome/browser/chromeos/extensions/file_manager/file_tasks.h
@@ -80,9 +80,10 @@
 // (Files.app) and the latter looks like "419782477519" (Pixlr Editor).
 //
 // <task-type> is either of
-// - "file" - Files.app built-in handler
+// - "file" - File browser handler - app/extension declaring
+//            "file_browser_handlers" in manifest.
+// - "app" - File handler - app declaring "file_handlers" in manifest.json.
 // - "drive" - Drive App
-// - "app" - Regular Chrome Extension/App ID
 //
 // <task-action-id> is an ID string used for identifying actions provided
 // from a single Chrome Extension/App. In other words, a single
@@ -109,15 +110,13 @@
 #ifndef CHROME_BROWSER_CHROMEOS_EXTENSIONS_FILE_MANAGER_FILE_TASKS_H_
 #define CHROME_BROWSER_CHROMEOS_EXTENSIONS_FILE_MANAGER_FILE_TASKS_H_
 
+#include <set>
 #include <string>
 #include <vector>
 
+#include "base/basictypes.h"
 #include "base/callback_forward.h"
-#include "base/platform_file.h"
-#include "chrome/common/extensions/extension.h"
 
-class Browser;
-class FileBrowserHandler;
 class GURL;
 class Profile;
 
@@ -128,20 +127,29 @@
 namespace file_manager {
 namespace file_tasks {
 
-// Tasks are stored as a vector in order of priorities.
-typedef std::vector<const FileBrowserHandler*> FileBrowserHandlerList;
+// Task types encoded in task IDs. See also the comment at the beginning of
+// the file about <task-type>.
+extern const char kFileBrowserHandlerTaskType[];
+extern const char kFileHandlerTaskType[];
+extern const char kDriveTaskType[];
 
-// Specifies the task type for a task id that represents some file action, Drive
-// action, or Web Intent action.
-extern const char kTaskFile[];
-extern const char kTaskDrive[];
-extern const char kTaskApp[];
+// Describes a task.
+// See the comment above for <app-id>, <task-type>, and <action-id>.
+struct TaskDescriptor {
+  TaskDescriptor(const std::string& in_app_id,
+                 const std::string& in_task_type,
+                 const std::string& in_action_id)
+      : app_id(in_app_id),
+        task_type(in_task_type),
+        action_id(in_action_id) {
+  }
+  TaskDescriptor() {
+  }
 
-void UpdateFileHandlerUsageStats(Profile* profile, const std::string& task_id);
-
-// Returns true if the task should be used as a fallback. Such tasks are
-// Files.app's internal handlers as well as quick office extensions.
-bool IsFallbackTask(const FileBrowserHandler* task);
+  std::string app_id;
+  std::string task_type;
+  std::string action_id;
+};
 
 // Update the default file handler for the given sets of suffixes and MIME
 // types.
@@ -158,58 +166,51 @@
                                       const std::string& mime_type,
                                       const std::string& suffix);
 
-// Generates task id for the action specified by the extension. The |task_type|
-// must be one of kTaskFile, kTaskDrive or kTaskApp.
+// Generates task id for the task specified by |app_id|, |task_type| and
+// |action_id|. The |task_type| must be one of kFileBrowserHandlerTaskType,
+// kDriveTaskType or kFileHandlerTaskType.
+// <app-id> is either of Chrome Extension/App ID or Drive App ID.
 std::string MakeTaskID(const std::string& extension_id,
                        const std::string& task_type,
                        const std::string& action_id);
 
-// Extracts action, type and extension id bound to the file task ID. Either
-// |target_extension_id| or |action_id| are allowed to be NULL if caller isn't
-// interested in those values.  Returns false on failure to parse.
+// Returns a task id for the Drive app with |app_id|.
+// TODO(gspencer): For now, the action id is always "open-with", but we
+// could add any actions that the drive app supports.
+std::string MakeDriveAppTaskId(const std::string& app_id);
+
+// Parses the task ID and extracts app ID, task type, and action ID into
+// |task|. On failure, returns false, and the contents of |task| are
+// undefined.
 //
 // See also the comment at the beginning of the file for details for how
 // "task_id" looks like.
-bool CrackTaskID(const std::string& task_id,
-                 std::string* target_extension_id,
-                 std::string* task_type,
-                 std::string* action_id);
+bool ParseTaskID(const std::string& task_id, TaskDescriptor* task);
 
-// This generates a list of default tasks (tasks set as default by the user in
-// prefs) from the |common_tasks|.
-void FindDefaultTasks(Profile* profile,
-                      const std::vector<base::FilePath>& files_list,
-                      const FileBrowserHandlerList& common_tasks,
-                      FileBrowserHandlerList* default_tasks);
-
-// This generates list of tasks common for all files in |file_list|.
-bool FindCommonTasks(Profile* profile,
-                     const std::vector<GURL>& files_list,
-                     FileBrowserHandlerList* common_tasks);
-
-// Finds a task for a file whose URL is |url| and whose path is |path|.
-// Returns default task if one is defined (The default task is the task that is
-// assigned to file browser task button by default). If default task is not
-// found, tries to match the url with one of the builtin tasks.
-bool GetTaskForURLAndPath(Profile* profile,
-                          const GURL& url,
-                          const base::FilePath& path,
-                          const FileBrowserHandler** handler);
-
-// Used for returning success or failure from task executions.
-typedef base::Callback<void(bool)> FileTaskFinishedCallback;
+// The callback is used for ExecuteFileTask(). Will be called with true if
+// the file task execution is successful, or false if unsuccessful.
+typedef base::Callback<void(bool success)> FileTaskFinishedCallback;
 
 // Executes file handler task for each element of |file_urls|.
 // Returns |false| if the execution cannot be initiated. Otherwise returns
 // |true| and then eventually calls |done| when all the files have been handled.
 // |done| can be a null callback.
+//
+// Parameters:
+// profile    - The profile used for making this function call.
+// source_url - The source URL which originates this function call.
+// tab_id     - The ID of the tab which originates this function call.
+//              This can be 0 if no tab is associated.
+// task       - See the comment at TaskDescriptor struct.
+// file_urls  - URLs of the target files.
+// done       - The callback which will be called on completion.
+//              The callback won't be called if the function returns
+//              false.
 bool ExecuteFileTask(Profile* profile,
                      const GURL& source_url,
                      const std::string& file_browser_id,
                      int32 tab_id,
-                     const std::string& extension_id,
-                     const std::string& task_type,
-                     const std::string& action_id,
+                     const TaskDescriptor& task,
                      const std::vector<fileapi::FileSystemURL>& file_urls,
                      const FileTaskFinishedCallback& done);
 
diff --git a/chrome/browser/chromeos/extensions/file_manager/file_tasks_unittest.cc b/chrome/browser/chromeos/extensions/file_manager/file_tasks_unittest.cc
new file mode 100644
index 0000000..c9d7146
--- /dev/null
+++ b/chrome/browser/chromeos/extensions/file_manager/file_tasks_unittest.cc
@@ -0,0 +1,54 @@
+// 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/extensions/file_manager/file_tasks.h"
+
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace file_manager {
+namespace file_tasks {
+
+TEST(FileManagerFileTasksTest, MakeTaskID) {
+  EXPECT_EQ("app-id|app|action-id", MakeTaskID("app-id", "app", "action-id"));
+}
+
+TEST(FileManagerFileTasksTest, MakeDriveAppTaskId) {
+  EXPECT_EQ("app-id|drive|open-with", MakeDriveAppTaskId("app-id"));
+}
+
+TEST(FileManagerFileTasksTest, ParseTaskID_Basic) {
+  TaskDescriptor task;
+  // A task ID usually has three parts.
+  EXPECT_TRUE(ParseTaskID("app-id|app|action-id", &task));
+  EXPECT_EQ("app-id", task.app_id);
+  EXPECT_EQ("app", task.task_type);
+  EXPECT_EQ("action-id", task.action_id);
+}
+
+TEST(FileManagerFileTasksTest, ParseTaskID_Legacy) {
+  TaskDescriptor task;
+  // A legacy task ID only has two parts. The task type should be to "file".
+  EXPECT_TRUE(ParseTaskID("app-id|action-id", &task));
+  EXPECT_EQ("app-id", task.app_id);
+  EXPECT_EQ("file", task.task_type);
+  EXPECT_EQ("action-id", task.action_id);
+}
+
+TEST(FileManagerFileTasksTest, ParseTaskID_LegacyDrive) {
+  TaskDescriptor task;
+  // A legacy task ID only has two parts. For Drive app, the app ID is
+  // prefixed with "drive-app:".
+  EXPECT_TRUE(ParseTaskID("drive-app:app-id|action-id", &task));
+  EXPECT_EQ("app-id", task.app_id);
+  EXPECT_EQ("drive", task.task_type);
+  EXPECT_EQ("action-id", task.action_id);
+}
+
+TEST(FileManagerFileTasksTest, ParseTaskID_Invalid) {
+  TaskDescriptor task;
+  EXPECT_FALSE(ParseTaskID("invalid", &task));
+}
+
+}  // namespace file_tasks
+}  // namespace file_manager.
diff --git a/chrome/browser/chromeos/extensions/file_manager/fileapi_util.cc b/chrome/browser/chromeos/extensions/file_manager/fileapi_util.cc
new file mode 100644
index 0000000..52a93e4
--- /dev/null
+++ b/chrome/browser/chromeos/extensions/file_manager/fileapi_util.cc
@@ -0,0 +1,38 @@
+// 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/extensions/file_manager/fileapi_util.h"
+
+#include "chrome/browser/extensions/extension_service.h"
+#include "chrome/browser/extensions/extension_system.h"
+#include "chrome/browser/profiles/profile.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/render_view_host.h"
+#include "content/public/browser/site_instance.h"
+#include "content/public/browser/storage_partition.h"
+#include "url/gurl.h"
+#include "webkit/browser/fileapi/file_system_context.h"
+
+namespace file_manager {
+namespace fileapi_util {
+
+fileapi::FileSystemContext* GetFileSystemContextForExtensionId(
+    Profile* profile,
+    const std::string& extension_id) {
+  GURL site = extensions::ExtensionSystem::Get(profile)->
+      extension_service()->GetSiteForExtensionId(extension_id);
+  return content::BrowserContext::GetStoragePartitionForSite(profile, site)->
+      GetFileSystemContext();
+}
+
+fileapi::FileSystemContext* GetFileSystemContextForRenderViewHost(
+    Profile* profile,
+    content::RenderViewHost* render_view_host) {
+  content::SiteInstance* site_instance = render_view_host->GetSiteInstance();
+  return content::BrowserContext::GetStoragePartition(profile, site_instance)->
+      GetFileSystemContext();
+}
+
+}  // namespace fileapi_util
+}  // namespace file_manager
diff --git a/chrome/browser/chromeos/extensions/file_manager/fileapi_util.h b/chrome/browser/chromeos/extensions/file_manager/fileapi_util.h
new file mode 100644
index 0000000..415fb2c
--- /dev/null
+++ b/chrome/browser/chromeos/extensions/file_manager/fileapi_util.h
@@ -0,0 +1,40 @@
+// 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 provides File API related utilities.
+
+#ifndef CHROME_BROWSER_CHROMEOS_EXTENSIONS_FILE_MANAGER_FILEAPI_UTIL_H_
+#define CHROME_BROWSER_CHROMEOS_EXTENSIONS_FILE_MANAGER_FILEAPI_UTIL_H_
+
+#include <string>
+
+class Profile;
+
+namespace content {
+class RenderViewHost;
+}
+
+namespace fileapi {
+class FileSystemContext;
+}
+
+namespace file_manager {
+namespace fileapi_util {
+
+// Returns a file system context associated with the given profile and the
+// extension ID.
+fileapi::FileSystemContext* GetFileSystemContextForExtensionId(
+    Profile* profile,
+    const std::string& extension_id);
+
+// Returns a file system context associated with the given profile and the
+// render view host.
+fileapi::FileSystemContext* GetFileSystemContextForRenderViewHost(
+    Profile* profile,
+    content::RenderViewHost* render_view_host);
+
+}  // namespace fileapi_util
+}  // namespace file_manager
+
+#endif  // CHROME_BROWSER_CHROMEOS_EXTENSIONS_FILE_MANAGER_FILEAPI_UTIL_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 f86ccff..d0d4100 100644
--- a/chrome/browser/chromeos/extensions/file_manager/private_api_drive.cc
+++ b/chrome/browser/chromeos/extensions/file_manager/private_api_drive.cc
@@ -141,9 +141,11 @@
         profile_,
         file_specific_info.content_mime_type(),
         file_path_.Extension());
-    std::string default_app_id;
-    file_tasks::CrackTaskID(
-        default_task_id, &default_app_id, NULL, NULL);
+    file_tasks::TaskDescriptor default_task;
+    if (!file_tasks::ParseTaskID(default_task_id, &default_task)) {
+      LOG(WARNING) << "Invalid task ID: " << default_task_id;
+      return;
+    }
 
     ListValue* apps = new ListValue();
     properties_->Set("driveApps", apps);
@@ -163,7 +165,8 @@
       if (!doc_icon.is_empty())
         app->SetString("docIcon", doc_icon.spec());
       app->SetString("objectType", app_info->object_type);
-      app->SetBoolean("isPrimary", default_app_id == app_info->app_id);
+      app->SetBoolean("isPrimary",
+                      default_task.app_id == app_info->app_id);
       apps->Append(app);
     }
   }
diff --git a/chrome/browser/chromeos/extensions/file_manager/private_api_file_system.cc b/chrome/browser/chromeos/extensions/file_manager/private_api_file_system.cc
index fb74bc1..c77c7c4 100644
--- a/chrome/browser/chromeos/extensions/file_manager/private_api_file_system.cc
+++ b/chrome/browser/chromeos/extensions/file_manager/private_api_file_system.cc
@@ -20,6 +20,7 @@
 #include "chrome/browser/chromeos/extensions/file_manager/event_router.h"
 #include "chrome/browser/chromeos/extensions/file_manager/file_browser_private_api.h"
 #include "chrome/browser/chromeos/extensions/file_manager/file_manager_util.h"
+#include "chrome/browser/chromeos/extensions/file_manager/fileapi_util.h"
 #include "chrome/browser/chromeos/extensions/file_manager/private_api_util.h"
 #include "chrome/browser/chromeos/fileapi/file_system_backend.h"
 #include "chrome/browser/profiles/profile.h"
@@ -272,10 +273,9 @@
 
   set_log_on_completion(true);
 
-  content::SiteInstance* site_instance = render_view_host()->GetSiteInstance();
   scoped_refptr<fileapi::FileSystemContext> file_system_context =
-      BrowserContext::GetStoragePartition(profile_, site_instance)->
-      GetFileSystemContext();
+      fileapi_util::GetFileSystemContextForRenderViewHost(
+          profile(), render_view_host());
 
   const GURL origin_url = source_url_.GetOrigin();
   file_system_context->OpenFileSystem(
@@ -312,10 +312,9 @@
   if (!args_->GetString(0, &url) || url.empty())
     return false;
 
-  content::SiteInstance* site_instance = render_view_host()->GetSiteInstance();
   scoped_refptr<fileapi::FileSystemContext> file_system_context =
-      BrowserContext::GetStoragePartition(profile(), site_instance)->
-      GetFileSystemContext();
+      fileapi_util::GetFileSystemContextForRenderViewHost(
+          profile(), render_view_host());
 
   FileSystemURL file_watch_url = file_system_context->CrackURL(GURL(url));
   base::FilePath local_path = file_watch_url.path();
@@ -538,10 +537,10 @@
   if (!args_->GetString(1, &name))
     return false;
 
-  content::SiteInstance* site_instance = render_view_host()->GetSiteInstance();
   scoped_refptr<fileapi::FileSystemContext> file_system_context =
-      BrowserContext::GetStoragePartition(profile(), site_instance)->
-      GetFileSystemContext();
+      fileapi_util::GetFileSystemContextForRenderViewHost(
+          profile(), render_view_host());
+
   fileapi::FileSystemURL filesystem_url(
       file_system_context->CrackURL(GURL(parent_url)));
   if (!chromeos::FileSystemBackend::CanHandleURL(filesystem_url))
diff --git a/chrome/browser/chromeos/extensions/file_manager/private_api_strings.cc b/chrome/browser/chromeos/extensions/file_manager/private_api_strings.cc
index 6d6505e..465d4f3 100644
--- a/chrome/browser/chromeos/extensions/file_manager/private_api_strings.cc
+++ b/chrome/browser/chromeos/extensions/file_manager/private_api_strings.cc
@@ -252,6 +252,8 @@
              IDS_FILE_BROWSER_CREATE_FOLDER_SHORTCUT_BUTTON_LABEL);
   SET_STRING("REMOVE_FOLDER_SHORTCUT_BUTTON_LABEL",
              IDS_FILE_BROWSER_REMOVE_FOLDER_SHORTCUT_BUTTON_LABEL);
+  SET_STRING("SHORTCUT_TARGET_UNAVAILABLE",
+             IDS_FILE_BROWSER_SHORTCUT_TARGET_UNAVAILABLE);
   SET_STRING("SHARE_BUTTON_LABEL",
              IDS_FILE_BROWSER_SHARE_BUTTON_LABEL);
 
diff --git a/chrome/browser/chromeos/extensions/file_manager/private_api_tasks.cc b/chrome/browser/chromeos/extensions/file_manager/private_api_tasks.cc
index e257dce..23f0275 100644
--- a/chrome/browser/chromeos/extensions/file_manager/private_api_tasks.cc
+++ b/chrome/browser/chromeos/extensions/file_manager/private_api_tasks.cc
@@ -6,6 +6,7 @@
 
 #include "chrome/browser/chromeos/drive/drive_app_registry.h"
 #include "chrome/browser/chromeos/drive/drive_integration_service.h"
+#include "chrome/browser/chromeos/extensions/file_manager/file_browser_handlers.h"
 #include "chrome/browser/chromeos/extensions/file_manager/file_manager_util.h"
 #include "chrome/browser/chromeos/extensions/file_manager/file_tasks.h"
 #include "chrome/browser/chromeos/extensions/file_manager/private_api_util.h"
@@ -73,14 +74,6 @@
   }
 }
 
-// Returns a task id for the web app with |app_id|.
-std::string MakeWebAppTaskId(const std::string& app_id) {
-  // TODO(gspencer): For now, the action id is always "open-with", but we
-  // could add any actions that the drive app supports.
-  return file_tasks::MakeTaskID(
-      app_id, file_tasks::kTaskDrive, "open-with");
-}
-
 // Gets the mime types for the given file paths.
 void GetMimeTypesForFileURLs(const std::vector<base::FilePath>& file_paths,
                              PathAndMimeTypeSet* files) {
@@ -146,11 +139,8 @@
   if (!args_->GetList(1, &files_list))
     return false;
 
-  std::string extension_id;
-  std::string task_type;
-  std::string action_id;
-  if (!file_tasks::CrackTaskID(
-          task_id, &extension_id, &task_type, &action_id)) {
+  file_tasks::TaskDescriptor task;
+  if (!file_tasks::ParseTaskID(task_id, &task)) {
     LOG(WARNING) << "Invalid task " << task_id;
     return false;
   }
@@ -184,9 +174,7 @@
       source_url(),
       extension_->id(),
       tab_id,
-      extension_id,
-      task_type,
-      action_id,
+      task,
       file_urls,
       base::Bind(&ExecuteTaskFunction::OnTaskExecuted, this));
 }
@@ -243,7 +231,7 @@
         GURL icon_url = util::FindPreferredIcon(app_info.app_icons,
                                                 util::kPreferredIconSize);
         task_info_map->insert(std::pair<std::string, TaskInfo>(
-            MakeWebAppTaskId(app_info.app_id),
+            file_tasks::MakeDriveAppTaskId(app_info.app_id),
             TaskInfo(app_info.app_name, icon_url)));
       }
     } else {
@@ -251,7 +239,8 @@
       // based on the task id.
       std::set<std::string> task_id_set;
       for (size_t j = 0; j < app_info_list.size(); ++j) {
-        task_id_set.insert(MakeWebAppTaskId(app_info_list[j]->app_id));
+        task_id_set.insert(
+            file_tasks::MakeDriveAppTaskId(app_info_list[j]->app_id));
       }
       for (TaskInfoMap::iterator iter = task_info_map->begin();
            iter != task_info_map->end(); ) {
@@ -315,11 +304,7 @@
   }
 }
 
-// Find special tasks here for Drive (Blox) apps. Iterate through matching drive
-// apps and add them, with generated task ids. Extension ids will be the app_ids
-// from drive. We'll know that they are drive apps because the extension id will
-// begin with kDriveTaskExtensionPrefix.
-bool GetFileTasksFunction::FindDriveAppTasks(
+void GetFileTasksFunction::FindDriveAppTasks(
     const FileInfoList& file_info_list,
     ListValue* result_list,
     bool* default_already_set) {
@@ -327,7 +312,7 @@
   DCHECK(default_already_set);
 
   if (file_info_list.empty())
-    return true;
+    return;
 
   drive::DriveIntegrationService* integration_service =
       drive::DriveIntegrationServiceFactory::GetForProfile(profile_);
@@ -335,7 +320,7 @@
   // case because there might be other extension tasks, even if we don't have
   // any to add.
   if (!integration_service || !integration_service->drive_app_registry())
-    return true;
+    return;
 
   drive::DriveAppRegistry* registry =
       integration_service->drive_app_registry();
@@ -348,17 +333,19 @@
   FindDefaultDriveTasks(file_info_list, task_info_map, &default_tasks);
   CreateDriveTasks(
       task_info_map, default_tasks, result_list, default_already_set);
-  return true;
 }
 
-bool GetFileTasksFunction::FindAppTasks(
+void GetFileTasksFunction::FindFileHandlerTasks(
     const std::vector<base::FilePath>& file_paths,
     ListValue* result_list,
     bool* default_already_set) {
   DCHECK(!file_paths.empty());
+  DCHECK(result_list);
+  DCHECK(default_already_set);
+
   ExtensionService* service = profile_->GetExtensionService();
   if (!service)
-    return false;
+    return;
 
   PathAndMimeTypeSet files;
   GetMimeTypesForFileURLs(file_paths, &files);
@@ -391,7 +378,7 @@
          i != file_handlers.end(); ++i) {
       DictionaryValue* task = new DictionaryValue;
       std::string task_id = file_tasks::MakeTaskID(
-          extension->id(), file_tasks::kTaskApp, (*i)->id);
+          extension->id(), file_tasks::kFileHandlerTaskType, (*i)->id);
       task->SetString("taskId", task_id);
       task->SetString("title", (*i)->title);
       if (!(*default_already_set) && ContainsKey(default_tasks, task_id)) {
@@ -416,8 +403,63 @@
       result_list->Append(task);
     }
   }
+}
 
-  return true;
+void GetFileTasksFunction::FindFileBrowserHandlerTasks(
+    const std::vector<GURL>& file_urls,
+    const std::vector<base::FilePath>& file_paths,
+    ListValue* result_list,
+    bool* default_already_set) {
+  DCHECK(!file_paths.empty());
+  DCHECK(!file_urls.empty());
+  DCHECK(result_list);
+  DCHECK(default_already_set);
+
+  file_browser_handlers::FileBrowserHandlerList common_tasks =
+      file_browser_handlers::FindCommonFileBrowserHandlers(profile_, file_urls);
+  if (common_tasks.empty())
+    return;
+  file_browser_handlers::FileBrowserHandlerList default_tasks =
+      file_browser_handlers::FindDefaultFileBrowserHandlers(
+          profile_, file_paths, common_tasks);
+
+  ExtensionService* service =
+      extensions::ExtensionSystem::Get(profile_)->extension_service();
+  for (file_browser_handlers::FileBrowserHandlerList::const_iterator iter =
+           common_tasks.begin();
+       iter != common_tasks.end();
+       ++iter) {
+    const FileBrowserHandler* handler = *iter;
+    const std::string extension_id = handler->extension_id();
+    const Extension* extension = service->GetExtensionById(extension_id, false);
+    CHECK(extension);
+    DictionaryValue* task = new DictionaryValue;
+    task->SetString("taskId", file_tasks::MakeTaskID(
+        extension_id, file_tasks::kFileBrowserHandlerTaskType, handler->id()));
+    task->SetString("title", handler->title());
+    // TODO(zelidrag): Figure out how to expose icon URL that task defined in
+    // manifest instead of the default extension icon.
+    GURL icon = extensions::ExtensionIconSource::GetIconURL(
+        extension,
+        extension_misc::EXTENSION_ICON_BITTY,
+        ExtensionIconSet::MATCH_BIGGER,
+        false,  // grayscale
+        NULL);  // exists
+    task->SetString("iconUrl", icon.spec());
+    task->SetBoolean("driveApp", false);
+
+    // Only set the default if there isn't already a default set.
+    if (!*default_already_set &&
+        std::find(default_tasks.begin(), default_tasks.end(), *iter) !=
+        default_tasks.end()) {
+      task->SetBoolean("isDefault", true);
+      *default_already_set = true;
+    } else {
+      task->SetBoolean("isDefault", false);
+    }
+
+    result_list->Append(task);
+  }
 }
 
 bool GetFileTasksFunction::RunImpl() {
@@ -483,72 +525,25 @@
   ListValue* result_list = new ListValue();
   SetResult(result_list);
 
-  // Find the Drive apps first, because we want them to take precedence
+  // Find the Drive app tasks first, because we want them to take precedence
   // when setting the default app.
   bool default_already_set = false;
   // Google document are not opened by drive apps but file manager.
-  if (!has_google_document) {
-    if (!FindDriveAppTasks(info_list, result_list, &default_already_set))
-      return false;
-  }
+  if (!has_google_document)
+    FindDriveAppTasks(info_list, result_list, &default_already_set);
 
-  // Take the union of platform app file handlers, and all previous Drive
-  // and extension tasks. As above, we know there aren't duplicates because
-  // they're entirely different kinds of
+  // Find and append file handler tasks. We know there aren't duplicates
+  // because Drive apps and platform apps are entirely different kinds of
   // tasks.
-  if (!FindAppTasks(file_paths, result_list, &default_already_set))
-    return false;
+  FindFileHandlerTasks(file_paths, result_list, &default_already_set);
 
-  // Take the union of Drive and extension tasks: Because any Drive tasks we
-  // found must apply to all of the files (intersection), and because the same
-  // is true of the extensions, we simply take the union of two lists by adding
-  // the extension tasks to the Drive task list. We know there aren't duplicates
-  // because they're entirely different kinds of tasks, but there could be both
-  // kinds of tasks for a file type (an image file, for instance).
-  file_tasks::FileBrowserHandlerList common_tasks;
-  file_tasks::FileBrowserHandlerList default_tasks;
-  if (!file_tasks::FindCommonTasks(profile_, file_urls, &common_tasks))
-    return false;
-  file_tasks::FindDefaultTasks(profile_, file_paths,
-                                      common_tasks, &default_tasks);
-
-  ExtensionService* service =
-      extensions::ExtensionSystem::Get(profile_)->extension_service();
-  for (file_tasks::FileBrowserHandlerList::const_iterator iter =
-           common_tasks.begin();
-       iter != common_tasks.end();
-       ++iter) {
-    const FileBrowserHandler* handler = *iter;
-    const std::string extension_id = handler->extension_id();
-    const Extension* extension = service->GetExtensionById(extension_id, false);
-    CHECK(extension);
-    DictionaryValue* task = new DictionaryValue;
-    task->SetString("taskId", file_tasks::MakeTaskID(
-        extension_id, file_tasks::kTaskFile, handler->id()));
-    task->SetString("title", handler->title());
-    // TODO(zelidrag): Figure out how to expose icon URL that task defined in
-    // manifest instead of the default extension icon.
-    GURL icon = extensions::ExtensionIconSource::GetIconURL(
-        extension,
-        extension_misc::EXTENSION_ICON_BITTY,
-        ExtensionIconSet::MATCH_BIGGER,
-        false,  // grayscale
-        NULL);  // exists
-    task->SetString("iconUrl", icon.spec());
-    task->SetBoolean("driveApp", false);
-
-    // Only set the default if there isn't already a default set.
-    if (!default_already_set &&
-        std::find(default_tasks.begin(), default_tasks.end(), *iter) !=
-        default_tasks.end()) {
-      task->SetBoolean("isDefault", true);
-      default_already_set = true;
-    } else {
-      task->SetBoolean("isDefault", false);
-    }
-
-    result_list->Append(task);
-  }
+  // Find and append file browser handler tasks. We know there aren't
+  // duplicates because "file_browser_handlers" and "file_handlers" shouldn't
+  // be used in the same manifest.json.
+  FindFileBrowserHandlerTasks(file_urls,
+                              file_paths,
+                              result_list,
+                              &default_already_set);
 
   SendResponse(true);
   return true;
diff --git a/chrome/browser/chromeos/extensions/file_manager/private_api_tasks.h b/chrome/browser/chromeos/extensions/file_manager/private_api_tasks.h
index a81bf94..4c12832 100644
--- a/chrome/browser/chromeos/extensions/file_manager/private_api_tasks.h
+++ b/chrome/browser/chromeos/extensions/file_manager/private_api_tasks.h
@@ -82,19 +82,36 @@
                                ListValue* result_list,
                                bool* default_already_set);
 
-  // Find the list of drive apps that can be used with the given file types. If
-  // a default task is set in the result list, then |default_already_set| is set
-  // to true.
-  bool FindDriveAppTasks(const FileInfoList& file_info_list,
+  // Finds the drive app tasks that can be used with the given files, and
+  // append them to the |result_list|. |*default_already_set| indicates if
+  // the |result_list| already contains the default task. If the value is
+  // false, the function will find the default task and set the value to true
+  // if found.
+  //
+  // "taskId" field in |result_list| will look like
+  // "<drive-app-id>|drive|open-with" (See also file_tasks.h).
+  // "driveApp" field in |result_list| will be set to "true".
+  void FindDriveAppTasks(const FileInfoList& file_info_list,
                          ListValue* result_list,
                          bool* default_already_set);
 
-  // Find the list of app file handlers that can be used with the given file
-  // types, appending them to the |result_list|. If a default task is set in the
-  // result list, then |default_already_set| is set to true.
-  bool FindAppTasks(const std::vector<base::FilePath>& file_paths,
-                    ListValue* result_list,
-                    bool* default_already_set);
+  // Find the file handler tasks (apps declaring "file_handlers" in
+  // manifest.json) that can be used with the given files, appending them to
+  // the |result_list|. See the comment at FindDriveAppTasks() about
+  // |default_already_set|
+  void FindFileHandlerTasks(const std::vector<base::FilePath>& file_paths,
+                            ListValue* result_list,
+                            bool* default_already_set);
+
+  // Find the file browser handler tasks (app/extensions declaring
+  // "file_browser_handlers" in manifest.json) that can be used with the
+  // given files, appending them to the |result_list|. See the comment at
+  // FindDriveAppTasks() about |default_already_set|
+  void FindFileBrowserHandlerTasks(
+      const std::vector<GURL>& file_urls,
+      const std::vector<base::FilePath>& file_paths,
+      ListValue* result_list,
+      bool* default_already_set);
 };
 
 // Implements the chrome.fileBrowserPrivate.setDefaultTask method.
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 be35838..771b8ab 100644
--- a/chrome/browser/chromeos/extensions/file_manager/private_api_util.cc
+++ b/chrome/browser/chromeos/extensions/file_manager/private_api_util.cc
@@ -9,6 +9,7 @@
 #include "chrome/browser/chromeos/drive/drive_integration_service.h"
 #include "chrome/browser/chromeos/drive/file_errors.h"
 #include "chrome/browser/chromeos/drive/file_system_util.h"
+#include "chrome/browser/chromeos/extensions/file_manager/fileapi_util.h"
 #include "chrome/browser/chromeos/fileapi/file_system_backend.h"
 #include "chrome/browser/extensions/extension_function_dispatcher.h"
 #include "chrome/browser/extensions/extension_tab_util.h"
@@ -48,19 +49,17 @@
 void GetSelectedFileInfoInternal(Profile* profile,
                                  scoped_ptr<GetSelectedFileInfoParams> params) {
   DCHECK(profile);
+  drive::DriveIntegrationService* integration_service =
+      drive::DriveIntegrationServiceFactory::GetForProfile(profile);
 
   for (size_t i = params->selected_files.size();
        i < params->file_paths.size(); ++i) {
     const base::FilePath& file_path = params->file_paths[i];
-    // When the caller of the select file dialog wants local file paths,
-    // we should retrieve Drive files onto the local cache.
-    if (params->local_path_option == NO_LOCAL_PATH_RESOLUTION ||
-        !drive::util::IsUnderDriveMountPoint(file_path)) {
+
+    if (!drive::util::IsUnderDriveMountPoint(file_path)) {
       params->selected_files.push_back(
           ui::SelectedFileInfo(file_path, base::FilePath()));
     } else {
-      drive::DriveIntegrationService* integration_service =
-          drive::DriveIntegrationServiceFactory::GetForProfile(profile);
       // |integration_service| is NULL if Drive is disabled.
       if (!integration_service) {
         ContinueGetSelectedFileInfo(profile,
@@ -70,15 +69,29 @@
                                     scoped_ptr<drive::ResourceEntry>());
         return;
       }
-      // TODO(kinaba): crbug.com/140425 support FOR_SAVING
-      DCHECK(params->local_path_option == NEED_LOCAL_PATH_FOR_OPENING);
-      integration_service->file_system()->GetFileByPath(
-          drive::util::ExtractDrivePath(file_path),
-          base::Bind(&ContinueGetSelectedFileInfo,
-                     profile,
-                     base::Passed(&params)));
-      return;
-    }
+      // When the caller of the select file dialog wants local file paths,
+      // we should retrieve Drive files onto the local cache.
+      switch (params->local_path_option) {
+        case NO_LOCAL_PATH_RESOLUTION:
+          params->selected_files.push_back(
+              ui::SelectedFileInfo(file_path, base::FilePath()));
+          break;
+        case NEED_LOCAL_PATH_FOR_OPENING:
+          integration_service->file_system()->GetFileByPath(
+              drive::util::ExtractDrivePath(file_path),
+              base::Bind(&ContinueGetSelectedFileInfo,
+                         profile,
+                         base::Passed(&params)));
+          return;  // Remaining work is done in ContinueGetSelectedFileInfo.
+        case NEED_LOCAL_PATH_FOR_SAVING:
+          integration_service->file_system()->GetFileByPathForSaving(
+              drive::util::ExtractDrivePath(file_path),
+              base::Bind(&ContinueGetSelectedFileInfo,
+                         profile,
+                         base::Passed(&params)));
+          return;  // Remaining work is done in ContinueGetSelectedFileInfo.
+      }
+   }
   }
   params->callback.Run(params->selected_files);
 }
@@ -144,10 +157,9 @@
   DCHECK(render_view_host);
   DCHECK(profile);
 
-  content::SiteInstance* site_instance = render_view_host->GetSiteInstance();
   scoped_refptr<fileapi::FileSystemContext> file_system_context =
-      content::BrowserContext::GetStoragePartition(profile, site_instance)->
-      GetFileSystemContext();
+      fileapi_util::GetFileSystemContextForRenderViewHost(
+          profile, render_view_host);
 
   const fileapi::FileSystemURL filesystem_url(
       file_system_context->CrackURL(url));
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 628137f..376b90a 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
@@ -43,6 +43,11 @@
     "/usr/share/chromeos-assets/input_methods/nacl_mozc",
   },
   {
+    // Google Chinese Input (zhuyin)
+    "goedamlknlnjaengojinmfgpmdjmkooo",
+    "/usr/share/chromeos-assets/input_methods/zhuyin",
+  },
+  {
     // Google Chinese Input (pinyin)
     "nmblnjkfdkabgdofidlkienfnnbjhnab",
     "/usr/share/chromeos-assets/input_methods/pinyin",
@@ -53,11 +58,6 @@
     "/usr/share/chromeos-assets/input_methods/cangjie",
   },
   {
-    // Google Chinese Input (wubi)
-    "jcffnbbngddhenhcnebafkbdomehdhpd",
-    "/usr/share/chromeos-assets/input_methods/wubi",
-  },
-  {
     // Google input tools.
     "gjaehgfemfahhmlgpdfknkhdnemmolop",
     "/usr/share/chromeos-assets/input_methods/input_tools",
@@ -69,6 +69,11 @@
     "/usr/share/chromeos-assets/input_methods/pinyin",
   },
   {
+    // Open-sourced Zhuyin Chinese Input Method.
+    "ekbifjdfhkmdeeajnolmgdlmkllopefi",
+    "/usr/share/chromeos-assets/input_methods/zhuyin",
+  },
+  {
     // Open-sourced Cangjie Chinese Input Method.
     "aeebooiibjahgpgmhkeocbeekccfknbj",
     "/usr/share/chromeos-assets/input_methods/cangjie",
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 ad93cc8..20fba08 100644
--- a/chrome/browser/chromeos/input_method/input_method_manager_impl.cc
+++ b/chrome/browser/chromeos/input_method/input_method_manager_impl.cc
@@ -51,8 +51,12 @@
   { "mozc-dv", "_comp_ime_fpfbhcjppmaeaijcidgiibchfbnhbeljnacl_mozc_us" },
   { "pinyin", "_comp_ime_nmblnjkfdkabgdofidlkienfnnbjhnabzh-t-i0-pinyin" },
   { "pinyin-dv", "_comp_ime_nmblnjkfdkabgdofidlkienfnnbjhnabzh-t-i0-pinyin" },
+  { "mozc-chewing",
+    "_comp_ime_ekbifjdfhkmdeeajnolmgdlmkllopefizh-hant-t-i0-und "},
   { "m17n:zh:cangjie",
     "_comp_ime_gjhclobljhjhgoebiipblnmdodbmpdgdzh-hant-t-i0-cangjie-1987" },
+  { "_comp_ime_jcffnbbngddhenhcnebafkbdomehdhpdzh-t-i0-wubi-1986",
+    "_comp_ime_gjhclobljhjhgoebiipblnmdodbmpdgdzh-t-i0-wubi-1986" },
   // TODO(nona): Remove following migration map in M31.
   { "m17n:ta:itrans",
     "_comp_ime_jhffeifommiaekmbkkjlpmilogcfdohpvkd_ta_itrans" },
@@ -93,6 +97,9 @@
     "_comp_ime_jhffeifommiaekmbkkjlpmilogcfdohpvkd_te_phone" },
   { "m17n:fa:isiri", "_comp_ime_jhffeifommiaekmbkkjlpmilogcfdohpvkd_fa" },
   { "m17n:ar:kbd", "_comp_ime_jhffeifommiaekmbkkjlpmilogcfdohpvkd_ar" },
+  // TODO(nona): Remove following migration map in M32
+  { "m17n:zh:quick",
+    "_comp_ime_ekbifjdfhkmdeeajnolmgdlmkllopefizh-hant-t-i0-und" },
 };
 
 const struct MigrationHangulKeyboardToInputMethodID {
diff --git a/chrome/browser/chromeos/input_method/input_method_util.cc b/chrome/browser/chromeos/input_method/input_method_util.cc
index 6270f2b..fc91b63 100644
--- a/chrome/browser/chromeos/input_method/input_method_util.cc
+++ b/chrome/browser/chromeos/input_method/input_method_util.cc
@@ -53,7 +53,7 @@
     "\xe6\x8b\xbc" },
   { "_comp_ime_nmblnjkfdkabgdofidlkienfnnbjhnabzh-t-i0-pinyin",
     "\xe6\x8b\xbc" },
-  { "_comp_ime_jcffnbbngddhenhcnebafkbdomehdhpdzh-t-i0-wubi-1986",
+  { "_comp_ime_gjhclobljhjhgoebiipblnmdodbmpdgdzh-t-i0-wubi-1986",
     "\xe4\xba\x94" }, // U+4E94
   { "pinyin-dv", "\xe6\x8b\xbc" },
   // For traditional Chinese input methods
@@ -102,7 +102,7 @@
     IDS_LANGUAGES_MEDIUM_LEN_NAME_CHINESE_SIMPLIFIED},
   { "_comp_ime_nmblnjkfdkabgdofidlkienfnnbjhnabzh-t-i0-pinyin",
     IDS_LANGUAGES_MEDIUM_LEN_NAME_CHINESE_SIMPLIFIED },
-  { "_comp_ime_jcffnbbngddhenhcnebafkbdomehdhpdzh-t-i0-wubi-1986",
+  { "_comp_ime_gjhclobljhjhgoebiipblnmdodbmpdgdzh-t-i0-wubi-1986",
     IDS_LANGUAGES_MEDIUM_LEN_NAME_CHINESE_SIMPLIFIED },
   { "_comp_ime_ekbifjdfhkmdeeajnolmgdlmkllopefizh-hant-t-i0-und",
     IDS_LANGUAGES_MEDIUM_LEN_NAME_CHINESE_TRADITIONAL },
@@ -128,6 +128,8 @@
   { "ja", "us", "_comp_ime_fpfbhcjppmaeaijcidgiibchfbnhbeljnacl_mozc_us" },
   { "ja", "jp", "_comp_ime_fpfbhcjppmaeaijcidgiibchfbnhbeljnacl_mozc_jp" },
   { "zh-CN", "us", "_comp_ime_nmblnjkfdkabgdofidlkienfnnbjhnabzh-t-i0-pinyin" },
+  { "zh-TW", "us",
+    "_comp_ime_goedamlknlnjaengojinmfgpmdjmkooozh-hant-t-i0-und" },
   { "th", "us", "_comp_ime_jhffeifommiaekmbkkjlpmilogcfdohpvkd_th" },
   { "vi", "us", "_comp_ime_jhffeifommiaekmbkkjlpmilogcfdohpvkd_vi_tcvn" },
   { "vi", "us", "_comp_ime_jhffeifommiaekmbkkjlpmilogcfdohpvkd_vi_tcvn" },
diff --git a/chrome/browser/chromeos/input_method/input_method_util_unittest.cc b/chrome/browser/chromeos/input_method/input_method_util_unittest.cc
index 1a2afac..74a16b9 100644
--- a/chrome/browser/chromeos/input_method/input_method_util_unittest.cc
+++ b/chrome/browser/chromeos/input_method/input_method_util_unittest.cc
@@ -413,6 +413,18 @@
   EXPECT_EQ("xkb:ru::rus", input_method_ids[1]);  // Russian keyboard.
 }
 
+// US keyboard + Traditional Chinese = US keyboard + chewing.
+TEST_F(InputMethodUtilTest, TestGetFirstLoginInputMethodIds_Us_And_ZhTw) {
+  const InputMethodDescriptor* descriptor =
+      util_.GetInputMethodDescriptorFromId("xkb:us::eng");  // US keyboard.
+  ASSERT_TRUE(NULL != descriptor);  // ASSERT_NE doesn't compile.
+  std::vector<std::string> input_method_ids;
+  util_.GetFirstLoginInputMethodIds("zh-TW", *descriptor, &input_method_ids);
+  ASSERT_EQ(2U, input_method_ids.size());
+  EXPECT_EQ("xkb:us::eng", input_method_ids[0]);
+  EXPECT_EQ(zhuyin_ime_id, input_method_ids[1]);  // Chewing.
+}
+
 // US keyboard + Thai = US keyboard + kesmanee.
 TEST_F(InputMethodUtilTest, TestGetFirstLoginInputMethodIds_Us_And_Th) {
   const InputMethodDescriptor* descriptor =
diff --git a/chrome/browser/chromeos/login/auth_prewarmer.cc b/chrome/browser/chromeos/login/auth_prewarmer.cc
index b7f8a59..64eb2ac 100644
--- a/chrome/browser/chromeos/login/auth_prewarmer.cc
+++ b/chrome/browser/chromeos/login/auth_prewarmer.cc
@@ -5,10 +5,12 @@
 #include "chrome/browser/chromeos/login/auth_prewarmer.h"
 
 #include "chrome/browser/chrome_notification_types.h"
-#include "chrome/browser/chromeos/net/connectivity_state_helper.h"
 #include "chrome/browser/chromeos/profiles/profile_helper.h"
 #include "chrome/browser/net/chrome_url_request_context.h"
 #include "chrome/browser/net/preconnect.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 "google_apis/gaia/gaia_urls.h"
 #include "url/gurl.h"
@@ -29,7 +31,8 @@
         chrome::NOTIFICATION_PROFILE_URL_REQUEST_CONTEXT_GETTER_INITIALIZED,
         content::Source<Profile>(ProfileHelper::GetSigninProfile()));
   }
-  ConnectivityStateHelper::Get()->RemoveNetworkManagerObserver(this);
+  NetworkHandler::Get()->network_state_handler()->RemoveObserver(this,
+                                                                 FROM_HERE);
 }
 
 void AuthPrewarmer::PrewarmAuthentication(
@@ -45,7 +48,8 @@
     return;
   }
   if (!IsNetworkConnected())
-    ConnectivityStateHelper::Get()->AddNetworkManagerObserver(this);
+    NetworkHandler::Get()->network_state_handler()->AddObserver(this,
+                                                                FROM_HERE);
   if (!GetRequestContext()) {
     registrar_.Add(
         this,
@@ -56,13 +60,14 @@
 
 void AuthPrewarmer::NetworkManagerChanged() {
   if (IsNetworkConnected()) {
-    ConnectivityStateHelper::Get()->RemoveNetworkManagerObserver(this);
+    NetworkHandler::Get()->network_state_handler()->RemoveObserver(this,
+                                                                   FROM_HERE);
     if (GetRequestContext())
       DoPrewarm();
   }
 }
 
-void AuthPrewarmer::DefaultNetworkChanged() {
+void AuthPrewarmer::DefaultNetworkChanged(const NetworkState* network) {
   NetworkManagerChanged();
 }
 
@@ -106,7 +111,9 @@
 }
 
 bool AuthPrewarmer::IsNetworkConnected() const {
-  return ConnectivityStateHelper::Get()->IsConnected();
+  NetworkStateHandler* nsh = NetworkHandler::Get()->network_state_handler();
+  return (nsh->ConnectedNetworkByType(NetworkStateHandler::kMatchTypeDefault) !=
+          NULL);
 }
 
 net::URLRequestContextGetter* AuthPrewarmer::GetRequestContext() const {
diff --git a/chrome/browser/chromeos/login/auth_prewarmer.h b/chrome/browser/chromeos/login/auth_prewarmer.h
index aa77fa8..861343d 100644
--- a/chrome/browser/chromeos/login/auth_prewarmer.h
+++ b/chrome/browser/chromeos/login/auth_prewarmer.h
@@ -7,7 +7,7 @@
 
 #include "base/basictypes.h"
 #include "base/callback.h"
-#include "chrome/browser/chromeos/net/connectivity_state_helper_observer.h"
+#include "chromeos/network/network_state_handler_observer.h"
 #include "content/public/browser/notification_observer.h"
 #include "content/public/browser/notification_registrar.h"
 
@@ -17,8 +17,10 @@
 
 namespace chromeos {
 
+class NetworkState;
+
 // Class for prewarming authentication network connection.
-class AuthPrewarmer : public ConnectivityStateHelperObserver,
+class AuthPrewarmer : public NetworkStateHandlerObserver,
                       public content::NotificationObserver {
  public:
   AuthPrewarmer();
@@ -27,9 +29,9 @@
   void PrewarmAuthentication(const base::Closure& completion_callback);
 
  private:
-  // chromeos::ConnectivityStateHelperObserver overrides.
+  // chromeos::NetworkStateHandlerObserver overrides.
   virtual void NetworkManagerChanged() OVERRIDE;
-  virtual void DefaultNetworkChanged() OVERRIDE;
+  virtual void DefaultNetworkChanged(const NetworkState* network) OVERRIDE;
 
   // content::NotificationObserver overrides.
   virtual void Observe(int type,
diff --git a/chrome/browser/chromeos/login/captive_portal_view.cc b/chrome/browser/chromeos/login/captive_portal_view.cc
index c61b7a3..05bae47 100644
--- a/chrome/browser/chromeos/login/captive_portal_view.cc
+++ b/chrome/browser/chromeos/login/captive_portal_view.cc
@@ -7,7 +7,9 @@
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/browser/captive_portal/captive_portal_detector.h"
 #include "chrome/browser/chromeos/login/captive_portal_window_proxy.h"
-#include "chrome/browser/chromeos/net/connectivity_state_helper.h"
+#include "chromeos/network/network_handler.h"
+#include "chromeos/network/network_state.h"
+#include "chromeos/network/network_state_handler.h"
 #include "content/public/browser/web_contents.h"
 #include "grit/generated_resources.h"
 #include "ui/base/l10n/l10n_util.h"
@@ -47,8 +49,10 @@
 
 string16 CaptivePortalView::GetWindowTitle() const {
   string16 network_name;
-  ConnectivityStateHelper* csh = ConnectivityStateHelper::Get();
-  std::string default_network_name = csh->DefaultNetworkName();
+  const NetworkState* default_network =
+      NetworkHandler::Get()->network_state_handler()->DefaultNetwork();
+  std::string default_network_name =
+      default_network ? default_network->name() : std::string();
   if (!default_network_name.empty()) {
     network_name = ASCIIToUTF16(default_network_name);
   } else {
diff --git a/chrome/browser/chromeos/login/chrome_restart_request.cc b/chrome/browser/chromeos/login/chrome_restart_request.cc
index 94bd1b5..55cc35c 100644
--- a/chrome/browser/chromeos/login/chrome_restart_request.cc
+++ b/chrome/browser/chromeos/login/chrome_restart_request.cc
@@ -40,7 +40,6 @@
 #include "ui/gl/gl_switches.h"
 #include "ui/views/corewm/corewm_switches.h"
 #include "url/gurl.h"
-#include "webkit/plugins/plugin_switches.h"
 
 using content::BrowserThread;
 
@@ -184,7 +183,6 @@
       chromeos::switches::kLoginProfile,
       chromeos::switches::kNaturalScrollDefault,
       chromeos::switches::kUseNewNetworkConfigurationHandlers,
-      chromeos::switches::kUseNewNetworkConnectionHandler,
       gfx::switches::kEnableBrowserTextSubpixelPositioning,
       gfx::switches::kEnableWebkitTextSubpixelPositioning,
       views::corewm::switches::kNoDropShadows,
diff --git a/chrome/browser/chromeos/login/default_user_images.cc b/chrome/browser/chromeos/login/default_user_images.cc
index c84934a..6d325e7 100644
--- a/chrome/browser/chromeos/login/default_user_images.cc
+++ b/chrome/browser/chromeos/login/default_user_images.cc
@@ -127,7 +127,7 @@
   return GetDefaultImageString(index, kDefaultUrlPrefix);
 }
 
-bool IsDefaultImageUrl(const std::string url, int* image_id) {
+bool IsDefaultImageUrl(const std::string& url, int* image_id) {
   if (url == kZeroDefaultUrl) {
     *image_id = 0;
     return true;
diff --git a/chrome/browser/chromeos/login/default_user_images.h b/chrome/browser/chromeos/login/default_user_images.h
index b45fac9..d30bd11 100644
--- a/chrome/browser/chromeos/login/default_user_images.h
+++ b/chrome/browser/chromeos/login/default_user_images.h
@@ -31,7 +31,7 @@
 
 // Checks if the given URL points to one of the default images. If it is,
 // returns true and its index through |image_id|. If not, returns false.
-bool IsDefaultImageUrl(const std::string url, int* image_id);
+bool IsDefaultImageUrl(const std::string& url, int* image_id);
 
 // Returns bitmap of default user image with specified index.
 const gfx::ImageSkia& GetDefaultImage(int index);
diff --git a/chrome/browser/chromeos/login/existing_user_controller.cc b/chrome/browser/chromeos/login/existing_user_controller.cc
index e6da685..f0e2e8b 100644
--- a/chrome/browser/chromeos/login/existing_user_controller.cc
+++ b/chrome/browser/chromeos/login/existing_user_controller.cc
@@ -32,7 +32,6 @@
 #include "chrome/browser/chromeos/login/startup_utils.h"
 #include "chrome/browser/chromeos/login/user_manager.h"
 #include "chrome/browser/chromeos/login/wizard_controller.h"
-#include "chrome/browser/chromeos/net/connectivity_state_helper.h"
 #include "chrome/browser/chromeos/policy/device_local_account.h"
 #include "chrome/browser/chromeos/profiles/profile_helper.h"
 #include "chrome/browser/chromeos/settings/cros_settings.h"
@@ -135,7 +134,8 @@
       is_login_in_progress_(false),
       password_changed_(false),
       do_auto_enrollment_(false),
-      signin_screen_ready_(false) {
+      signin_screen_ready_(false),
+      network_state_helper_(new login::NetworkStateHelper) {
   DCHECK(current_controller_ == NULL);
   current_controller_ = this;
 
@@ -388,7 +388,7 @@
 }
 
 string16 ExistingUserController::GetConnectedNetworkName() {
-  return GetCurrentNetworkName();
+  return network_state_helper_->GetCurrentNetworkName();
 }
 
 bool ExistingUserController::IsSigninInProgress() const {
@@ -736,7 +736,7 @@
     // cached locally or the local admin account.
     bool is_known_user =
         UserManager::Get()->IsKnownUser(last_login_attempt_username_);
-    if (!ConnectivityStateHelper::Get()->IsConnected()) {
+    if (!network_state_helper_->IsConnected()) {
       if (is_known_user)
         ShowError(IDS_LOGIN_ERROR_AUTHENTICATING, error);
       else
@@ -1089,7 +1089,7 @@
   // for end users, developers can see details string in Chrome logs.
   VLOG(1) << details;
   HelpAppLauncher::HelpTopic help_topic_id;
-  bool is_offline = !ConnectivityStateHelper::Get()->IsConnected();
+  bool is_offline = !network_state_helper_->IsConnected();
   switch (login_performer_->error().state()) {
     case GoogleServiceAuthError::CONNECTION_FAILED:
       help_topic_id = HelpAppLauncher::HELP_CANT_ACCESS_ACCOUNT_OFFLINE;
diff --git a/chrome/browser/chromeos/login/existing_user_controller.h b/chrome/browser/chromeos/login/existing_user_controller.h
index b249219..7a2ff11 100644
--- a/chrome/browser/chromeos/login/existing_user_controller.h
+++ b/chrome/browser/chromeos/login/existing_user_controller.h
@@ -32,6 +32,10 @@
 class CrosSettings;
 class LoginDisplayHost;
 
+namespace login {
+class NetworkStateHelper;
+}
+
 // ExistingUserController is used to handle login when someone has
 // already logged into the machine.
 // To use ExistingUserController create an instance of it and invoke Init.
@@ -296,6 +300,8 @@
   // Timer for the interval to wait for the reboot after TPM error UI was shown.
   base::OneShotTimer<ExistingUserController> reboot_timer_;
 
+  scoped_ptr<login::NetworkStateHelper> network_state_helper_;
+
   FRIEND_TEST_ALL_PREFIXES(ExistingUserControllerTest, ExistingUserLogin);
 
   DISALLOW_COPY_AND_ASSIGN(ExistingUserController);
diff --git a/chrome/browser/chromeos/login/helper.cc b/chrome/browser/chromeos/login/helper.cc
index ff60abe..a09f0c0 100644
--- a/chrome/browser/chromeos/login/helper.cc
+++ b/chrome/browser/chromeos/login/helper.cc
@@ -6,7 +6,9 @@
 
 #include "ash/shell.h"
 #include "base/strings/utf_string_conversions.h"
-#include "chrome/browser/chromeos/net/connectivity_state_helper.h"
+#include "chromeos/network/network_handler.h"
+#include "chromeos/network/network_state.h"
+#include "chromeos/network/network_state_handler.h"
 #include "grit/generated_resources.h"
 #include "grit/theme_resources.h"
 #include "third_party/cros_system_api/dbus/service_constants.h"
@@ -26,31 +28,6 @@
   return bounds;
 }
 
-string16 GetCurrentNetworkName() {
-  ConnectivityStateHelper* csh =
-      ConnectivityStateHelper::Get();
-
-  if (csh->IsConnectedType(flimflam::kTypeEthernet)) {
-    return l10n_util::GetStringUTF16(IDS_STATUSBAR_NETWORK_DEVICE_ETHERNET);
-  } else if (csh->IsConnectedType(flimflam::kTypeWifi)) {
-    return UTF8ToUTF16(csh->NetworkNameForType(flimflam::kTypeWifi));
-  } else if (csh->IsConnectedType(flimflam::kTypeCellular)) {
-    return UTF8ToUTF16(csh->NetworkNameForType(flimflam::kTypeCellular));
-  } else if (csh->IsConnectedType(flimflam::kTypeWimax)) {
-    return UTF8ToUTF16(csh->NetworkNameForType(flimflam::kTypeWimax));
-  } else if (csh->IsConnectingType(flimflam::kTypeEthernet)) {
-    return l10n_util::GetStringUTF16(IDS_STATUSBAR_NETWORK_DEVICE_ETHERNET);
-  } else if (csh->IsConnectingType(flimflam::kTypeWifi)) {
-    return UTF8ToUTF16(csh->NetworkNameForType(flimflam::kTypeWifi));
-  } else if (csh->IsConnectingType(flimflam::kTypeCellular)) {
-    return UTF8ToUTF16(csh->NetworkNameForType(flimflam::kTypeCellular));
-  } else if (csh->IsConnectingType(flimflam::kTypeWimax)) {
-    return UTF8ToUTF16(csh->NetworkNameForType(flimflam::kTypeWimax));
-  } else {
-    return string16();
-  }
-}
-
 int GetCurrentUserImageSize() {
   // The biggest size that the profile picture is displayed at is currently
   // 220px, used for the big preview on OOBE and Change Picture options page.
@@ -62,4 +39,45 @@
       ui::GetScaleFactorScale(ui::GetMaxScaleFactor());
 }
 
+namespace login {
+
+NetworkStateHelper::NetworkStateHelper() {}
+NetworkStateHelper::~NetworkStateHelper() {}
+
+string16 NetworkStateHelper::GetCurrentNetworkName() const {
+  NetworkStateHandler* nsh = NetworkHandler::Get()->network_state_handler();
+  const NetworkState* network = nsh->ConnectedNetworkByType(
+      NetworkStateHandler::kMatchTypeNonVirtual);
+  if (network) {
+    if (network->type() == flimflam::kTypeEthernet)
+      return l10n_util::GetStringUTF16(IDS_STATUSBAR_NETWORK_DEVICE_ETHERNET);
+    return UTF8ToUTF16(network->name());
+  }
+
+  network = nsh->ConnectingNetworkByType(
+      NetworkStateHandler::kMatchTypeNonVirtual);
+  if (network) {
+    if (network->type() == flimflam::kTypeEthernet)
+      return l10n_util::GetStringUTF16(IDS_STATUSBAR_NETWORK_DEVICE_ETHERNET);
+    return UTF8ToUTF16(network->name());
+  }
+  return string16();
+}
+
+bool NetworkStateHelper::IsConnected() const {
+  chromeos::NetworkStateHandler* nsh =
+      chromeos::NetworkHandler::Get()->network_state_handler();
+  return nsh->ConnectedNetworkByType(
+      chromeos::NetworkStateHandler::kMatchTypeDefault) != NULL;
+}
+
+bool NetworkStateHelper::IsConnecting() const {
+  chromeos::NetworkStateHandler* nsh =
+      chromeos::NetworkHandler::Get()->network_state_handler();
+  return nsh->ConnectingNetworkByType(
+      chromeos::NetworkStateHandler::kMatchTypeDefault) != NULL;
+}
+
+}  // namespace login
+
 }  // namespace chromeos
diff --git a/chrome/browser/chromeos/login/helper.h b/chrome/browser/chromeos/login/helper.h
index 41bc75d..543e6e5 100644
--- a/chrome/browser/chromeos/login/helper.h
+++ b/chrome/browser/chromeos/login/helper.h
@@ -26,13 +26,6 @@
 // |size| is not empty. Otherwise the whole monitor is occupied.
 gfx::Rect CalculateScreenBounds(const gfx::Size& size);
 
-// Returns name of the currently connected network.
-// If there are no connected networks, returns name of the network
-// that is in the "connecting" state. Otherwise empty string is returned.
-// If there are multiple connected networks, network priority:
-// Ethernet > WiFi > Cellular. Same for connecting network.
-string16 GetCurrentNetworkName();
-
 // Returns the size of user image required for proper display under current DPI.
 int GetCurrentUserImageSize();
 
@@ -44,6 +37,29 @@
 // displayed under all possible DPI values.
 const int kMaxUserImageSize = 512;
 
+// A helper class for easily mocking out Network*Handler calls for tests.
+class NetworkStateHelper {
+ public:
+  NetworkStateHelper();
+  virtual ~NetworkStateHelper();
+
+  // Returns name of the currently connected network.
+  // If there are no connected networks, returns name of the network
+  // that is in the "connecting" state. Otherwise empty string is returned.
+  // If there are multiple connected networks, network priority:
+  // Ethernet > WiFi > Cellular. Same for connecting network.
+  virtual string16 GetCurrentNetworkName() const;
+
+  // Returns true if the default network is in connected state.
+  virtual bool IsConnected() const;
+
+  // Returns true if the default network is in connecting state.
+  virtual bool IsConnecting() const;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(NetworkStateHelper);
+};
+
 }  // namespace login
 
 }  // namespace chromeos
diff --git a/chrome/browser/chromeos/login/login_browsertest.cc b/chrome/browser/chromeos/login/login_browsertest.cc
index c1aa932..3bf47c8 100644
--- a/chrome/browser/chromeos/login/login_browsertest.cc
+++ b/chrome/browser/chromeos/login/login_browsertest.cc
@@ -65,7 +65,6 @@
     command_line->AppendSwitchASCII(
         chromeos::switches::kLoginUser, "TestUser@gmail.com");
     command_line->AppendSwitchASCII(chromeos::switches::kLoginProfile, "user");
-    command_line->AppendSwitch(::switches::kNoFirstRun);
   }
 };
 
@@ -75,7 +74,6 @@
     command_line->AppendSwitch(chromeos::switches::kGuestSession);
     command_line->AppendSwitch(::switches::kIncognito);
     command_line->AppendSwitchASCII(chromeos::switches::kLoginProfile, "user");
-    command_line->AppendSwitch(::switches::kNoFirstRun);
   }
 };
 
diff --git a/chrome/browser/chromeos/login/login_utils_browsertest.cc b/chrome/browser/chromeos/login/login_utils_browsertest.cc
index 60923be..0b9d798 100644
--- a/chrome/browser/chromeos/login/login_utils_browsertest.cc
+++ b/chrome/browser/chromeos/login/login_utils_browsertest.cc
@@ -23,8 +23,6 @@
 #include "chrome/browser/chromeos/login/authenticator.h"
 #include "chrome/browser/chromeos/login/login_status_consumer.h"
 #include "chrome/browser/chromeos/login/user_manager.h"
-#include "chrome/browser/chromeos/net/connectivity_state_helper.h"
-#include "chrome/browser/chromeos/net/mock_connectivity_state_helper.h"
 #include "chrome/browser/chromeos/policy/enterprise_install_attributes.h"
 #include "chrome/browser/chromeos/settings/cros_settings.h"
 #include "chrome/browser/chromeos/settings/device_settings_service.h"
@@ -217,9 +215,6 @@
 
     CryptohomeLibrary::Initialize();
     LoginState::Initialize();
-    ConnectivityStateHelper::SetForTest(&mock_connectivity_state_helper_);
-    EXPECT_CALL(mock_connectivity_state_helper_, DefaultNetworkOnline())
-        .WillRepeatedly(Return(false));
 
     mock_input_method_manager_ = new input_method::MockInputMethodManager();
     input_method::InitializeForTesting(mock_input_method_manager_);
@@ -314,7 +309,6 @@
     LoginUtils::Set(NULL);
 
     input_method::Shutdown();
-    ConnectivityStateHelper::SetForTest(NULL);
     LoginState::Shutdown();
     CryptohomeLibrary::Shutdown();
 
@@ -529,7 +523,6 @@
   input_method::MockInputMethodManager* mock_input_method_manager_;
   disks::MockDiskMountManager mock_disk_mount_manager_;
   net::TestURLFetcherFactory test_url_fetcher_factory_;
-  MockConnectivityStateHelper mock_connectivity_state_helper_;
 
   cryptohome::MockAsyncMethodCaller* mock_async_method_caller_;
 
diff --git a/chrome/browser/chromeos/login/oauth2_login_verifier.cc b/chrome/browser/chromeos/login/oauth2_login_verifier.cc
index ab82a37..70bfc5c 100644
--- a/chrome/browser/chromeos/login/oauth2_login_verifier.cc
+++ b/chrome/browser/chromeos/login/oauth2_login_verifier.cc
@@ -11,12 +11,15 @@
 #include "base/strings/string_util.h"
 #include "base/strings/stringprintf.h"
 #include "base/time/time.h"
-#include "chrome/browser/chromeos/net/connectivity_state_helper.h"
 #include "chrome/browser/signin/profile_oauth2_token_service.h"
 #include "chrome/browser/signin/profile_oauth2_token_service_factory.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 "google_apis/gaia/gaia_constants.h"
 #include "google_apis/gaia/gaia_urls.h"
+#include "third_party/cros_system_api/dbus/service_constants.h"
 
 using content::BrowserThread;
 
@@ -50,8 +53,10 @@
 
   // Delay the verification if the network is not connected or on a captive
   // portal.
-  ConnectivityStateHelper* csh = ConnectivityStateHelper::Get();
-  if (!csh->DefaultNetworkOnline()) {
+  const NetworkState* default_network =
+      NetworkHandler::Get()->network_state_handler()->DefaultNetwork();
+  if (!default_network ||
+      default_network->connection_state() == flimflam::kStatePortal) {
     // If network is offline, defer the token fetching until online.
     VLOG(1) << "Network is offline.  Deferring OAuth2 access token fetch.";
     BrowserThread::PostDelayedTask(
diff --git a/chrome/browser/chromeos/login/oauth2_token_fetcher.cc b/chrome/browser/chromeos/login/oauth2_token_fetcher.cc
index f66c1ca..31d3fd4 100644
--- a/chrome/browser/chromeos/login/oauth2_token_fetcher.cc
+++ b/chrome/browser/chromeos/login/oauth2_token_fetcher.cc
@@ -6,10 +6,13 @@
 
 #include "base/logging.h"
 #include "base/strings/string_util.h"
-#include "chrome/browser/chromeos/net/connectivity_state_helper.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 "google_apis/gaia/gaia_constants.h"
 #include "google_apis/gaia/google_service_auth_error.h"
+#include "third_party/cros_system_api/dbus/service_constants.h"
 
 using content::BrowserThread;
 
@@ -41,8 +44,10 @@
 
   // Delay the verification if the network is not connected or on a captive
   // portal.
-  ConnectivityStateHelper* csh = ConnectivityStateHelper::Get();
-  if (!csh->DefaultNetworkOnline()) {
+  const NetworkState* default_network =
+      NetworkHandler::Get()->network_state_handler()->DefaultNetwork();
+  if (!default_network ||
+      default_network->connection_state() == flimflam::kStatePortal) {
     // If network is offline, defer the token fetching until online.
     VLOG(1) << "Network is offline.  Deferring OAuth2 token fetch.";
     BrowserThread::PostDelayedTask(
@@ -61,8 +66,10 @@
   auth_code_ = auth_code;
   // Delay the verification if the network is not connected or on a captive
   // portal.
-  ConnectivityStateHelper* csh = ConnectivityStateHelper::Get();
-  if (!csh->DefaultNetworkOnline()) {
+  const NetworkState* default_network =
+      NetworkHandler::Get()->network_state_handler()->DefaultNetwork();
+  if (!default_network ||
+      default_network->connection_state() == flimflam::kStatePortal) {
     // If network is offline, defer the token fetching until online.
     VLOG(1) << "Network is offline.  Deferring OAuth2 token fetch.";
     BrowserThread::PostDelayedTask(
diff --git a/chrome/browser/chromeos/login/screens/network_screen.cc b/chrome/browser/chromeos/login/screens/network_screen.cc
index a4632b6..fd20947 100644
--- a/chrome/browser/chromeos/login/screens/network_screen.cc
+++ b/chrome/browser/chromeos/login/screens/network_screen.cc
@@ -4,6 +4,7 @@
 
 #include "chrome/browser/chromeos/login/screens/network_screen.h"
 
+#include "base/location.h"
 #include "base/logging.h"
 #include "base/strings/string16.h"
 #include "base/strings/utf_string_conversions.h"
@@ -12,7 +13,8 @@
 #include "chrome/browser/chromeos/login/login_utils.h"
 #include "chrome/browser/chromeos/login/screens/screen_observer.h"
 #include "chrome/browser/chromeos/login/wizard_controller.h"
-#include "chrome/browser/chromeos/net/connectivity_state_helper.h"
+#include "chromeos/network/network_handler.h"
+#include "chromeos/network/network_state_handler.h"
 #include "grit/chromium_strings.h"
 #include "grit/generated_resources.h"
 #include "grit/theme_resources.h"
@@ -36,7 +38,8 @@
     : WizardScreen(screen_observer),
       is_network_subscribed_(false),
       continue_pressed_(false),
-      actor_(actor) {
+      actor_(actor),
+      network_state_helper_(new login::NetworkStateHelper) {
   DCHECK(actor_);
   if (actor_)
     actor_->SetDelegate(this);
@@ -73,13 +76,13 @@
 }
 
 ////////////////////////////////////////////////////////////////////////////////
-// NetworkScreen, ConnectivityStateHelperObserver implementation:
+// NetworkScreen, NetworkStateHandlerObserver implementation:
 
 void NetworkScreen::NetworkManagerChanged() {
   UpdateStatus();
 }
 
-void NetworkScreen::DefaultNetworkChanged() {
+void NetworkScreen::DefaultNetworkChanged(const NetworkState* network) {
   NetworkManagerChanged();
 }
 
@@ -100,7 +103,7 @@
 }
 
 void NetworkScreen::OnContinuePressed() {
-  if (ConnectivityStateHelper::Get()->IsConnected()) {
+  if (network_state_helper_->IsConnected()) {
     NotifyOnConnection();
   } else {
     continue_pressed_ = true;
@@ -111,17 +114,24 @@
 ////////////////////////////////////////////////////////////////////////////////
 // NetworkScreen, private:
 
+void NetworkScreen::SetNetworkStateHelperForTest(
+    login::NetworkStateHelper* helper) {
+  network_state_helper_.reset(helper);
+}
+
 void NetworkScreen::SubscribeNetworkNotification() {
   if (!is_network_subscribed_) {
     is_network_subscribed_ = true;
-    ConnectivityStateHelper::Get()->AddNetworkManagerObserver(this);
+    NetworkHandler::Get()->network_state_handler()->AddObserver(
+        this, FROM_HERE);
   }
 }
 
 void NetworkScreen::UnsubscribeNetworkNotification() {
   if (is_network_subscribed_) {
     is_network_subscribed_ = false;
-    ConnectivityStateHelper::Get()->RemoveNetworkManagerObserver(this);
+    NetworkHandler::Get()->network_state_handler()->RemoveObserver(
+        this, FROM_HERE);
   }
 }
 
@@ -134,7 +144,7 @@
 
 void NetworkScreen::OnConnectionTimeout() {
   StopWaitingForConnection(network_id_);
-  if (!ConnectivityStateHelper::Get()->IsConnected() && actor_) {
+  if (!network_state_helper_->IsConnected() && actor_) {
     // Show error bubble.
     actor_->ShowError(
         l10n_util::GetStringFUTF16(
@@ -148,14 +158,14 @@
   if (!actor_)
     return;
 
-  bool is_connected = ConnectivityStateHelper::Get()->IsConnected();
+  bool is_connected = network_state_helper_->IsConnected();
   if (is_connected)
     actor_->ClearErrors();
 
-  string16 network_name = GetCurrentNetworkName();
+  string16 network_name = network_state_helper_->GetCurrentNetworkName();
   if (is_connected) {
     StopWaitingForConnection(network_name);
-  } else if (ConnectivityStateHelper::Get()->IsConnecting()) {
+  } else if (network_state_helper_->IsConnecting()) {
     WaitForConnection(network_name);
   } else {
     StopWaitingForConnection(network_id_);
@@ -163,7 +173,7 @@
 }
 
 void NetworkScreen::StopWaitingForConnection(const string16& network_id) {
-  bool is_connected = ConnectivityStateHelper::Get()->IsConnected();
+  bool is_connected = network_state_helper_->IsConnected();
   if (is_connected && continue_pressed_) {
     NotifyOnConnection();
     return;
diff --git a/chrome/browser/chromeos/login/screens/network_screen.h b/chrome/browser/chromeos/login/screens/network_screen.h
index 1a3ccf2..c8fae5c 100644
--- a/chrome/browser/chromeos/login/screens/network_screen.h
+++ b/chrome/browser/chromeos/login/screens/network_screen.h
@@ -12,12 +12,16 @@
 #include "chrome/browser/chromeos/login/language_switch_menu.h"
 #include "chrome/browser/chromeos/login/screens/network_screen_actor.h"
 #include "chrome/browser/chromeos/login/screens/wizard_screen.h"
-#include "chrome/browser/chromeos/net/connectivity_state_helper_observer.h"
+#include "chromeos/network/network_state_handler_observer.h"
 
 namespace chromeos {
 
+namespace login {
+class NetworkStateHelper;
+}  // namespace login
+
 class NetworkScreen : public WizardScreen,
-                      public ConnectivityStateHelperObserver,
+                      public NetworkStateHandlerObserver,
                       public NetworkScreenActor::Delegate {
  public:
   NetworkScreen(ScreenObserver* screen_observer, NetworkScreenActor* actor);
@@ -29,9 +33,9 @@
   virtual void Hide() OVERRIDE;
   virtual std::string GetName() const OVERRIDE;
 
-  // ConnectivityStateHelperObserver implementation:
+  // NetworkStateHandlerObserver implementation:
   virtual void NetworkManagerChanged() OVERRIDE;
-  virtual void DefaultNetworkChanged() OVERRIDE;
+  virtual void DefaultNetworkChanged(const NetworkState* network) OVERRIDE;
 
   // NetworkScreenActor::Delegate implementation:
   virtual void OnActorDestroyed(NetworkScreenActor* actor) OVERRIDE;
@@ -45,7 +49,13 @@
   virtual void Refresh();
 
  private:
+  friend class NetworkScreenTest;
   FRIEND_TEST_ALL_PREFIXES(NetworkScreenTest, Timeout);
+  FRIEND_TEST_ALL_PREFIXES(NetworkScreenTest, CanConnect);
+
+  // Sets the NetworkStateHelper for use in tests. This
+  // class will take ownership of the pointed object.
+  void SetNetworkStateHelperForTest(login::NetworkStateHelper* helper);
 
   // Subscribes to network change notifications.
   void SubscribeNetworkNotification();
@@ -82,6 +92,7 @@
   base::OneShotTimer<NetworkScreen> connection_timer_;
 
   NetworkScreenActor* actor_;
+  scoped_ptr<login::NetworkStateHelper> network_state_helper_;
 
   DISALLOW_COPY_AND_ASSIGN(NetworkScreen);
 };
diff --git a/chrome/browser/chromeos/login/screens/network_screen_browsertest.cc b/chrome/browser/chromeos/login/screens/network_screen_browsertest.cc
index dcaeda3..92b94bf 100644
--- a/chrome/browser/chromeos/login/screens/network_screen_browsertest.cc
+++ b/chrome/browser/chromeos/login/screens/network_screen_browsertest.cc
@@ -3,12 +3,12 @@
 // found in the LICENSE file.
 
 #include "base/memory/scoped_ptr.h"
+#include "chrome/browser/chromeos/login/helper.h"
 #include "chrome/browser/chromeos/login/screens/mock_screen_observer.h"
 #include "chrome/browser/chromeos/login/screens/network_screen.h"
 #include "chrome/browser/chromeos/login/screens/wizard_screen.h"
 #include "chrome/browser/chromeos/login/wizard_controller.h"
 #include "chrome/browser/chromeos/login/wizard_in_process_browser_test.h"
-#include "chrome/browser/chromeos/net/mock_connectivity_state_helper.h"
 #include "chrome/test/base/ui_test_utils.h"
 #include "chromeos/dbus/fake_session_manager_client.h"
 #include "chromeos/dbus/mock_dbus_thread_manager_without_gmock.h"
@@ -32,6 +32,17 @@
                              const ui::Event& event) OVERRIDE {}
 };
 
+namespace login {
+
+class MockNetworkStateHelper : public NetworkStateHelper {
+ public:
+  MOCK_CONST_METHOD0(GetCurrentNetworkName, string16(void));
+  MOCK_CONST_METHOD0(IsConnected, bool(void));
+  MOCK_CONST_METHOD0(IsConnecting, bool(void));
+};
+
+}  // namespace login
+
 class NetworkScreenTest : public WizardInProcessBrowserTest {
  public:
   NetworkScreenTest(): WizardInProcessBrowserTest("network"),
@@ -47,19 +58,6 @@
     DBusThreadManager::InitializeForTesting(mock_dbus_thread_manager);
     fake_session_manager_client_ =
         mock_dbus_thread_manager->fake_session_manager_client();
-
-    mock_connectivity_state_helper_.reset(new MockConnectivityStateHelper);
-    ConnectivityStateHelper::SetForTest(mock_connectivity_state_helper_.get());
-    SetDefaultMockConnectivityStateHelperExpectations();
-
-    cellular_.reset(new NetworkDevice("cellular"));
-
-    // Minimal set of expectations needed on NetworkScreen initialization.
-    // Status bar expectations are defined with RetiresOnSaturation() so
-    EXPECT_CALL(*mock_connectivity_state_helper_,
-                IsConnectedType(flimflam::kTypeWifi))
-        .Times(1)
-        .WillRepeatedly(Return(false));
   }
 
   virtual void SetUpOnMainThread() OVERRIDE {
@@ -73,50 +71,41 @@
               network_screen_);
     network_screen_->screen_observer_ = mock_screen_observer_.get();
     ASSERT_TRUE(network_screen_->actor() != NULL);
+
+    mock_network_state_helper_ = new login::MockNetworkStateHelper;
+    SetDefaultNetworkStateHelperExpectations();
+    network_screen_->SetNetworkStateHelperForTest(mock_network_state_helper_);
   }
 
   virtual void TearDownInProcessBrowserTestFixture() OVERRIDE {
     CrosInProcessBrowserTest::TearDownInProcessBrowserTestFixture();
     DBusThreadManager::Shutdown();
-    ConnectivityStateHelper::SetForTest(NULL);
   }
 
   void EmulateContinueButtonExit(NetworkScreen* network_screen) {
     EXPECT_CALL(*mock_screen_observer_,
                 OnExit(ScreenObserver::NETWORK_CONNECTED))
         .Times(1);
-    EXPECT_CALL(*mock_connectivity_state_helper_, IsConnected())
+    EXPECT_CALL(*mock_network_state_helper_, IsConnected())
         .WillOnce(Return(true));
     network_screen->OnContinuePressed();
     content::RunAllPendingInMessageLoop();
   }
 
-  void SetDefaultMockConnectivityStateHelperExpectations() {
-    EXPECT_CALL(*mock_connectivity_state_helper_, AddNetworkManagerObserver(_))
-        .Times(AnyNumber());
-    EXPECT_CALL(*mock_connectivity_state_helper_,
-                RemoveNetworkManagerObserver(_))
-        .Times(AnyNumber());
-    EXPECT_CALL(*mock_connectivity_state_helper_, NetworkNameForType(_))
+  void SetDefaultNetworkStateHelperExpectations() {
+    EXPECT_CALL(*mock_network_state_helper_, GetCurrentNetworkName())
         .Times(AnyNumber())
-        .WillRepeatedly((Return("")));
-    EXPECT_CALL(*mock_connectivity_state_helper_, IsConnected())
+        .WillRepeatedly((Return(string16())));
+    EXPECT_CALL(*mock_network_state_helper_, IsConnected())
         .Times(AnyNumber())
         .WillRepeatedly((Return(false)));
-    EXPECT_CALL(*mock_connectivity_state_helper_, IsConnecting())
-        .Times(AnyNumber())
-        .WillRepeatedly((Return(false)));
-    EXPECT_CALL(*mock_connectivity_state_helper_, IsConnectedType(_))
-        .Times(AnyNumber())
-        .WillRepeatedly((Return(false)));
-    EXPECT_CALL(*mock_connectivity_state_helper_, IsConnectingType(_))
+    EXPECT_CALL(*mock_network_state_helper_, IsConnecting())
         .Times(AnyNumber())
         .WillRepeatedly((Return(false)));
   }
 
   scoped_ptr<MockScreenObserver> mock_screen_observer_;
-  scoped_ptr<MockConnectivityStateHelper> mock_connectivity_state_helper_;
-  scoped_ptr<NetworkDevice> cellular_;
+  login::MockNetworkStateHelper* mock_network_state_helper_;
   NetworkScreen* network_screen_;
   FakeSessionManagerClient* fake_session_manager_client_;
 
@@ -124,101 +113,13 @@
   DISALLOW_COPY_AND_ASSIGN(NetworkScreenTest);
 };
 
-IN_PROC_BROWSER_TEST_F(NetworkScreenTest, Ethernet) {
-  EXPECT_CALL(*mock_connectivity_state_helper_,
-              IsConnectedType(flimflam::kTypeEthernet))
-      .WillOnce((Return(false)));
-  EXPECT_CALL(*mock_connectivity_state_helper_,
-              IsConnectedType(flimflam::kTypeWifi))
-      .WillOnce((Return(false)));
-  EXPECT_CALL(*mock_connectivity_state_helper_,
-              IsConnectedType(flimflam::kTypeCellular))
-      .WillOnce((Return(false)));
-  EXPECT_CALL(*mock_connectivity_state_helper_,
-              IsConnectingType(flimflam::kTypeEthernet))
+IN_PROC_BROWSER_TEST_F(NetworkScreenTest, CanConnect) {
+  EXPECT_CALL(*mock_network_state_helper_, IsConnecting())
       .WillOnce((Return(true)));
   // EXPECT_FALSE(actor_->IsContinueEnabled());
   network_screen_->NetworkManagerChanged();
 
-  EXPECT_CALL(*mock_connectivity_state_helper_,
-              IsConnectedType(flimflam::kTypeEthernet))
-      .WillOnce(Return(true));
-  EXPECT_CALL(*mock_connectivity_state_helper_, IsConnected())
-      .Times(2)
-      .WillRepeatedly(Return(true));
-  // TODO(nkostylev): Add integration with WebUI actor http://crosbug.com/22570
-  // EXPECT_FALSE(actor_->IsContinueEnabled());
-  // EXPECT_FALSE(actor_->IsConnecting());
-  network_screen_->NetworkManagerChanged();
-
-  // EXPECT_TRUE(actor_->IsContinueEnabled());
-  EmulateContinueButtonExit(network_screen_);
-  EXPECT_EQ(
-      1, fake_session_manager_client_->emit_login_prompt_ready_call_count());
-}
-
-IN_PROC_BROWSER_TEST_F(NetworkScreenTest, Wifi) {
-  EXPECT_CALL(*mock_connectivity_state_helper_,
-              IsConnectedType(flimflam::kTypeEthernet))
-      .WillOnce((Return(false)));
-  EXPECT_CALL(*mock_connectivity_state_helper_,
-              IsConnectedType(flimflam::kTypeWifi))
-      .WillOnce((Return(false)));
-  EXPECT_CALL(*mock_connectivity_state_helper_,
-              IsConnectedType(flimflam::kTypeCellular))
-      .WillOnce((Return(false)));
-  EXPECT_CALL(*mock_connectivity_state_helper_,
-              IsConnectingType(flimflam::kTypeEthernet))
-      .WillOnce((Return(false)));
-  EXPECT_CALL(*mock_connectivity_state_helper_,
-              IsConnectingType(flimflam::kTypeWifi))
-      .WillOnce((Return(true)));
-  // EXPECT_FALSE(actor_->IsContinueEnabled());
-  network_screen_->NetworkManagerChanged();
-
-  EXPECT_CALL(*mock_connectivity_state_helper_,
-              IsConnectedType(flimflam::kTypeEthernet))
-      .WillOnce(Return(true));
-  EXPECT_CALL(*mock_connectivity_state_helper_, IsConnected())
-        .Times(2)
-        .WillRepeatedly(Return(true));
-  // TODO(nkostylev): Add integration with WebUI actor http://crosbug.com/22570
-  // EXPECT_FALSE(actor_->IsContinueEnabled());
-  // EXPECT_FALSE(actor_->IsConnecting());
-  network_screen_->NetworkManagerChanged();
-
-  // EXPECT_TRUE(actor_->IsContinueEnabled());
-  EmulateContinueButtonExit(network_screen_);
-  EXPECT_EQ(
-      1, fake_session_manager_client_->emit_login_prompt_ready_call_count());
-}
-
-IN_PROC_BROWSER_TEST_F(NetworkScreenTest, Cellular) {
-  EXPECT_CALL(*mock_connectivity_state_helper_,
-              IsConnectedType(flimflam::kTypeEthernet))
-      .WillOnce((Return(false)));
-  EXPECT_CALL(*mock_connectivity_state_helper_,
-              IsConnectedType(flimflam::kTypeWifi))
-      .WillOnce((Return(false)));
-  EXPECT_CALL(*mock_connectivity_state_helper_,
-              IsConnectedType(flimflam::kTypeCellular))
-      .WillOnce((Return(false)));
-  EXPECT_CALL(*mock_connectivity_state_helper_,
-              IsConnectingType(flimflam::kTypeEthernet))
-      .WillOnce((Return(false)));
-  EXPECT_CALL(*mock_connectivity_state_helper_,
-              IsConnectingType(flimflam::kTypeWifi))
-      .WillOnce((Return(false)));
-  EXPECT_CALL(*mock_connectivity_state_helper_,
-              IsConnectingType(flimflam::kTypeCellular))
-      .WillOnce((Return(true)));
-  // EXPECT_FALSE(actor_->IsContinueEnabled());
-  network_screen_->NetworkManagerChanged();
-
-  EXPECT_CALL(*mock_connectivity_state_helper_,
-              IsConnectedType(flimflam::kTypeEthernet))
-      .WillOnce(Return(true));
-  EXPECT_CALL(*mock_connectivity_state_helper_, IsConnected())
+  EXPECT_CALL(*mock_network_state_helper_, IsConnected())
       .Times(2)
       .WillRepeatedly(Return(true));
   // TODO(nkostylev): Add integration with WebUI actor http://crosbug.com/22570
@@ -233,25 +134,12 @@
 }
 
 IN_PROC_BROWSER_TEST_F(NetworkScreenTest, Timeout) {
-  EXPECT_CALL(*mock_connectivity_state_helper_,
-              IsConnectedType(flimflam::kTypeEthernet))
-      .WillOnce((Return(false)));
-  EXPECT_CALL(*mock_connectivity_state_helper_,
-              IsConnectedType(flimflam::kTypeWifi))
-      .WillOnce((Return(false)));
-  EXPECT_CALL(*mock_connectivity_state_helper_,
-              IsConnectedType(flimflam::kTypeCellular))
-      .WillOnce((Return(false)));
-  EXPECT_CALL(*mock_connectivity_state_helper_,
-              IsConnectingType(flimflam::kTypeEthernet))
-      .WillOnce((Return(false)));
-  EXPECT_CALL(*mock_connectivity_state_helper_,
-              IsConnectingType(flimflam::kTypeWifi))
+  EXPECT_CALL(*mock_network_state_helper_, IsConnecting())
       .WillOnce((Return(true)));
   // EXPECT_FALSE(actor_->IsContinueEnabled());
   network_screen_->NetworkManagerChanged();
 
-  EXPECT_CALL(*mock_connectivity_state_helper_, IsConnected())
+  EXPECT_CALL(*mock_network_state_helper_, IsConnected())
       .Times(2)
       .WillRepeatedly(Return(false));
   // TODO(nkostylev): Add integration with WebUI actor http://crosbug.com/22570
diff --git a/chrome/browser/chromeos/login/user.h b/chrome/browser/chromeos/login/user.h
index 1c8fc9c..35911bb 100644
--- a/chrome/browser/chromeos/login/user.h
+++ b/chrome/browser/chromeos/login/user.h
@@ -48,22 +48,24 @@
 // to by |email()|.
 class User {
  public:
-  // The user type.
+  // The user type. Used in a histogram; do not modify existing types.
   typedef enum {
     // Regular user, has a user name and password.
     USER_TYPE_REGULAR = 0,
     // Guest user, logs in without authentication.
-    USER_TYPE_GUEST,
+    USER_TYPE_GUEST = 1,
     // Retail mode user, logs in without authentication. This is a special user
     // type used in retail mode only.
-    USER_TYPE_RETAIL_MODE,
+    USER_TYPE_RETAIL_MODE = 2,
     // Public account user, logs in without authentication. Available only if
     // enabled through policy.
-    USER_TYPE_PUBLIC_ACCOUNT,
+    USER_TYPE_PUBLIC_ACCOUNT = 3,
     // Locally managed user, logs in only with local authentication.
-    USER_TYPE_LOCALLY_MANAGED,
+    USER_TYPE_LOCALLY_MANAGED = 4,
     // Kiosk app robot, logs in without authentication.
-    USER_TYPE_KIOSK_APP
+    USER_TYPE_KIOSK_APP = 5,
+    // Maximum histogram value.
+    NUM_USER_TYPES = 6
   } UserType;
 
   // User OAuth token status according to the last check.
diff --git a/chrome/browser/chromeos/login/user_manager_impl.cc b/chrome/browser/chromeos/login/user_manager_impl.cc
index 874e865..cdcf4bb 100644
--- a/chrome/browser/chromeos/login/user_manager_impl.cc
+++ b/chrome/browser/chromeos/login/user_manager_impl.cc
@@ -7,7 +7,6 @@
 #include <cstddef>
 #include <set>
 
-#include "ash/shell.h"
 #include "base/bind.h"
 #include "base/bind_helpers.h"
 #include "base/chromeos/chromeos_version.h"
@@ -15,6 +14,7 @@
 #include "base/compiler_specific.h"
 #include "base/files/file_path.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/rand_util.h"
@@ -111,6 +111,15 @@
 // A dictionary that maps usernames to OAuth token presence flag.
 const char kUserOAuthTokenStatus[] = "OAuthTokenStatus";
 
+// A string pref containing the ID of the last user who logged in if it was
+// a regular user or an empty string if it was another type of user (guest,
+// kiosk, public account, etc.).
+const char kLastLoggedInRegularUser[] = "LastLoggedInRegularUser";
+
+// Upper bound for a histogram metric reporting the amount of time between
+// one regular user logging out and a different regular user logging in.
+const int kLogoutToLoginDelayMaxSec = 1800;
+
 // Callback that is called after user removal is complete.
 void OnRemoveUserComplete(const std::string& user_email,
                           bool success,
@@ -189,6 +198,7 @@
       kLocallyManagedUserCreationTransactionDisplayName, "");
   registry->RegisterStringPref(
       kLocallyManagedUserCreationTransactionUserId, "");
+  registry->RegisterStringPref(kLastLoggedInRegularUser, "");
   registry->RegisterDictionaryPref(kUserOAuthTokenStatus);
   registry->RegisterDictionaryPref(kUserDisplayName);
   registry->RegisterDictionaryPref(kUserDisplayEmail);
@@ -213,7 +223,8 @@
       locally_managed_users_enabled_by_policy_(false),
       merge_session_state_(MERGE_STATUS_NOT_STARTED),
       observed_sync_service_(NULL),
-      user_image_manager_(new UserImageManagerImpl) {
+      user_image_manager_(new UserImageManagerImpl),
+      manager_creation_time_(base::TimeTicks::Now()) {
   // UserManager instance should be used only on UI thread.
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
   registrar_.Add(this, chrome::NOTIFICATION_OWNERSHIP_STATUS_CHANGED,
@@ -317,10 +328,8 @@
     User* user = FindUserInListAndModify(email);
     if (user && user->GetType() == User::USER_TYPE_PUBLIC_ACCOUNT) {
       PublicAccountUserLoggedIn(user);
-    } else if ((user &&
-                user->GetType() == User::USER_TYPE_LOCALLY_MANAGED) ||
-               (!user &&
-                gaia::ExtractDomainName(email) ==
+    } else if ((user && user->GetType() == User::USER_TYPE_LOCALLY_MANAGED) ||
+               (!user && gaia::ExtractDomainName(email) ==
                     UserManager::kLocallyManagedUserDomain)) {
       LocallyManagedUserLoggedIn(email);
     } else if (browser_restart && email == g_browser_process->local_state()->
@@ -347,6 +356,14 @@
   logged_in_users_.insert(logged_in_users_.begin(), active_user_);
   SetLRUUser(active_user_);
 
+  UMA_HISTOGRAM_ENUMERATION("UserManager.LoginUserType",
+                            active_user_->GetType(), User::NUM_USER_TYPES);
+
+  if (active_user_->GetType() == User::USER_TYPE_REGULAR)
+    SendRegularUserLoginMetrics(email);
+  g_browser_process->local_state()->SetString(kLastLoggedInRegularUser,
+    (active_user_->GetType() == User::USER_TYPE_REGULAR) ? email : "");
+
   NotifyOnLogin();
 }
 
@@ -1064,7 +1081,7 @@
 
   // If ephemeral users are enabled and we are on the login screen, take this
   // opportunity to clean up by removing all regular users except the owner.
-  if (ephemeral_users_enabled_  && !IsUserLoggedIn()) {
+  if (ephemeral_users_enabled_ && !IsUserLoggedIn()) {
     ListPrefUpdate prefs_users_update(g_browser_process->local_state(),
                                       kRegularUsers);
     prefs_users_update->Clear();
@@ -1776,4 +1793,21 @@
   }
 }
 
+void UserManagerImpl::SendRegularUserLoginMetrics(const std::string& email) {
+  // If this isn't the first time Chrome was run after the system booted,
+  // assume that Chrome was restarted because a previous session ended.
+  if (!CommandLine::ForCurrentProcess()->HasSwitch(
+          switches::kFirstExecAfterBoot)) {
+    const std::string last_email =
+        g_browser_process->local_state()->GetString(kLastLoggedInRegularUser);
+    const base::TimeDelta time_to_login =
+        base::TimeTicks::Now() - manager_creation_time_;
+    if (!last_email.empty() && email != last_email &&
+        time_to_login.InSeconds() <= kLogoutToLoginDelayMaxSec) {
+      UMA_HISTOGRAM_CUSTOM_COUNTS("UserManager.LogoutToLoginDelay",
+          time_to_login.InSeconds(), 0, kLogoutToLoginDelayMaxSec, 50);
+    }
+  }
+}
+
 }  // namespace chromeos
diff --git a/chrome/browser/chromeos/login/user_manager_impl.h b/chrome/browser/chromeos/login/user_manager_impl.h
index cdfe74d..577e1d6 100644
--- a/chrome/browser/chromeos/login/user_manager_impl.h
+++ b/chrome/browser/chromeos/login/user_manager_impl.h
@@ -13,6 +13,7 @@
 #include "base/memory/scoped_ptr.h"
 #include "base/observer_list.h"
 #include "base/synchronization/lock.h"
+#include "base/time/time.h"
 #include "chrome/browser/chromeos/login/login_utils.h"
 #include "chrome/browser/chromeos/login/user.h"
 #include "chrome/browser/chromeos/login/user_image_manager_impl.h"
@@ -301,6 +302,9 @@
   // Process continues till |pending_user_sessions_| map is not empty.
   void RestorePendingUserSessions();
 
+  // Sends metrics in response to a regular user logging in.
+  void SendRegularUserLoginMetrics(const std::string& email);
+
   // Interface to the signed settings store.
   CrosSettings* cros_settings_;
 
@@ -409,6 +413,9 @@
   // [user_id] > [user_id_hash]
   SessionManagerClient::ActiveSessionsMap pending_user_sessions_;
 
+  // Time at which this object was created.
+  base::TimeTicks manager_creation_time_;
+
   DISALLOW_COPY_AND_ASSIGN(UserManagerImpl);
 };
 
diff --git a/chrome/browser/chromeos/login/webui_screen_locker.cc b/chrome/browser/chromeos/login/webui_screen_locker.cc
index c5532df..adee217 100644
--- a/chrome/browser/chromeos/login/webui_screen_locker.cc
+++ b/chrome/browser/chromeos/login/webui_screen_locker.cc
@@ -48,6 +48,7 @@
     : ScreenLockerDelegate(screen_locker),
       lock_ready_(false),
       webui_ready_(false),
+      network_state_helper_(new login::NetworkStateHelper),
       weak_factory_(this) {
   set_should_emit_login_prompt_visible(false);
   ash::Shell::GetInstance()->lock_state_controller()->AddObserver(this);
@@ -200,7 +201,7 @@
 }
 
 string16 WebUIScreenLocker::GetConnectedNetworkName() {
-  return GetCurrentNetworkName();
+  return network_state_helper_->GetCurrentNetworkName();
 }
 
 bool WebUIScreenLocker::IsSigninInProgress() const {
diff --git a/chrome/browser/chromeos/login/webui_screen_locker.h b/chrome/browser/chromeos/login/webui_screen_locker.h
index 4da5d30..4521525 100644
--- a/chrome/browser/chromeos/login/webui_screen_locker.h
+++ b/chrome/browser/chromeos/login/webui_screen_locker.h
@@ -33,6 +33,10 @@
 class WebUILoginDisplay;
 struct UserContext;
 
+namespace login {
+class NetworkStateHelper;
+}
+
 namespace test {
 class WebUIScreenLockerTester;
 }
@@ -135,6 +139,8 @@
   // Time when lock was initiated, required for metrics.
   base::TimeTicks lock_time_;
 
+  scoped_ptr<login::NetworkStateHelper> network_state_helper_;
+
   base::WeakPtrFactory<WebUIScreenLocker> weak_factory_;
 
   DISALLOW_COPY_AND_ASSIGN(WebUIScreenLocker);
diff --git a/chrome/browser/chromeos/login/wizard_controller.cc b/chrome/browser/chromeos/login/wizard_controller.cc
index ff92afd..bc83452 100644
--- a/chrome/browser/chromeos/login/wizard_controller.cc
+++ b/chrome/browser/chromeos/login/wizard_controller.cc
@@ -21,7 +21,6 @@
 #include "base/values.h"
 #include "chrome/app/breakpad_linux.h"
 #include "chrome/browser/browser_process.h"
-#include "chrome/browser/chrome_notification_types.h"
 #include "chrome/browser/chromeos/app_mode/kiosk_app_launcher.h"
 #include "chrome/browser/chromeos/app_mode/kiosk_app_manager.h"
 #include "chrome/browser/chromeos/customization_document.h"
@@ -60,9 +59,6 @@
 #include "chromeos/dbus/session_manager_client.h"
 #include "chromeos/network/network_state_handler.h"
 #include "content/public/browser/browser_thread.h"
-#include "content/public/browser/notification_service.h"
-#include "content/public/browser/notification_source.h"
-#include "content/public/browser/notification_types.h"
 #include "ui/base/accelerators/accelerator.h"
 #include "ui/base/l10n/l10n_util.h"
 
@@ -186,10 +182,6 @@
     is_out_of_box_ = true;
 
   AdvanceToScreen(first_screen_name);
-  content::NotificationService::current()->Notify(
-      chrome::NOTIFICATION_WIZARD_FIRST_SCREEN_SHOWN,
-      content::NotificationService::AllSources(),
-      content::NotificationService::NoDetails());
   if (!IsMachineHWIDCorrect() && !StartupUtils::IsDeviceRegistered() &&
       first_screen_name.empty())
     ShowWrongHWIDScreen();
@@ -833,7 +825,9 @@
   KioskAppManager::App app_data;
   std::string app_id = KioskAppManager::Get()->GetAutoLaunchApp();
   CHECK(KioskAppManager::Get()->GetApp(app_id, &app_data));
-  ExistingUserController::current_controller()->PrepareKioskAppLaunch();
+  if (ExistingUserController::current_controller())
+    ExistingUserController::current_controller()->PrepareKioskAppLaunch();
+
   // KioskAppLauncher deletes itself when done.
   (new KioskAppLauncher(KioskAppManager::Get(), app_id))->Start();
 }
diff --git a/chrome/browser/chromeos/mobile/mobile_activator.cc b/chrome/browser/chromeos/mobile/mobile_activator.cc
index 2c42584..3e1a82e 100644
--- a/chrome/browser/chromeos/mobile/mobile_activator.cc
+++ b/chrome/browser/chromeos/mobile/mobile_activator.cc
@@ -8,6 +8,7 @@
 #include <map>
 #include <string>
 
+#include "ash/system/chromeos/network/network_connect.h"
 #include "base/bind.h"
 #include "base/bind_helpers.h"
 #include "base/file_util.h"
@@ -515,7 +516,8 @@
     LOG(WARNING) << "Connect failed, will try again in a little bit.";
     if (network) {
       LOG(INFO) << "Connecting to: " << network->service_path();
-      GetNetworkLibrary()->ConnectToCellularNetwork(network);
+      ash::network_connect::ConnectToNetwork(
+          network->service_path(), NULL /* no parent window */);
     }
   }
 }
diff --git a/chrome/browser/chromeos/net/connectivity_state_helper.cc b/chrome/browser/chromeos/net/connectivity_state_helper.cc
deleted file mode 100644
index 59c626b..0000000
--- a/chrome/browser/chromeos/net/connectivity_state_helper.cc
+++ /dev/null
@@ -1,287 +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/chromeos/net/connectivity_state_helper.h"
-
-#include "base/command_line.h"
-#include "chrome/browser/chromeos/cros/network_library.h"
-#include "chromeos/chromeos_switches.h"
-#include "chromeos/network/network_state.h"
-#include "chromeos/network/network_state_handler.h"
-#include "chromeos/network/network_state_handler_observer.h"
-#include "third_party/cros_system_api/dbus/service_constants.h"
-
-namespace chromeos {
-
-static ConnectivityStateHelper* g_connectivity_state_helper = NULL;
-static ConnectivityStateHelper* g_test_connectivity_state_helper = NULL;
-
-// Implementation of the connectivity state helper that uses the network
-// state handler for fetching connectivity state.
-class ConnectivityStateHelperImpl
-    : public ConnectivityStateHelper,
-      public NetworkStateHandlerObserver {
- public:
-  ConnectivityStateHelperImpl();
-  virtual ~ConnectivityStateHelperImpl();
-
-  // NetworkStateHandler overrides.
-  virtual bool IsConnected() OVERRIDE;
-  virtual bool IsConnecting() OVERRIDE;
-  virtual bool IsConnectedType(const std::string& type) OVERRIDE;
-  virtual bool IsConnectingType(const std::string& type) OVERRIDE;
-  virtual std::string NetworkNameForType(const std::string& type) OVERRIDE;
-  virtual std::string DefaultNetworkName() OVERRIDE;
-  virtual bool DefaultNetworkOnline() OVERRIDE;
-  virtual void RequestScan() const OVERRIDE;
-
-  // NetworkStateHandlerObserver overrides.
-  virtual void NetworkManagerChanged() OVERRIDE;
-  virtual void DefaultNetworkChanged(const NetworkState* network) OVERRIDE;
-
- private:
-  NetworkStateHandler* network_state_handler_;
-};
-
-// Implementation of the connectivity state helper that uses the network
-// library for fetching connectivity state.
-class ConnectivityStateHelperNetworkLibrary
-    : public ConnectivityStateHelper,
-      public NetworkLibrary::NetworkManagerObserver {
- public:
-  ConnectivityStateHelperNetworkLibrary();
-  virtual ~ConnectivityStateHelperNetworkLibrary();
-
-  // ConnectivityStateHelper overrides.
-  virtual bool IsConnected() OVERRIDE;
-  virtual bool IsConnecting() OVERRIDE;
-  virtual bool IsConnectedType(const std::string& type) OVERRIDE;
-  virtual bool IsConnectingType(const std::string& type) OVERRIDE;
-  virtual std::string NetworkNameForType(const std::string& type) OVERRIDE;
-  virtual std::string DefaultNetworkName() OVERRIDE;
-  virtual bool DefaultNetworkOnline() OVERRIDE;
-  virtual void RequestScan() const OVERRIDE;
-
-  // NetworkLibrary::NetworkManagerObserver overrides.
-  virtual void OnNetworkManagerChanged(
-      NetworkLibrary* network_library) OVERRIDE;
-
- private:
-  NetworkLibrary* network_library_;
-};
-
-ConnectivityStateHelper::ConnectivityStateHelper() {
-}
-
-ConnectivityStateHelper::~ConnectivityStateHelper() {
-}
-
-// static
-void ConnectivityStateHelper::Initialize() {
-  CHECK(!g_connectivity_state_helper);
-  if (!CommandLine::ForCurrentProcess()->HasSwitch(
-          chromeos::switches::kDisableNewNetworkChangeNotifier)) {
-    g_connectivity_state_helper = new ConnectivityStateHelperImpl();
-  } else {
-    g_connectivity_state_helper =
-        new ConnectivityStateHelperNetworkLibrary();
-  }
-}
-
-// static
-bool ConnectivityStateHelper::IsInitialized() {
-  return g_connectivity_state_helper != NULL;
-}
-
-// static
-void ConnectivityStateHelper::Shutdown() {
-  CHECK(g_connectivity_state_helper);
-  delete g_connectivity_state_helper;
-  g_connectivity_state_helper = NULL;
-}
-
-// static
-ConnectivityStateHelper* ConnectivityStateHelper::Get() {
-  CHECK(g_connectivity_state_helper || g_test_connectivity_state_helper)
-      << "ConnectivityStateHelper: Get() called before Initialize()";
-  if (g_test_connectivity_state_helper)
-    return g_test_connectivity_state_helper;
-  return g_connectivity_state_helper;
-}
-
-// static
-void ConnectivityStateHelper::SetForTest(ConnectivityStateHelper* impl) {
-  CHECK(!g_test_connectivity_state_helper || !impl);
-  g_test_connectivity_state_helper = impl;
-}
-
-void ConnectivityStateHelper::AddNetworkManagerObserver(
-    ConnectivityStateHelperObserver* observer) {
-  connectivity_observers_.AddObserver(observer);
-}
-
-void ConnectivityStateHelper::RemoveNetworkManagerObserver(
-    ConnectivityStateHelperObserver* observer) {
-  connectivity_observers_.RemoveObserver(observer);
-}
-
-ConnectivityStateHelperImpl::ConnectivityStateHelperImpl() {
-  network_state_handler_ = NetworkHandler::Get()->network_state_handler();
-  network_state_handler_->AddObserver(this, FROM_HERE);
-}
-
-ConnectivityStateHelperImpl::~ConnectivityStateHelperImpl() {
-  network_state_handler_->RemoveObserver(this, FROM_HERE);
-}
-
-bool ConnectivityStateHelperImpl::IsConnected() {
-  return network_state_handler_->ConnectedNetworkByType(
-      NetworkStateHandler::kMatchTypeDefault) != NULL;
-}
-
-bool ConnectivityStateHelperImpl::IsConnecting() {
-  return network_state_handler_->ConnectingNetworkByType(
-      NetworkStateHandler::kMatchTypeDefault) != NULL;
-}
-
-bool ConnectivityStateHelperImpl::IsConnectedType(
-    const std::string& type) {
-  return network_state_handler_->ConnectedNetworkByType(type) != NULL;
-}
-
-bool ConnectivityStateHelperImpl::IsConnectingType(
-    const std::string& type) {
-  return network_state_handler_->ConnectingNetworkByType(type) != NULL;
-}
-
-std::string ConnectivityStateHelperImpl::NetworkNameForType(
-    const std::string& type) {
-  const NetworkState* network = network_state_handler_->
-      ConnectedNetworkByType(type);
-  if (!network)
-    network = network_state_handler_->ConnectingNetworkByType(type);
-  return network ? network->name() : std::string();
-}
-
-std::string ConnectivityStateHelperImpl::DefaultNetworkName() {
-  const NetworkState* default_network = network_state_handler_->
-      DefaultNetwork();
-  return default_network ? default_network->name() : std::string();
-}
-
-bool ConnectivityStateHelperImpl::DefaultNetworkOnline() {
-  const NetworkState* network = network_state_handler_->DefaultNetwork();
-  if (!network)
-    return false;
-  if (!network->IsConnectedState())
-    return false;
-  if (network->connection_state() == flimflam::kStatePortal)
-    return false;
-  return true;
-}
-
-void ConnectivityStateHelperImpl::RequestScan() const {
-  network_state_handler_->RequestScan();
-}
-
-void ConnectivityStateHelperImpl::NetworkManagerChanged() {
-  FOR_EACH_OBSERVER(ConnectivityStateHelperObserver, connectivity_observers_,
-                    NetworkManagerChanged());
-}
-
-void ConnectivityStateHelperImpl::DefaultNetworkChanged(
-    const NetworkState* network) {
-  FOR_EACH_OBSERVER(ConnectivityStateHelperObserver, connectivity_observers_,
-                    DefaultNetworkChanged());
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// NetworkLibrary implementation.
-//
-
-ConnectivityStateHelperNetworkLibrary::ConnectivityStateHelperNetworkLibrary() {
-  network_library_ = NetworkLibrary::Get();
-  network_library_->AddNetworkManagerObserver(this);
-}
-
-ConnectivityStateHelperNetworkLibrary::~ConnectivityStateHelperNetworkLibrary()
-{
-  network_library_->RemoveNetworkManagerObserver(this);
-}
-
-bool ConnectivityStateHelperNetworkLibrary::IsConnected() {
-  return network_library_->Connected();
-}
-
-bool ConnectivityStateHelperNetworkLibrary::IsConnecting() {
-  return network_library_->Connecting();
-}
-
-bool ConnectivityStateHelperNetworkLibrary::IsConnectedType(
-    const std::string& type) {
-  if (type == flimflam::kTypeEthernet)
-    return network_library_->ethernet_connected();
-  if (type == flimflam::kTypeWifi)
-    return network_library_->wifi_connected();
-  if (type == flimflam::kTypeCellular)
-    return network_library_->cellular_connected();
-  if (type == flimflam::kTypeWimax)
-    return network_library_->wimax_connected();
-  return false;
-}
-
-bool ConnectivityStateHelperNetworkLibrary::IsConnectingType(
-    const std::string& type) {
-  if (type == flimflam::kTypeEthernet)
-    return network_library_->ethernet_connecting();
-  if (type == flimflam::kTypeWifi)
-    return network_library_->wifi_connecting();
-  if (type == flimflam::kTypeCellular)
-    return network_library_->cellular_connecting();
-  if (type == flimflam::kTypeWimax)
-    return network_library_->wimax_connecting();
-  return false;
-}
-
-std::string ConnectivityStateHelperNetworkLibrary::NetworkNameForType(
-    const std::string& type) {
-  if (type == flimflam::kTypeEthernet && network_library_->ethernet_network())
-    return network_library_->ethernet_network()->name();
-  if (type == flimflam::kTypeWifi && network_library_->wifi_network())
-    return network_library_->wifi_network()->name();
-  if (type == flimflam::kTypeCellular && network_library_->cellular_network())
-    return network_library_->cellular_network()->name();
-  if (type == flimflam::kTypeWimax && network_library_->wimax_network())
-    return network_library_->wimax_network()->name();
-  return std::string();
-}
-
-std::string ConnectivityStateHelperNetworkLibrary::DefaultNetworkName() {
-  if (network_library_->active_network())
-    return network_library_->active_network()->name();
-  return std::string();
-}
-
-bool ConnectivityStateHelperNetworkLibrary::DefaultNetworkOnline() {
-  const Network* active_network = network_library_->active_network();
-  if (!active_network)
-    return false;
-  if (!active_network->connected())
-    return false;
-  if (active_network->restricted_pool())
-    return false;
-  return true;
-}
-
-void ConnectivityStateHelperNetworkLibrary::RequestScan() const {
-  network_library_->RequestNetworkScan();
-}
-
-void ConnectivityStateHelperNetworkLibrary::OnNetworkManagerChanged(
-    NetworkLibrary* network_library) {
-  FOR_EACH_OBSERVER(ConnectivityStateHelperObserver, connectivity_observers_,
-                    NetworkManagerChanged());
-}
-
-}  // namespace chromeos
diff --git a/chrome/browser/chromeos/net/connectivity_state_helper.h b/chrome/browser/chromeos/net/connectivity_state_helper.h
deleted file mode 100644
index d4b1201..0000000
--- a/chrome/browser/chromeos/net/connectivity_state_helper.h
+++ /dev/null
@@ -1,72 +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_CHROMEOS_NET_CONNECTIVITY_STATE_HELPER_H_
-#define CHROME_BROWSER_CHROMEOS_NET_CONNECTIVITY_STATE_HELPER_H_
-
-#include "base/observer_list.h"
-#include "chrome/browser/chromeos/cros/network_library.h"
-#include "chrome/browser/chromeos/net/connectivity_state_helper_observer.h"
-#include "chromeos/network/network_state_handler.h"
-
-namespace chromeos {
-
-// This class provides an interface for consumers to query the connectivity
-// state on Chrome OS. Subclasses must implement the query methods using an
-// appropriate source (e.g. NetworkStateHandler).
-class ConnectivityStateHelper {
- public:
-  virtual ~ConnectivityStateHelper();
-
-  // Initializes the state helper singleton to use the default (network state
-  // handler) implementation or the network library implementation based
-  // on the value of command line flag.
-  static void Initialize();
-  static bool IsInitialized();
-  static void Shutdown();
-  static ConnectivityStateHelper* Get();
-
-  // Sets up Get() to return |impl| for testing (e.g. with a mock
-  // implementation). Call SetForTest(NUL) when |impl| is deleted.
-  static void SetForTest(ConnectivityStateHelper* impl);
-
-  // Returns true if in a connected state.
-  virtual bool IsConnected() = 0;
-
-  // Returns true if in a connecting state.
-  virtual bool IsConnecting() = 0;
-
-  // Returns true if there's a network of |type| in connected state.
-  virtual bool IsConnectedType(const std::string& type) = 0;
-
-  // Returns true if there's a network of |type| in connecting state.
-  virtual bool IsConnectingType(const std::string& type) = 0;
-
-  // Get the name for the primary network of type |type| which is not
-  // in non-idle state (i.e. connecting or connected state).
-  virtual std::string NetworkNameForType(const std::string& type) = 0;
-
-  // Returns the name of the default network.
-  virtual std::string DefaultNetworkName() = 0;
-
-  // Returns true if we have a default network and are in online state.
-  virtual bool DefaultNetworkOnline() = 0;
-
-  // Request a network scan.
-  virtual void RequestScan() const = 0;
-
-  // Add/remove observers for listening to connection manager changes.
-  virtual void AddNetworkManagerObserver(
-      ConnectivityStateHelperObserver* observer);
-  virtual void RemoveNetworkManagerObserver(
-      ConnectivityStateHelperObserver* observer);
-
- protected:
-  ConnectivityStateHelper();
-  ObserverList<ConnectivityStateHelperObserver> connectivity_observers_;
-};
-
-}  // namespace chromeos
-
-#endif  // CHROME_BROWSER_CHROMEOS_NET_CONNECTIVITY_STATE_HELPER_H_
diff --git a/chrome/browser/chromeos/net/connectivity_state_helper_observer.h b/chrome/browser/chromeos/net/connectivity_state_helper_observer.h
deleted file mode 100644
index c907898..0000000
--- a/chrome/browser/chromeos/net/connectivity_state_helper_observer.h
+++ /dev/null
@@ -1,24 +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_CHROMEOS_NET_CONNECTIVITY_STATE_HELPER_OBSERVER_H_
-#define CHROME_BROWSER_CHROMEOS_NET_CONNECTIVITY_STATE_HELPER_OBSERVER_H_
-
-namespace chromeos {
-
-// A common observer interface used by the ConnectivityStateHelper object to
-// relay observing events received from the (older) NetworkLibrary or the (new)
-// NetworkStateHandler implementations.
-class ConnectivityStateHelperObserver {
- public:
-  // Called when there's a change on the connection manager.
-  virtual void NetworkManagerChanged() = 0;
-
-  // Called when the default network changes.
-  virtual void DefaultNetworkChanged() = 0;
-};
-
-}  // namespace chromeos
-
-#endif  // CHROME_BROWSER_CHROMEOS_NET_CONNECTIVITY_STATE_HELPER_OBSERVER_H_
diff --git a/chrome/browser/chromeos/net/cros_network_change_notifier_factory.cc b/chrome/browser/chromeos/net/cros_network_change_notifier_factory.cc
deleted file mode 100644
index 6941f45..0000000
--- a/chrome/browser/chromeos/net/cros_network_change_notifier_factory.cc
+++ /dev/null
@@ -1,28 +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/chromeos/net/cros_network_change_notifier_factory.h"
-
-#include "chrome/browser/chromeos/net/network_change_notifier_network_library.h"
-
-namespace chromeos {
-
-namespace {
-
-NetworkChangeNotifierNetworkLibrary* g_network_change_notifier = NULL;
-
-}  // namespace
-
-net::NetworkChangeNotifier* CrosNetworkChangeNotifierFactory::CreateInstance() {
-  DCHECK(!g_network_change_notifier);
-  g_network_change_notifier = new NetworkChangeNotifierNetworkLibrary();
-  return g_network_change_notifier;
-}
-
-// static
-NetworkChangeNotifierNetworkLibrary*
-CrosNetworkChangeNotifierFactory::GetInstance() {
-  return g_network_change_notifier;
-}
-
-}  // namespace net
diff --git a/chrome/browser/chromeos/net/cros_network_change_notifier_factory.h b/chrome/browser/chromeos/net/cros_network_change_notifier_factory.h
deleted file mode 100644
index b51d46f..0000000
--- a/chrome/browser/chromeos/net/cros_network_change_notifier_factory.h
+++ /dev/null
@@ -1,32 +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 CHROME_BROWSER_CHROMEOS_NET_CROS_NETWORK_CHANGE_NOTIFIER_FACTORY_H_
-#define CHROME_BROWSER_CHROMEOS_NET_CROS_NETWORK_CHANGE_NOTIFIER_FACTORY_H_
-
-#include "base/compiler_specific.h"
-#include "net/base/network_change_notifier_factory.h"
-
-namespace chromeos {
-
-class NetworkChangeNotifierNetworkLibrary;
-
-// CrosNetworkChangeNotifierFactory creates ChromeOS-specific specialization of
-// NetworkChangeNotifier.
-class CrosNetworkChangeNotifierFactory
-    : public net::NetworkChangeNotifierFactory {
- public:
-  CrosNetworkChangeNotifierFactory() {}
-
-  // Overrides of net::NetworkChangeNotifierFactory.
-  virtual net::NetworkChangeNotifier* CreateInstance() OVERRIDE;
-
-  // Gets the instance of the NetworkChangeNotifier for Chrome OS.
-  // This is used for setting up the notifier at startup.
-  static NetworkChangeNotifierNetworkLibrary* GetInstance();
-};
-
-}  // namespace net
-
-#endif  // CHROME_BROWSER_CHROMEOS_NET_CROS_NETWORK_CHANGE_NOTIFIER_FACTORY_H_
diff --git a/chrome/browser/chromeos/net/mock_connectivity_state_helper.cc b/chrome/browser/chromeos/net/mock_connectivity_state_helper.cc
deleted file mode 100644
index be9caa1..0000000
--- a/chrome/browser/chromeos/net/mock_connectivity_state_helper.cc
+++ /dev/null
@@ -1,12 +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/chromeos/net/mock_connectivity_state_helper.h"
-
-namespace chromeos {
-
-MockConnectivityStateHelper::MockConnectivityStateHelper() {}
-MockConnectivityStateHelper::~MockConnectivityStateHelper() {}
-
-}  // namespace chromeos
diff --git a/chrome/browser/chromeos/net/mock_connectivity_state_helper.h b/chrome/browser/chromeos/net/mock_connectivity_state_helper.h
deleted file mode 100644
index cbef21d..0000000
--- a/chrome/browser/chromeos/net/mock_connectivity_state_helper.h
+++ /dev/null
@@ -1,37 +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_CHROMEOS_NET_MOCK_CONNECTIVITY_STATE_HELPER_H_
-#define CHROME_BROWSER_CHROMEOS_NET_MOCK_CONNECTIVITY_STATE_HELPER_H_
-
-#include "chrome/browser/chromeos/net/connectivity_state_helper.h"
-
-#include <string>
-
-#include "chrome/browser/chromeos/net/connectivity_state_helper_observer.h"
-#include "testing/gmock/include/gmock/gmock.h"
-
-namespace chromeos {
-
-class MockConnectivityStateHelper : public ConnectivityStateHelper {
- public:
-  MockConnectivityStateHelper();
-  virtual ~MockConnectivityStateHelper();
-  MOCK_METHOD0(IsConnected, bool(void));
-  MOCK_METHOD0(IsConnecting, bool(void));
-  MOCK_METHOD1(IsConnectedType, bool(const std::string&));
-  MOCK_METHOD1(IsConnectingType, bool(const std::string&));
-  MOCK_METHOD1(NetworkNameForType, std::string(const std::string&));
-  MOCK_METHOD0(DefaultNetworkName, std::string(void));
-  MOCK_METHOD0(DefaultNetworkOnline, bool(void));
-  MOCK_CONST_METHOD0(RequestScan, void(void));
-  MOCK_METHOD1(AddNetworkManagerObserver,
-               void(ConnectivityStateHelperObserver*));
-  MOCK_METHOD1(RemoveNetworkManagerObserver,
-               void(ConnectivityStateHelperObserver*));
-};
-
-}  // namespace chromeos
-
-#endif  // CHROME_BROWSER_CHROMEOS_NET_MOCK_CONNECTIVITY_STATE_HELPER_H_
diff --git a/chrome/browser/chromeos/network_login_observer.cc b/chrome/browser/chromeos/network_login_observer.cc
index b4d4310..65cbd85 100644
--- a/chrome/browser/chromeos/network_login_observer.cc
+++ b/chrome/browser/chromeos/network_login_observer.cc
@@ -36,7 +36,7 @@
           wifi->error() == ERROR_BAD_WEPKEY ||
           wifi->connection_started() ||
           (wifi->encrypted() && wifi->added())) {
-        NetworkConfigView::Show(wifi, NULL);
+        NetworkConfigView::Show(wifi->service_path(), NULL);
         return;  // Only support one failure per notification.
       }
     }
@@ -58,7 +58,7 @@
           wimax->error() == ERROR_BAD_WEPKEY ||
           wimax->connection_started() ||
           (wimax->passphrase_required() && wimax->added())) {
-        NetworkConfigView::Show(wimax, NULL);
+        NetworkConfigView::Show(wimax->service_path(), NULL);
         return;  // Only support one failure per notification.
       }
     }
@@ -74,7 +74,7 @@
               << ", added: " << vpn->added();
       // Display login dialog for any error or newly added network.
       if (vpn->error() != ERROR_NO_ERROR || vpn->added()) {
-        NetworkConfigView::Show(vpn, NULL);
+        NetworkConfigView::Show(vpn->service_path(), NULL);
         return;  // Only support one failure per notification.
       }
     }
diff --git a/chrome/browser/chromeos/options/network_config_view.cc b/chrome/browser/chromeos/options/network_config_view.cc
index 0a74836..257bbdc 100644
--- a/chrome/browser/chromeos/options/network_config_view.cc
+++ b/chrome/browser/chromeos/options/network_config_view.cc
@@ -12,7 +12,6 @@
 #include "chrome/browser/chromeos/cros/network_property_ui_data.h"
 #include "chrome/browser/chromeos/login/login_display_host_impl.h"
 #include "chrome/browser/chromeos/login/user.h"
-#include "chrome/browser/chromeos/login/user_manager.h"
 #include "chrome/browser/chromeos/options/vpn_config_view.h"
 #include "chrome/browser/chromeos/options/wifi_config_view.h"
 #include "chrome/browser/chromeos/options/wimax_config_view.h"
@@ -21,7 +20,8 @@
 #include "chrome/browser/ui/browser_finder.h"
 #include "chrome/browser/ui/browser_window.h"
 #include "chrome/browser/ui/host_desktop.h"
-#include "chromeos/network/managed_network_configuration_handler.h"
+#include "chromeos/network/network_state.h"
+#include "chromeos/network/network_state_handler.h"
 #include "grit/chromium_strings.h"
 #include "grit/generated_resources.h"
 #include "grit/locale_settings.h"
@@ -76,39 +76,38 @@
 // static
 const int ChildNetworkConfigView::kInputFieldMinWidth = 270;
 
-NetworkConfigView::NetworkConfigView(Network* network)
+NetworkConfigView::NetworkConfigView()
     : child_config_view_(NULL),
       delegate_(NULL),
       advanced_button_(NULL) {
   DCHECK(GetActiveDialog() == NULL);
   SetActiveDialog(this);
-  if (network->type() == TYPE_WIFI) {
-    child_config_view_ =
-        new WifiConfigView(this, static_cast<WifiNetwork*>(network));
-  } else if (network->type() == TYPE_WIMAX) {
-    child_config_view_ =
-        new WimaxConfigView(this, static_cast<WimaxNetwork*>(network));
-  } else if (network->type() == TYPE_VPN) {
-    child_config_view_ =
-        new VPNConfigView(this, static_cast<VirtualNetwork*>(network));
-  } else {
-    NOTREACHED();
-  }
 }
 
-NetworkConfigView::NetworkConfigView(ConnectionType type)
-    : child_config_view_(NULL),
-      delegate_(NULL),
-      advanced_button_(NULL) {
-  DCHECK(GetActiveDialog() == NULL);
-  SetActiveDialog(this);
-  if (type == TYPE_WIFI) {
-    child_config_view_ = new WifiConfigView(this, false /* show_8021x */);
+void NetworkConfigView::InitWithNetworkState(const NetworkState* network) {
+  DCHECK(network);
+  std::string service_path = network->path();
+  if (network->type() == flimflam::kTypeWifi)
+    child_config_view_ = new WifiConfigView(this, service_path, false);
+  else if (network->type() == flimflam::kTypeWimax)
+    child_config_view_ = new WimaxConfigView(this, service_path);
+  else if (network->type() == flimflam::kTypeVPN)
+    child_config_view_ = new VPNConfigView(this, service_path);
+  else
+    NOTREACHED();
+}
+
+void NetworkConfigView::InitWithType(const std::string& type) {
+  if (type == flimflam::kTypeWifi) {
+    child_config_view_ = new WifiConfigView(this,
+                                            "" /* service_path */,
+                                            false /* show_8021x */);
     advanced_button_ = new views::LabelButton(this, l10n_util::GetStringUTF16(
         IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_ADVANCED_BUTTON));
     advanced_button_->SetStyle(views::Button::STYLE_NATIVE_TEXTBUTTON);
-  } else if (type == TYPE_VPN) {
-    child_config_view_ = new VPNConfigView(this);
+  } else if (type == flimflam::kTypeVPN) {
+    child_config_view_ = new VPNConfigView(this,
+                                           "" /* service_path */);
   } else {
     NOTREACHED();
   }
@@ -120,31 +119,28 @@
 }
 
 // static
-void NetworkConfigView::Show(Network* network, gfx::NativeWindow parent) {
+void NetworkConfigView::Show(const std::string& service_path,
+                             gfx::NativeWindow parent) {
   if (GetActiveDialog() != NULL)
     return;
-  NetworkConfigView* view = new NetworkConfigView(network);
+  NetworkConfigView* view = new NetworkConfigView();
+  const NetworkState* network = NetworkHandler::Get()->network_state_handler()->
+      GetNetworkState(service_path);
+  if (!network) {
+    LOG(ERROR) << "NetworkConfigView::Show called with invalid service_path";
+    return;
+  }
+  view->InitWithNetworkState(network);
   view->ShowDialog(parent);
 }
 
 // static
-void NetworkConfigView::ShowForType(ConnectionType type,
+void NetworkConfigView::ShowForType(const std::string& type,
                                     gfx::NativeWindow parent) {
   if (GetActiveDialog() != NULL)
     return;
-  NetworkConfigView* view = new NetworkConfigView(type);
-  view->ShowDialog(parent);
-}
-
-// static
-void NetworkConfigView::ShowForPath(const std::string& path,
-                                    gfx::NativeWindow parent) {
-  if (GetActiveDialog() != NULL)
-    return;
-  Network* network = NetworkLibrary::Get()->FindNetworkByPath(path);
-  if (!network)
-    return;
-  NetworkConfigView* view = new NetworkConfigView(network);
+  NetworkConfigView* view = new NetworkConfigView();
+  view->InitWithType(type);
   view->ShowDialog(parent);
 }
 
@@ -219,7 +215,9 @@
   RemoveChildView(child_config_view_);
   delete child_config_view_;
   // For now, there is only an advanced view for Wi-Fi 802.1X.
-  child_config_view_ = new WifiConfigView(this, true /* show_8021x */);
+  child_config_view_ = new WifiConfigView(this,
+                                          "" /* service_path */,
+                                          true /* show_8021x */);
   AddChildView(child_config_view_);
   // Resize the window to be able to hold the new widgets.
   gfx::Size size = views::Widget::GetLocalizedContentsSize(
@@ -271,6 +269,20 @@
   window->Show();
 }
 
+// ChildNetworkConfigView
+
+ChildNetworkConfigView::ChildNetworkConfigView(
+    NetworkConfigView* parent,
+    const std::string& service_path)
+    : parent_(parent),
+      service_path_(service_path) {
+}
+
+ChildNetworkConfigView::~ChildNetworkConfigView() {
+}
+
+// ControlledSettingIndicatorView
+
 ControlledSettingIndicatorView::ControlledSettingIndicatorView()
     : managed_(false),
       image_view_(NULL) {
@@ -301,17 +313,6 @@
                                  : gfx::Size();
 }
 
-// static
-const base::DictionaryValue* NetworkConfigView::FindPolicyForActiveUser(
-    const Network* network,
-    onc::ONCSource* onc_source) {
-  const User* user = UserManager::Get()->GetActiveUser();
-  std::string username_hash = user ? user->username_hash() : std::string();
-  std::string guid = network->unique_id();
-  return NetworkHandler::Get()->managed_network_configuration_handler()
-      ->FindPolicyByGUID(username_hash, guid, onc_source);
-}
-
 void ControlledSettingIndicatorView::Layout() {
   image_view_->SetBounds(0, 0, width(), height());
 }
diff --git a/chrome/browser/chromeos/options/network_config_view.h b/chrome/browser/chromeos/options/network_config_view.h
index 26b3905..f51e3e7 100644
--- a/chrome/browser/chromeos/options/network_config_view.h
+++ b/chrome/browser/chromeos/options/network_config_view.h
@@ -9,7 +9,6 @@
 
 #include "base/compiler_specific.h"
 #include "base/strings/string16.h"
-#include "chrome/browser/chromeos/cros/network_library.h"
 #include "ui/gfx/native_widget_types.h"  // gfx::NativeWindow
 #include "ui/views/controls/button/button.h"  // views::ButtonListener
 #include "ui/views/window/dialog_delegate.h"
@@ -27,6 +26,7 @@
 
 class ChildNetworkConfigView;
 class NetworkPropertyUIData;
+class NetworkState;
 
 // A dialog box for showing a password textfield.
 class NetworkConfigView : public views::DialogDelegateView,
@@ -45,9 +45,10 @@
   };
 
   // Shows a network connection dialog if none is currently visible.
-  static void Show(Network* network, gfx::NativeWindow parent);
-  static void ShowForType(ConnectionType type, gfx::NativeWindow parent);
-  static void ShowForPath(const std::string& path, gfx::NativeWindow parent);
+  static void Show(const std::string& service_path, gfx::NativeWindow parent);
+  // Shows a dialog to configure a new network. |type| must be a valid Shill
+  // 'Type' property value.
+  static void ShowForType(const std::string& type, gfx::NativeWindow parent);
 
   // Returns corresponding native window.
   gfx::NativeWindow GetNativeWindow() const;
@@ -75,10 +76,6 @@
     delegate_ = delegate;
   }
 
-  static const base::DictionaryValue* FindPolicyForActiveUser(
-      const Network* network,
-      onc::ONCSource* onc_source);
-
  protected:
   // views::View overrides:
   virtual void Layout() OVERRIDE;
@@ -87,12 +84,14 @@
       const ViewHierarchyChangedDetails& details) OVERRIDE;
 
  private:
-  // Login dialog for known networks.
-  explicit NetworkConfigView(Network* network);
-  // Login dialog for new/hidden networks.
-  explicit NetworkConfigView(ConnectionType type);
+  NetworkConfigView();
   virtual ~NetworkConfigView();
 
+  // Login dialog for known networks.
+  void InitWithNetworkState(const NetworkState* network);
+  // Login dialog for new/hidden networks.
+  void InitWithType(const std::string& type);
+
   // Creates and shows a dialog containing this view.
   void ShowDialog(gfx::NativeWindow parent);
 
@@ -115,12 +114,11 @@
 // methods, which are called by NetworkConfigView.
 class ChildNetworkConfigView : public views::View {
  public:
-  ChildNetworkConfigView(NetworkConfigView* parent, Network* network)
-      : service_path_(network->service_path()),
-        parent_(parent) {}
-  explicit ChildNetworkConfigView(NetworkConfigView* parent)
-      : parent_(parent) {}
-  virtual ~ChildNetworkConfigView() {}
+  // If |service_path| is NULL, a dialog for configuring a new network will
+  // be created.
+  ChildNetworkConfigView(NetworkConfigView* parent,
+                         const std::string& service_path);
+  virtual ~ChildNetworkConfigView();
 
   // Get the title to show for the dialog.
   virtual string16 GetTitle() const = 0;
@@ -146,8 +144,8 @@
   static const int kInputFieldMinWidth;
 
  protected:
-  std::string service_path_;
   NetworkConfigView* parent_;
+  std::string service_path_;
 
  private:
   DISALLOW_COPY_AND_ASSIGN(ChildNetworkConfigView);
diff --git a/chrome/browser/chromeos/options/network_connect.cc b/chrome/browser/chromeos/options/network_connect.cc
index c44822b..a494325 100644
--- a/chrome/browser/chromeos/options/network_connect.cc
+++ b/chrome/browser/chromeos/options/network_connect.cc
@@ -12,8 +12,8 @@
 #include "base/command_line.h"
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
-#include "chrome/browser/chromeos/cros/network_library.h"
 #include "chrome/browser/chromeos/enrollment_dialog_view.h"
+#include "chrome/browser/chromeos/login/user_manager.h"
 #include "chrome/browser/chromeos/options/network_config_view.h"
 #include "chrome/browser/profiles/profile_manager.h"
 #include "chrome/browser/ui/browser_finder.h"
@@ -21,6 +21,13 @@
 #include "chrome/browser/ui/webui/chromeos/mobile_setup_dialog.h"
 #include "chrome/common/url_constants.h"
 #include "chromeos/chromeos_switches.h"
+#include "chromeos/network/certificate_pattern.h"
+#include "chromeos/network/certificate_pattern_matcher.h"
+#include "chromeos/network/managed_network_configuration_handler.h"
+#include "chromeos/network/network_event_log.h"
+#include "chromeos/network/network_handler.h"
+#include "chromeos/network/network_state.h"
+#include "chromeos/network/network_state_handler.h"
 #include "content/public/browser/user_metrics.h"
 #include "grit/generated_resources.h"
 #include "net/base/escape.h"
@@ -28,84 +35,28 @@
 #include "ui/base/l10n/l10n_util.h"
 
 namespace chromeos {
-namespace network_connect {
 
 namespace {
 
-void DoConnect(Network* network, gfx::NativeWindow parent_window) {
-  NetworkLibrary* cros = NetworkLibrary::Get();
-  if (network->type() == TYPE_VPN) {
-    VirtualNetwork* vpn = static_cast<VirtualNetwork*>(network);
-    if (vpn->NeedMoreInfoToConnect()) {
-      // Show the connection UI if info for a field is missing.
-      NetworkConfigView::Show(vpn, parent_window);
-    } else {
-      cros->ConnectToVirtualNetwork(vpn);
-      // Connection failures are responsible for updating the UI, including
-      // reopening dialogs.
-    }
-  } else if (network->type() == TYPE_WIFI) {
-    WifiNetwork* wifi = static_cast<WifiNetwork*>(network);
-    if (wifi->IsPassphraseRequired()) {
-      // Show the connection UI if we require a passphrase.
-      NetworkConfigView::Show(wifi, parent_window);
-    } else {
-      cros->ConnectToWifiNetwork(wifi);
-      // Connection failures are responsible for updating the UI, including
-      // reopening dialogs.
-    }
-  } else if (network->type() == TYPE_WIMAX) {
-    WimaxNetwork* wimax = static_cast<WimaxNetwork*>(network);
-    if (wimax->passphrase_required()) {
-      // Show the connection UI if we require a passphrase.
-      NetworkConfigView::Show(wimax, parent_window);
-    } else {
-      cros->ConnectToWimaxNetwork(wimax);
-      // Connection failures are responsible for updating the UI, including
-      // reopening dialogs.
-    }
-  } else if (network->type() == TYPE_CELLULAR) {
-    CellularNetwork* cellular = static_cast<CellularNetwork*>(network);
-    if (cellular->activation_state() != ACTIVATION_STATE_ACTIVATED ||
-        cellular->out_of_credits()) {
-      ActivateCellular(cellular->service_path());
-    } else {
-      cros->ConnectToCellularNetwork(cellular);
-    }
-  }
+void EnrollmentComplete(const std::string& service_path) {
+  NET_LOG_USER("Enrollment Complete", service_path);
 }
 
-}  // namespace
-
-void ActivateCellular(const std::string& service_path) {
-  chromeos::NetworkLibrary* cros =
-      chromeos::NetworkLibrary::Get();
-  if (!cros->CellularDeviceUsesDirectActivation()) {
-    // For non direct activation, show the mobile setup dialog which can be
-    // used to activate the network.
-    ShowMobileSetup(service_path);
-    return;
-  }
-  chromeos::CellularNetwork* cellular =
-      cros->FindCellularNetworkByPath(service_path);
-  if (!cellular)
-    return;
-  if (cellular->activation_state() != chromeos::ACTIVATION_STATE_ACTIVATED)
-    cellular->StartActivation();
-  return;
 }
 
+namespace network_connect {
+
 void ShowMobileSetup(const std::string& service_path) {
-  NetworkLibrary* cros = NetworkLibrary::Get();
-  const CellularNetwork* cellular =
-      cros->FindCellularNetworkByPath(service_path);
-  if (cellular && !cellular->activated() &&
-      cellular->activate_over_non_cellular_network() &&
-      (!cros->connected_network() || !cros->connected_network()->online())) {
-    NetworkTechnology technology = cellular->network_technology();
+  NetworkStateHandler* handler = NetworkHandler::Get()->network_state_handler();
+  const NetworkState* cellular = handler->GetNetworkState(service_path);
+  if (cellular && cellular->type() == flimflam::kTypeCellular &&
+      cellular->activation_state() != flimflam::kActivationStateActivated &&
+      cellular->activate_over_non_cellular_networks() &&
+      !handler->DefaultNetwork()) {
+    std::string technology = cellular->network_technology();
     ash::NetworkObserver::NetworkType network_type =
-        (technology == chromeos::NETWORK_TECHNOLOGY_LTE ||
-         technology == chromeos::NETWORK_TECHNOLOGY_LTE_ADVANCED)
+        (technology == flimflam::kNetworkTechnologyLte ||
+         technology == flimflam::kNetworkTechnologyLteAdvanced)
         ? ash::NetworkObserver::NETWORK_CELLULAR_LTE
         : ash::NetworkObserver::NETWORK_CELLULAR;
     ash::Shell::GetInstance()->system_tray_notifier()->NotifySetNetworkMessage(
@@ -121,100 +72,21 @@
   MobileSetupDialog::Show(service_path);
 }
 
-ConnectResult ConnectToNetwork(const std::string& service_path,
-                               gfx::NativeWindow parent_window) {
-  if (CommandLine::ForCurrentProcess()->HasSwitch(
-          chromeos::switches::kUseNewNetworkConnectionHandler)) {
-    ash::network_connect::ConnectToNetwork(service_path);
-    return CONNECT_STARTED;
-  }
-
-  NetworkLibrary* cros = NetworkLibrary::Get();
-  Network* network = cros->FindNetworkByPath(service_path);
-  if (!network)
-    return NETWORK_NOT_FOUND;
-
-  if (network->connecting_or_connected())
-    return CONNECT_NOT_STARTED;
-
-  if (network->type() == TYPE_ETHERNET)
-    return CONNECT_NOT_STARTED;  // Normally this shouldn't happen
-
-  if (network->type() == TYPE_WIFI || network->type() == TYPE_VPN) {
-    network->SetEnrollmentDelegate(chromeos::CreateEnrollmentDelegate(
-        parent_window, network->name(), ProfileManager::GetLastUsedProfile()));
-    network->AttemptConnection(base::Bind(&DoConnect, network, parent_window));
-    return CONNECT_STARTED;
-  }
-
-  if (network->type() == TYPE_WIMAX) {
-    WimaxNetwork* wimax = static_cast<WimaxNetwork*>(network);
-    wimax->AttemptConnection(base::Bind(&DoConnect, wimax, parent_window));
-    return CONNECT_STARTED;
-  }
-
-  if (network->type() == TYPE_CELLULAR) {
-    CellularNetwork* cellular = static_cast<CellularNetwork*>(network);
-    if (cellular->NeedsActivation() || cellular->out_of_credits()) {
-      ActivateCellular(service_path);
-      return CONNECT_STARTED;
-    }
-    if (cellular->activation_state() == ACTIVATION_STATE_ACTIVATING)
-      return CONNECT_NOT_STARTED;
-    cros->ConnectToCellularNetwork(cellular);
-    return CONNECT_STARTED;
-  }
-
-  NOTREACHED();
-  return CONNECT_NOT_STARTED;
-}
-
-void HandleUnconfiguredNetwork(const std::string& service_path,
-                               gfx::NativeWindow parent_window) {
-  NetworkLibrary* cros = NetworkLibrary::Get();
-  Network* network = cros->FindNetworkByPath(service_path);
-  if (!network) {
-    LOG(WARNING) << "Unknown network: " << service_path;
-    return;
-  }
-
-  if (network->type() == TYPE_WIFI || network->type() == TYPE_VPN) {
-    network->SetEnrollmentDelegate(chromeos::CreateEnrollmentDelegate(
-        parent_window, network->name(), ProfileManager::GetLastUsedProfile()));
-    // This will connect to the network only if the network just needs to have
-    // its certificate configured. Otherwise it will show an enrollment dialog
-    // if available, or call NetworkConfigView::Show().
-    network->AttemptConnection(
-        base::Bind(&NetworkConfigView::Show, network, parent_window));
-    return;
-  }
-
-  if (network->type() == TYPE_WIMAX) {
-    NetworkConfigView::Show(network, parent_window);
-    return;
-  }
-
-  if (network->type() == TYPE_CELLULAR) {
-    CellularNetwork* cellular = static_cast<CellularNetwork*>(network);
-    if (cellular->NeedsActivation()) {
-      ActivateCellular(service_path);
-      return;
-    } else if (cellular->out_of_credits()) {
-      ShowMobileSetup(service_path);
-      return;
-    }
-  }
-
-  // No special configure or setup for |service_path|, show the settings UI.
+void ShowNetworkSettings(const std::string& service_path) {
   std::string page = chrome::kInternetOptionsSubPage;
-  std::string name = network->name();
-  if (name.empty() && network->type() == TYPE_ETHERNET)
-    name = l10n_util::GetStringUTF8(IDS_STATUSBAR_NETWORK_DEVICE_ETHERNET);
-  page += base::StringPrintf(
-      "?servicePath=%s&networkType=%d&networkName=%s",
-      net::EscapeUrlEncodedData(service_path, true).c_str(),
-      network->type(),
-      net::EscapeUrlEncodedData(name, false).c_str());
+  const NetworkState* network = service_path.empty() ? NULL :
+      NetworkHandler::Get()->network_state_handler()->GetNetworkState(
+          service_path);
+  if (network) {
+    std::string name(network->name());
+    if (name.empty() && network->type() == flimflam::kTypeEthernet)
+      name = l10n_util::GetStringUTF8(IDS_STATUSBAR_NETWORK_DEVICE_ETHERNET);
+    page += base::StringPrintf(
+        "?servicePath=%s&networkType=%s&networkName=%s",
+        net::EscapeUrlEncodedData(service_path, true).c_str(),
+        net::EscapeUrlEncodedData(network->type(), true).c_str(),
+        net::EscapeUrlEncodedData(name, false).c_str());
+  }
   content::RecordAction(
       content::UserMetricsAction("OpenInternetOptionsDialog"));
   Browser* browser = chrome::FindOrCreateTabbedBrowser(
@@ -223,5 +95,78 @@
   chrome::ShowSettingsSubPage(browser, page);
 }
 
+void HandleUnconfiguredNetwork(const std::string& service_path,
+                               gfx::NativeWindow parent_window) {
+  const NetworkState* network = NetworkHandler::Get()->network_state_handler()->
+      GetNetworkState(service_path);
+  if (!network) {
+    NET_LOG_ERROR("Configuring unknown network", service_path);
+    return;
+  }
+
+  if (network->type() == flimflam::kTypeWifi) {
+    // Only show the config view for secure networks, otherwise do nothing.
+    if (network->security() != flimflam::kSecurityNone)
+      NetworkConfigView::Show(service_path, parent_window);
+    return;
+  }
+
+  if (network->type() == flimflam::kTypeWimax ||
+      network->type() == flimflam::kTypeVPN) {
+    NetworkConfigView::Show(service_path, parent_window);
+    return;
+  }
+
+  if (network->type() == flimflam::kTypeCellular) {
+    if (network->activation_state() != flimflam::kActivationStateActivated) {
+      ash::network_connect::ActivateCellular(service_path);
+      return;
+    }
+    if (network->cellular_out_of_credits()) {
+      ShowMobileSetup(service_path);
+      return;
+    }
+    // No special configure or setup for |network|, show the settings UI.
+    ShowNetworkSettings(service_path);
+  }
+  NOTREACHED();
+}
+
+bool EnrollNetwork(const std::string& service_path,
+                   gfx::NativeWindow parent_window) {
+  const NetworkState* network = NetworkHandler::Get()->network_state_handler()->
+      GetNetworkState(service_path);
+  if (!network) {
+    NET_LOG_ERROR("Enrolling Unknown network", service_path);
+    return false;
+  }
+  // We skip certificate patterns for device policy ONC so that an unmanaged
+  // user can't get to the place where a cert is presented for them
+  // involuntarily.
+  if (network->ui_data().onc_source() == onc::ONC_SOURCE_DEVICE_POLICY)
+    return false;
+
+  const CertificatePattern& certificate_pattern =
+      network->ui_data().certificate_pattern();
+  if (certificate_pattern.Empty())
+    return false;
+
+  NET_LOG_USER("Enrolling", service_path);
+
+  EnrollmentDelegate* enrollment = CreateEnrollmentDelegate(
+      parent_window, network->name(), ProfileManager::GetDefaultProfile());
+  return enrollment->Enroll(certificate_pattern.enrollment_uri_list(),
+                            base::Bind(&EnrollmentComplete, service_path));
+}
+
+const base::DictionaryValue* FindPolicyForActiveUser(
+    const NetworkState* network,
+    onc::ONCSource* onc_source) {
+  const User* user = UserManager::Get()->GetActiveUser();
+  std::string username_hash = user ? user->username_hash() : std::string();
+  return NetworkHandler::Get()->managed_network_configuration_handler()->
+      FindPolicyByGUID(username_hash, network->guid(), onc_source);
+}
+
 }  // namespace network_connect
 }  // namespace chromeos
diff --git a/chrome/browser/chromeos/options/network_connect.h b/chrome/browser/chromeos/options/network_connect.h
index 9872cbc..2d8acbe 100644
--- a/chrome/browser/chromeos/options/network_connect.h
+++ b/chrome/browser/chromeos/options/network_connect.h
@@ -6,46 +6,47 @@
 #define CHROME_BROWSER_CHROMEOS_OPTIONS_NETWORK_CONNECT_H_
 
 #include <string>
+#include <vector>
 
+#include "chromeos/network/onc/onc_constants.h"
 #include "ui/gfx/native_widget_types.h"  // gfx::NativeWindow
 
+namespace base {
+class DictionaryValue;
+}
+
 namespace chromeos {
+
+class NetworkState;
+
 namespace network_connect {
 
-enum ConnectResult {
-  NETWORK_NOT_FOUND,
-  CONNECT_NOT_STARTED,
-  CONNECT_STARTED
-};
-
-// Activate the cellular network associated with |service_path| if direct
-// activation is supported, otherwise call ShowMobileSetup.
-void ActivateCellular(const std::string& service_path);
-
 // Shows the mobile setup dialog which handles:
 // * Activation for non direct-activation networks
 // * Showing network plan info
 void ShowMobileSetup(const std::string& service_path);
 
-// Attempts to connect to the network specified by |service_path|.
-// Returns one of the following results:
-//  NETWORK_NOT_FOUND if the network does not exist.
-//  CONNECT_NOT_STARTED if no connection attempt was started, e.g. because the
-//   network is already connected, connecting, or activating.
-//  CONNECT_STARTED if a connection attempt was started.
-ConnectResult ConnectToNetwork(const std::string& service_path,
-                               gfx::NativeWindow parent_window);
+// Shows the network settings subpage for |service_path| (or the main
+// network settings page if empty).
+void ShowNetworkSettings(const std::string& service_path);
 
-// Handle an unconfigured network which might do any of the following:
-// * Configure and connect to the network with a matching cert but without
-//   pcks11id and tpm pin / slot configured.
-// * Show the enrollment dialog for the network.
-// * Show the configuration dialog for the network.
-// * Show the activation dialog for the network.
-// * Show the settings UI for the network.
+// Handle an unconfigured network:
+// * Show the Configure dialog for wifi/wimax/VPN
+// * Show the Activation, MobileSetup dialog, or settings page for cellular
 void HandleUnconfiguredNetwork(const std::string& service_path,
                                gfx::NativeWindow parent_window);
 
+// If the network UIData has a matching enrollment URL, triggers the enrollment
+// dialog and returns true.
+bool EnrollNetwork(const std::string& service_path,
+                   gfx::NativeWindow parent_window);
+
+// Looks up the policy for |network| for the current active user and sets
+// |onc_source| accordingly.
+const base::DictionaryValue* FindPolicyForActiveUser(
+    const NetworkState* network,
+    onc::ONCSource* onc_source);
+
 }  // namespace network_connect
 }  // namespace chromeos
 
diff --git a/chrome/browser/chromeos/options/passphrase_textfield.cc b/chrome/browser/chromeos/options/passphrase_textfield.cc
index 598d192..9cc9bd3 100644
--- a/chrome/browser/chromeos/options/passphrase_textfield.cc
+++ b/chrome/browser/chromeos/options/passphrase_textfield.cc
@@ -8,12 +8,18 @@
 
 namespace chromeos {
 
-PassphraseTextfield::PassphraseTextfield(bool show_fake)
+PassphraseTextfield::PassphraseTextfield()
     : Textfield(views::Textfield::STYLE_OBSCURED),
-      show_fake_(show_fake),
+      show_fake_(false),
       changed_(true) {
+}
+
+void PassphraseTextfield::SetShowFake(bool show_fake) {
+  show_fake_ = show_fake;
   if (show_fake_)
     SetFakePassphrase();
+  else
+    ClearFakePassphrase();
 }
 
 void PassphraseTextfield::OnFocus() {
diff --git a/chrome/browser/chromeos/options/passphrase_textfield.h b/chrome/browser/chromeos/options/passphrase_textfield.h
index 16d5301..1f1b590 100644
--- a/chrome/browser/chromeos/options/passphrase_textfield.h
+++ b/chrome/browser/chromeos/options/passphrase_textfield.h
@@ -13,8 +13,10 @@
 
 class PassphraseTextfield : public views::Textfield {
  public:
-  // If show_already_set is true, then the text field will show a fake password.
-  explicit PassphraseTextfield(bool show_fake);
+  PassphraseTextfield();
+
+  // If show_fake is true, then the text field will show a fake password.
+  void SetShowFake(bool show_fake);
 
   // Override views::Textfield so that when focus is gained, then clear out the
   // fake password if appropriate. Replace it when focus is lost if the user has
diff --git a/chrome/browser/chromeos/options/vpn_config_view.cc b/chrome/browser/chromeos/options/vpn_config_view.cc
index d8e019b..4aa6682 100644
--- a/chrome/browser/chromeos/options/vpn_config_view.cc
+++ b/chrome/browser/chromeos/options/vpn_config_view.cc
@@ -4,19 +4,25 @@
 
 #include "chrome/browser/chromeos/options/vpn_config_view.h"
 
+#include "ash/system/chromeos/network/network_connect.h"
 #include "base/strings/string_util.h"
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
-#include "chrome/browser/chromeos/cros/network_library.h"
 #include "chrome/browser/chromeos/enrollment_dialog_view.h"
+#include "chrome/browser/chromeos/options/network_connect.h"
 #include "chrome/browser/profiles/profile_manager.h"
 #include "chrome/common/net/x509_certificate_model.h"
+#include "chromeos/network/network_configuration_handler.h"
+#include "chromeos/network/network_event_log.h"
+#include "chromeos/network/network_state.h"
+#include "chromeos/network/network_state_handler.h"
 #include "chromeos/network/network_ui_data.h"
 #include "chromeos/network/onc/onc_constants.h"
 #include "grit/chromium_strings.h"
 #include "grit/generated_resources.h"
 #include "grit/locale_settings.h"
 #include "grit/theme_resources.h"
+#include "third_party/cros_system_api/dbus/service_constants.h"
 #include "ui/base/events/event.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/base/models/combobox_model.h"
@@ -35,41 +41,73 @@
 // Root CA certificates that are built into Chrome use this token name.
 const char* const kRootCertificateTokenName = "Builtin Object Token";
 
-string16 ProviderTypeToString(chromeos::ProviderType type) {
-  switch (type) {
-    case chromeos::PROVIDER_TYPE_L2TP_IPSEC_PSK:
+enum ProviderTypeIndex {
+  PROVIDER_TYPE_INDEX_L2TP_IPSEC_PSK = 0,
+  PROVIDER_TYPE_INDEX_L2TP_IPSEC_USER_CERT = 1,
+  PROVIDER_TYPE_INDEX_OPEN_VPN = 2,
+  PROVIDER_TYPE_INDEX_MAX = 3,
+};
+
+string16 ProviderTypeIndexToString(int index) {
+  switch (index) {
+    case PROVIDER_TYPE_INDEX_L2TP_IPSEC_PSK:
       return l10n_util::GetStringUTF16(
           IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_L2TP_IPSEC_PSK);
-    case chromeos::PROVIDER_TYPE_L2TP_IPSEC_USER_CERT:
+    case PROVIDER_TYPE_INDEX_L2TP_IPSEC_USER_CERT:
       return l10n_util::GetStringUTF16(
           IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_L2TP_IPSEC_USER_CERT);
-    case chromeos::PROVIDER_TYPE_OPEN_VPN:
+    case PROVIDER_TYPE_INDEX_OPEN_VPN:
       return l10n_util::GetStringUTF16(
           IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_OPEN_VPN);
-    case chromeos::PROVIDER_TYPE_MAX:
-      break;
   }
   NOTREACHED();
   return string16();
 }
 
+int ProviderTypeToIndex(const std::string& provider_type,
+                        const std::string& client_cert_id) {
+  if (provider_type == flimflam::kProviderL2tpIpsec) {
+    if (!client_cert_id.empty())
+      return PROVIDER_TYPE_INDEX_L2TP_IPSEC_USER_CERT;
+    else
+      return PROVIDER_TYPE_INDEX_L2TP_IPSEC_PSK;
+  } else {
+    DCHECK(provider_type == flimflam::kProviderOpenVpn);
+    return PROVIDER_TYPE_INDEX_OPEN_VPN;
+  }
+}
+
 // Translates the provider type to the name of the respective ONC dictionary
 // containing configuration data for the type.
-std::string ProviderTypeToONCDictKey(chromeos::ProviderType type) {
-  switch (type) {
-    case chromeos::PROVIDER_TYPE_L2TP_IPSEC_PSK:
-    case chromeos::PROVIDER_TYPE_L2TP_IPSEC_USER_CERT:
+std::string ProviderTypeIndexToONCDictKey(int provider_type_index) {
+  switch (provider_type_index) {
+    case PROVIDER_TYPE_INDEX_L2TP_IPSEC_PSK:
+    case PROVIDER_TYPE_INDEX_L2TP_IPSEC_USER_CERT:
       return chromeos::onc::vpn::kIPsec;
-    case chromeos::PROVIDER_TYPE_OPEN_VPN:
+    case PROVIDER_TYPE_INDEX_OPEN_VPN:
       return chromeos::onc::vpn::kOpenVPN;
-    case chromeos::PROVIDER_TYPE_MAX:
-      break;
   }
-
-  NOTREACHED() << "Unhandled provider type " << type;
+  NOTREACHED() << "Unhandled provider type index " << provider_type_index;
   return std::string();
 }
 
+std::string GetPemFromDictionary(
+    const base::DictionaryValue* provider_properties,
+    const std::string& key) {
+  const base::ListValue* pems = NULL;
+  if (!provider_properties->GetListWithoutPathExpansion(key, &pems))
+    return std::string();
+  std::string pem;
+  pems->GetString(0, &pem);
+  return pem;
+}
+
+void ShillError(const std::string& function,
+                const std::string& error_name,
+                scoped_ptr<base::DictionaryValue> error_data) {
+  NET_LOG_ERROR("Shill Error from VpnConfigView: " + error_name, function);
+}
+
 }  // namespace
 
 namespace chromeos {
@@ -124,12 +162,11 @@
 }
 
 int ProviderTypeComboboxModel::GetItemCount() const {
-  return PROVIDER_TYPE_MAX;
+  return PROVIDER_TYPE_INDEX_MAX;
 }
 
 string16 ProviderTypeComboboxModel::GetItemAt(int index) {
-  ProviderType type = static_cast<ProviderType>(index);
-  return ProviderTypeToString(type);
+  return ProviderTypeIndexToString(index);
 }
 
 // VpnServerCACertComboboxModel ------------------------------------------------
@@ -193,16 +230,39 @@
 
 }  // namespace internal
 
-VPNConfigView::VPNConfigView(NetworkConfigView* parent, VirtualNetwork* vpn)
-    : ChildNetworkConfigView(parent, vpn),
-      title_(0) {
-  Init(vpn);
-}
-
-VPNConfigView::VPNConfigView(NetworkConfigView* parent)
-    : ChildNetworkConfigView(parent),
-      title_(0) {
-  Init(NULL);
+VPNConfigView::VPNConfigView(NetworkConfigView* parent,
+                             const std::string& service_path)
+    : ChildNetworkConfigView(parent, service_path),
+      service_text_modified_(false),
+      enable_psk_passphrase_(false),
+      enable_user_cert_(false),
+      enable_server_ca_cert_(false),
+      enable_otp_(false),
+      enable_group_name_(false),
+      title_(0),
+      layout_(NULL),
+      server_textfield_(NULL),
+      service_text_(NULL),
+      service_textfield_(NULL),
+      provider_type_combobox_(NULL),
+      provider_type_text_label_(NULL),
+      psk_passphrase_label_(NULL),
+      psk_passphrase_textfield_(NULL),
+      user_cert_label_(NULL),
+      user_cert_combobox_(NULL),
+      server_ca_cert_label_(NULL),
+      server_ca_cert_combobox_(NULL),
+      username_textfield_(NULL),
+      user_passphrase_textfield_(NULL),
+      otp_label_(NULL),
+      otp_textfield_(NULL),
+      group_name_label_(NULL),
+      group_name_textfield_(NULL),
+      save_credentials_checkbox_(NULL),
+      error_label_(NULL),
+      provider_type_index_(PROVIDER_TYPE_INDEX_MAX),
+      weak_ptr_factory_(this) {
+  Init();
 }
 
 VPNConfigView::~VPNConfigView() {
@@ -243,7 +303,9 @@
     return false;
 
   // Block login if certs are required but user has none.
-  if (UserCertRequired() && (!HaveUserCerts() || !IsUserCertValid()))
+  bool cert_required =
+      GetProviderTypeIndex() == PROVIDER_TYPE_INDEX_L2TP_IPSEC_USER_CERT;
+  if (cert_required && (!HaveUserCerts() || !IsUserCertValid()))
     return false;
 
   return true;
@@ -283,15 +345,7 @@
 }
 
 void VPNConfigView::OnSelectedIndexChanged(views::Combobox* combobox) {
-  if (combobox == provider_type_combobox_) {
-    provider_type_ = static_cast<ProviderType>(combobox->selected_index());
-    UpdateControls();
-  } else if (combobox == user_cert_combobox_ ||
-             combobox == server_ca_cert_combobox_) {
-    // Do nothing.
-  } else {
-    NOTREACHED();
-  }
+  UpdateControls();
   UpdateErrorLabel();
   UpdateCanLogin();
 }
@@ -301,77 +355,35 @@
 }
 
 bool VPNConfigView::Login() {
-  NetworkLibrary* cros = NetworkLibrary::Get();
   if (service_path_.empty()) {
-    NetworkLibrary::VPNConfigData config_data;
-    switch (provider_type_) {
-      case PROVIDER_TYPE_L2TP_IPSEC_PSK:
-        config_data.psk = GetPSKPassphrase();
-        config_data.username = GetUsername();
-        config_data.user_passphrase = GetUserPassphrase();
-        config_data.group_name = GetGroupName();
-        break;
-      case PROVIDER_TYPE_L2TP_IPSEC_USER_CERT: {
-        config_data.server_ca_cert_pem = GetServerCACertPEM();
-        config_data.client_cert_pkcs11_id = GetUserCertID();
-        config_data.username = GetUsername();
-        config_data.user_passphrase = GetUserPassphrase();
-        config_data.group_name = GetGroupName();
-        break;
-      }
-      case PROVIDER_TYPE_OPEN_VPN:
-        config_data.server_ca_cert_pem = GetServerCACertPEM();
-        config_data.client_cert_pkcs11_id = GetUserCertID();
-        config_data.username = GetUsername();
-        config_data.user_passphrase = GetUserPassphrase();
-        config_data.otp = GetOTP();
-        break;
-      case PROVIDER_TYPE_MAX:
-        break;
-    }
-    config_data.save_credentials = GetSaveCredentials();
-    cros->ConnectToUnconfiguredVirtualNetwork(
-        GetService(), GetServer(), provider_type_, config_data);
+    base::DictionaryValue properties;
+    // Identifying properties
+    properties.SetStringWithoutPathExpansion(
+        flimflam::kTypeProperty, flimflam::kTypeVPN);
+    properties.SetStringWithoutPathExpansion(
+        flimflam::kNameProperty, GetService());
+    properties.SetStringWithoutPathExpansion(
+        flimflam::kProviderHostProperty, GetServer());
+    properties.SetStringWithoutPathExpansion(
+        flimflam::kProviderTypeProperty, GetProviderTypeString());
+
+    SetConfigProperties(&properties);
+    ash::network_connect::CreateConfigurationAndConnect(
+        &properties, false /* not shared */);
   } else {
-    VirtualNetwork* vpn = cros->FindVirtualNetworkByPath(service_path_);
+    const NetworkState* vpn = NetworkHandler::Get()->network_state_handler()->
+        GetNetworkState(service_path_);
     if (!vpn) {
+      // Shill no longer knows about this network (edge case).
       // TODO(stevenjb): Add notification for this.
-      LOG(WARNING) << "VPN no longer exists: " << service_path_;
-      return true;  // Close dialog.
+      NET_LOG_ERROR("Network not found", service_path_);
+      return true;  // Close dialog
     }
-    switch (provider_type_) {
-      case PROVIDER_TYPE_L2TP_IPSEC_PSK:
-        vpn->SetL2TPIPsecPSKCredentials(GetPSKPassphrase(),
-                                        GetUsername(),
-                                        GetUserPassphrase(),
-                                        GetGroupName());
-        break;
-      case PROVIDER_TYPE_L2TP_IPSEC_USER_CERT: {
-        vpn->SetL2TPIPsecCertCredentials(GetUserCertID(),
-                                         GetUsername(),
-                                         GetUserPassphrase(),
-                                         GetGroupName());
-        break;
-      }
-      case PROVIDER_TYPE_OPEN_VPN: {
-        vpn->SetOpenVPNCredentials(GetUserCertID(),
-                                   GetUsername(),
-                                   GetUserPassphrase(),
-                                   GetOTP());
-        break;
-      }
-      case PROVIDER_TYPE_MAX:
-        break;
-    }
-    vpn->SetEnrollmentDelegate(
-        CreateEnrollmentDelegate(GetWidget()->GetNativeWindow(),
-                                 vpn->name(),
-                                 ProfileManager::GetLastUsedProfile()));
-    vpn->SetSaveCredentials(GetSaveCredentials());
-    cros->ConnectToVirtualNetwork(vpn);
+    base::DictionaryValue properties;
+    SetConfigProperties(&properties);
+    ash::network_connect::ConfigureNetworkAndConnect(
+        service_path_, properties, false /* not shared */);
   }
-  // Connection failures are responsible for updating the UI, including
-  // reopening dialogs.
   return true;  // Close dialog.
 }
 
@@ -393,7 +405,7 @@
 const std::string VPNConfigView::GetServer() const {
   if (server_textfield_ != NULL)
     return GetTextFromField(server_textfield_, true);
-  return server_hostname_;
+  return std::string();
 }
 
 const std::string VPNConfigView::GetPSKPassphrase() const {
@@ -448,44 +460,39 @@
   return save_credentials_checkbox_->checked();
 }
 
-void VPNConfigView::Init(VirtualNetwork* vpn) {
-  if (vpn) {
-    ProviderType type = vpn->provider_type();
-    std::string type_dict_name = ProviderTypeToONCDictKey(type);
+int VPNConfigView::GetProviderTypeIndex() const {
+  if (provider_type_combobox_)
+    return provider_type_combobox_->selected_index();
+  return provider_type_index_;
+}
 
-    if (type == PROVIDER_TYPE_L2TP_IPSEC_PSK) {
-      ParseVPNUIProperty(&ca_cert_ui_data_, vpn, type_dict_name,
-                         onc::ipsec::kServerCARef);
-      ParseVPNUIProperty(&psk_passphrase_ui_data_, vpn, type_dict_name,
-                         onc::ipsec::kPSK);
-      ParseVPNUIProperty(&group_name_ui_data_, vpn, type_dict_name,
-                         onc::ipsec::kGroup);
-    } else { // OpenVPN
-      ParseVPNUIProperty(&ca_cert_ui_data_, vpn, type_dict_name,
-                         onc::openvpn::kServerCARef);
-    }
-    ParseVPNUIProperty(&user_cert_ui_data_, vpn, type_dict_name,
-                       onc::vpn::kClientCertRef);
-
-    const std::string credentials_dict_name(
-        type == PROVIDER_TYPE_L2TP_IPSEC_PSK ?
-            onc::vpn::kL2TP : type_dict_name);
-    ParseVPNUIProperty(&username_ui_data_, vpn, credentials_dict_name,
-                       onc::vpn::kUsername);
-    ParseVPNUIProperty(&user_passphrase_ui_data_, vpn, credentials_dict_name,
-                       onc::vpn::kPassword);
-    ParseVPNUIProperty(&save_credentials_ui_data_, vpn, credentials_dict_name,
-                       onc::vpn::kSaveCredentials);
+std::string VPNConfigView::GetProviderTypeString() const {
+  int index = GetProviderTypeIndex();
+  switch (index) {
+    case PROVIDER_TYPE_INDEX_L2TP_IPSEC_PSK:
+    case PROVIDER_TYPE_INDEX_L2TP_IPSEC_USER_CERT:
+      return flimflam::kProviderL2tpIpsec;
+    case PROVIDER_TYPE_INDEX_OPEN_VPN:
+      return flimflam::kProviderOpenVpn;
   }
+  NOTREACHED();
+  return std::string();
+}
 
-  views::GridLayout* layout = views::GridLayout::CreatePanel(this);
-  SetLayoutManager(layout);
+void VPNConfigView::Init() {
+  const NetworkState* vpn = NULL;
+  if (!service_path_.empty()) {
+    vpn = NetworkHandler::Get()->network_state_handler()->
+        GetNetworkState(service_path_);
+    DCHECK(vpn && vpn->type() == flimflam::kTypeVPN);
+  }
+  layout_ = views::GridLayout::CreatePanel(this);
+  SetLayoutManager(layout_);
 
   // Observer any changes to the certificate list.
   CertLibrary::Get()->AddObserver(this);
 
-  const int column_view_set_id = 0;
-  views::ColumnSet* column_set = layout->AddColumnSet(column_view_set_id);
+  views::ColumnSet* column_set = layout_->AddColumnSet(0);
   // Label.
   column_set->AddColumn(views::GridLayout::LEADING, views::GridLayout::FILL, 1,
                         views::GridLayout::USE_PREF, 0, 0);
@@ -501,232 +508,376 @@
 
   // Initialize members.
   service_text_modified_ = false;
-  if (vpn) {
-    provider_type_ = vpn->provider_type();
-    // Sets enable_* based on the provider type which we use to control
-    // which controls to make visible.
-    UpdateControlsToEnable();
-  } else {
-    // Set the default provider type.
-    provider_type_ = PROVIDER_TYPE_L2TP_IPSEC_PSK;
-    // Provider Type is user selectable, so enable all controls during init.
-    enable_psk_passphrase_ = true;
-    enable_user_cert_ = true;
-    enable_server_ca_cert_ = true;
-    enable_otp_ = true;
-    enable_group_name_ = true;
-  }
-
-  // Initialize the title string ID used for the dialog.
   title_ = vpn ? IDS_OPTIONS_SETTINGS_JOIN_VPN : IDS_OPTIONS_SETTINGS_ADD_VPN;
 
+  // By default enable all controls.
+  enable_psk_passphrase_ = true;
+  enable_user_cert_ = true;
+  enable_server_ca_cert_ = true;
+  enable_otp_ = true;
+  enable_group_name_ = true;
+
   // Server label and input.
   // Only provide Server name when configuring a new VPN.
-  if (!vpn) {
-    layout->StartRow(0, column_view_set_id);
-    layout->AddView(new views::Label(l10n_util::GetStringUTF16(
+  if (service_path_.empty()) {
+    layout_->StartRow(0, 0);
+    layout_->AddView(new views::Label(l10n_util::GetStringUTF16(
       IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_VPN_SERVER_HOSTNAME)));
     server_textfield_ = new views::Textfield(views::Textfield::STYLE_DEFAULT);
     server_textfield_->SetController(this);
-    layout->AddView(server_textfield_);
-    layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
+    layout_->AddView(server_textfield_);
+    layout_->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
   } else {
     server_textfield_ = NULL;
   }
 
   // Service label and name or input.
-  layout->StartRow(0, column_view_set_id);
-  layout->AddView(new views::Label(l10n_util::GetStringUTF16(
+  layout_->StartRow(0, 0);
+  layout_->AddView(new views::Label(l10n_util::GetStringUTF16(
       IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_VPN_SERVICE_NAME)));
-  if (!vpn) {
+  if (service_path_.empty()) {
     service_textfield_ = new views::Textfield(views::Textfield::STYLE_DEFAULT);
     service_textfield_->SetController(this);
-    layout->AddView(service_textfield_);
+    layout_->AddView(service_textfield_);
     service_text_ = NULL;
   } else {
-    service_text_ = new views::Label(ASCIIToUTF16(vpn->name()));
+    service_text_ = new views::Label();
     service_text_->SetHorizontalAlignment(gfx::ALIGN_LEFT);
-    layout->AddView(service_text_);
+    layout_->AddView(service_text_);
     service_textfield_ = NULL;
   }
-  layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
+  layout_->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
 
   // Provider type label and select.
-  layout->StartRow(0, column_view_set_id);
-  layout->AddView(new views::Label(l10n_util::GetStringUTF16(
+  layout_->StartRow(0, 0);
+  layout_->AddView(new views::Label(l10n_util::GetStringUTF16(
       IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_VPN_PROVIDER_TYPE)));
-  if (!vpn) {
+  if (service_path_.empty()) {
     provider_type_combobox_model_.reset(
         new internal::ProviderTypeComboboxModel);
     provider_type_combobox_ = new views::Combobox(
         provider_type_combobox_model_.get());
     provider_type_combobox_->set_listener(this);
-    layout->AddView(provider_type_combobox_);
+    layout_->AddView(provider_type_combobox_);
     provider_type_text_label_ = NULL;
   } else {
-    provider_type_text_label_ =
-        new views::Label(ProviderTypeToString(provider_type_));
+    provider_type_text_label_ = new views::Label();
     provider_type_text_label_->SetHorizontalAlignment(gfx::ALIGN_LEFT);
-    layout->AddView(provider_type_text_label_);
+    layout_->AddView(provider_type_text_label_);
     provider_type_combobox_ = NULL;
   }
-  layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
+  layout_->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
 
   // PSK passphrase label, input and visible button.
-  if (enable_psk_passphrase_) {
-    layout->StartRow(0, column_view_set_id);
-    psk_passphrase_label_ =  new views::Label(l10n_util::GetStringUTF16(
-        IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_VPN_PSK_PASSPHRASE));
-    layout->AddView(psk_passphrase_label_);
-    bool has_psk_passphrase = vpn && !vpn->IsPSKPassphraseRequired();
-    psk_passphrase_textfield_ = new PassphraseTextfield(has_psk_passphrase);
-    psk_passphrase_textfield_->SetController(this);
-    layout->AddView(psk_passphrase_textfield_);
-    layout->AddView(
-        new ControlledSettingIndicatorView(psk_passphrase_ui_data_));
-    layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
-  } else {
-    psk_passphrase_label_ = NULL;
-    psk_passphrase_textfield_ = NULL;
-  }
+  layout_->StartRow(0, 0);
+  psk_passphrase_label_ =  new views::Label(l10n_util::GetStringUTF16(
+      IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_VPN_PSK_PASSPHRASE));
+  layout_->AddView(psk_passphrase_label_);
+  psk_passphrase_textfield_ = new PassphraseTextfield();
+  psk_passphrase_textfield_->SetController(this);
+  layout_->AddView(psk_passphrase_textfield_);
+  layout_->AddView(
+      new ControlledSettingIndicatorView(psk_passphrase_ui_data_));
+  layout_->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
 
   // Server CA certificate
-  // Only provide Server CA when configuring a new VPN.
-  if (!vpn) {
-    layout->StartRow(0, column_view_set_id);
-    server_ca_cert_label_ =
-        new views::Label(l10n_util::GetStringUTF16(
-            IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_CERT_SERVER_CA));
-    layout->AddView(server_ca_cert_label_);
+  if (service_path_.empty()) {
+    layout_->StartRow(0, 0);
+    server_ca_cert_label_ = new views::Label(l10n_util::GetStringUTF16(
+        IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_CERT_SERVER_CA));
+    layout_->AddView(server_ca_cert_label_);
     server_ca_cert_combobox_model_.reset(
         new internal::VpnServerCACertComboboxModel());
     server_ca_cert_combobox_ = new views::Combobox(
         server_ca_cert_combobox_model_.get());
-    layout->AddView(server_ca_cert_combobox_);
-    layout->AddView(new ControlledSettingIndicatorView(ca_cert_ui_data_));
-    layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
+    layout_->AddView(server_ca_cert_combobox_);
+    layout_->AddView(new ControlledSettingIndicatorView(ca_cert_ui_data_));
+    layout_->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
   } else {
     server_ca_cert_label_ = NULL;
     server_ca_cert_combobox_ = NULL;
   }
 
   // User certificate label and input.
-  if (enable_user_cert_) {
-    layout->StartRow(0, column_view_set_id);
-    user_cert_label_ = new views::Label(l10n_util::GetStringUTF16(
-        IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_VPN_USER_CERT));
-    layout->AddView(user_cert_label_);
-    user_cert_combobox_model_.reset(
-        new internal::VpnUserCertComboboxModel());
-    user_cert_combobox_ = new views::Combobox(user_cert_combobox_model_.get());
-    user_cert_combobox_->set_listener(this);
-    layout->AddView(user_cert_combobox_);
-    layout->AddView(new ControlledSettingIndicatorView(user_cert_ui_data_));
-    layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
-  } else {
-    user_cert_label_ = NULL;
-    user_cert_combobox_ = NULL;
-  }
+  layout_->StartRow(0, 0);
+  user_cert_label_ = new views::Label(l10n_util::GetStringUTF16(
+      IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_VPN_USER_CERT));
+  layout_->AddView(user_cert_label_);
+  user_cert_combobox_model_.reset(
+      new internal::VpnUserCertComboboxModel());
+  user_cert_combobox_ = new views::Combobox(user_cert_combobox_model_.get());
+  user_cert_combobox_->set_listener(this);
+  layout_->AddView(user_cert_combobox_);
+  layout_->AddView(new ControlledSettingIndicatorView(user_cert_ui_data_));
+  layout_->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
 
   // Username label and input.
-  layout->StartRow(0, column_view_set_id);
-  layout->AddView(new views::Label(l10n_util::GetStringUTF16(
+  layout_->StartRow(0, 0);
+  layout_->AddView(new views::Label(l10n_util::GetStringUTF16(
       IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_VPN_USERNAME)));
   username_textfield_ = new views::Textfield(views::Textfield::STYLE_DEFAULT);
   username_textfield_->SetController(this);
   username_textfield_->SetEnabled(username_ui_data_.IsEditable());
-  if (vpn && !vpn->username().empty())
-    username_textfield_->SetText(UTF8ToUTF16(vpn->username()));
-  layout->AddView(username_textfield_);
-  layout->AddView(new ControlledSettingIndicatorView(username_ui_data_));
-  layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
+  layout_->AddView(username_textfield_);
+  layout_->AddView(new ControlledSettingIndicatorView(username_ui_data_));
+  layout_->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
 
   // User passphrase label, input and visble button.
-  layout->StartRow(0, column_view_set_id);
-  layout->AddView(new views::Label(l10n_util::GetStringUTF16(
+  layout_->StartRow(0, 0);
+  layout_->AddView(new views::Label(l10n_util::GetStringUTF16(
       IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_VPN_USER_PASSPHRASE)));
-  bool has_user_passphrase = vpn && !vpn->IsUserPassphraseRequired();
-  user_passphrase_textfield_ = new PassphraseTextfield(has_user_passphrase);
+  user_passphrase_textfield_ = new PassphraseTextfield();
   user_passphrase_textfield_->SetController(this);
   user_passphrase_textfield_->SetEnabled(user_passphrase_ui_data_.IsEditable());
-  layout->AddView(user_passphrase_textfield_);
-  layout->AddView(new ControlledSettingIndicatorView(user_passphrase_ui_data_));
-  layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
+  layout_->AddView(user_passphrase_textfield_);
+  layout_->AddView(
+      new ControlledSettingIndicatorView(user_passphrase_ui_data_));
+  layout_->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
 
   // OTP label and input.
-  if (enable_otp_) {
-    layout->StartRow(0, column_view_set_id);
-    otp_label_ = new views::Label(l10n_util::GetStringUTF16(
-        IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_VPN_OTP));
-    layout->AddView(otp_label_);
-    otp_textfield_ = new views::Textfield(views::Textfield::STYLE_DEFAULT);
-    otp_textfield_->SetController(this);
-    layout->AddView(otp_textfield_);
-    layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
-  } else {
-    otp_label_ = NULL;
-    otp_textfield_ = NULL;
-  }
+  layout_->StartRow(0, 0);
+  otp_label_ = new views::Label(l10n_util::GetStringUTF16(
+      IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_VPN_OTP));
+  layout_->AddView(otp_label_);
+  otp_textfield_ = new views::Textfield(views::Textfield::STYLE_DEFAULT);
+  otp_textfield_->SetController(this);
+  layout_->AddView(otp_textfield_);
+  layout_->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
 
   // Group Name label and input.
-  if (enable_group_name_) {
-    layout->StartRow(0, column_view_set_id);
-    group_name_label_ = new views::Label(l10n_util::GetStringUTF16(
-        IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_VPN_GROUP_NAME));
-    layout->AddView(group_name_label_);
-    group_name_textfield_ =
-        new views::Textfield(views::Textfield::STYLE_DEFAULT);
-    group_name_textfield_->SetController(this);
-    if (vpn && !vpn->group_name().empty())
-      group_name_textfield_->SetText(UTF8ToUTF16(vpn->group_name()));
-    layout->AddView(group_name_textfield_);
-    layout->AddView(new ControlledSettingIndicatorView(group_name_ui_data_));
-    layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
-  } else {
-    group_name_label_ = NULL;
-    group_name_textfield_ = NULL;
-  }
+  layout_->StartRow(0, 0);
+  group_name_label_ = new views::Label(l10n_util::GetStringUTF16(
+      IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_VPN_GROUP_NAME));
+  layout_->AddView(group_name_label_);
+  group_name_textfield_ =
+      new views::Textfield(views::Textfield::STYLE_DEFAULT);
+  group_name_textfield_->SetController(this);
+  layout_->AddView(group_name_textfield_);
+  layout_->AddView(new ControlledSettingIndicatorView(group_name_ui_data_));
+  layout_->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
 
   // Save credentials
-  layout->StartRow(0, column_view_set_id);
+  layout_->StartRow(0, 0);
   save_credentials_checkbox_ = new views::Checkbox(
       l10n_util::GetStringUTF16(
           IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_SAVE_CREDENTIALS));
   save_credentials_checkbox_->SetEnabled(
       save_credentials_ui_data_.IsEditable());
-  bool save_credentials = vpn ? vpn->save_credentials() : false;
-  save_credentials_checkbox_->SetChecked(save_credentials);
-  layout->SkipColumns(1);
-  layout->AddView(save_credentials_checkbox_);
-  layout->AddView(
+  layout_->SkipColumns(1);
+  layout_->AddView(save_credentials_checkbox_);
+  layout_->AddView(
       new ControlledSettingIndicatorView(save_credentials_ui_data_));
 
   // Error label.
-  layout->StartRow(0, column_view_set_id);
-  layout->SkipColumns(1);
+  layout_->StartRow(0, 0);
+  layout_->SkipColumns(1);
   error_label_ = new views::Label();
   error_label_->SetHorizontalAlignment(gfx::ALIGN_LEFT);
   error_label_->SetEnabledColor(SK_ColorRED);
-  layout->AddView(error_label_);
+  layout_->AddView(error_label_);
 
   // Set or hide the UI, update comboboxes and error labels.
   Refresh();
+
+  if (vpn) {
+    NetworkHandler::Get()->network_configuration_handler()->GetProperties(
+        service_path_,
+        base::Bind(&VPNConfigView::InitFromProperties,
+                   weak_ptr_factory_.GetWeakPtr()),
+        base::Bind(&VPNConfigView::GetPropertiesError,
+                   weak_ptr_factory_.GetWeakPtr()));
+  }
+}
+
+void VPNConfigView::InitFromProperties(
+    const std::string& service_path,
+    const base::DictionaryValue& service_properties) {
+  const NetworkState* vpn = NetworkHandler::Get()->network_state_handler()->
+      GetNetworkState(service_path);
+  if (!vpn) {
+    NET_LOG_ERROR("Shill Error getting properties VpnConfigView", service_path);
+    return;
+  }
+
+  std::string provider_type, server_hostname, username, group_name;
+  bool psk_passphrase_required = false;
+  const base::DictionaryValue* provider_properties;
+  if (service_properties.GetDictionaryWithoutPathExpansion(
+          flimflam::kProviderProperty, &provider_properties)) {
+    provider_properties->GetStringWithoutPathExpansion(
+        flimflam::kTypeProperty, &provider_type);
+    provider_properties->GetStringWithoutPathExpansion(
+        flimflam::kHostProperty, &server_hostname);
+  }
+  if (provider_type == flimflam::kProviderL2tpIpsec) {
+    provider_properties->GetStringWithoutPathExpansion(
+        flimflam::kL2tpIpsecClientCertIdProperty, &client_cert_id_);
+    ca_cert_pem_ = GetPemFromDictionary(
+        provider_properties, shill::kL2tpIpsecCaCertPemProperty);
+    provider_properties->GetBooleanWithoutPathExpansion(
+        flimflam::kL2tpIpsecPskRequiredProperty, &psk_passphrase_required);
+    provider_properties->GetStringWithoutPathExpansion(
+        flimflam::kL2tpIpsecUserProperty, &username);
+    provider_properties->GetStringWithoutPathExpansion(
+        shill::kL2tpIpsecTunnelGroupProperty, &group_name);
+  } else if (provider_type == flimflam::kProviderOpenVpn) {
+    provider_properties->GetStringWithoutPathExpansion(
+        flimflam::kOpenVPNClientCertIdProperty, &client_cert_id_);
+    ca_cert_pem_ = GetPemFromDictionary(
+        provider_properties, shill::kOpenVPNCaCertPemProperty);
+    provider_properties->GetStringWithoutPathExpansion(
+        flimflam::kOpenVPNUserProperty, &username);
+  }
+  bool save_credentials = false;
+  service_properties.GetBooleanWithoutPathExpansion(
+      flimflam::kSaveCredentialsProperty, &save_credentials);
+
+  provider_type_index_ = ProviderTypeToIndex(provider_type, client_cert_id_);
+
+  if (service_text_)
+    service_text_->SetText(ASCIIToUTF16(vpn->name()));
+  if (provider_type_text_label_)
+    provider_type_text_label_->SetText(
+        ProviderTypeIndexToString(provider_type_index_));
+
+  if (server_textfield_ && !server_hostname.empty())
+    server_textfield_->SetText(UTF8ToUTF16(server_hostname));
+  if (username_textfield_ && !username.empty())
+    username_textfield_->SetText(UTF8ToUTF16(username));
+  if (group_name_textfield_ && !group_name.empty())
+    group_name_textfield_->SetText(UTF8ToUTF16(group_name));
+  if (psk_passphrase_textfield_)
+    psk_passphrase_textfield_->SetShowFake(!psk_passphrase_required);
+  if (save_credentials_checkbox_)
+    save_credentials_checkbox_->SetChecked(save_credentials);
+
+  Refresh();
+}
+
+void VPNConfigView::ParseUIProperties(const NetworkState* vpn) {
+  std::string type_dict_name =
+      ProviderTypeIndexToONCDictKey(provider_type_index_);
+  if (provider_type_index_ == PROVIDER_TYPE_INDEX_L2TP_IPSEC_PSK) {
+    ParseVPNUIProperty(vpn, type_dict_name, onc::ipsec::kServerCARef,
+                       &ca_cert_ui_data_);
+    ParseVPNUIProperty(vpn, type_dict_name, onc::ipsec::kPSK,
+                       &psk_passphrase_ui_data_);
+    ParseVPNUIProperty(vpn, type_dict_name, onc::ipsec::kGroup,
+                       &group_name_ui_data_);
+  } else if (provider_type_index_ == PROVIDER_TYPE_INDEX_OPEN_VPN) {
+    ParseVPNUIProperty(vpn, type_dict_name, onc::openvpn::kServerCARef,
+                       &ca_cert_ui_data_);
+  }
+  ParseVPNUIProperty(vpn, type_dict_name, onc::vpn::kClientCertRef,
+                     &user_cert_ui_data_);
+
+  const std::string credentials_dict_name(
+      provider_type_index_ == PROVIDER_TYPE_INDEX_L2TP_IPSEC_PSK ?
+      onc::vpn::kL2TP : type_dict_name);
+  ParseVPNUIProperty(vpn, credentials_dict_name, onc::vpn::kUsername,
+                     &username_ui_data_);
+  ParseVPNUIProperty(vpn, credentials_dict_name, onc::vpn::kPassword,
+                     &user_passphrase_ui_data_);
+  ParseVPNUIProperty(vpn, credentials_dict_name, onc::vpn::kSaveCredentials,
+                     &save_credentials_ui_data_);
+}
+
+void VPNConfigView::GetPropertiesError(
+    const std::string& error_name,
+    scoped_ptr<base::DictionaryValue> error_data) {
+  NET_LOG_ERROR("Shill Error from VpnConfigView: " + error_name, "");
+}
+
+void VPNConfigView::SetConfigProperties(
+    base::DictionaryValue* properties) {
+  int provider_type_index = GetProviderTypeIndex();
+  std::string user_passphrase = GetUserPassphrase();
+  std::string user_name = GetUsername();
+  std::string group_name = GetGroupName();
+  switch (provider_type_index) {
+    case PROVIDER_TYPE_INDEX_L2TP_IPSEC_PSK: {
+      std::string psk_passphrase = GetPSKPassphrase();
+      if (!psk_passphrase.empty()) {
+        properties->SetStringWithoutPathExpansion(
+            flimflam::kL2tpIpsecPskProperty, GetPSKPassphrase());
+      }
+      if (!group_name.empty()) {
+        properties->SetStringWithoutPathExpansion(
+            shill::kL2tpIpsecTunnelGroupProperty, group_name);
+      }
+      if (!user_name.empty()) {
+        properties->SetStringWithoutPathExpansion(
+            flimflam::kL2tpIpsecUserProperty, user_name);
+      }
+      if (!user_passphrase.empty()) {
+        properties->SetStringWithoutPathExpansion(
+            flimflam::kL2tpIpsecPasswordProperty, user_passphrase);
+      }
+      break;
+    }
+    case PROVIDER_TYPE_INDEX_L2TP_IPSEC_USER_CERT: {
+      std::string ca_cert_pem = GetServerCACertPEM();
+      if (!ca_cert_pem.empty()) {
+        properties->SetStringWithoutPathExpansion(
+            shill::kL2tpIpsecCaCertPemProperty, ca_cert_pem);
+      }
+      properties->SetStringWithoutPathExpansion(
+          flimflam::kL2tpIpsecClientCertIdProperty, GetUserCertID());
+      if (!group_name.empty()) {
+        properties->SetStringWithoutPathExpansion(
+            shill::kL2tpIpsecTunnelGroupProperty, GetGroupName());
+      }
+      if (!user_name.empty()) {
+        properties->SetStringWithoutPathExpansion(
+            flimflam::kL2tpIpsecUserProperty, user_name);
+      }
+      if (!user_passphrase.empty()) {
+        properties->SetStringWithoutPathExpansion(
+            flimflam::kL2tpIpsecPasswordProperty, user_passphrase);
+      }
+      break;
+    }
+    case PROVIDER_TYPE_INDEX_OPEN_VPN: {
+      std::string ca_cert_pem = GetServerCACertPEM();
+      if (!ca_cert_pem.empty()) {
+        base::ListValue* pem_list = new base::ListValue;
+        pem_list->AppendString(GetServerCACertPEM());
+        properties->SetWithoutPathExpansion(
+            shill::kOpenVPNCaCertPemProperty, pem_list);
+      }
+      properties->SetStringWithoutPathExpansion(
+          flimflam::kOpenVPNClientCertIdProperty, GetUserCertID());
+      properties->SetStringWithoutPathExpansion(
+          flimflam::kOpenVPNUserProperty, GetUsername());
+      if (!user_passphrase.empty()) {
+        properties->SetStringWithoutPathExpansion(
+            flimflam::kOpenVPNPasswordProperty, user_passphrase);
+      }
+      std::string otp = GetOTP();
+      if (!otp.empty()) {
+        properties->SetStringWithoutPathExpansion(
+            flimflam::kOpenVPNOTPProperty, otp);
+      }
+      break;
+    }
+    case PROVIDER_TYPE_INDEX_MAX:
+      NOTREACHED();
+      break;
+  }
+  properties->SetBooleanWithoutPathExpansion(
+      flimflam::kSaveCredentialsProperty, GetSaveCredentials());
 }
 
 void VPNConfigView::Refresh() {
-  NetworkLibrary* cros = NetworkLibrary::Get();
-
   UpdateControls();
 
   // Set certificate combo boxes.
-  VirtualNetwork* vpn = cros->FindVirtualNetworkByPath(service_path_);
   if (server_ca_cert_combobox_) {
     server_ca_cert_combobox_->ModelChanged();
-    if (enable_server_ca_cert_ &&
-        (vpn && !vpn->ca_cert_pem().empty())) {
+    if (enable_server_ca_cert_ && !ca_cert_pem_.empty()) {
       // Select the current server CA certificate in the combobox.
       int cert_index = CertLibrary::Get()->GetCertIndexByPEM(
-          CertLibrary::CERT_TYPE_SERVER_CA, vpn->ca_cert_pem());
+          CertLibrary::CERT_TYPE_SERVER_CA, ca_cert_pem_);
       if (cert_index >= 0) {
         // Skip item for "Default"
         server_ca_cert_combobox_->SetSelectedIndex(1 + cert_index);
@@ -740,10 +891,9 @@
 
   if (user_cert_combobox_) {
     user_cert_combobox_->ModelChanged();
-    if (enable_user_cert_ &&
-        (vpn && !vpn->client_cert_id().empty())) {
+    if (enable_user_cert_ && !client_cert_id_.empty()) {
       int cert_index = CertLibrary::Get()->GetCertIndexByPkcs11Id(
-          CertLibrary::CERT_TYPE_USER, vpn->client_cert_id());
+          CertLibrary::CERT_TYPE_USER, client_cert_id_);
       if (cert_index >= 0)
         user_cert_combobox_->SetSelectedIndex(cert_index);
       else
@@ -757,30 +907,23 @@
 }
 
 void VPNConfigView::UpdateControlsToEnable() {
-  // Set which controls are enabled.
   enable_psk_passphrase_ = false;
   enable_user_cert_ = false;
   enable_server_ca_cert_ = false;
   enable_otp_ = false;
   enable_group_name_ = false;
-  switch (provider_type_) {
-    case PROVIDER_TYPE_L2TP_IPSEC_PSK:
-      enable_psk_passphrase_ = true;
-      enable_group_name_ = true;
-      break;
-    case PROVIDER_TYPE_L2TP_IPSEC_USER_CERT:
-      enable_server_ca_cert_ = true;
-      enable_user_cert_ = HaveUserCerts();
-      enable_group_name_ = true;
-      break;
-    case PROVIDER_TYPE_OPEN_VPN:
-      enable_server_ca_cert_ = true;
-      enable_user_cert_ = HaveUserCerts();
-      enable_otp_ = true;
-      break;
-    default:
-      NOTREACHED();
-      break;
+  int provider_type_index = GetProviderTypeIndex();
+  if (provider_type_index == PROVIDER_TYPE_INDEX_L2TP_IPSEC_PSK) {
+    enable_psk_passphrase_ = true;
+    enable_group_name_ = true;
+  } else if (provider_type_index == PROVIDER_TYPE_INDEX_L2TP_IPSEC_USER_CERT) {
+    enable_server_ca_cert_ = true;
+    enable_user_cert_ = HaveUserCerts();
+    enable_group_name_ = true;
+  } else {  // PROVIDER_TYPE_INDEX_OPEN_VPN (default)
+    enable_server_ca_cert_ = true;
+    enable_user_cert_ = HaveUserCerts();
+    enable_otp_ = true;
   }
 }
 
@@ -818,33 +961,28 @@
 }
 
 void VPNConfigView::UpdateErrorLabel() {
-  NetworkLibrary* cros = NetworkLibrary::Get();
-
   // Error message.
-  std::string error_msg;
-  if (UserCertRequired() && CertLibrary::Get()->CertificatesLoaded()) {
+  string16 error_msg;
+  bool cert_required =
+      GetProviderTypeIndex() == PROVIDER_TYPE_INDEX_L2TP_IPSEC_USER_CERT;
+  if (cert_required && CertLibrary::Get()->CertificatesLoaded()) {
     if (!HaveUserCerts()) {
-      error_msg = l10n_util::GetStringUTF8(
+      error_msg = l10n_util::GetStringUTF16(
           IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_PLEASE_INSTALL_USER_CERT);
     } else if (!IsUserCertValid()) {
-      error_msg = l10n_util::GetStringUTF8(
+      error_msg = l10n_util::GetStringUTF16(
           IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_REQUIRE_HARDWARE_BACKED);
     }
   }
   if (error_msg.empty() && !service_path_.empty()) {
     // TODO(kuan): differentiate between bad psk and user passphrases.
-    VirtualNetwork* vpn = cros->FindVirtualNetworkByPath(service_path_);
-    if (vpn && vpn->failed()) {
-      if (vpn->error() == ERROR_BAD_PASSPHRASE) {
-        error_msg = l10n_util::GetStringUTF8(
-            IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_BAD_PASSPHRASE);
-      } else {
-        error_msg = vpn->GetErrorString();
-      }
-    }
+    const NetworkState* vpn = NetworkHandler::Get()->network_state_handler()->
+        GetNetworkState(service_path_);
+    if (vpn && vpn->connection_state() == flimflam::kStateFailure)
+      error_msg = ash::network_connect::ErrorString(vpn->error());
   }
   if (!error_msg.empty()) {
-    error_label_->SetText(UTF8ToUTF16(error_msg));
+    error_label_->SetText(error_msg);
     error_label_->SetVisible(true);
   } else {
     error_label_->SetVisible(false);
@@ -855,10 +993,6 @@
   parent_->GetDialogClientView()->UpdateDialogButtons();
 }
 
-bool VPNConfigView::UserCertRequired() const {
-  return provider_type_ == PROVIDER_TYPE_L2TP_IPSEC_USER_CERT;
-}
-
 bool VPNConfigView::HaveUserCerts() const {
   return CertLibrary::Get()->NumCertificates(CertLibrary::CERT_TYPE_USER) > 0;
 }
@@ -896,15 +1030,16 @@
   return textfield->GetPassphrase();
 }
 
-void VPNConfigView::ParseVPNUIProperty(NetworkPropertyUIData* property_ui_data,
-                                       Network* network,
-                                       const std::string& dict_key,
-                                       const std::string& key) {
+void VPNConfigView::ParseVPNUIProperty(
+    const NetworkState* network,
+    const std::string& dict_key,
+    const std::string& key,
+    NetworkPropertyUIData* property_ui_data) {
   onc::ONCSource onc_source = onc::ONC_SOURCE_NONE;
   const base::DictionaryValue* onc =
-      NetworkConfigView::FindPolicyForActiveUser(network, &onc_source);
+      network_connect::FindPolicyForActiveUser(network, &onc_source);
 
-  VLOG_IF(1, !onc) << "No ONC found for VPN network " << network->unique_id();
+  VLOG_IF(1, !onc) << "No ONC found for VPN network " << network->guid();
   property_ui_data->ParseOncProperty(
       onc_source,
       onc,
diff --git a/chrome/browser/chromeos/options/vpn_config_view.h b/chrome/browser/chromeos/options/vpn_config_view.h
index cb5f7ce..24c1a5a 100644
--- a/chrome/browser/chromeos/options/vpn_config_view.h
+++ b/chrome/browser/chromeos/options/vpn_config_view.h
@@ -18,13 +18,20 @@
 #include "ui/views/controls/textfield/textfield_controller.h"
 #include "ui/views/view.h"
 
+namespace base {
+class DictionaryValue;
+}
+
 namespace views {
 class Checkbox;
+class GridLayout;
 class Label;
 }
 
 namespace chromeos {
 
+class NetworkState;
+
 namespace internal {
 class ProviderTypeComboboxModel;
 class VpnServerCACertComboboxModel;
@@ -38,8 +45,7 @@
                       public views::ComboboxListener,
                       public CertLibrary::Observer {
  public:
-  VPNConfigView(NetworkConfigView* parent, VirtualNetwork* vpn);
-  explicit VPNConfigView(NetworkConfigView* parent);
+  VPNConfigView(NetworkConfigView* parent, const std::string& service_path);
   virtual ~VPNConfigView();
 
   // views::TextfieldController:
@@ -68,7 +74,17 @@
 
  private:
   // Initializes data members and create UI controls.
-  void Init(VirtualNetwork* vpn);
+  void Init();
+
+  // Callback to initialize fields from uncached network properties.
+  void InitFromProperties(const std::string& service_path,
+                          const base::DictionaryValue& dictionary);
+  void ParseUIProperties(const NetworkState* vpn);
+  void GetPropertiesError(const std::string& error_name,
+                          scoped_ptr<base::DictionaryValue> error_data);
+
+  // Helper function to set configurable properties.
+  void SetConfigProperties(base::DictionaryValue* properties);
 
   // Set and update all control values.
   void Refresh();
@@ -81,9 +97,6 @@
   // Update state of the Login button.
   void UpdateCanLogin();
 
-  // Returns true if the provider type requires a user certificate.
-  bool UserCertRequired() const;
-
   // Returns true if there is at least one user certificate installed.
   bool HaveUserCerts() const;
 
@@ -109,22 +122,21 @@
   const std::string GetServerCACertPEM() const;
   const std::string GetUserCertID() const;
   bool GetSaveCredentials() const;
+  int GetProviderTypeIndex() const;
+  std::string GetProviderTypeString() const;
 
   // Parses a VPN UI |property| from the given |network|. |key| is the property
   // name within the type-specific VPN subdictionary named |dict_key|.
-  void ParseVPNUIProperty(NetworkPropertyUIData* property_ui_data,
-                          Network* network,
+  void ParseVPNUIProperty(const NetworkState* network,
                           const std::string& dict_key,
-                          const std::string& key);
+                          const std::string& key,
+                          NetworkPropertyUIData* property_ui_data);
 
-  std::string server_hostname_;
   string16 service_name_from_server_;
   bool service_text_modified_;
 
   // Initialized in Init():
 
-  ProviderType provider_type_;
-
   bool enable_psk_passphrase_;
   bool enable_user_cert_;
   bool enable_server_ca_cert_;
@@ -141,6 +153,7 @@
 
   int title_;
 
+  views::GridLayout* layout_;
   views::Textfield* server_textfield_;
   views::Label* service_text_;
   views::Textfield* service_textfield_;
@@ -165,6 +178,13 @@
   views::Checkbox* save_credentials_checkbox_;
   views::Label* error_label_;
 
+  // Cached VPN properties, only set when configuring an existing network.
+  int provider_type_index_;
+  std::string ca_cert_pem_;
+  std::string client_cert_id_;
+
+  base::WeakPtrFactory<VPNConfigView> weak_ptr_factory_;
+
   DISALLOW_COPY_AND_ASSIGN(VPNConfigView);
 };
 
diff --git a/chrome/browser/chromeos/options/wifi_config_view.cc b/chrome/browser/chromeos/options/wifi_config_view.cc
index 211f728..9827218 100644
--- a/chrome/browser/chromeos/options/wifi_config_view.cc
+++ b/chrome/browser/chromeos/options/wifi_config_view.cc
@@ -4,19 +4,26 @@
 
 #include "chrome/browser/chromeos/options/wifi_config_view.h"
 
+#include "ash/system/chromeos/network/network_connect.h"
 #include "base/strings/string_util.h"
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
-#include "chrome/browser/chromeos/cros/network_library.h"
 #include "chrome/browser/chromeos/enrollment_dialog_view.h"
+#include "chrome/browser/chromeos/options/network_connect.h"
 #include "chrome/browser/profiles/profile_manager.h"
 #include "chromeos/login/login_state.h"
+#include "chromeos/network/network_configuration_handler.h"
+#include "chromeos/network/network_event_log.h"
+#include "chromeos/network/network_handler.h"
+#include "chromeos/network/network_state.h"
+#include "chromeos/network/network_state_handler.h"
 #include "chromeos/network/network_ui_data.h"
 #include "chromeos/network/onc/onc_constants.h"
 #include "grit/chromium_strings.h"
 #include "grit/generated_resources.h"
 #include "grit/locale_settings.h"
 #include "grit/theme_resources.h"
+#include "third_party/cros_system_api/dbus/service_constants.h"
 #include "ui/base/events/event.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/base/resource/resource_bundle.h"
@@ -34,11 +41,6 @@
 
 namespace {
 
-// Returns true if network is known to require 802.1x.
-bool Is8021x(const WifiNetwork* wifi) {
-  return wifi && wifi->encrypted() && wifi->encryption() == SECURITY_8021X;
-}
-
 // Combobox that supports a preferred width.  Used by Server CA combobox
 // because the strings inside it are too wide.
 class ComboboxWithWidth : public views::Combobox {
@@ -85,6 +87,12 @@
   PHASE_2_AUTH_INDEX_COUNT    = 6
 };
 
+void ShillError(const std::string& function,
+                const std::string& error_name,
+                scoped_ptr<base::DictionaryValue> error_data) {
+  NET_LOG_ERROR("Shill Error from WifiConfigView: " + error_name, function);
+}
+
 }  // namespace
 
 namespace internal {
@@ -322,8 +330,10 @@
 
 }  // namespace internal
 
-WifiConfigView::WifiConfigView(NetworkConfigView* parent, WifiNetwork* wifi)
-    : ChildNetworkConfigView(parent, wifi),
+WifiConfigView::WifiConfigView(NetworkConfigView* parent,
+                               const std::string& service_path,
+                               bool show_8021x)
+    : ChildNetworkConfigView(parent, service_path),
       ssid_textfield_(NULL),
       eap_method_combobox_(NULL),
       phase_2_auth_label_(NULL),
@@ -343,36 +353,17 @@
       passphrase_label_(NULL),
       passphrase_textfield_(NULL),
       passphrase_visible_button_(NULL),
-      error_label_(NULL) {
-  Init(wifi, Is8021x(wifi));
-}
-
-WifiConfigView::WifiConfigView(NetworkConfigView* parent, bool show_8021x)
-    : ChildNetworkConfigView(parent),
-      ssid_textfield_(NULL),
-      eap_method_combobox_(NULL),
-      phase_2_auth_label_(NULL),
-      phase_2_auth_combobox_(NULL),
-      user_cert_label_(NULL),
-      user_cert_combobox_(NULL),
-      server_ca_cert_label_(NULL),
-      server_ca_cert_combobox_(NULL),
-      identity_label_(NULL),
-      identity_textfield_(NULL),
-      identity_anonymous_label_(NULL),
-      identity_anonymous_textfield_(NULL),
-      save_credentials_checkbox_(NULL),
-      share_network_checkbox_(NULL),
-      shared_network_label_(NULL),
-      security_combobox_(NULL),
-      passphrase_label_(NULL),
-      passphrase_textfield_(NULL),
-      passphrase_visible_button_(NULL),
-      error_label_(NULL) {
-  Init(NULL, show_8021x);
+      error_label_(NULL),
+      weak_ptr_factory_(this) {
+  Init(show_8021x);
+  NetworkHandler::Get()->network_state_handler()->AddObserver(this, FROM_HERE);
 }
 
 WifiConfigView::~WifiConfigView() {
+  if (NetworkHandler::IsInitialized()) {
+    NetworkHandler::Get()->network_state_handler()->RemoveObserver(
+        this, FROM_HERE);
+  }
   CertLibrary::Get()->RemoveObserver(this);
 }
 
@@ -541,8 +532,8 @@
     // user certificates are enabled.
     share_network_checkbox_->SetEnabled(false);
     share_network_checkbox_->SetChecked(false);
-  } else if (!LoginState::Get()->IsUserLoggedIn()) {
-    // If not logged in, networks must be shared.
+  } else if (!LoginState::Get()->IsUserAuthenticated()) {
+    // If not logged in as an authenticated user, networks must be shared.
     share_network_checkbox_->SetEnabled(false);
     share_network_checkbox_->SetChecked(true);
   } else {
@@ -552,47 +543,29 @@
 }
 
 void WifiConfigView::UpdateErrorLabel() {
-  std::string error_msg;
+  base::string16 error_msg;
   if (UserCertRequired() && CertLibrary::Get()->CertificatesLoaded()) {
     if (!HaveUserCerts()) {
-      if (!LoginState::Get()->IsUserLoggedIn()) {
-        error_msg = l10n_util::GetStringUTF8(
+      if (!LoginState::Get()->IsUserAuthenticated()) {
+        error_msg = l10n_util::GetStringUTF16(
             IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_LOGIN_FOR_USER_CERT);
       } else {
-        error_msg = l10n_util::GetStringUTF8(
+        error_msg = l10n_util::GetStringUTF16(
             IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_PLEASE_INSTALL_USER_CERT);
       }
     } else if (!IsUserCertValid()) {
-      error_msg = l10n_util::GetStringUTF8(
+      error_msg = l10n_util::GetStringUTF16(
           IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_REQUIRE_HARDWARE_BACKED);
     }
   }
   if (error_msg.empty() && !service_path_.empty()) {
-    NetworkLibrary* cros = NetworkLibrary::Get();
-    const WifiNetwork* wifi = cros->FindWifiNetworkByPath(service_path_);
-    if (wifi && wifi->failed()) {
-      bool passphrase_empty = wifi->GetPassphrase().empty();
-      switch (wifi->error()) {
-        case ERROR_BAD_PASSPHRASE:
-          if (!passphrase_empty) {
-            error_msg = l10n_util::GetStringUTF8(
-                IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_BAD_PASSPHRASE);
-          }
-          break;
-        case ERROR_BAD_WEPKEY:
-          if (!passphrase_empty) {
-            error_msg = l10n_util::GetStringUTF8(
-                IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_BAD_WEPKEY);
-          }
-          break;
-        default:
-          error_msg = wifi->GetErrorString();
-          break;
-      }
-    }
+    const NetworkState* wifi = NetworkHandler::Get()->network_state_handler()->
+        GetNetworkState(service_path_);
+    if (wifi && wifi->connection_state() == flimflam::kStateFailure)
+      error_msg = ash::network_connect::ErrorString(wifi->error());
   }
   if (!error_msg.empty()) {
-    error_label_->SetText(UTF8ToUTF16(error_msg));
+    error_label_->SetText(error_msg);
     error_label_->SetVisible(true);
   } else {
     error_label_->SetVisible(false);
@@ -651,83 +624,74 @@
 }
 
 bool WifiConfigView::Login() {
-  NetworkLibrary* cros = NetworkLibrary::Get();
+  const bool share_default = true;
   if (service_path_.empty()) {
-    const bool share_default = true;  // share networks by default
+    // Set configuration properties.
+    base::DictionaryValue properties;
+    properties.SetStringWithoutPathExpansion(
+        flimflam::kTypeProperty, flimflam::kTypeWifi);
+    properties.SetStringWithoutPathExpansion(
+        flimflam::kSSIDProperty, GetSsid());
+    properties.SetStringWithoutPathExpansion(
+        flimflam::kModeProperty, flimflam::kModeManaged);
+    properties.SetBooleanWithoutPathExpansion(
+        flimflam::kSaveCredentialsProperty, GetSaveCredentials());
+    std::string security = flimflam::kSecurityNone;
     if (!eap_method_combobox_) {
       // Hidden ordinary Wi-Fi connection.
-      ConnectionSecurity security = SECURITY_UNKNOWN;
       switch (security_combobox_->selected_index()) {
         case SECURITY_INDEX_NONE:
-          security = SECURITY_NONE;
+          security = flimflam::kSecurityNone;
           break;
         case SECURITY_INDEX_WEP:
-          security = SECURITY_WEP;
+          security = flimflam::kSecurityWep;
           break;
         case SECURITY_INDEX_PSK:
-          security = SECURITY_PSK;
+          security = flimflam::kSecurityPsk;
           break;
       }
-      cros->ConnectToUnconfiguredWifiNetwork(
-          GetSsid(),
-          security,
-          GetPassphrase(),
-          NULL,
-          GetSaveCredentials(),
-          GetShareNetwork(share_default));
+      std::string passphrase = GetPassphrase();
+      if (!passphrase.empty()) {
+        properties.SetStringWithoutPathExpansion(
+            flimflam::kPassphraseProperty, GetPassphrase());
+      }
     } else {
       // Hidden 802.1X EAP Wi-Fi connection.
-      chromeos::NetworkLibrary::EAPConfigData config_data;
-      config_data.method = GetEapMethod();
-      config_data.auth = GetEapPhase2Auth();
-      config_data.server_ca_cert_pem = GetEapServerCaCertPEM();
-      config_data.use_system_cas = GetEapUseSystemCas();
-      config_data.client_cert_pkcs11_id = GetEapClientCertPkcs11Id();
-      config_data.identity = GetEapIdentity();
-      config_data.anonymous_identity = GetEapAnonymousIdentity();
-      cros->ConnectToUnconfiguredWifiNetwork(
-          GetSsid(),
-          SECURITY_8021X,
-          GetPassphrase(),
-          &config_data,
-          GetSaveCredentials(),
-          GetShareNetwork(share_default));
+      security = flimflam::kSecurity8021x;
+      SetEapProperties(&properties);
     }
+    properties.SetStringWithoutPathExpansion(
+        flimflam::kSecurityProperty, security);
+
+    // Configure and connect to network.
+    bool shared = GetShareNetwork(share_default);
+    ash::network_connect::CreateConfigurationAndConnect(&properties, shared);
   } else {
-    WifiNetwork* wifi = cros->FindWifiNetworkByPath(service_path_);
+    const NetworkState* wifi = NetworkHandler::Get()->network_state_handler()->
+        GetNetworkState(service_path_);
     if (!wifi) {
       // Shill no longer knows about this wifi network (edge case).
-      // TODO(stevenjb): Add a notification (chromium-os13225).
-      LOG(WARNING) << "Wifi network: " << service_path_ << " no longer exists.";
-      return true;
+      // TODO(stevenjb): Add notification for this.
+      NET_LOG_ERROR("Network not found", service_path_);
+      return true;  // Close dialog
     }
+    base::DictionaryValue properties;
     if (eap_method_combobox_) {
       // Visible 802.1X EAP Wi-Fi connection.
-      EAPMethod method = GetEapMethod();
-      DCHECK(method != EAP_METHOD_UNKNOWN);
-      wifi->SetEAPMethod(method);
-      wifi->SetEAPPhase2Auth(GetEapPhase2Auth());
-      wifi->SetEAPServerCaCertPEM(GetEapServerCaCertPEM());
-      wifi->SetEAPUseSystemCAs(GetEapUseSystemCas());
-      wifi->SetEAPClientCertPkcs11Id(GetEapClientCertPkcs11Id());
-      wifi->SetEAPIdentity(GetEapIdentity());
-      wifi->SetEAPAnonymousIdentity(GetEapAnonymousIdentity());
-      wifi->SetEAPPassphrase(GetPassphrase());
-      wifi->SetSaveCredentials(GetSaveCredentials());
+      SetEapProperties(&properties);
+      properties.SetBooleanWithoutPathExpansion(
+          flimflam::kSaveCredentialsProperty, GetSaveCredentials());
     } else {
       // Visible ordinary Wi-Fi connection.
       const std::string passphrase = GetPassphrase();
-      if (passphrase != wifi->passphrase())
-        wifi->SetPassphrase(passphrase);
+      if (!passphrase.empty()) {
+        properties.SetStringWithoutPathExpansion(
+            flimflam::kPassphraseProperty, passphrase);
+      }
     }
-    bool share_default = (wifi->profile_type() != PROFILE_USER);
-    wifi->SetEnrollmentDelegate(
-        CreateEnrollmentDelegate(GetWidget()->GetNativeWindow(),
-                                 wifi->name(),
-                                 ProfileManager::GetLastUsedProfile()));
-    cros->ConnectToWifiNetwork(wifi, GetShareNetwork(share_default));
-    // Connection failures are responsible for updating the UI, including
-    // reopening dialogs.
+    bool share_network = GetShareNetwork(share_default);
+    ash::network_connect::ConfigureNetworkAndConnect(
+        service_path_, properties, share_network);
   }
   return true;  // dialog will be closed
 }
@@ -760,41 +724,42 @@
   return share_network_checkbox_->checked();
 }
 
-EAPMethod WifiConfigView::GetEapMethod() const {
+std::string WifiConfigView::GetEapMethod() const {
   DCHECK(eap_method_combobox_);
   switch (eap_method_combobox_->selected_index()) {
-    case EAP_METHOD_INDEX_NONE:
-      return EAP_METHOD_UNKNOWN;
     case EAP_METHOD_INDEX_PEAP:
-      return EAP_METHOD_PEAP;
+      return flimflam::kEapMethodPEAP;
     case EAP_METHOD_INDEX_TLS:
-      return EAP_METHOD_TLS;
+      return flimflam::kEapMethodTLS;
     case EAP_METHOD_INDEX_TTLS:
-      return EAP_METHOD_TTLS;
+      return flimflam::kEapMethodTTLS;
     case EAP_METHOD_INDEX_LEAP:
-      return EAP_METHOD_LEAP;
+      return flimflam::kEapMethodLEAP;
+    case EAP_METHOD_INDEX_NONE:
     default:
-      return EAP_METHOD_UNKNOWN;
+      return "";
   }
 }
 
-EAPPhase2Auth WifiConfigView::GetEapPhase2Auth() const {
+std::string WifiConfigView::GetEapPhase2Auth() const {
   DCHECK(phase_2_auth_combobox_);
+  bool is_peap = (GetEapMethod() == flimflam::kEapMethodPEAP);
   switch (phase_2_auth_combobox_->selected_index()) {
-    case PHASE_2_AUTH_INDEX_AUTO:
-      return EAP_PHASE_2_AUTH_AUTO;
     case PHASE_2_AUTH_INDEX_MD5:
-      return EAP_PHASE_2_AUTH_MD5;
+      return is_peap ? flimflam::kEapPhase2AuthPEAPMD5
+          : flimflam::kEapPhase2AuthTTLSMD5;
     case PHASE_2_AUTH_INDEX_MSCHAPV2:
-      return EAP_PHASE_2_AUTH_MSCHAPV2;
+      return is_peap ? flimflam::kEapPhase2AuthPEAPMSCHAPV2
+          : flimflam::kEapPhase2AuthTTLSMSCHAPV2;
     case PHASE_2_AUTH_INDEX_MSCHAP:
-      return EAP_PHASE_2_AUTH_MSCHAP;
+      return flimflam::kEapPhase2AuthTTLSMSCHAP;
     case PHASE_2_AUTH_INDEX_PAP:
-      return EAP_PHASE_2_AUTH_PAP;
+      return flimflam::kEapPhase2AuthTTLSPAP;
     case PHASE_2_AUTH_INDEX_CHAP:
-      return EAP_PHASE_2_AUTH_CHAP;
+      return flimflam::kEapPhase2AuthTTLSCHAP;
+    case PHASE_2_AUTH_INDEX_AUTO:
     default:
-      return EAP_PHASE_2_AUTH_AUTO;
+      return "";
   }
 }
 
@@ -842,6 +807,34 @@
   return UTF16ToUTF8(identity_anonymous_textfield_->text());
 }
 
+void WifiConfigView::SetEapProperties(base::DictionaryValue* properties) {
+  properties->SetStringWithoutPathExpansion(
+      flimflam::kEapIdentityProperty, GetEapIdentity());
+  properties->SetStringWithoutPathExpansion(
+      flimflam::kEapMethodProperty, GetEapMethod());
+  properties->SetStringWithoutPathExpansion(
+      flimflam::kEapPhase2AuthProperty, GetEapPhase2Auth());
+  properties->SetStringWithoutPathExpansion(
+      flimflam::kEapAnonymousIdentityProperty, GetEapAnonymousIdentity());
+
+  // shill requires both CertID and KeyID for TLS connections, despite
+  // the fact that by convention they are the same ID.
+  properties->SetStringWithoutPathExpansion(
+      flimflam::kEapCertIdProperty, GetEapClientCertPkcs11Id());
+  properties->SetStringWithoutPathExpansion(
+      flimflam::kEapKeyIdProperty, GetEapClientCertPkcs11Id());
+
+  properties->SetBooleanWithoutPathExpansion(
+      flimflam::kEapUseSystemCasProperty, GetEapUseSystemCas());
+  properties->SetStringWithoutPathExpansion(
+      flimflam::kEapPasswordProperty, GetPassphrase());
+
+  base::ListValue* pem_list = new base::ListValue;
+  pem_list->AppendString(GetEapServerCaCertPEM());
+  properties->SetWithoutPathExpansion(
+      shill::kEapCaCertPemProperty, pem_list);
+}
+
 void WifiConfigView::Cancel() {
 }
 
@@ -851,8 +844,13 @@
 // 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(WifiNetwork* wifi, bool show_8021x) {
+void WifiConfigView::Init(bool show_8021x) {
+  const NetworkState* wifi = NetworkHandler::Get()->network_state_handler()->
+      GetNetworkState(service_path_);
   if (wifi) {
+    DCHECK(wifi->type() == flimflam::kTypeWifi);
+    if (wifi->security() == flimflam::kSecurity8021x)
+      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);
@@ -1007,8 +1005,6 @@
         views::Textfield::STYLE_DEFAULT);
     identity_textfield_->SetAccessibleName(identity_label_text);
     identity_textfield_->SetController(this);
-    if (wifi && !wifi->identity().empty())
-      identity_textfield_->SetText(UTF8ToUTF16(wifi->identity()));
     identity_textfield_->SetEnabled(identity_ui_data_.IsEditable());
     layout->AddView(identity_textfield_);
     layout->AddView(new ControlledSettingIndicatorView(identity_ui_data_));
@@ -1024,8 +1020,6 @@
   passphrase_textfield_ = new views::Textfield(
       views::Textfield::STYLE_OBSCURED);
   passphrase_textfield_->SetController(this);
-  if (wifi && !wifi->GetPassphrase().empty())
-    passphrase_textfield_->SetText(UTF8ToUTF16(wifi->GetPassphrase()));
   // Disable passphrase input initially for other network.
   passphrase_label_->SetEnabled(wifi != NULL);
   passphrase_textfield_->SetEnabled(wifi && passphrase_ui_data_.IsEditable());
@@ -1102,10 +1096,7 @@
   }
 
   // Share network
-  if (!wifi ||
-      (wifi->profile_type() == PROFILE_NONE &&
-       wifi->IsPassphraseRequired() &&
-       !wifi->RequiresUserProfile())) {
+  if (!wifi || wifi->profile_path().empty()) {
     layout->StartRow(0, column_view_set_id);
     share_network_checkbox_ = new views::Checkbox(
         l10n_util::GetStringUTF16(
@@ -1125,111 +1116,131 @@
 
   // Initialize the field and checkbox values.
 
-  // After creating the fields, we set the values. Fields need to be created
-  // first because RefreshEapFields() will enable/disable them as appropriate.
-  if (show_8021x) {
-    EAPMethod eap_method = (wifi ? wifi->eap_method() : EAP_METHOD_UNKNOWN);
-    switch (eap_method) {
-      case EAP_METHOD_PEAP:
-        eap_method_combobox_->SetSelectedIndex(EAP_METHOD_INDEX_PEAP);
-        break;
-      case EAP_METHOD_TTLS:
-        eap_method_combobox_->SetSelectedIndex(EAP_METHOD_INDEX_TTLS);
-        break;
-      case EAP_METHOD_TLS:
-        eap_method_combobox_->SetSelectedIndex(EAP_METHOD_INDEX_TLS);
-        break;
-      case EAP_METHOD_LEAP:
-        eap_method_combobox_->SetSelectedIndex(EAP_METHOD_INDEX_LEAP);
-        break;
-      default:
-        break;
-    }
+  if (!wifi && show_8021x)
     RefreshEapFields();
 
-    // Phase 2 authentication and anonymous identity.
-    if (Phase2AuthActive()) {
-      EAPPhase2Auth eap_phase_2_auth =
-          (wifi ? wifi->eap_phase_2_auth() : EAP_PHASE_2_AUTH_AUTO);
-      switch (eap_phase_2_auth) {
-        case EAP_PHASE_2_AUTH_MD5:
-          phase_2_auth_combobox_->SetSelectedIndex(PHASE_2_AUTH_INDEX_MD5);
-          break;
-        case EAP_PHASE_2_AUTH_MSCHAPV2:
-          phase_2_auth_combobox_->SetSelectedIndex(PHASE_2_AUTH_INDEX_MSCHAPV2);
-          break;
-        case EAP_PHASE_2_AUTH_MSCHAP:
-          phase_2_auth_combobox_->SetSelectedIndex(PHASE_2_AUTH_INDEX_MSCHAP);
-          break;
-        case EAP_PHASE_2_AUTH_PAP:
-          phase_2_auth_combobox_->SetSelectedIndex(PHASE_2_AUTH_INDEX_PAP);
-          break;
-        case EAP_PHASE_2_AUTH_CHAP:
-          phase_2_auth_combobox_->SetSelectedIndex(PHASE_2_AUTH_INDEX_CHAP);
-          break;
-        default:
-          break;
-      }
+  RefreshShareCheckbox();
+  UpdateErrorLabel();
 
-      const std::string& eap_anonymous_identity =
-          (wifi ? wifi->eap_anonymous_identity() : std::string());
-      identity_anonymous_textfield_->SetText(
-          UTF8ToUTF16(eap_anonymous_identity));
-    }
-
-    // Server CA certificate.
-    if (CaCertActive()) {
-      const std::string& ca_cert_pem =
-          (wifi ? wifi->eap_server_ca_cert_pem() : std::string());
-      if (ca_cert_pem.empty()) {
-        if (wifi->eap_use_system_cas()) {
-          // "Default".
-          server_ca_cert_combobox_->SetSelectedIndex(0);
-        } else {
-          // "Do not check".
-          server_ca_cert_combobox_->SetSelectedIndex(
-              server_ca_cert_combobox_->model()->GetItemCount() - 1);
-        }
-      } else {
-        // Select the certificate if available.
-        int cert_index = CertLibrary::Get()->GetCertIndexByPEM(
-            CertLibrary::CERT_TYPE_SERVER_CA, ca_cert_pem);
-        if (cert_index >= 0) {
-          // Skip item for "Default".
-          server_ca_cert_combobox_->SetSelectedIndex(1 + cert_index);
-        }
-      }
-    }
-
-    // User certificate.
-    if (UserCertActive()) {
-      const std::string& pkcs11_id =
-          (wifi ? wifi->eap_client_cert_pkcs11_id() : std::string());
-      if (!pkcs11_id.empty()) {
-        int cert_index = CertLibrary::Get()->GetCertIndexByPkcs11Id(
-            CertLibrary::CERT_TYPE_USER, pkcs11_id);
-        if (cert_index >= 0) {
-          user_cert_combobox_->SetSelectedIndex(cert_index);
-        }
-      }
-    }
-
-    // Identity is always active.
-    const std::string& eap_identity =
-        (wifi ? wifi->eap_identity() : std::string());
-    identity_textfield_->SetText(UTF8ToUTF16(eap_identity));
-
-    // Passphrase
-    if (PassphraseActive()) {
-      const std::string& eap_passphrase =
-          (wifi ? wifi->eap_passphrase() : std::string());
-      passphrase_textfield_->SetText(UTF8ToUTF16(eap_passphrase));
-    }
-
-    // Save credentials
-    bool save_credentials = (wifi ? wifi->save_credentials() : false);
-    save_credentials_checkbox_->SetChecked(save_credentials);
+  if (wifi) {
+    NetworkHandler::Get()->network_configuration_handler()->GetProperties(
+        service_path_,
+        base::Bind(&WifiConfigView::InitFromProperties,
+                   weak_ptr_factory_.GetWeakPtr(), show_8021x),
+        base::Bind(&ShillError, "GetProperties"));
   }
+}
+
+void WifiConfigView::InitFromProperties(
+    bool show_8021x,
+    const std::string& service_path,
+    const base::DictionaryValue& properties) {
+  std::string passphrase;
+  properties.GetStringWithoutPathExpansion(
+      flimflam::kPassphraseProperty, &passphrase);
+  passphrase_textfield_->SetText(UTF8ToUTF16(passphrase));
+
+  if (!show_8021x)
+    return;
+
+  // EAP Method
+  std::string eap_method;
+  properties.GetStringWithoutPathExpansion(
+      flimflam::kEapMethodProperty, &eap_method);
+  if (eap_method == flimflam::kEapMethodPEAP)
+    eap_method_combobox_->SetSelectedIndex(EAP_METHOD_INDEX_PEAP);
+  else if (eap_method == flimflam::kEapMethodTTLS)
+    eap_method_combobox_->SetSelectedIndex(EAP_METHOD_INDEX_TTLS);
+  else if (eap_method == flimflam::kEapMethodTLS)
+    eap_method_combobox_->SetSelectedIndex(EAP_METHOD_INDEX_TLS);
+  else if (eap_method == flimflam::kEapMethodLEAP)
+    eap_method_combobox_->SetSelectedIndex(EAP_METHOD_INDEX_LEAP);
+  RefreshEapFields();
+
+  // Phase 2 authentication and anonymous identity.
+  if (Phase2AuthActive()) {
+    std::string eap_phase_2_auth;
+    properties.GetStringWithoutPathExpansion(
+        flimflam::kEapPhase2AuthProperty, &eap_phase_2_auth);
+    if (eap_phase_2_auth == flimflam::kEapPhase2AuthTTLSMD5)
+      phase_2_auth_combobox_->SetSelectedIndex(PHASE_2_AUTH_INDEX_MD5);
+    else if (eap_phase_2_auth == flimflam::kEapPhase2AuthTTLSMSCHAPV2)
+      phase_2_auth_combobox_->SetSelectedIndex(PHASE_2_AUTH_INDEX_MSCHAPV2);
+    else if (eap_phase_2_auth == flimflam::kEapPhase2AuthTTLSMSCHAP)
+      phase_2_auth_combobox_->SetSelectedIndex(PHASE_2_AUTH_INDEX_MSCHAP);
+    else if (eap_phase_2_auth == flimflam::kEapPhase2AuthTTLSPAP)
+      phase_2_auth_combobox_->SetSelectedIndex(PHASE_2_AUTH_INDEX_PAP);
+    else if (eap_phase_2_auth == flimflam::kEapPhase2AuthTTLSCHAP)
+      phase_2_auth_combobox_->SetSelectedIndex(PHASE_2_AUTH_INDEX_CHAP);
+
+    std::string eap_anonymous_identity;
+    properties.GetStringWithoutPathExpansion(
+        flimflam::kEapAnonymousIdentityProperty, &eap_anonymous_identity);
+    identity_anonymous_textfield_->SetText(UTF8ToUTF16(eap_anonymous_identity));
+  }
+
+  // Server CA certificate.
+  if (CaCertActive()) {
+    std::string eap_ca_cert_pem;
+    const base::ListValue* pems = NULL;
+    if (properties.GetListWithoutPathExpansion(
+            shill::kEapCaCertPemProperty, &pems))
+      pems->GetString(0, &eap_ca_cert_pem);
+    if (eap_ca_cert_pem.empty()) {
+      bool eap_use_system_cas = false;
+      properties.GetBooleanWithoutPathExpansion(
+          flimflam::kEapUseSystemCasProperty, &eap_use_system_cas);
+      if (eap_use_system_cas) {
+        // "Default"
+        server_ca_cert_combobox_->SetSelectedIndex(0);
+      } else {
+        // "Do not check".
+        server_ca_cert_combobox_->SetSelectedIndex(
+            server_ca_cert_combobox_->model()->GetItemCount() - 1);
+      }
+    } else {
+      // Select the certificate if available.
+      int cert_index = CertLibrary::Get()->GetCertIndexByPEM(
+          CertLibrary::CERT_TYPE_SERVER_CA, eap_ca_cert_pem);
+      if (cert_index >= 0) {
+        // Skip item for "Default".
+        server_ca_cert_combobox_->SetSelectedIndex(1 + cert_index);
+      }
+    }
+  }
+
+  // User certificate.
+  if (UserCertActive()) {
+    std::string eap_cert_id;
+    properties.GetStringWithoutPathExpansion(
+        flimflam::kEapCertIdProperty, &eap_cert_id);
+    if (!eap_cert_id.empty()) {
+      int cert_index = CertLibrary::Get()->GetCertIndexByPkcs11Id(
+          CertLibrary::CERT_TYPE_USER, eap_cert_id);
+      if (cert_index >= 0)
+        user_cert_combobox_->SetSelectedIndex(cert_index);
+    }
+  }
+
+  // Identity is always active.
+  std::string eap_identity;
+  properties.GetStringWithoutPathExpansion(
+      flimflam::kEapIdentityProperty, &eap_identity);
+  identity_textfield_->SetText(UTF8ToUTF16(eap_identity));
+
+  // Passphrase
+  if (PassphraseActive()) {
+    std::string eap_password;
+    properties.GetStringWithoutPathExpansion(
+        flimflam::kEapPasswordProperty, &eap_password);
+    passphrase_textfield_->SetText(UTF8ToUTF16(eap_password));
+  }
+
+  // Save credentials
+  bool save_credentials = false;
+  properties.GetBooleanWithoutPathExpansion(
+      flimflam::kSaveCredentialsProperty, &save_credentials);
+  save_credentials_checkbox_->SetChecked(save_credentials);
 
   RefreshShareCheckbox();
   UpdateErrorLabel();
@@ -1241,14 +1252,20 @@
     view_to_focus->RequestFocus();
 }
 
+void WifiConfigView::NetworkPropertiesUpdated(const NetworkState* network) {
+  if (network->path() != service_path_)
+    return;
+  UpdateErrorLabel();
+}
+
 // static
 void WifiConfigView::ParseWiFiUIProperty(
     NetworkPropertyUIData* property_ui_data,
-    Network* network,
+    const NetworkState* network,
     const std::string& key) {
   onc::ONCSource onc_source = onc::ONC_SOURCE_NONE;
   const base::DictionaryValue* onc =
-      NetworkConfigView::FindPolicyForActiveUser(network, &onc_source);
+      network_connect::FindPolicyForActiveUser(network, &onc_source);
 
   property_ui_data->ParseOncProperty(
       onc_source,
@@ -1259,7 +1276,7 @@
 // static
 void WifiConfigView::ParseWiFiEAPUIProperty(
     NetworkPropertyUIData* property_ui_data,
-    Network* network,
+    const NetworkState* network,
     const std::string& key) {
   ParseWiFiUIProperty(
       property_ui_data, network,
diff --git a/chrome/browser/chromeos/options/wifi_config_view.h b/chrome/browser/chromeos/options/wifi_config_view.h
index 574072d..7956499 100644
--- a/chrome/browser/chromeos/options/wifi_config_view.h
+++ b/chrome/browser/chromeos/options/wifi_config_view.h
@@ -10,10 +10,13 @@
 #include "base/basictypes.h"
 #include "base/compiler_specific.h"
 #include "base/memory/scoped_ptr.h"
+#include "base/memory/weak_ptr.h"
 #include "base/strings/string16.h"
 #include "chrome/browser/chromeos/cros/cert_library.h"
 #include "chrome/browser/chromeos/cros/network_property_ui_data.h"
 #include "chrome/browser/chromeos/options/network_config_view.h"
+#include "chromeos/network/network_state_handler_observer.h"
+#include "third_party/cros_system_api/dbus/service_constants.h"
 #include "ui/base/models/combobox_model.h"
 #include "ui/views/controls/button/button.h"
 #include "ui/views/controls/combobox/combobox_listener.h"
@@ -28,6 +31,8 @@
 
 namespace chromeos {
 
+class NetworkState;
+
 namespace internal {
 class EAPMethodComboboxModel;
 class Phase2AuthComboboxModel;
@@ -41,32 +46,31 @@
                        public views::TextfieldController,
                        public views::ButtonListener,
                        public views::ComboboxListener,
-                       public CertLibrary::Observer {
+                       public CertLibrary::Observer,
+                       public NetworkStateHandlerObserver {
  public:
-  // Wifi login dialog for wifi network |wifi|. |wifi| must be a non NULL
-  // pointer to a WifiNetwork in NetworkLibrary.
-  WifiConfigView(NetworkConfigView* parent, WifiNetwork* wifi);
-  // Wifi login dialog for "Joining other network..."
-  WifiConfigView(NetworkConfigView* parent, bool show_8021x);
+  WifiConfigView(NetworkConfigView* parent,
+                 const std::string& service_path,
+                 bool show_8021x);
   virtual ~WifiConfigView();
 
-  // views::TextfieldController:
+  // views::TextfieldController
   virtual void ContentsChanged(views::Textfield* sender,
                                const string16& new_contents) OVERRIDE;
   virtual bool HandleKeyEvent(views::Textfield* sender,
                               const ui::KeyEvent& key_event) OVERRIDE;
 
-  // views::ButtonListener:
+  // views::ButtonListener
   virtual void ButtonPressed(views::Button* sender,
                              const ui::Event& event) OVERRIDE;
 
-  // views::ComboboxListener:
+  // views::ComboboxListener
   virtual void OnSelectedIndexChanged(views::Combobox* combobox) OVERRIDE;
 
-  // CertLibrary::Observer:
+  // CertLibrary::Observer
   virtual void OnCertificatesLoaded(bool initial_load) OVERRIDE;
 
-  // ChildNetworkConfigView:
+  // ChildNetworkConfigView
   virtual string16 GetTitle() const OVERRIDE;
   virtual views::View* GetInitiallyFocusedView() OVERRIDE;
   virtual bool CanLogin() OVERRIDE;
@@ -74,21 +78,29 @@
   virtual void Cancel() OVERRIDE;
   virtual void InitFocus() 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,
-                                  Network* network,
+                                  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,
-                                     Network* network,
+                                     const NetworkState* network,
                                      const std::string& key);
 
  private:
   // Initializes UI.  If |show_8021x| includes 802.1x config options.
-  void Init(WifiNetwork* wifi, bool show_8021x);
+  void Init(bool show_8021x);
+
+  // Callback to initialize fields from uncached network properties.
+  void InitFromProperties(bool show_8021x,
+                          const std::string& service_path,
+                          const base::DictionaryValue& dictionary);
 
   // Get input values.
   std::string GetSsid() const;
@@ -97,14 +109,17 @@
   bool GetShareNetwork(bool share_default) const;
 
   // Get various 802.1X EAP values from the widgets.
-  EAPMethod GetEapMethod() const;
-  EAPPhase2Auth GetEapPhase2Auth() const;
+  std::string GetEapMethod() const;
+  std::string GetEapPhase2Auth() const;
   std::string GetEapServerCaCertPEM() const;
   bool GetEapUseSystemCas() const;
   std::string GetEapClientCertPkcs11Id() const;
   std::string GetEapIdentity() const;
   std::string GetEapAnonymousIdentity() const;
 
+  // Fill in |properties| with the appropriate values.
+  void SetEapProperties(base::DictionaryValue* properties);
+
   // Returns true if the EAP method requires a user certificate.
   bool UserCertRequired() const;
 
@@ -174,6 +189,8 @@
   views::ToggleImageButton* passphrase_visible_button_;
   views::Label* error_label_;
 
+  base::WeakPtrFactory<WifiConfigView> weak_ptr_factory_;
+
   DISALLOW_COPY_AND_ASSIGN(WifiConfigView);
 };
 
diff --git a/chrome/browser/chromeos/options/wimax_config_view.cc b/chrome/browser/chromeos/options/wimax_config_view.cc
index 5ae075b..8ea3788 100644
--- a/chrome/browser/chromeos/options/wimax_config_view.cc
+++ b/chrome/browser/chromeos/options/wimax_config_view.cc
@@ -4,19 +4,27 @@
 
 #include "chrome/browser/chromeos/options/wimax_config_view.h"
 
+#include "ash/system/chromeos/network/network_connect.h"
 #include "base/strings/string_util.h"
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
-#include "chrome/browser/chromeos/cros/network_library.h"
 #include "chrome/browser/chromeos/enrollment_dialog_view.h"
 #include "chrome/browser/chromeos/login/startup_utils.h"
+#include "chrome/browser/chromeos/options/network_connect.h"
 #include "chrome/browser/profiles/profile_manager.h"
 #include "chromeos/login/login_state.h"
+#include "chromeos/network/network_configuration_handler.h"
+#include "chromeos/network/network_event_log.h"
+#include "chromeos/network/network_profile.h"
+#include "chromeos/network/network_profile_handler.h"
+#include "chromeos/network/network_state.h"
+#include "chromeos/network/network_state_handler.h"
 #include "chromeos/network/onc/onc_constants.h"
 #include "grit/chromium_strings.h"
 #include "grit/generated_resources.h"
 #include "grit/locale_settings.h"
 #include "grit/theme_resources.h"
+#include "third_party/cros_system_api/dbus/service_constants.h"
 #include "ui/base/events/event.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/base/resource/resource_bundle.h"
@@ -31,8 +39,19 @@
 
 namespace chromeos {
 
-WimaxConfigView::WimaxConfigView(NetworkConfigView* parent, WimaxNetwork* wimax)
-    : ChildNetworkConfigView(parent, wimax),
+namespace {
+
+void ShillError(const std::string& function,
+                const std::string& error_name,
+                scoped_ptr<base::DictionaryValue> error_data) {
+  NET_LOG_ERROR("Shill Error from WimaxConfigView: " + error_name, function);
+}
+
+}  // namespace
+
+WimaxConfigView::WimaxConfigView(NetworkConfigView* parent,
+                                 const std::string& service_path)
+    : ChildNetworkConfigView(parent, service_path),
       identity_label_(NULL),
       identity_textfield_(NULL),
       save_credentials_checkbox_(NULL),
@@ -41,8 +60,9 @@
       passphrase_label_(NULL),
       passphrase_textfield_(NULL),
       passphrase_visible_button_(NULL),
-      error_label_(NULL) {
-  Init(wimax);
+      error_label_(NULL),
+      weak_ptr_factory_(this) {
+  Init();
 }
 
 WimaxConfigView::~WimaxConfigView() {
@@ -76,33 +96,15 @@
 }
 
 void WimaxConfigView::UpdateErrorLabel() {
-  std::string error_msg;
+  base::string16 error_msg;
   if (!service_path_.empty()) {
-    NetworkLibrary* cros = NetworkLibrary::Get();
-    const WimaxNetwork* wimax = cros->FindWimaxNetworkByPath(service_path_);
-    if (wimax && wimax->failed()) {
-      bool passphrase_empty = wimax->eap_passphrase().empty();
-      switch (wimax->error()) {
-        case ERROR_BAD_PASSPHRASE:
-          if (!passphrase_empty) {
-            error_msg = l10n_util::GetStringUTF8(
-                IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_BAD_PASSPHRASE);
-          }
-          break;
-        case ERROR_BAD_WEPKEY:
-          if (!passphrase_empty) {
-            error_msg = l10n_util::GetStringUTF8(
-                IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_BAD_WEPKEY);
-          }
-          break;
-        default:
-          error_msg = wimax->GetErrorString();
-          break;
-      }
-    }
+    const NetworkState* wimax = NetworkHandler::Get()->network_state_handler()->
+        GetNetworkState(service_path_);
+    if (wimax && wimax->connection_state() == flimflam::kStateFailure)
+      error_msg = ash::network_connect::ErrorString(wimax->error());
   }
   if (!error_msg.empty()) {
-    error_label_->SetText(UTF8ToUTF16(error_msg));
+    error_label_->SetText(error_msg);
     error_label_->SetVisible(true);
   } else {
     error_label_->SetVisible(false);
@@ -137,26 +139,26 @@
 }
 
 bool WimaxConfigView::Login() {
-  NetworkLibrary* cros = NetworkLibrary::Get();
-  WimaxNetwork* wimax = cros->FindWimaxNetworkByPath(service_path_);
+  const NetworkState* wimax = NetworkHandler::Get()->network_state_handler()->
+      GetNetworkState(service_path_);
   if (!wimax) {
-    // Shill no longer knows about this wimax network (edge case).
-    // TODO(stevenjb): Add a notification (chromium-os13225).
-    LOG(WARNING) << "Wimax network: " << service_path_ << " no longer exists.";
-    return true;
+    // 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
   }
-  wimax->SetEAPIdentity(GetEapIdentity());
-  wimax->SetEAPPassphrase(GetEapPassphrase());
-  wimax->SetSaveCredentials(GetSaveCredentials());
-  bool share_default = (wimax->profile_type() != PROFILE_USER);
-  bool share = GetShareNetwork(share_default);
-  wimax->SetEnrollmentDelegate(
-      CreateEnrollmentDelegate(GetWidget()->GetNativeWindow(),
-                               wimax->name(),
-                               ProfileManager::GetLastUsedProfile()));
-  cros->ConnectToWimaxNetwork(wimax, share);
-  // Connection failures are responsible for updating the UI, including
-  // reopening dialogs.
+  base::DictionaryValue properties;
+  properties.SetStringWithoutPathExpansion(
+      flimflam::kEapIdentityProperty, GetEapIdentity());
+  properties.SetStringWithoutPathExpansion(
+      flimflam::kEapPasswordProperty, GetEapPassphrase());
+  properties.SetBooleanWithoutPathExpansion(
+      flimflam::kSaveCredentialsProperty, GetSaveCredentials());
+
+  const bool share_default = true;
+  bool share_network = GetShareNetwork(share_default);
+  ash::network_connect::ConfigureNetworkAndConnect(
+      service_path_, properties, share_network);
   return true;  // dialog will be closed
 }
 
@@ -183,8 +185,11 @@
 void WimaxConfigView::Cancel() {
 }
 
-void WimaxConfigView::Init(WimaxNetwork* wimax) {
-  DCHECK(wimax);
+void WimaxConfigView::Init() {
+  const NetworkState* wimax = NetworkHandler::Get()->network_state_handler()->
+      GetNetworkState(service_path_);
+  DCHECK(wimax && wimax->type() == flimflam::kTypeWimax);
+
   WifiConfigView::ParseWiFiEAPUIProperty(
       &save_credentials_ui_data_, wimax, onc::eap::kSaveCredentials);
   WifiConfigView::ParseWiFiEAPUIProperty(
@@ -230,8 +235,6 @@
       views::Textfield::STYLE_DEFAULT);
   identity_textfield_->SetAccessibleName(identity_label_text);
   identity_textfield_->SetController(this);
-  const std::string& eap_identity = wimax->eap_identity();
-  identity_textfield_->SetText(UTF8ToUTF16(eap_identity));
   identity_textfield_->SetEnabled(identity_ui_data_.IsEditable());
   layout->AddView(identity_textfield_);
   layout->AddView(new ControlledSettingIndicatorView(identity_ui_data_));
@@ -288,7 +291,7 @@
 
   // Checkboxes.
 
-  if (LoginState::Get()->IsUserLoggedIn()) {
+  if (LoginState::Get()->IsUserAuthenticated()) {
     // Save credentials
     layout->StartRow(0, column_view_set_id);
     save_credentials_checkbox_ = new views::Checkbox(
@@ -296,23 +299,28 @@
             IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_SAVE_CREDENTIALS));
     save_credentials_checkbox_->SetEnabled(
         save_credentials_ui_data_.IsEditable());
-    save_credentials_checkbox_->SetChecked(wimax->save_credentials());
     layout->SkipColumns(1);
     layout->AddView(save_credentials_checkbox_);
     layout->AddView(
         new ControlledSettingIndicatorView(save_credentials_ui_data_));
+  }
 
-    // Share network
-    if (wimax->profile_type() == PROFILE_NONE && wimax->passphrase_required()) {
-      layout->StartRow(0, column_view_set_id);
-      share_network_checkbox_ = new views::Checkbox(
-          l10n_util::GetStringUTF16(
-              IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_SHARE_NETWORK));
+  // Share network
+  if (wimax->profile_path().empty()) {
+    layout->StartRow(0, column_view_set_id);
+    share_network_checkbox_ = new views::Checkbox(
+        l10n_util::GetStringUTF16(
+            IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_SHARE_NETWORK));
+    if (LoginState::Get()->IsUserAuthenticated()) {
+      share_network_checkbox_->SetChecked(false);  // Default to unshared
       share_network_checkbox_->SetEnabled(true);
-      share_network_checkbox_->SetChecked(false);  // Default to unshared.
-      layout->SkipColumns(1);
-      layout->AddView(share_network_checkbox_);
+    } else {
+      // Not logged in, must be shared
+      share_network_checkbox_->SetChecked(true);
+      share_network_checkbox_->SetEnabled(false);
     }
+    layout->SkipColumns(1);
+    layout->AddView(share_network_checkbox_);
   }
   layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
 
@@ -325,6 +333,32 @@
   layout->AddView(error_label_);
 
   UpdateErrorLabel();
+
+  if (wimax) {
+    NetworkHandler::Get()->network_configuration_handler()->GetProperties(
+        service_path_,
+        base::Bind(&WimaxConfigView::InitFromProperties,
+                   weak_ptr_factory_.GetWeakPtr()),
+        base::Bind(&ShillError, "GetProperties"));
+  }
+}
+
+void WimaxConfigView::InitFromProperties(
+    const std::string& service_path,
+    const base::DictionaryValue& properties) {
+  // EapIdentity
+  std::string eap_identity;
+  properties.GetStringWithoutPathExpansion(
+      flimflam::kEapIdentityProperty, &eap_identity);
+  identity_textfield_->SetText(UTF8ToUTF16(eap_identity));
+
+  // Save credentials
+  if (save_credentials_checkbox_) {
+    bool save_credentials = false;
+    properties.GetBooleanWithoutPathExpansion(
+        flimflam::kSaveCredentialsProperty, &save_credentials);
+    save_credentials_checkbox_->SetChecked(save_credentials);
+  }
 }
 
 void WimaxConfigView::InitFocus() {
diff --git a/chrome/browser/chromeos/options/wimax_config_view.h b/chrome/browser/chromeos/options/wimax_config_view.h
index f76702a..baa3ae7 100644
--- a/chrome/browser/chromeos/options/wimax_config_view.h
+++ b/chrome/browser/chromeos/options/wimax_config_view.h
@@ -9,6 +9,7 @@
 
 #include "base/basictypes.h"
 #include "base/compiler_specific.h"
+#include "base/memory/weak_ptr.h"
 #include "base/strings/string16.h"
 #include "chrome/browser/chromeos/options/network_config_view.h"
 #include "chrome/browser/chromeos/options/wifi_config_view.h"
@@ -31,7 +32,7 @@
  public:
   // Wimax login dialog for wimax network |wimax|. |wimax| must be a non NULL
   // pointer to a WimaxNetwork in NetworkLibrary.
-  WimaxConfigView(NetworkConfigView* parent, WimaxNetwork* wimax);
+  WimaxConfigView(NetworkConfigView* parent, const std::string& service_path);
   virtual ~WimaxConfigView();
 
   // views::TextfieldController:
@@ -53,7 +54,12 @@
   virtual void InitFocus() OVERRIDE;
 
  private:
-  void Init(WimaxNetwork* wimax);
+  // Initializes UI.
+  void Init();
+
+  // Callback to initialize fields from uncached network properties.
+  void InitFromProperties(const std::string& service_path,
+                          const base::DictionaryValue& dictionary);
 
   // Get input values.
   std::string GetEapIdentity() const;
@@ -81,6 +87,8 @@
   views::ToggleImageButton* passphrase_visible_button_;
   views::Label* error_label_;
 
+  base::WeakPtrFactory<WimaxConfigView> weak_ptr_factory_;
+
   DISALLOW_COPY_AND_ASSIGN(WimaxConfigView);
 };
 
diff --git a/chrome/browser/chromeos/policy/app_pack_updater.cc b/chrome/browser/chromeos/policy/app_pack_updater.cc
index 3aca24a..9230628 100644
--- a/chrome/browser/chromeos/policy/app_pack_updater.cc
+++ b/chrome/browser/chromeos/policy/app_pack_updater.cc
@@ -66,7 +66,7 @@
     : weak_ptr_factory_(this),
       created_extension_loader_(false),
       install_attributes_(install_attributes),
-      external_cache_(kAppPackCacheDir, request_context, this) {
+      external_cache_(kAppPackCacheDir, request_context, this, false) {
   chromeos::CrosSettings::Get()->AddSettingsObserver(chromeos::kAppPack, this);
 
   if (install_attributes_->GetMode() == DEVICE_MODE_RETAIL_KIOSK) {
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 ff380c1..9f50d06 100644
--- a/chrome/browser/chromeos/policy/device_cloud_policy_manager_chromeos.cc
+++ b/chrome/browser/chromeos/policy/device_cloud_policy_manager_chromeos.cc
@@ -59,7 +59,7 @@
   chromeos::system::StatisticsProvider* provider =
       chromeos::system::StatisticsProvider::GetInstance();
   if (!provider->GetMachineStatistic(key, &value))
-    LOG(WARNING) << "Failed to get machine statistic " << key;
+    return std::string();
 
   return value;
 }
@@ -70,10 +70,8 @@
   bool value = default_value;
   chromeos::system::StatisticsProvider* provider =
       chromeos::system::StatisticsProvider::GetInstance();
-  if (!provider->GetMachineFlag(key, &value)) {
-    LOG(WARNING) << "Failed to get machine flag " << key;
+  if (!provider->GetMachineFlag(key, &value))
     return default_value;
-  }
 
   return value;
 }
diff --git a/chrome/browser/chromeos/settings/device_oauth2_token_service.cc b/chrome/browser/chromeos/settings/device_oauth2_token_service.cc
index 2e63102..adcf750 100644
--- a/chrome/browser/chromeos/settings/device_oauth2_token_service.cc
+++ b/chrome/browser/chromeos/settings/device_oauth2_token_service.cc
@@ -193,13 +193,18 @@
   token_service_->OnValidationComplete(token_is_valid_);
   // Note: this object (which is also the Request instance) may be deleted in
   // these consumer callbacks, so the callbacks must be the last line executed.
+  // Also, make copies of the parameters passed to the consumer to avoid invalid
+  // memory accesses when the consumer deletes |this| immediately.
   if (!token_is_valid_) {
     consumer_->OnGetTokenFailure(this, GoogleServiceAuthError(
         GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS));
   } else if (error_) {
-    consumer_->OnGetTokenFailure(this, *error_.get());
+    GoogleServiceAuthError error_copy = *error_;
+    consumer_->OnGetTokenFailure(this, error_copy);
   } else {
-    consumer_->OnGetTokenSuccess(this, access_token_, expiration_time_);
+    std::string access_token_copy = access_token_;
+    base::Time expiration_time_copy = expiration_time_;
+    consumer_->OnGetTokenSuccess(this, access_token_copy, expiration_time_copy);
   }
 }
 
diff --git a/chrome/browser/chromeos/status/network_menu.cc b/chrome/browser/chromeos/status/network_menu.cc
index 980af04..2701f92 100644
--- a/chrome/browser/chromeos/status/network_menu.cc
+++ b/chrome/browser/chromeos/status/network_menu.cc
@@ -8,6 +8,7 @@
 
 #include "ash/shell.h"
 #include "ash/shell_delegate.h"
+#include "ash/system/chromeos/network/network_connect.h"
 #include "ash/system/chromeos/network/network_icon.h"
 #include "base/bind.h"
 #include "base/logging.h"
@@ -17,7 +18,6 @@
 #include "chrome/browser/chromeos/login/user_manager.h"
 #include "chrome/browser/chromeos/mobile_config.h"
 #include "chrome/browser/chromeos/options/network_config_view.h"
-#include "chrome/browser/chromeos/options/network_connect.h"
 #include "chrome/browser/defaults.h"
 #include "chrome/browser/profiles/profile_manager.h"
 #include "chrome/common/url_constants.h"
@@ -219,17 +219,9 @@
 
 void NetworkMenuModel::ConnectToNetworkAt(int index) {
   const std::string& service_path = menu_items_[index].service_path;
-  network_connect::ConnectResult result =
-      network_connect::ConnectToNetwork(
-          service_path, owner_->delegate()->GetNativeWindow());
+  gfx::NativeWindow native_window = owner_->delegate()->GetNativeWindow();
+  ash::network_connect::ConnectToNetwork(service_path, native_window);
   owner_->delegate()->OnConnectToNetworkRequested(service_path);
-  if (result == network_connect::NETWORK_NOT_FOUND) {
-    // If we are attempting to connect to a network that no longer exists,
-    // display a notification.
-    LOG(WARNING) << "Network does not exist to connect to: "
-                 << service_path;
-    // TODO(stevenjb): Show notification.
-  }
 }
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -350,7 +342,7 @@
   if (type == flimflam::kTypeCellular)
     ChooseMobileNetworkDialog::ShowDialog(native_window);
   else
-    NetworkConfigView::ShowForType(chromeos::TYPE_WIFI, native_window);
+    NetworkConfigView::ShowForType(flimflam::kTypeWifi, native_window);
 }
 
 ////////////////////////////////////////////////////////////////////////////////
diff --git a/chrome/browser/chromeos/system/ash_system_tray_delegate.cc b/chrome/browser/chromeos/system/ash_system_tray_delegate.cc
index 764b81e..eb0b9a7 100644
--- a/chrome/browser/chromeos/system/ash_system_tray_delegate.cc
+++ b/chrome/browser/chromeos/system/ash_system_tray_delegate.cc
@@ -72,6 +72,7 @@
 #include "chrome/browser/chromeos/system/timezone_settings.h"
 #include "chrome/browser/chromeos/system_key_event_listener.h"
 #include "chrome/browser/drive/drive_service_interface.h"
+#include "chrome/browser/feedback/tracing_manager.h"
 #include "chrome/browser/google/google_util.h"
 #include "chrome/browser/lifetime/application_lifetime.h"
 #include "chrome/browser/policy/browser_policy_connector.h"
@@ -463,8 +464,9 @@
   virtual const string16 GetLocallyManagedUserMessage() const OVERRIDE {
     if (GetUserLoginStatus() != ash::user::LOGGED_IN_LOCALLY_MANAGED)
         return string16();
-    return l10n_util::GetStringFUTF16(IDS_USER_IS_LOCALLY_MANAGED_BY_NOTICE,
-                                      GetLocallyManagedUserManagerName());
+    return l10n_util::GetStringFUTF16(
+        IDS_USER_IS_LOCALLY_MANAGED_BY_NOTICE,
+        UTF8ToUTF16(GetLocallyManagedUserManager()));
   }
 
   virtual bool SystemShouldUpgrade() const OVERRIDE {
@@ -489,24 +491,7 @@
   virtual void ShowNetworkSettings(const std::string& service_path) OVERRIDE {
     if (!LoginState::Get()->IsUserLoggedIn())
       return;
-
-    std::string page = chrome::kInternetOptionsSubPage;
-    const chromeos::NetworkState* network = service_path.empty() ? NULL :
-        NetworkHandler::Get()->network_state_handler()->GetNetworkState(
-            service_path);
-    if (network) {
-      std::string name(network->name());
-      if (name.empty() && network->type() == flimflam::kTypeEthernet)
-        name = l10n_util::GetStringUTF8(IDS_STATUSBAR_NETWORK_DEVICE_ETHERNET);
-      page += base::StringPrintf(
-          "?servicePath=%s&networkType=%s&networkName=%s",
-          net::EscapeUrlEncodedData(service_path, true).c_str(),
-          net::EscapeUrlEncodedData(network->type(), true).c_str(),
-          net::EscapeUrlEncodedData(name, false).c_str());
-    }
-    content::RecordAction(
-        content::UserMetricsAction("OpenInternetOptionsDialog"));
-    chrome::ShowSettingsSubPage(GetAppropriateBrowser(), page);
+    network_connect::ShowNetworkSettings(service_path);
   }
 
   virtual void ShowBluetoothSettings() OVERRIDE {
@@ -519,6 +504,10 @@
                                 kDisplaySettingsSubPageName);
   }
 
+  virtual void ShowChromeSlow() OVERRIDE {
+    chrome::ShowSlow(GetAppropriateBrowser());
+  }
+
   virtual bool ShouldShowDisplayNotification() OVERRIDE {
     // Packaged app is not counted as 'last active', so if a browser opening the
     // display settings is in background of a packaged app, it will return true.
@@ -767,15 +756,12 @@
     network_connect::HandleUnconfiguredNetwork(network_id, GetNativeWindow());
   }
 
-  virtual void ConnectToNetwork(const std::string& network_id) OVERRIDE {
-    DCHECK(!CommandLine::ForCurrentProcess()->HasSwitch(
-        chromeos::switches::kUseNewNetworkConnectionHandler));
-    network_connect::ConnectResult result =
-        network_connect::ConnectToNetwork(network_id, GetNativeWindow());
-    if (result == network_connect::NETWORK_NOT_FOUND)
-      ShowNetworkSettings("");
-    else if (result == network_connect::CONNECT_NOT_STARTED)
-      ShowNetworkSettings(network_id);
+  virtual void EnrollOrConfigureNetwork(
+      const std::string& network_id,
+      gfx::NativeWindow parent_window) OVERRIDE {
+    if (network_connect::EnrollNetwork(network_id, parent_window))
+      return;
+    network_connect::HandleUnconfiguredNetwork(network_id, parent_window);
   }
 
   virtual void ManageBluetoothDevices() OVERRIDE {
@@ -797,12 +783,16 @@
                                   SimDialogDelegate::SIM_DIALOG_UNLOCK);
   }
 
+  virtual void ShowMobileSetup(const std::string& network_id) OVERRIDE {
+    network_connect::ShowMobileSetup(network_id);
+  }
+
   virtual void ShowOtherWifi() OVERRIDE {
-    NetworkConfigView::ShowForType(chromeos::TYPE_WIFI, GetNativeWindow());
+    NetworkConfigView::ShowForType(flimflam::kTypeWifi, GetNativeWindow());
   }
 
   virtual void ShowOtherVPN() OVERRIDE {
-    NetworkConfigView::ShowForType(chromeos::TYPE_VPN, GetNativeWindow());
+    NetworkConfigView::ShowForType(flimflam::kTypeVPN, GetNativeWindow());
   }
 
   virtual void ShowOtherCellular() OVERRIDE {
@@ -943,9 +933,14 @@
         base::Bind(&SystemTrayDelegate::OnAccessibilityModeChanged,
                    base::Unretained(this),
                    ash::A11Y_NOTIFICATION_NONE));
+    user_pref_registrar_->Add(
+        prefs::kPerformanceTracingEnabled,
+        base::Bind(&SystemTrayDelegate::UpdatePerformanceTracing,
+                   base::Unretained(this)));
 
     UpdateClockType();
     UpdateShowLogoutButtonInTray();
+    UpdatePerformanceTracing();
     search_key_mapped_to_ =
         profile->GetPrefs()->GetInteger(prefs::kLanguageRemapSearchKeyTo);
   }
@@ -1162,6 +1157,15 @@
     GetSystemTrayNotifier()->NotifyAccessibilityModeChanged(notify);
   }
 
+  void UpdatePerformanceTracing() {
+    if (!user_pref_registrar_)
+      return;
+    bool value =
+        user_pref_registrar_->prefs()->GetBoolean(
+            prefs::kPerformanceTracingEnabled);
+    GetSystemTrayNotifier()->NotifyTracingModeChanged(value);
+  }
+
   // Overridden from InputMethodManager::Observer.
   virtual void InputMethodChanged(
       input_method::InputMethodManager* manager, bool show_message) OVERRIDE {
@@ -1252,10 +1256,12 @@
       ash::NetworkObserver::MessageType message_type,
       size_t link_index) OVERRIDE {
     if (message_type == ash::NetworkObserver::ERROR_OUT_OF_CREDITS) {
-      const CellularNetwork* cellular =
-          NetworkLibrary::Get()->cellular_network();
-      if (cellular)
-        ConnectToNetwork(cellular->service_path());
+      const NetworkState* cellular =
+          NetworkHandler::Get()->network_state_handler()->
+          FirstNetworkByType(flimflam::kTypeCellular);
+      std::string service_path = cellular ? cellular->path() : "";
+      ShowNetworkSettings(service_path);
+
       ash::Shell::GetInstance()->system_tray_notifier()->
           NotifyClearNetworkMessage(message_type);
     }
diff --git a/chrome/browser/chromeos/system_logs/about_system_logs_fetcher.cc b/chrome/browser/chromeos/system_logs/about_system_logs_fetcher.cc
new file mode 100644
index 0000000..e519ddb
--- /dev/null
+++ b/chrome/browser/chromeos/system_logs/about_system_logs_fetcher.cc
@@ -0,0 +1,43 @@
+// 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/system_logs/about_system_logs_fetcher.h"
+
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "chrome/browser/chromeos/system_logs/chrome_internal_log_source.h"
+#include "chrome/browser/chromeos/system_logs/command_line_log_source.h"
+#include "chrome/browser/chromeos/system_logs/dbus_log_source.h"
+#include "chrome/browser/chromeos/system_logs/debug_daemon_log_source.h"
+#include "chrome/browser/chromeos/system_logs/lsb_release_log_source.h"
+#include "chrome/browser/chromeos/system_logs/memory_details_log_source.h"
+#include "chrome/browser/chromeos/system_logs/network_event_log_source.h"
+#include "chrome/browser/chromeos/system_logs/touch_log_source.h"
+#include "content/public/browser/browser_thread.h"
+
+using content::BrowserThread;
+
+namespace chromeos {
+
+AboutSystemLogsFetcher::AboutSystemLogsFetcher() {
+  // Debug Daemon data source.
+  const bool scrub_data = false;
+  data_sources_.push_back(new DebugDaemonLogSource(scrub_data));
+
+  // Chrome data sources.
+  data_sources_.push_back(new ChromeInternalLogSource());
+  data_sources_.push_back(new CommandLineLogSource());
+  data_sources_.push_back(new DBusLogSource());
+  data_sources_.push_back(new LsbReleaseLogSource());
+  data_sources_.push_back(new MemoryDetailsLogSource());
+  data_sources_.push_back(new NetworkEventLogSource());
+  data_sources_.push_back(new TouchLogSource());
+
+  num_pending_requests_ = data_sources_.size();
+}
+
+AboutSystemLogsFetcher::~AboutSystemLogsFetcher() {
+}
+
+}  // namespace chromeos
diff --git a/chrome/browser/chromeos/system_logs/about_system_logs_fetcher.h b/chrome/browser/chromeos/system_logs/about_system_logs_fetcher.h
new file mode 100644
index 0000000..3c6d9ad
--- /dev/null
+++ b/chrome/browser/chromeos/system_logs/about_system_logs_fetcher.h
@@ -0,0 +1,27 @@
+// 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_SYSTEM_LOGS_ABOUT_SYSTEM_LOGS_FETCHER_H_
+#define CHROME_BROWSER_CHROMEOS_SYSTEM_LOGS_ABOUT_SYSTEM_LOGS_FETCHER_H_
+
+#include "chrome/browser/chromeos/system_logs/system_logs_fetcher_base.h"
+
+namespace chromeos {
+
+// The AboutAboutSystemLogsFetcher aggregates the unscrubbed logs for display
+// in the about:system page.
+class AboutSystemLogsFetcher : public SystemLogsFetcherBase {
+ public:
+  AboutSystemLogsFetcher();
+  ~AboutSystemLogsFetcher();
+
+ private:
+
+  DISALLOW_COPY_AND_ASSIGN(AboutSystemLogsFetcher);
+};
+
+}  // namespace chromeos
+
+#endif  // CHROME_BROWSER_CHROMEOS_SYSTEM_LOGS_ABOUT_SYSTEM_LOGS_FETCHER_H_
+
diff --git a/chrome/browser/chromeos/system_logs/chrome_internal_log_source.cc b/chrome/browser/chromeos/system_logs/chrome_internal_log_source.cc
index 9370a61..f368097 100644
--- a/chrome/browser/chromeos/system_logs/chrome_internal_log_source.cc
+++ b/chrome/browser/chromeos/system_logs/chrome_internal_log_source.cc
@@ -7,7 +7,6 @@
 #include "base/json/json_string_value_serializer.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/chromeos/settings/cros_settings.h"
-#include "chrome/browser/chromeos/system_logs/system_logs_fetcher.h"
 #include "chrome/browser/extensions/extension_service.h"
 #include "chrome/browser/extensions/extension_system.h"
 #include "chrome/browser/profiles/profile_manager.h"
diff --git a/chrome/browser/chromeos/system_logs/chrome_internal_log_source.h b/chrome/browser/chromeos/system_logs/chrome_internal_log_source.h
index 268a3ab..1aa6546 100644
--- a/chrome/browser/chromeos/system_logs/chrome_internal_log_source.h
+++ b/chrome/browser/chromeos/system_logs/chrome_internal_log_source.h
@@ -5,7 +5,7 @@
 #ifndef CHROME_BROWSER_CHROMEOS_SYSTEM_LOGS_CHROME_INTERNAL_LOG_SOURCE_H_
 #define CHROME_BROWSER_CHROMEOS_SYSTEM_LOGS_CHROME_INTERNAL_LOG_SOURCE_H_
 
-#include "chrome/browser/chromeos/system_logs/system_logs_fetcher.h"
+#include "chrome/browser/chromeos/system_logs/system_logs_fetcher_base.h"
 
 namespace chromeos {
 
diff --git a/chrome/browser/chromeos/system_logs/command_line_log_source.cc b/chrome/browser/chromeos/system_logs/command_line_log_source.cc
index 43b7651..fe1a352 100644
--- a/chrome/browser/chromeos/system_logs/command_line_log_source.cc
+++ b/chrome/browser/chromeos/system_logs/command_line_log_source.cc
@@ -33,6 +33,16 @@
   command.AppendArg("--dump_server_info");
   commands.push_back(std::make_pair("cras", command));
 
+  command = CommandLine((base::FilePath("/usr/bin/cras_test_client")));
+  command.AppendArg("--loopback_file");
+  command.AppendArg("/dev/null");
+  command.AppendArg("--rate");
+  command.AppendArg("44100");
+  command.AppendArg("--duration_seconds");
+  command.AppendArg("0.01");
+  command.AppendArg("--show_total_rms");
+  commands.push_back(std::make_pair("cras_rms", command));
+
   command = CommandLine((base::FilePath("/usr/bin/printenv")));
   commands.push_back(std::make_pair("env", command));
 
diff --git a/chrome/browser/chromeos/system_logs/command_line_log_source.h b/chrome/browser/chromeos/system_logs/command_line_log_source.h
index 4ddee4f..4dc9a98 100644
--- a/chrome/browser/chromeos/system_logs/command_line_log_source.h
+++ b/chrome/browser/chromeos/system_logs/command_line_log_source.h
@@ -5,7 +5,7 @@
 #ifndef CHROME_BROWSER_CHROMEOS_SYSTEM_LOGS_COMMAND_LINE_LOG_SOURCE_H_
 #define CHROME_BROWSER_CHROMEOS_SYSTEM_LOGS_COMMAND_LINE_LOG_SOURCE_H_
 
-#include "chrome/browser/chromeos/system_logs/system_logs_fetcher.h"
+#include "chrome/browser/chromeos/system_logs/system_logs_fetcher_base.h"
 
 namespace chromeos {
 
diff --git a/chrome/browser/chromeos/system_logs/dbus_log_source.cc b/chrome/browser/chromeos/system_logs/dbus_log_source.cc
index 8f92518..861f724 100644
--- a/chrome/browser/chromeos/system_logs/dbus_log_source.cc
+++ b/chrome/browser/chromeos/system_logs/dbus_log_source.cc
@@ -4,7 +4,6 @@
 
 #include "chrome/browser/chromeos/system_logs/dbus_log_source.h"
 
-#include "chrome/browser/chromeos/system_logs/system_logs_fetcher.h"
 #include "content/public/browser/browser_thread.h"
 #include "dbus/dbus_statistics.h"
 
diff --git a/chrome/browser/chromeos/system_logs/dbus_log_source.h b/chrome/browser/chromeos/system_logs/dbus_log_source.h
index 810368d..622aa56 100644
--- a/chrome/browser/chromeos/system_logs/dbus_log_source.h
+++ b/chrome/browser/chromeos/system_logs/dbus_log_source.h
@@ -5,7 +5,7 @@
 #ifndef CHROME_BROWSER_CHROMEOS_SYSTEM_LOGS_DBUS_LOG_SOURCE_H_
 #define CHROME_BROWSER_CHROMEOS_SYSTEM_LOGS_DBUS_LOG_SOURCE_H_
 
-#include "chrome/browser/chromeos/system_logs/system_logs_fetcher.h"
+#include "chrome/browser/chromeos/system_logs/system_logs_fetcher_base.h"
 
 namespace chromeos {
 
diff --git a/chrome/browser/chromeos/system_logs/debug_daemon_log_source.cc b/chrome/browser/chromeos/system_logs/debug_daemon_log_source.cc
index feb1d8f..8a8aeb5 100644
--- a/chrome/browser/chromeos/system_logs/debug_daemon_log_source.cc
+++ b/chrome/browser/chromeos/system_logs/debug_daemon_log_source.cc
@@ -12,7 +12,6 @@
 #include "base/memory/weak_ptr.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_util.h"
-#include "chrome/browser/chromeos/system_logs/system_logs_fetcher.h"
 #include "chrome/browser/profiles/profile_manager.h"
 #include "chrome/common/chrome_switches.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
@@ -28,9 +27,10 @@
 
 namespace chromeos {
 
-DebugDaemonLogSource::DebugDaemonLogSource()
+DebugDaemonLogSource::DebugDaemonLogSource(bool scrub)
     : response_(new SystemLogsResponse()),
       num_pending_requests_(0),
+      scrub_(scrub),
       weak_ptr_factory_(this) {}
 
 DebugDaemonLogSource::~DebugDaemonLogSource() {}
@@ -57,12 +57,18 @@
   client->GetWiMaxStatus(base::Bind(&DebugDaemonLogSource::OnGetWiMaxStatus,
                                     weak_ptr_factory_.GetWeakPtr()));
   ++num_pending_requests_;
-  client->GetAllLogs(base::Bind(&DebugDaemonLogSource::OnGetLogs,
-                                weak_ptr_factory_.GetWeakPtr()));
-  ++num_pending_requests_;
   client->GetUserLogFiles(base::Bind(&DebugDaemonLogSource::OnGetUserLogFiles,
                                      weak_ptr_factory_.GetWeakPtr()));
   ++num_pending_requests_;
+
+  if (scrub_) {
+    client->GetScrubbedLogs(base::Bind(&DebugDaemonLogSource::OnGetLogs,
+                                       weak_ptr_factory_.GetWeakPtr()));
+  } else {
+    client->GetAllLogs(base::Bind(&DebugDaemonLogSource::OnGetLogs,
+                                  weak_ptr_factory_.GetWeakPtr()));
+  }
+  ++num_pending_requests_;
 }
 
 void DebugDaemonLogSource::OnGetRoutes(bool succeeded,
diff --git a/chrome/browser/chromeos/system_logs/debug_daemon_log_source.h b/chrome/browser/chromeos/system_logs/debug_daemon_log_source.h
index 8d1626c..e68e60d 100644
--- a/chrome/browser/chromeos/system_logs/debug_daemon_log_source.h
+++ b/chrome/browser/chromeos/system_logs/debug_daemon_log_source.h
@@ -10,14 +10,14 @@
 #include <vector>
 
 #include "base/memory/weak_ptr.h"
-#include "chrome/browser/chromeos/system_logs/system_logs_fetcher.h"
+#include "chrome/browser/chromeos/system_logs/system_logs_fetcher_base.h"
 
 namespace chromeos {
 
 // Gathers log data from Debug Daemon.
 class DebugDaemonLogSource : public SystemLogsSource {
  public:
-  DebugDaemonLogSource();
+  explicit DebugDaemonLogSource(bool scrub);
   virtual ~DebugDaemonLogSource();
 
   // SystemLogsSource override:
@@ -49,6 +49,7 @@
   scoped_ptr<SystemLogsResponse> response_;
   SysLogsSourceCallback callback_;
   int num_pending_requests_;
+  bool scrub_;
   base::WeakPtrFactory<DebugDaemonLogSource> weak_ptr_factory_;
 
   DISALLOW_COPY_AND_ASSIGN(DebugDaemonLogSource);
diff --git a/chrome/browser/chromeos/system_logs/lsb_release_log_source.h b/chrome/browser/chromeos/system_logs/lsb_release_log_source.h
index 8680fc2..146c7532 100644
--- a/chrome/browser/chromeos/system_logs/lsb_release_log_source.h
+++ b/chrome/browser/chromeos/system_logs/lsb_release_log_source.h
@@ -4,7 +4,7 @@
 #ifndef CHROME_BROWSER_CHROMEOS_SYSTEM_LOGS_LSB_RELEASE_LOG_SOURCE_H_
 #define CHROME_BROWSER_CHROMEOS_SYSTEM_LOGS_LSB_RELEASE_LOG_SOURCE_H_
 
-#include "chrome/browser/chromeos/system_logs/system_logs_fetcher.h"
+#include "chrome/browser/chromeos/system_logs/system_logs_fetcher_base.h"
 
 namespace chromeos {
 
diff --git a/chrome/browser/chromeos/system_logs/memory_details_log_source.cc b/chrome/browser/chromeos/system_logs/memory_details_log_source.cc
index 75680cd..6618563 100644
--- a/chrome/browser/chromeos/system_logs/memory_details_log_source.cc
+++ b/chrome/browser/chromeos/system_logs/memory_details_log_source.cc
@@ -4,7 +4,6 @@
 
 #include "chrome/browser/chromeos/system_logs/memory_details_log_source.h"
 
-#include "chrome/browser/chromeos/system_logs/system_logs_fetcher.h"
 #include "chrome/browser/memory_details.h"
 #include "content/public/browser/browser_thread.h"
 
diff --git a/chrome/browser/chromeos/system_logs/memory_details_log_source.h b/chrome/browser/chromeos/system_logs/memory_details_log_source.h
index c716eb5..777c576 100644
--- a/chrome/browser/chromeos/system_logs/memory_details_log_source.h
+++ b/chrome/browser/chromeos/system_logs/memory_details_log_source.h
@@ -5,7 +5,7 @@
 #ifndef CHROME_BROWSER_CHROMEOS_SYSTEM_LOGS_MEMORY_DETAILS_LOG_SOURCE_H_
 #define CHROME_BROWSER_CHROMEOS_SYSTEM_LOGS_MEMORY_DETAILS_LOG_SOURCE_H_
 
-#include "chrome/browser/chromeos/system_logs/system_logs_fetcher.h"
+#include "chrome/browser/chromeos/system_logs/system_logs_fetcher_base.h"
 
 namespace chromeos {
 
diff --git a/chrome/browser/chromeos/system_logs/network_event_log_source.cc b/chrome/browser/chromeos/system_logs/network_event_log_source.cc
index a0e214f..76c743b 100644
--- a/chrome/browser/chromeos/system_logs/network_event_log_source.cc
+++ b/chrome/browser/chromeos/system_logs/network_event_log_source.cc
@@ -5,7 +5,6 @@
 #include "chrome/browser/chromeos/system_logs/network_event_log_source.h"
 
 #include "base/message_loop/message_loop.h"
-#include "chrome/browser/chromeos/system_logs/system_logs_fetcher.h"
 #include "chromeos/network/network_event_log.h"
 #include "content/public/browser/browser_thread.h"
 
diff --git a/chrome/browser/chromeos/system_logs/network_event_log_source.h b/chrome/browser/chromeos/system_logs/network_event_log_source.h
index 0c4e5e7..6df6e9a 100644
--- a/chrome/browser/chromeos/system_logs/network_event_log_source.h
+++ b/chrome/browser/chromeos/system_logs/network_event_log_source.h
@@ -5,7 +5,7 @@
 #ifndef CHROME_BROWSER_CHROMEOS_SYSTEM_LOGS_NETWORK_EVENT_LOG_SOURCE_H_
 #define CHROME_BROWSER_CHROMEOS_SYSTEM_LOGS_NETWORK_EVENT_LOG_SOURCE_H_
 
-#include "chrome/browser/chromeos/system_logs/system_logs_fetcher.h"
+#include "chrome/browser/chromeos/system_logs/system_logs_fetcher_base.h"
 
 namespace chromeos {
 
diff --git a/chrome/browser/chromeos/system_logs/scrubbed_system_logs_fetcher.cc b/chrome/browser/chromeos/system_logs/scrubbed_system_logs_fetcher.cc
new file mode 100644
index 0000000..5845c13
--- /dev/null
+++ b/chrome/browser/chromeos/system_logs/scrubbed_system_logs_fetcher.cc
@@ -0,0 +1,43 @@
+// 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/system_logs/scrubbed_system_logs_fetcher.h"
+
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "chrome/browser/chromeos/system_logs/chrome_internal_log_source.h"
+#include "chrome/browser/chromeos/system_logs/command_line_log_source.h"
+#include "chrome/browser/chromeos/system_logs/dbus_log_source.h"
+#include "chrome/browser/chromeos/system_logs/debug_daemon_log_source.h"
+#include "chrome/browser/chromeos/system_logs/lsb_release_log_source.h"
+#include "chrome/browser/chromeos/system_logs/memory_details_log_source.h"
+#include "chrome/browser/chromeos/system_logs/network_event_log_source.h"
+#include "chrome/browser/chromeos/system_logs/touch_log_source.h"
+#include "content/public/browser/browser_thread.h"
+
+using content::BrowserThread;
+
+namespace chromeos {
+
+ScrubbedSystemLogsFetcher::ScrubbedSystemLogsFetcher() {
+  // Debug Daemon data source.
+  const bool scrub_data = true;
+  data_sources_.push_back(new DebugDaemonLogSource(scrub_data));
+
+  // Chrome data sources.
+  data_sources_.push_back(new ChromeInternalLogSource());
+  data_sources_.push_back(new CommandLineLogSource());
+  data_sources_.push_back(new DBusLogSource());
+  data_sources_.push_back(new LsbReleaseLogSource());
+  data_sources_.push_back(new MemoryDetailsLogSource());
+  data_sources_.push_back(new NetworkEventLogSource());
+  data_sources_.push_back(new TouchLogSource());
+
+  num_pending_requests_ = data_sources_.size();
+}
+
+ScrubbedSystemLogsFetcher::~ScrubbedSystemLogsFetcher() {
+}
+
+}  // namespace chromeos
diff --git a/chrome/browser/chromeos/system_logs/scrubbed_system_logs_fetcher.h b/chrome/browser/chromeos/system_logs/scrubbed_system_logs_fetcher.h
new file mode 100644
index 0000000..7d47151
--- /dev/null
+++ b/chrome/browser/chromeos/system_logs/scrubbed_system_logs_fetcher.h
@@ -0,0 +1,29 @@
+// 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_SYSTEM_LOGS_SCRUBBED_SYSTEM_LOGS_FETCHER_H_
+#define CHROME_BROWSER_CHROMEOS_SYSTEM_LOGS_SCRUBBED_SYSTEM_LOGS_FETCHER_H_
+
+#include "chrome/browser/chromeos/system_logs/system_logs_fetcher_base.h"
+
+namespace chromeos {
+
+// The ScrubbedSystemLogsFetcher aggregates the scrubbed logs for sending
+// with feedback reports.
+// TODO: This class needs to be expanded to provide better scrubbing of
+// system logs.
+class ScrubbedSystemLogsFetcher : public SystemLogsFetcherBase {
+ public:
+  ScrubbedSystemLogsFetcher();
+  ~ScrubbedSystemLogsFetcher();
+
+ private:
+
+  DISALLOW_COPY_AND_ASSIGN(ScrubbedSystemLogsFetcher);
+};
+
+}  // namespace chromeos
+
+#endif  // CHROME_BROWSER_CHROMEOS_SYSTEM_LOGS_SCRUBBED_SYSTEM_LOGS_FETCHER_H_
+
diff --git a/chrome/browser/chromeos/system_logs/system_logs_fetcher.cc b/chrome/browser/chromeos/system_logs/system_logs_fetcher_base.cc
similarity index 61%
rename from chrome/browser/chromeos/system_logs/system_logs_fetcher.cc
rename to chrome/browser/chromeos/system_logs/system_logs_fetcher_base.cc
index e34c06d..09a177b 100644
--- a/chrome/browser/chromeos/system_logs/system_logs_fetcher.cc
+++ b/chrome/browser/chromeos/system_logs/system_logs_fetcher_base.cc
@@ -1,8 +1,8 @@
-// Copyright (c) 2012 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.
 
-#include "chrome/browser/chromeos/system_logs/system_logs_fetcher.h"
+#include "chrome/browser/chromeos/system_logs/system_logs_fetcher_base.h"
 
 #include "base/bind.h"
 #include "base/bind_helpers.h"
@@ -20,40 +20,26 @@
 
 namespace chromeos {
 
-SystemLogsFetcher::SystemLogsFetcher()
+SystemLogsFetcherBase::SystemLogsFetcherBase()
     : response_(new SystemLogsResponse),
-      num_pending_requests_(0),
-      weak_ptr_factory_(this) {
-  // Debug Daemon data source.
-  data_sources_.push_back(new DebugDaemonLogSource());
-
-  // Chrome data sources.
-  data_sources_.push_back(new ChromeInternalLogSource());
-  data_sources_.push_back(new CommandLineLogSource());
-  data_sources_.push_back(new DBusLogSource());
-  data_sources_.push_back(new LsbReleaseLogSource());
-  data_sources_.push_back(new MemoryDetailsLogSource());
-  data_sources_.push_back(new NetworkEventLogSource());
-  data_sources_.push_back(new TouchLogSource());
-
-  num_pending_requests_ = data_sources_.size();
+      num_pending_requests_(0) {
 }
 
-SystemLogsFetcher::~SystemLogsFetcher() {}
+SystemLogsFetcherBase::~SystemLogsFetcherBase() {}
 
-void SystemLogsFetcher::Fetch(const SysLogsFetcherCallback& callback) {
+void SystemLogsFetcherBase::Fetch(const SysLogsFetcherCallback& callback) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
   DCHECK(callback_.is_null());
   DCHECK(!callback.is_null());
 
   callback_ = callback;
   for (size_t i = 0; i < data_sources_.size(); ++i) {
-    data_sources_[i]->Fetch(base::Bind(&SystemLogsFetcher::AddResponse,
-                                       weak_ptr_factory_.GetWeakPtr()));
+    data_sources_[i]->Fetch(base::Bind(&SystemLogsFetcherBase::AddResponse,
+                                       AsWeakPtr()));
   }
 }
 
-void SystemLogsFetcher::AddResponse(SystemLogsResponse* response) {
+void SystemLogsFetcherBase::AddResponse(SystemLogsResponse* response) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
 
   for (SystemLogsResponse::const_iterator it = response->begin();
diff --git a/chrome/browser/chromeos/system_logs/system_logs_fetcher.h b/chrome/browser/chromeos/system_logs/system_logs_fetcher_base.h
similarity index 68%
rename from chrome/browser/chromeos/system_logs/system_logs_fetcher.h
rename to chrome/browser/chromeos/system_logs/system_logs_fetcher_base.h
index 6bd5412..986b678 100644
--- a/chrome/browser/chromeos/system_logs/system_logs_fetcher.h
+++ b/chrome/browser/chromeos/system_logs/system_logs_fetcher_base.h
@@ -1,9 +1,9 @@
-// Copyright (c) 2012 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.
 
-#ifndef CHROME_BROWSER_CHROMEOS_SYSTEM_LOGS_SYSTEM_LOGS_FETCHER_H_
-#define CHROME_BROWSER_CHROMEOS_SYSTEM_LOGS_SYSTEM_LOGS_FETCHER_H_
+#ifndef CHROME_BROWSER_CHROMEOS_SYSTEM_LOGS_SYSTEM_LOGS_FETCHER_BASE_H_
+#define CHROME_BROWSER_CHROMEOS_SYSTEM_LOGS_SYSTEM_LOGS_FETCHER_BASE_H_
 
 #include <map>
 #include <string>
@@ -20,12 +20,12 @@
 typedef base::Callback<void(SystemLogsResponse* response)>
     SysLogsSourceCallback;
 
-// Callback that the SystemLogsFetcher uses to return data.
+// Callback that the SystemLogsFetcherBase uses to return data.
 typedef base::Callback<void(scoped_ptr<SystemLogsResponse> response)>
     SysLogsFetcherCallback;
 
 // The SystemLogsSource provides a interface for the data sources that
-// the SystemLogsFetcher class uses to fetch logs and other
+// the SystemLogsFetcherBase class uses to fetch logs and other
 // information.
 class SystemLogsSource {
  public:
@@ -34,13 +34,9 @@
   virtual ~SystemLogsSource() {}
 };
 
-// The SystemLogsFetcher creates a list of data sources which must be
-// classes that implement the SystemLogsSource. It's Fetch function
-// receives as a parameter a callback that takes only one parameter
-// SystemLogsResponse that is a map of keys and values.
-// Each data source also returns a SystemLogsResponse. If two data sources
-// return the same key, only the first one will be stored.
-// The class runs on the UI thread.
+// The SystemLogsFetcherBaseBase specifies an interface for LogFetcher classes.
+// Derived LogFetcher classes aggregate the logs from a list of SystemLogSource
+// classes.
 //
 // EXAMPLE:
 // class Example {
@@ -49,17 +45,18 @@
 //      //do something with the logs
 //   }
 //   void GetLogs() {
-//     SystemLogsFetcher* fetcher = new SystemLogsFetcher();
+//     SystemLogsFetcherBase* fetcher = new SystemLogsFetcherBase();
 //     fetcher->Fetch(base::Bind(&Example::ProcessLogs, this));
 //   }
-class SystemLogsFetcher {
+class SystemLogsFetcherBase
+    : public base::SupportsWeakPtr<SystemLogsFetcherBase> {
  public:
-  SystemLogsFetcher();
-  ~SystemLogsFetcher();
+  SystemLogsFetcherBase();
+  ~SystemLogsFetcherBase();
 
   void Fetch(const SysLogsFetcherCallback& callback);
 
- private:
+ protected:
   // Callback passed to all the data sources. It merges the |data| it recieves
   // into response_. When all the data sources have responded, it deletes their
   // objects and returns the response to the callback_. After this it
@@ -72,12 +69,12 @@
   scoped_ptr<SystemLogsResponse> response_;  // The actual response data.
   size_t num_pending_requests_;   // The number of callbacks it should get.
 
-  base::WeakPtrFactory<SystemLogsFetcher> weak_ptr_factory_;
+ private:
 
-  DISALLOW_COPY_AND_ASSIGN(SystemLogsFetcher);
+  DISALLOW_COPY_AND_ASSIGN(SystemLogsFetcherBase);
 };
 
 }  // namespace chromeos
 
-#endif  // CHROME_BROWSER_CHROMEOS_SYSTEM_LOGS_SYSTEM_LOGS_FETCHER_H_
+#endif  // CHROME_BROWSER_CHROMEOS_SYSTEM_LOGS_SYSTEM_LOGS_FETCHER_BASE_H_
 
diff --git a/chrome/browser/chromeos/system_logs/touch_log_source.h b/chrome/browser/chromeos/system_logs/touch_log_source.h
index d88816b..42465d3 100644
--- a/chrome/browser/chromeos/system_logs/touch_log_source.h
+++ b/chrome/browser/chromeos/system_logs/touch_log_source.h
@@ -5,7 +5,7 @@
 #ifndef CHROME_BROWSER_CHROMEOS_SYSTEM_LOGS_TOUCH_LOG_SOURCE_H_
 #define CHROME_BROWSER_CHROMEOS_SYSTEM_LOGS_TOUCH_LOG_SOURCE_H_
 
-#include "chrome/browser/chromeos/system_logs/system_logs_fetcher.h"
+#include "chrome/browser/chromeos/system_logs/system_logs_fetcher_base.h"
 
 namespace chromeos {
 
diff --git a/chrome/browser/component_updater/DEPS b/chrome/browser/component_updater/DEPS
index 2c90430..2bac0cf 100644
--- a/chrome/browser/component_updater/DEPS
+++ b/chrome/browser/component_updater/DEPS
@@ -1,4 +1,5 @@
 include_rules = [
   "+ppapi/shared_impl/ppapi_permissions.h",
+  "+ppapi/thunk",
   "+third_party/widevine"
 ]
diff --git a/chrome/browser/component_updater/component_updater_service.cc b/chrome/browser/component_updater/component_updater_service.cc
index f595ba9..1a6f935 100644
--- a/chrome/browser/component_updater/component_updater_service.cc
+++ b/chrome/browser/component_updater/component_updater_service.cc
@@ -22,7 +22,6 @@
 #include "base/strings/stringprintf.h"
 #include "base/timer/timer.h"
 #include "chrome/browser/browser_process.h"
-#include "chrome/browser/chrome_notification_types.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"
@@ -31,7 +30,6 @@
 #include "chrome/common/chrome_version_info.h"
 #include "chrome/common/extensions/extension.h"
 #include "content/public/browser/browser_thread.h"
-#include "content/public/browser/notification_service.h"
 #include "content/public/browser/utility_process_host.h"
 #include "content/public/browser/utility_process_host_client.h"
 #include "net/base/escape.h"
@@ -398,11 +396,6 @@
 
   NotifyComponentObservers(ComponentObserver::COMPONENT_UPDATER_STARTED, 0);
 
-  content::NotificationService::current()->Notify(
-    chrome::NOTIFICATION_COMPONENT_UPDATER_STARTED,
-    content::Source<ComponentUpdateService>(this),
-    content::NotificationService::NoDetails());
-
   timer_.Start(FROM_HERE, base::TimeDelta::FromSeconds(config_->InitialDelay()),
                this, &CrxUpdateService::ProcessPendingItems);
   return kOk;
@@ -439,10 +432,6 @@
   if (!step_delay) {
     NotifyComponentObservers(ComponentObserver::COMPONENT_UPDATER_SLEEPING, 0);
 
-    content::NotificationService::current()->Notify(
-        chrome::NOTIFICATION_COMPONENT_UPDATER_SLEEPING,
-        content::Source<ComponentUpdateService>(this),
-        content::NotificationService::NoDetails());
     // Zero is only used for unit tests.
     if (0 == delay)
       return;
@@ -791,11 +780,6 @@
       crx->component.observer->OnEvent(
           ComponentObserver::COMPONENT_UPDATE_FOUND, 0);
     }
-
-    content::NotificationService::current()->Notify(
-        chrome::NOTIFICATION_COMPONENT_UPDATE_FOUND,
-        content::Source<std::string>(&crx->id),
-        content::NotificationService::NoDetails());
   }
 
   // All the components that are not mentioned in the manifest we
@@ -873,11 +857,6 @@
           ComponentObserver::COMPONENT_UPDATE_READY, 0);
     }
 
-    content::NotificationService::current()->Notify(
-        chrome::NOTIFICATION_COMPONENT_UPDATE_READY,
-        content::Source<std::string>(&context->id),
-        content::NotificationService::NoDetails());
-
     // Why unretained? See comment at top of file.
     BrowserThread::PostDelayedTask(
         BrowserThread::FILE,
diff --git a/chrome/browser/component_updater/pepper_flash_component_installer.cc b/chrome/browser/component_updater/pepper_flash_component_installer.cc
index d9ac58c..e463a8e 100644
--- a/chrome/browser/component_updater/pepper_flash_component_installer.cc
+++ b/chrome/browser/component_updater/pepper_flash_component_installer.cc
@@ -25,6 +25,7 @@
 #include "base/version.h"
 #include "build/build_config.h"
 #include "chrome/browser/component_updater/component_updater_service.h"
+#include "chrome/browser/component_updater/ppapi_utils.h"
 #include "chrome/browser/plugins/plugin_prefs.h"
 #include "chrome/common/chrome_constants.h"
 #include "chrome/common/chrome_paths.h"
@@ -32,11 +33,10 @@
 #include "chrome/common/pepper_flash.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/plugin_service.h"
+#include "content/public/common/content_constants.h"
 #include "content/public/common/pepper_plugin_info.h"
 #include "ppapi/c/private/ppb_pdf.h"
 #include "ppapi/shared_impl/ppapi_permissions.h"
-#include "webkit/common/plugins/ppapi/ppapi_utils.h"
-#include "webkit/plugins/plugin_constants.h"
 
 #include "flapper_version.h"  // In SHARED_INTERMEDIATE_DIR.
 
@@ -125,7 +125,7 @@
 // Returns true if the Pepper |interface_name| is implemented  by this browser.
 // It does not check if the interface is proxied.
 bool SupportsPepperInterface(const char* interface_name) {
-  if (webkit::ppapi::IsSupportedPepperInterface(interface_name))
+  if (IsSupportedPepperInterface(interface_name))
     return true;
   // The PDF interface is invisible to SupportsInterface() on the browser
   // process because it is provided using PpapiInterfaceFactoryManager. We need
@@ -147,22 +147,22 @@
   plugin_info->is_internal = false;
   plugin_info->is_out_of_process = out_of_process;
   plugin_info->path = flash_path;
-  plugin_info->name = kFlashPluginName;
+  plugin_info->name = content::kFlashPluginName;
   plugin_info->permissions = kPepperFlashPermissions;
 
   // The description is like "Shockwave Flash 10.2 r154".
   plugin_info->description = base::StringPrintf("%s %d.%d r%d",
-      kFlashPluginName, ver_nums[0], ver_nums[1], ver_nums[2]);
+      content::kFlashPluginName, ver_nums[0], ver_nums[1], ver_nums[2]);
 
   plugin_info->version = flash_version.GetString();
 
-  content::WebPluginMimeType swf_mime_type(kFlashPluginSwfMimeType,
-                                           kFlashPluginSwfExtension,
-                                           kFlashPluginName);
+  content::WebPluginMimeType swf_mime_type(content::kFlashPluginSwfMimeType,
+                                           content::kFlashPluginSwfExtension,
+                                           content::kFlashPluginName);
   plugin_info->mime_types.push_back(swf_mime_type);
-  content::WebPluginMimeType spl_mime_type(kFlashPluginSplMimeType,
-                                           kFlashPluginSplExtension,
-                                           kFlashPluginName);
+  content::WebPluginMimeType spl_mime_type(content::kFlashPluginSplMimeType,
+                                           content::kFlashPluginSplExtension,
+                                           content::kFlashPluginName);
   plugin_info->mime_types.push_back(spl_mime_type);
   return true;
 }
diff --git a/webkit/common/plugins/ppapi/ppapi_utils.cc b/chrome/browser/component_updater/ppapi_utils.cc
similarity index 97%
rename from webkit/common/plugins/ppapi/ppapi_utils.cc
rename to chrome/browser/component_updater/ppapi_utils.cc
index 619b03d..1de518c 100644
--- a/webkit/common/plugins/ppapi/ppapi_utils.cc
+++ b/chrome/browser/component_updater/ppapi_utils.cc
@@ -1,7 +1,7 @@
 // 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 "webkit/common/plugins/ppapi/ppapi_utils.h"
+#include "chrome/browser/component_updater/ppapi_utils.h"
 
 #include <cstring>
 
@@ -105,9 +105,6 @@
 #include "ppapi/c/trusted/ppb_url_loader_trusted.h"
 #include "ppapi/thunk/thunk.h"
 
-namespace webkit {
-namespace ppapi {
-
 bool IsSupportedPepperInterface(const char* name) {
   // TODO(brettw) put these in a hash map for better performance.
   #define UNPROXIED_IFACE(api_name, iface_str, iface_struct) \
@@ -134,6 +131,3 @@
   #undef LEGACY_IFACE
   return false;
 }
-
-}  // namespace ppapi
-}  // namespace webkit
diff --git a/chrome/browser/component_updater/ppapi_utils.h b/chrome/browser/component_updater/ppapi_utils.h
new file mode 100644
index 0000000..41100eb
--- /dev/null
+++ b/chrome/browser/component_updater/ppapi_utils.h
@@ -0,0 +1,14 @@
+// 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_COMPONENT_UPDATER_PPAPI_UTILS_H_
+#define CHROME_BROWSER_COMPONENT_UPDATER_PPAPI_UTILS_H_
+
+// Returns true if the interface name passed in is supported by the
+// browser.
+bool IsSupportedPepperInterface(const char* name);
+
+#endif  // CHROME_BROWSER_COMPONENT_UPDATER_PPAPI_UTILS_H_
+
+
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 82165b6..0f1512f 100644
--- a/chrome/browser/component_updater/test/component_updater_service_unittest.cc
+++ b/chrome/browser/component_updater/test/component_updater_service_unittest.cc
@@ -10,11 +10,9 @@
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/stringprintf.h"
 #include "base/values.h"
-#include "chrome/browser/chrome_notification_types.h"
 #include "chrome/browser/component_updater/component_updater_service.h"
 #include "chrome/browser/component_updater/test/test_installer.h"
 #include "chrome/common/chrome_paths.h"
-#include "content/public/browser/notification_service.h"
 #include "content/test/net/url_request_prepackaged_interceptor.h"
 #include "libxml/globals.h"
 #include "net/base/upload_bytes_element_reader.h"
@@ -22,7 +20,6 @@
 #include "url/gurl.h"
 
 using content::BrowserThread;
-using content::TestNotificationTracker;
 
 using ::testing::_;
 using ::testing::InSequence;
@@ -145,18 +142,6 @@
   PathService::Get(chrome::DIR_TEST_DATA, &test_data_dir_);
   test_data_dir_ = test_data_dir_.AppendASCII("components");
 
-  // Subscribe to all component updater notifications.
-  const int notifications[] = {
-    chrome::NOTIFICATION_COMPONENT_UPDATER_STARTED,
-    chrome::NOTIFICATION_COMPONENT_UPDATER_SLEEPING,
-    chrome::NOTIFICATION_COMPONENT_UPDATE_FOUND,
-    chrome::NOTIFICATION_COMPONENT_UPDATE_READY
-  };
-
-  for (int ix = 0; ix != arraysize(notifications); ++ix) {
-    notification_tracker_.ListenFor(
-        notifications[ix], content::NotificationService::AllSources());
-  }
   net::URLFetcher::SetEnableInterceptionForTests(true);
 
   io_thread_.StartIOThread();
@@ -180,10 +165,6 @@
   return test_data_dir_.AppendASCII(file);
 }
 
-TestNotificationTracker& ComponentUpdaterTest::notification_tracker() {
-  return notification_tracker_;
-}
-
 TestConfigurator* ComponentUpdaterTest::test_configurator() {
   return test_config_;
 }
@@ -254,18 +235,14 @@
 // be created and destroyed with no side effects.
 TEST_F(ComponentUpdaterTest, VerifyFixture) {
   EXPECT_TRUE(component_updater() != NULL);
-  EXPECT_EQ(0ul, notification_tracker().size());
 }
 
 // Verify that the component updater can be caught in a quick
-// start-shutdown situation. Failure of this test will be a crash. Also
-// if there is no work to do, there are no notifications generated.
+// start-shutdown situation. Failure of this test will be a crash.
 TEST_F(ComponentUpdaterTest, StartStop) {
   component_updater()->Start();
   message_loop_.RunUntilIdle();
   component_updater()->Stop();
-
-  EXPECT_EQ(0ul, notification_tracker().size());
 }
 
 // Verify that when the server has no updates, we go back to sleep and
@@ -300,20 +277,11 @@
               .Times(1);
   component_updater()->Start();
 
-  ASSERT_EQ(1ul, notification_tracker().size());
-  TestNotificationTracker::Event ev1 = notification_tracker().at(0);
-  EXPECT_EQ(chrome::NOTIFICATION_COMPONENT_UPDATER_STARTED, ev1.type);
-
   EXPECT_CALL(observer,
               OnEvent(ComponentObserver::COMPONENT_UPDATER_SLEEPING, 0))
               .Times(2);
   message_loop_.Run();
 
-  ASSERT_EQ(3ul, notification_tracker().size());
-  TestNotificationTracker::Event ev2 = notification_tracker().at(1);
-  EXPECT_EQ(chrome::NOTIFICATION_COMPONENT_UPDATER_SLEEPING, ev2.type);
-  TestNotificationTracker::Event ev3 = notification_tracker().at(2);
-  EXPECT_EQ(chrome::NOTIFICATION_COMPONENT_UPDATER_SLEEPING, ev2.type);
   EXPECT_EQ(2, interceptor.GetHitCount());
 
   EXPECT_EQ(0, static_cast<TestInstaller*>(com.installer)->error());
@@ -327,7 +295,6 @@
   interceptor.SetResponse(expected_update_url,
                           test_file("updatecheck_reply_empty"));
 
-  notification_tracker().Reset();
   test_configurator()->SetLoopCount(2);
 
   EXPECT_CALL(observer,
@@ -340,13 +307,6 @@
               .Times(2);
   message_loop_.Run();
 
-  ASSERT_EQ(3ul, notification_tracker().size());
-  ev1 = notification_tracker().at(0);
-  EXPECT_EQ(chrome::NOTIFICATION_COMPONENT_UPDATER_STARTED, ev1.type);
-  ev2 = notification_tracker().at(1);
-  EXPECT_EQ(chrome::NOTIFICATION_COMPONENT_UPDATER_SLEEPING, ev2.type);
-  ev3 = notification_tracker().at(2);
-  EXPECT_EQ(chrome::NOTIFICATION_COMPONENT_UPDATER_SLEEPING, ev2.type);
   EXPECT_EQ(4, interceptor.GetHitCount());
 
   EXPECT_EQ(0, static_cast<TestInstaller*>(com.installer)->error());
@@ -356,9 +316,9 @@
 }
 
 // Verify that we can check for updates and install one component. Besides
-// the notifications above NOTIFICATION_COMPONENT_UPDATE_FOUND and
-// NOTIFICATION_COMPONENT_UPDATE_READY should have been fired. We do two loops
-// so the second time around there should be nothing left to do.
+// the notifications above COMPONENT_UPDATE_FOUND and COMPONENT_UPDATE_READY
+// should have been fired. We do two loops so the second time around there
+// should be nothing left to do.
 // We also check that only 3 non-ping network requests are issued:
 // 1- manifest check
 // 2- download crx
@@ -442,23 +402,6 @@
   EXPECT_EQ(1, ping_checker.NumHits());
   EXPECT_EQ(0, ping_checker.NumMisses());
 
-  ASSERT_EQ(5ul, notification_tracker().size());
-
-  TestNotificationTracker::Event ev0 = notification_tracker().at(0);
-  EXPECT_EQ(chrome::NOTIFICATION_COMPONENT_UPDATER_STARTED, ev0.type);
-
-  TestNotificationTracker::Event ev1 = notification_tracker().at(1);
-  EXPECT_EQ(chrome::NOTIFICATION_COMPONENT_UPDATE_FOUND, ev1.type);
-
-  TestNotificationTracker::Event ev2 = notification_tracker().at(2);
-  EXPECT_EQ(chrome::NOTIFICATION_COMPONENT_UPDATE_READY, ev2.type);
-
-  TestNotificationTracker::Event ev3 = notification_tracker().at(3);
-  EXPECT_EQ(chrome::NOTIFICATION_COMPONENT_UPDATER_SLEEPING, ev3.type);
-
-  TestNotificationTracker::Event ev4 = notification_tracker().at(4);
-  EXPECT_EQ(chrome::NOTIFICATION_COMPONENT_UPDATER_SLEEPING, ev4.type);
-
   component_updater()->Stop();
 }
 
@@ -587,23 +530,6 @@
 
   EXPECT_EQ(3, interceptor.GetHitCount());
 
-  ASSERT_EQ(5ul, notification_tracker().size());
-
-  TestNotificationTracker::Event ev0= notification_tracker().at(0);
-  EXPECT_EQ(chrome::NOTIFICATION_COMPONENT_UPDATER_STARTED, ev0.type);
-
-  TestNotificationTracker::Event ev1 = notification_tracker().at(1);
-  EXPECT_EQ(chrome::NOTIFICATION_COMPONENT_UPDATER_SLEEPING, ev1.type);
-
-  TestNotificationTracker::Event ev2 = notification_tracker().at(2);
-  EXPECT_EQ(chrome::NOTIFICATION_COMPONENT_UPDATE_FOUND, ev2.type);
-
-  TestNotificationTracker::Event ev3 = notification_tracker().at(3);
-  EXPECT_EQ(chrome::NOTIFICATION_COMPONENT_UPDATE_READY, ev3.type);
-
-  TestNotificationTracker::Event ev4 = notification_tracker().at(4);
-  EXPECT_EQ(chrome::NOTIFICATION_COMPONENT_UPDATER_SLEEPING, ev4.type);
-
   // Also check what happens if previous check too soon.
   test_configurator()->SetOnDemandTime(60 * 60);
   EXPECT_EQ(ComponentUpdateService::kError,
@@ -643,7 +569,6 @@
   // No update: error from no server response
   interceptor.SetResponse(expected_update_url_3,
                           test_file("updatecheck_reply_empty"));
-  notification_tracker().Reset();
   test_configurator()->SetLoopCount(1);
   component_updater()->Start();
   EXPECT_EQ(ComponentUpdateService::kOk,
@@ -651,11 +576,6 @@
 
   message_loop_.Run();
 
-  ASSERT_EQ(2ul, notification_tracker().size());
-  ev0 = notification_tracker().at(0);
-  EXPECT_EQ(chrome::NOTIFICATION_COMPONENT_UPDATER_STARTED, ev0.type);
-  ev1 = notification_tracker().at(1);
-  EXPECT_EQ(chrome::NOTIFICATION_COMPONENT_UPDATER_SLEEPING, ev1.type);
   component_updater()->Stop();
 
   // No update: already updated to 1.0 so nothing new
@@ -682,7 +602,6 @@
 
   interceptor.SetResponse(expected_update_url_3,
                           test_file("updatecheck_reply_1.xml"));
-  notification_tracker().Reset();
   test_configurator()->SetLoopCount(1);
   component_updater()->Start();
   EXPECT_EQ(ComponentUpdateService::kOk,
@@ -692,11 +611,7 @@
 
   EXPECT_EQ(1, ping_checker.NumHits());
   EXPECT_EQ(0, ping_checker.NumMisses());
-  ASSERT_EQ(2ul, notification_tracker().size());
-  ev0 = notification_tracker().at(0);
-  EXPECT_EQ(chrome::NOTIFICATION_COMPONENT_UPDATER_STARTED, ev0.type);
-  ev1 = notification_tracker().at(1);
-  EXPECT_EQ(chrome::NOTIFICATION_COMPONENT_UPDATER_SLEEPING, ev1.type);
+
   component_updater()->Stop();
 }
 
@@ -790,23 +705,6 @@
   EXPECT_EQ(0, ping_checker.NumMisses());
   EXPECT_EQ(3, interceptor.GetHitCount());
 
-  ASSERT_EQ(5ul, notification_tracker().size());
-
-  TestNotificationTracker::Event ev0 = notification_tracker().at(0);
-  EXPECT_EQ(chrome::NOTIFICATION_COMPONENT_UPDATER_STARTED, ev0.type);
-
-  TestNotificationTracker::Event ev1 = notification_tracker().at(1);
-  EXPECT_EQ(chrome::NOTIFICATION_COMPONENT_UPDATE_FOUND, ev1.type);
-
-  TestNotificationTracker::Event ev2 = notification_tracker().at(2);
-  EXPECT_EQ(chrome::NOTIFICATION_COMPONENT_UPDATE_READY, ev2.type);
-
-  TestNotificationTracker::Event ev3 = notification_tracker().at(3);
-  EXPECT_EQ(chrome::NOTIFICATION_COMPONENT_UPDATER_SLEEPING, ev3.type);
-
-  TestNotificationTracker::Event ev4 = notification_tracker().at(4);
-  EXPECT_EQ(chrome::NOTIFICATION_COMPONENT_UPDATER_SLEEPING, ev4.type);
-
   component_updater()->Stop();
 
   // Now re-register, pretending to be an even newer version (2.2)
@@ -849,21 +747,11 @@
   interceptor.SetResponse(expected_update_url_3,
                           test_file("updatecheck_reply_1.xml"));
 
-  notification_tracker().Reset();
-
   // Loop once just to notice the check happening with the re-register version.
   test_configurator()->SetLoopCount(1);
   component_updater()->Start();
   message_loop_.Run();
 
-  ASSERT_EQ(2ul, notification_tracker().size());
-
-  ev0 = notification_tracker().at(0);
-  EXPECT_EQ(chrome::NOTIFICATION_COMPONENT_UPDATER_STARTED, ev0.type);
-
-  ev1 = notification_tracker().at(1);
-  EXPECT_EQ(chrome::NOTIFICATION_COMPONENT_UPDATER_SLEEPING, ev1.type);
-
   EXPECT_EQ(4, interceptor.GetHitCount());
 
   // We created a new installer, so the counts go back to 0.
@@ -954,7 +842,6 @@
 // There should be one ping for the first attempted update.
 
 TEST_F(ComponentUpdaterTest, DifferentialUpdateFails) {
-
   std::map<std::string, std::string> map;
   map.insert(std::pair<std::string, std::string>("eventtype", "\"3\""));
   map.insert(std::pair<std::string, std::string>("eventresult", "\"1\""));
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 4169c0a..752b17b 100644
--- a/chrome/browser/component_updater/test/component_updater_service_unittest.h
+++ b/chrome/browser/component_updater/test/component_updater_service_unittest.h
@@ -19,7 +19,6 @@
 #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.h"
-#include "content/public/test/test_notification_tracker.h"
 #include "net/url_request/url_request_test_util.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -119,8 +118,6 @@
   // Makes the full path to a component updater test file.
   const base::FilePath test_file(const char* file);
 
-  content::TestNotificationTracker& notification_tracker();
-
   TestConfigurator* test_configurator();
 
   ComponentUpdateService::Status RegisterComponent(CrxComponent* com,
@@ -133,7 +130,6 @@
  private:
   TestConfigurator* test_config_;
   base::FilePath test_data_dir_;
-  content::TestNotificationTracker notification_tracker_;
   content::TestBrowserThread ui_thread_;
   content::TestBrowserThread file_thread_;
   content::TestBrowserThread io_thread_;
diff --git a/chrome/browser/content_settings/tab_specific_content_settings.cc b/chrome/browser/content_settings/tab_specific_content_settings.cc
index f16589e..d8e4278 100644
--- a/chrome/browser/content_settings/tab_specific_content_settings.cc
+++ b/chrome/browser/content_settings/tab_specific_content_settings.cc
@@ -502,17 +502,13 @@
 void TabSpecificContentSettings::OnMIDISysExAccessed(
     const GURL& requesting_origin) {
   midi_usages_state_.OnPermissionSet(requesting_origin, true);
-  // TODO(toyoshim): Bubble icon for MIDI is disabled for now.
-  // http://crbug.com/257618
-  // OnContentAllowed(CONTENT_SETTINGS_TYPE_MIDI_SYSEX);
+  OnContentAllowed(CONTENT_SETTINGS_TYPE_MIDI_SYSEX);
 }
 
 void TabSpecificContentSettings::OnMIDISysExAccessBlocked(
     const GURL& requesting_origin) {
   midi_usages_state_.OnPermissionSet(requesting_origin, false);
-  // TODO(toyoshim): Bubble icon for MIDI is disabled for now.
-  // http://crbug.com/257618
-  // OnContentBlocked(CONTENT_SETTINGS_TYPE_MIDI_SYSEX, std::string());
+  OnContentBlocked(CONTENT_SETTINGS_TYPE_MIDI_SYSEX, std::string());
 }
 
 void TabSpecificContentSettings::ClearBlockedContentSettingsExceptForCookies() {
diff --git a/chrome/browser/devtools/adb/android_usb_device.cc b/chrome/browser/devtools/adb/android_usb_device.cc
index ce58cd9..82af86a 100644
--- a/chrome/browser/devtools/adb/android_usb_device.cc
+++ b/chrome/browser/devtools/adb/android_usb_device.cc
@@ -9,10 +9,12 @@
 #include "base/base64.h"
 #include "base/lazy_instance.h"
 #include "base/message_loop/message_loop.h"
+#include "base/stl_util.h"
 #include "base/strings/string_util.h"
 #include "base/strings/stringprintf.h"
 #include "chrome/browser/devtools/adb/android_rsa.h"
 #include "chrome/browser/devtools/adb/android_usb_socket.h"
+#include "chrome/browser/usb/usb_device.h"
 #include "chrome/browser/usb/usb_interface.h"
 #include "chrome/browser/usb/usb_service.h"
 #include "content/public/browser/browser_thread.h"
@@ -38,7 +40,7 @@
 
 using content::BrowserThread;
 
-typedef std::vector<scoped_refptr<UsbDeviceHandle> > UsbDevices;
+typedef std::vector<scoped_refptr<UsbDevice> > UsbDevices;
 
 base::LazyInstance<AndroidUsbDevices>::Leaky g_devices =
     LAZY_INSTANCE_INITIALIZER;
@@ -151,20 +153,20 @@
   AndroidUsbDevices& devices = g_devices.Get();
 
   UsbDevices usb_devices;
-  service->EnumerateDevices(&usb_devices);
+  service->GetDevices(&usb_devices);
 
   // GC Android devices with no actual usb device.
   AndroidUsbDevices::iterator it = devices.begin();
-  std::set<UsbDeviceHandle*> claimed_devices;
+  std::set<UsbDevice*> claimed_devices;
   while (it != devices.end()) {
     bool found_device = false;
     for (UsbDevices::iterator it2 = usb_devices.begin();
          it2 != usb_devices.end() && !found_device; ++it2) {
-      UsbDeviceHandle* usb_device = it2->get();
+      UsbDevice* usb_device = it2->get();
       AndroidUsbDevice* device = it->get();
-      if (usb_device == device->usb_device()) {
+      if (usb_device == device->usb_device()->device()) {
         found_device = true;
-        claimed_devices.insert(*it2);
+        claimed_devices.insert(usb_device);
       }
     }
 
@@ -177,13 +179,18 @@
   // Add new devices.
   for (UsbDevices::iterator it = usb_devices.begin(); it != usb_devices.end();
        ++it) {
-    scoped_refptr<UsbDeviceHandle> usb_device = *it;
-    if (claimed_devices.find(usb_device.get()) != claimed_devices.end())
+    if (ContainsKey(claimed_devices, it->get()))
       continue;
+
     scoped_refptr<UsbConfigDescriptor> config = new UsbConfigDescriptor();
-    bool success = usb_device->ListInterfaces(config.get());
+    bool success = (*it)->ListInterfaces(config.get());
     if (!success)
       continue;
+
+    scoped_refptr<UsbDeviceHandle> usb_device = (*it)->Open();
+    if (!usb_device)
+      continue;
+
     for (size_t j = 0; j < config->GetNumInterfaces(); ++j) {
       scoped_refptr<AndroidUsbDevice> device =
           ClaimInterface(rsa_key, usb_device, config->GetInterface(j));
diff --git a/chrome/browser/devtools/devtools_adb_bridge.cc b/chrome/browser/devtools/devtools_adb_bridge.cc
index 2973fa2..da72384 100644
--- a/chrome/browser/devtools/devtools_adb_bridge.cc
+++ b/chrome/browser/devtools/devtools_adb_bridge.cc
@@ -581,9 +581,6 @@
 
   virtual void OnSocketOpened() OVERRIDE {
     proxy_.reset(content::DevToolsExternalAgentProxy::Create(this));
-    tethering_adb_filter_.reset(new TetheringAdbFilter(
-        kAdbPort, serial_, adb_message_loop_, profile_->GetPrefs(),
-        web_socket_));
     OpenFrontend();
   }
 
@@ -598,7 +595,7 @@
   }
 
   virtual bool ProcessIncomingMessage(const std::string& message) OVERRIDE {
-    return tethering_adb_filter_->ProcessIncomingMessage(message);
+    return false;
   }
 
   const std::string id_;
@@ -608,7 +605,6 @@
   Profile* profile_;
 
   scoped_ptr<content::DevToolsExternalAgentProxy> proxy_;
-  scoped_ptr<TetheringAdbFilter> tethering_adb_filter_;
   scoped_refptr<AdbWebSocket> web_socket_;
   DISALLOW_COPY_AND_ASSIGN(AgentHostDelegate);
 };
diff --git a/chrome/browser/devtools/devtools_window.cc b/chrome/browser/devtools/devtools_window.cc
index ab503e5..3cc06c8 100644
--- a/chrome/browser/devtools/devtools_window.cc
+++ b/chrome/browser/devtools/devtools_window.cc
@@ -63,7 +63,6 @@
 #include "grit/generated_resources.h"
 #include "ui/base/l10n/l10n_util.h"
 
-using content::BrowserThread;
 using content::DevToolsAgentHost;
 
 
@@ -249,9 +248,10 @@
   DCHECK(it != instances->end());
   instances->erase(it);
 
-  IndexingJobsMap::const_iterator jobs_it = indexing_jobs_.begin();
-  for (; jobs_it != indexing_jobs_.end(); ++jobs_it)
+  for (IndexingJobsMap::const_iterator jobs_it(indexing_jobs_.begin());
+       jobs_it != indexing_jobs_.end(); ++jobs_it) {
     jobs_it->second->Stop();
+  }
   indexing_jobs_.clear();
 }
 
@@ -970,32 +970,32 @@
 
 void DevToolsWindow::IndexPath(int request_id,
                                const std::string& file_system_path) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
   CHECK(web_contents_->GetURL().SchemeIs(chrome::kChromeDevToolsScheme));
   if (!file_helper_->IsFileSystemAdded(file_system_path)) {
     IndexingDone(request_id, file_system_path);
     return;
   }
-  scoped_refptr<DevToolsFileSystemIndexer::FileSystemIndexingJob> indexing_job =
-      file_system_indexer_->IndexPath(
-          file_system_path,
-          Bind(&DevToolsWindow::IndexingTotalWorkCalculated,
-               weak_factory_.GetWeakPtr(),
-               request_id,
-               file_system_path),
-          Bind(&DevToolsWindow::IndexingWorked,
-               weak_factory_.GetWeakPtr(),
-               request_id,
-               file_system_path),
-          Bind(&DevToolsWindow::IndexingDone,
-               weak_factory_.GetWeakPtr(),
-               request_id,
-               file_system_path));
-  indexing_jobs_[request_id] = indexing_job;
+  indexing_jobs_[request_id] =
+      scoped_refptr<DevToolsFileSystemIndexer::FileSystemIndexingJob>(
+          file_system_indexer_->IndexPath(
+              file_system_path,
+              Bind(&DevToolsWindow::IndexingTotalWorkCalculated,
+                   weak_factory_.GetWeakPtr(),
+                   request_id,
+                   file_system_path),
+              Bind(&DevToolsWindow::IndexingWorked,
+                   weak_factory_.GetWeakPtr(),
+                   request_id,
+                   file_system_path),
+              Bind(&DevToolsWindow::IndexingDone,
+                   weak_factory_.GetWeakPtr(),
+                   request_id,
+                   file_system_path)));
 }
 
 void DevToolsWindow::StopIndexing(int request_id) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
   IndexingJobsMap::iterator it = indexing_jobs_.find(request_id);
   if (it == indexing_jobs_.end())
     return;
@@ -1006,7 +1006,7 @@
 void DevToolsWindow::SearchInPath(int request_id,
                                   const std::string& file_system_path,
                                   const std::string& query) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
   CHECK(web_contents_->GetURL().SchemeIs(chrome::kChromeDevToolsScheme));
   if (!file_helper_->IsFileSystemAdded(file_system_path)) {
     SearchCompleted(request_id, file_system_path, std::vector<std::string>());
@@ -1056,7 +1056,7 @@
     int request_id,
     const std::string& file_system_path,
     int total_work) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
   base::FundamentalValue request_id_value(request_id);
   StringValue file_system_path_value(file_system_path);
   base::FundamentalValue total_work_value(total_work);
@@ -1068,7 +1068,7 @@
 void DevToolsWindow::IndexingWorked(int request_id,
                                     const std::string& file_system_path,
                                     int worked) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
   base::FundamentalValue request_id_value(request_id);
   StringValue file_system_path_value(file_system_path);
   base::FundamentalValue worked_value(worked);
@@ -1079,7 +1079,7 @@
 void DevToolsWindow::IndexingDone(int request_id,
                                   const std::string& file_system_path) {
   indexing_jobs_.erase(request_id);
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
   base::FundamentalValue request_id_value(request_id);
   StringValue file_system_path_value(file_system_path);
   CallClientFunction("InspectorFrontendAPI.indexingDone", &request_id_value,
@@ -1090,10 +1090,10 @@
     int request_id,
     const std::string& file_system_path,
     const std::vector<std::string>& file_paths) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
   ListValue file_paths_value;
-  std::vector<std::string>::const_iterator it = file_paths.begin();
-  for (; it != file_paths.end(); ++it) {
+  for (std::vector<std::string>::const_iterator it(file_paths.begin());
+       it != file_paths.end(); ++it) {
     file_paths_value.AppendString(*it);
   }
   base::FundamentalValue request_id_value(request_id);
diff --git a/chrome/browser/devtools/tethering_adb_filter.cc b/chrome/browser/devtools/tethering_adb_filter.cc
index 887ba94..ce36334 100644
--- a/chrome/browser/devtools/tethering_adb_filter.cc
+++ b/chrome/browser/devtools/tethering_adb_filter.cc
@@ -28,7 +28,6 @@
 
 namespace {
 
-const int kAdbPort = 5037;
 const int kBufferSize = 16 * 1024;
 
 static const char kPortAttribute[] = "port";
@@ -36,7 +35,6 @@
 static const char kTetheringAccepted[] = "Tethering.accepted";
 static const char kTetheringBind[] = "Tethering.bind";
 static const char kTetheringUnbind[] = "Tethering.unbind";
-static const char kLocalAbstractCommand[] = "localabstract:%s";
 
 static const char kDevToolsRemoteSocketName[] = "chrome_devtools_remote";
 static const char kDevToolsRemoteBrowserTarget[] = "/devtools/browser";
@@ -194,13 +192,12 @@
 
 }  // namespace
 
-TetheringAdbFilter::TetheringAdbFilter(int adb_port,
-                                       const std::string& serial,
-                                       base::MessageLoop* adb_message_loop,
-                                       PrefService* pref_service,
-                                       scoped_refptr<AdbWebSocket> web_socket)
-    : adb_port_(adb_port),
-      serial_(serial),
+TetheringAdbFilter::TetheringAdbFilter(
+    scoped_refptr<DevToolsAdbBridge::AndroidDevice> device,
+    base::MessageLoop* adb_message_loop,
+    PrefService* pref_service,
+    scoped_refptr<AdbWebSocket> web_socket)
+    : device_(device),
       adb_message_loop_(adb_message_loop),
       web_socket_(web_socket),
       command_id_(0),
@@ -311,10 +308,7 @@
   std::string location = it->second;
 
   SocketTunnel* tunnel = new SocketTunnel(location);
-  std::string command = base::StringPrintf(kLocalAbstractCommand,
-                                           connection_id.c_str());
-  AdbClientSocket::TransportQuery(
-      adb_port_, serial_, command,
+  device_->OpenSocket(connection_id.c_str(),
       base::Bind(&SocketTunnel::Start, base::Unretained(tunnel)));
   return true;
 }
@@ -338,7 +332,7 @@
   virtual bool ProcessIncomingMessage(const std::string& message) OVERRIDE;
 
   Registry* registry_;
-  const std::string serial_;
+  scoped_refptr<DevToolsAdbBridge::AndroidDevice> device_;
   base::MessageLoop* adb_message_loop_;
   PrefService* pref_service_;
 
@@ -352,10 +346,10 @@
     base::MessageLoop* adb_message_loop,
     PrefService* pref_service)
     : registry_(registry),
-      serial_(device->serial()),
+      device_(device),
       adb_message_loop_(adb_message_loop),
       pref_service_(pref_service) {
-   (*registry_)[serial_] = this;
+   (*registry_)[device_->serial()] = this;
    web_socket_ = new AdbWebSocket(
         device, kDevToolsRemoteSocketName, kDevToolsRemoteBrowserTarget,
         adb_message_loop_, this);
@@ -370,8 +364,8 @@
 PortForwardingController::Connection::~Connection() {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
   if (registry_) {
-    DCHECK(registry_->find(serial_) != registry_->end());
-    registry_->erase(serial_);
+    DCHECK(registry_->find(device_->serial()) != registry_->end());
+    registry_->erase(device_->serial());
   }
 }
 
@@ -383,7 +377,7 @@
   }
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
   tethering_adb_filter_.reset(new TetheringAdbFilter(
-      kAdbPort, serial_, adb_message_loop_, pref_service_, web_socket_));
+      device_, adb_message_loop_, pref_service_, web_socket_));
 }
 
 void PortForwardingController::Connection::OnFrameRead(
diff --git a/chrome/browser/devtools/tethering_adb_filter.h b/chrome/browser/devtools/tethering_adb_filter.h
index 4267047..11c08b2 100644
--- a/chrome/browser/devtools/tethering_adb_filter.h
+++ b/chrome/browser/devtools/tethering_adb_filter.h
@@ -22,8 +22,7 @@
 
 class TetheringAdbFilter {
  public:
-  TetheringAdbFilter(int adb_port,
-                     const std::string& serial,
+  TetheringAdbFilter(scoped_refptr<DevToolsAdbBridge::AndroidDevice> device,
                      base::MessageLoop* adb_message_loop,
                      PrefService* pref_service,
                      scoped_refptr<AdbWebSocket> web_socket);
@@ -44,8 +43,7 @@
 
   void SendCommand(const std::string& method, int port);
 
-  int adb_port_;
-  std::string serial_;
+  scoped_refptr<DevToolsAdbBridge::AndroidDevice> device_;
   base::MessageLoop* adb_message_loop_;
   PrefChangeRegistrar pref_change_registrar_;
   scoped_refptr<AdbWebSocket> web_socket_;
diff --git a/chrome/browser/download/chrome_download_manager_delegate.cc b/chrome/browser/download/chrome_download_manager_delegate.cc
index a810537..aec10bb 100644
--- a/chrome/browser/download/chrome_download_manager_delegate.cc
+++ b/chrome/browser/download/chrome_download_manager_delegate.cc
@@ -34,6 +34,7 @@
 #include "chrome/browser/platform_util.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/safe_browsing/safe_browsing_service.h"
+#include "chrome/common/chrome_constants.h"
 #include "chrome/common/pref_names.h"
 #include "components/user_prefs/pref_registry_syncable.h"
 #include "content/public/browser/download_item.h"
@@ -402,6 +403,11 @@
       callback);
 }
 
+std::string
+ChromeDownloadManagerDelegate::ApplicationClientIdForFileScanning() const {
+  return std::string(chrome::kApplicationClientIDStringForAVScanning);
+}
+
 DownloadProtectionService*
     ChromeDownloadManagerDelegate::GetDownloadProtectionService() {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
diff --git a/chrome/browser/download/chrome_download_manager_delegate.h b/chrome/browser/download/chrome_download_manager_delegate.h
index e2c13ad..d23337d 100644
--- a/chrome/browser/download/chrome_download_manager_delegate.h
+++ b/chrome/browser/download/chrome_download_manager_delegate.h
@@ -93,6 +93,7 @@
   virtual void CheckForFileExistence(
       content::DownloadItem* download,
       const content::CheckForFileExistenceCallback& callback) OVERRIDE;
+  virtual std::string ApplicationClientIdForFileScanning() const OVERRIDE;
 
   DownloadPrefs* download_prefs() { return download_prefs_.get(); }
 
diff --git a/chrome/browser/download/download_browsertest.cc b/chrome/browser/download/download_browsertest.cc
index c065b85..1bacb68 100644
--- a/chrome/browser/download/download_browsertest.cc
+++ b/chrome/browser/download/download_browsertest.cc
@@ -15,6 +15,7 @@
 #include "base/prefs/pref_service.h"
 #include "base/stl_util.h"
 #include "base/strings/string_split.h"
+#include "base/strings/string_util.h"
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/sys_info.h"
@@ -1066,8 +1067,9 @@
   // A mock install prompt that simulates the user allowing an install request.
   void SetAllowMockInstallPrompt() {
     download_crx_util::SetMockInstallPromptForTesting(
-        new MockAutoConfirmExtensionInstallPrompt(
-            browser()->tab_strip_model()->GetActiveWebContents()));
+        scoped_ptr<ExtensionInstallPrompt>(
+            new MockAutoConfirmExtensionInstallPrompt(
+                browser()->tab_strip_model()->GetActiveWebContents())));
   }
 
   // This method:
@@ -1924,7 +1926,7 @@
   HistoryServiceFactory::GetForProfile(
       browser()->profile(), Profile::IMPLICIT_ACCESS)->FlushForTest(
       base::Bind(&base::MessageLoop::Quit,
-                  base::Unretained(base::MessageLoop::current()->current())));
+                 base::Unretained(base::MessageLoop::current()->current())));
   content::RunMessageLoop();
 }
 
@@ -1948,9 +1950,17 @@
   manager->GetAllDownloads(&downloads);
   ASSERT_EQ(1UL, downloads.size());
   DownloadItem* item = downloads[0];
-  ASSERT_EQ(file.value(), item->GetFullPath().BaseName().value());
-  ASSERT_EQ(file.value(), item->GetTargetFilePath().BaseName().value());
-  ASSERT_EQ(download_url, item->GetURL());
+  EXPECT_EQ(file.value(), item->GetFullPath().BaseName().value());
+  EXPECT_EQ(file.value(), item->GetTargetFilePath().BaseName().value());
+  EXPECT_EQ(download_url, item->GetURL());
+  // The following are set by download-test1.lib.mock-http-headers.
+  std::string etag = item->GetETag();
+  TrimWhitespaceASCII(etag, TRIM_ALL, &etag);
+  EXPECT_EQ("abracadabra", etag);
+
+  std::string last_modified = item->GetLastModifiedTime();
+  TrimWhitespaceASCII(last_modified, TRIM_ALL, &last_modified);
+  EXPECT_EQ("Mon, 13 Nov 2006 20:31:09 GMT", last_modified);
 }
 
 // Test for crbug.com/14505. This tests that chrome:// urls are still functional
@@ -2090,7 +2100,8 @@
   // Install a mock install UI that simulates a user denying permission to
   // finish the install.
   download_crx_util::SetMockInstallPromptForTesting(
-      new MockAbortExtensionInstallPrompt());
+      scoped_ptr<ExtensionInstallPrompt>(
+          new MockAbortExtensionInstallPrompt()));
 
   scoped_ptr<content::DownloadTestObserver> observer(
       DangerousDownloadWaiter(
diff --git a/chrome/browser/download/download_crx_util.cc b/chrome/browser/download/download_crx_util.cc
index 06e8b18..f6edf37 100644
--- a/chrome/browser/download/download_crx_util.cc
+++ b/chrome/browser/download/download_crx_util.cc
@@ -33,9 +33,9 @@
 ExtensionInstallPrompt* mock_install_prompt_for_testing = NULL;
 
 // Called to get an extension install UI object.  In tests, will return
-// a mock if the test calls download_util::SetMockInstallUIForTesting()
+// a mock if the test calls download_util::SetMockInstallPromptForTesting()
 // to set one.
-ExtensionInstallPrompt* CreateExtensionInstallPrompt(
+scoped_ptr<ExtensionInstallPrompt> CreateExtensionInstallPrompt(
     Profile* profile,
     const DownloadItem& download_item) {
   // Use a mock if one is present.  Otherwise, create a real extensions
@@ -43,7 +43,7 @@
   if (mock_install_prompt_for_testing) {
     ExtensionInstallPrompt* result = mock_install_prompt_for_testing;
     mock_install_prompt_for_testing = NULL;
-    return result;
+    return scoped_ptr<ExtensionInstallPrompt>(result);
   } else {
     content::WebContents* web_contents = download_item.GetWebContents();
     if (!web_contents) {
@@ -55,7 +55,8 @@
                                                     profile, active_desktop));
       web_contents = browser->tab_strip_model()->GetActiveWebContents();
     }
-    return new ExtensionInstallPrompt(web_contents);
+    return scoped_ptr<ExtensionInstallPrompt>(
+        new ExtensionInstallPrompt(web_contents));
   }
 }
 
@@ -63,8 +64,9 @@
 
 // Tests can call this method to inject a mock ExtensionInstallPrompt
 // to be used to confirm permissions on a downloaded CRX.
-void SetMockInstallPromptForTesting(ExtensionInstallPrompt* mock_prompt) {
-  mock_install_prompt_for_testing = mock_prompt;
+void SetMockInstallPromptForTesting(
+    scoped_ptr<ExtensionInstallPrompt> mock_prompt) {
+  mock_install_prompt_for_testing = mock_prompt.release();
 }
 
 scoped_refptr<extensions::CrxInstaller> OpenChromeExtension(
diff --git a/chrome/browser/download/download_crx_util.h b/chrome/browser/download/download_crx_util.h
index ac9b36c..1807a59 100644
--- a/chrome/browser/download/download_crx_util.h
+++ b/chrome/browser/download/download_crx_util.h
@@ -10,6 +10,7 @@
 
 #include "base/basictypes.h"
 #include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
 
 class ExtensionInstallPrompt;
 class Profile;
@@ -25,11 +26,9 @@
 namespace download_crx_util {
 
 // Allow tests to install a mock ExtensionInstallPrompt object, to fake
-// user clicks on the permissions dialog.  Each installed mock object
-// is only used once.  If you want to return a mock for two different
-// installs, you need to call this function once before the first
-// install, and again after the first install and before the second.
-void SetMockInstallPromptForTesting(ExtensionInstallPrompt* mock_prompt);
+// user clicks on the permissions dialog.
+void SetMockInstallPromptForTesting(
+    scoped_ptr<ExtensionInstallPrompt> mock_prompt);
 
 // Start installing a downloaded item item as a CRX (extension, theme, app,
 // ...).  The installer does work on the file thread, so the installation
diff --git a/chrome/browser/download/download_crx_util_android.cc b/chrome/browser/download/download_crx_util_android.cc
index 6bdba5b..4b068a8 100644
--- a/chrome/browser/download/download_crx_util_android.cc
+++ b/chrome/browser/download/download_crx_util_android.cc
@@ -23,7 +23,7 @@
     const DownloadItem& download_item) {
   NOTIMPLEMENTED() << "CrxInstaller not implemented on Android";
   scoped_refptr<extensions::CrxInstaller> installer(
-      extensions::CrxInstaller::Create(NULL, NULL));
+      extensions::CrxInstaller::CreateSilent(NULL));
   return installer;
 }
 
diff --git a/chrome/browser/download/download_danger_prompt.cc b/chrome/browser/download/download_danger_prompt.cc
index fc0948d..d795b71 100644
--- a/chrome/browser/download/download_danger_prompt.cc
+++ b/chrome/browser/download/download_danger_prompt.cc
@@ -5,8 +5,10 @@
 #include "chrome/browser/download/download_danger_prompt.h"
 
 #include "base/bind.h"
+#include "base/metrics/field_trial.h"
 #include "chrome/browser/chrome_notification_types.h"
 #include "chrome/browser/download/chrome_download_manager_delegate.h"
+#include "chrome/browser/download/download_util.h"
 #include "chrome/browser/ui/tab_modal_confirm_dialog.h"
 #include "chrome/browser/ui/tab_modal_confirm_dialog_delegate.h"
 #include "content/public/browser/download_danger_type.h"
@@ -103,29 +105,41 @@
     return l10n_util::GetStringUTF16(
         IDS_PROMPT_CONFIRM_KEEP_DANGEROUS_DOWNLOAD);
   switch (download_->GetDangerType()) {
-    case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE:
+    case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE: {
       return l10n_util::GetStringFUTF16(
           IDS_PROMPT_DANGEROUS_DOWNLOAD,
           download_->GetFileNameToReportUser().LossyDisplayName());
+    }
     case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_URL: // Fall through
     case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_CONTENT:
-    case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_HOST:
-      return l10n_util::GetStringFUTF16(
-          IDS_PROMPT_MALICIOUS_DOWNLOAD_CONTENT,
+    case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_HOST: {
+      std::string trial_condition =
+          base::FieldTrialList::FindFullName(download_util::kFinchTrialName);
+      if (trial_condition.empty()) {
+        return l10n_util::GetStringFUTF16(
+            IDS_PROMPT_MALICIOUS_DOWNLOAD_CONTENT,
+            download_->GetFileNameToReportUser().LossyDisplayName());
+      }
+      return download_util::AssembleMalwareFinchString(
+          trial_condition,
           download_->GetFileNameToReportUser().LossyDisplayName());
-    case content::DOWNLOAD_DANGER_TYPE_UNCOMMON_CONTENT:
+    }
+    case content::DOWNLOAD_DANGER_TYPE_UNCOMMON_CONTENT: {
       return l10n_util::GetStringFUTF16(
           IDS_PROMPT_UNCOMMON_DOWNLOAD_CONTENT,
           download_->GetFileNameToReportUser().LossyDisplayName());
-    case content::DOWNLOAD_DANGER_TYPE_POTENTIALLY_UNWANTED:
+    }
+    case content::DOWNLOAD_DANGER_TYPE_POTENTIALLY_UNWANTED: {
       return l10n_util::GetStringFUTF16(
           IDS_PROMPT_DOWNLOAD_CHANGES_SEARCH_SETTINGS,
           download_->GetFileNameToReportUser().LossyDisplayName());
+    }
     case content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS:
     case content::DOWNLOAD_DANGER_TYPE_MAYBE_DANGEROUS_CONTENT:
     case content::DOWNLOAD_DANGER_TYPE_USER_VALIDATED:
-    case content::DOWNLOAD_DANGER_TYPE_MAX:
+    case content::DOWNLOAD_DANGER_TYPE_MAX: {
       break;
+    }
   }
   NOTREACHED();
   return string16();
diff --git a/chrome/browser/download/download_extensions.cc b/chrome/browser/download/download_extensions.cc
index b8041b5..630d296 100644
--- a/chrome/browser/download/download_extensions.cc
+++ b/chrome/browser/download/download_extensions.cc
@@ -66,6 +66,8 @@
   { "class", DANGEROUS },
   { "jar", DANGEROUS },
   { "jnlp", DANGEROUS },
+#endif
+#if !defined(OS_CHROMEOS) && !defined(OS_ANDROID)
   // Relating to PDF.
   { "pdf", ALLOW_ON_USER_GESTURE },
   { "pdfxml", ALLOW_ON_USER_GESTURE },
@@ -77,6 +79,7 @@
   // Relating to scripting languages.
   { "pl", ALLOW_ON_USER_GESTURE },
   { "py", ALLOW_ON_USER_GESTURE },
+  { "pyc", ALLOW_ON_USER_GESTURE },
   { "pyw", ALLOW_ON_USER_GESTURE },
   { "rb", ALLOW_ON_USER_GESTURE },
 #endif
diff --git a/chrome/browser/download/download_history.cc b/chrome/browser/download/download_history.cc
index acda0ed..ea2f2e1 100644
--- a/chrome/browser/download/download_history.cc
+++ b/chrome/browser/download/download_history.cc
@@ -116,6 +116,8 @@
       item->GetReferrerUrl(),
       item->GetStartTime(),
       item->GetEndTime(),
+      item->GetETag(),
+      item->GetLastModifiedTime(),
       item->GetReceivedBytes(),
       item->GetTotalBytes(),
       item->GetState(),
@@ -136,6 +138,8 @@
           (previous->end_time != current.end_time) ||
           (previous->received_bytes != current.received_bytes) ||
           (previous->total_bytes != current.total_bytes) ||
+          (previous->etag != current.etag) ||
+          (previous->last_modified != current.last_modified) ||
           (previous->state != current.state) ||
           (previous->danger_type != current.danger_type) ||
           (previous->interrupt_reason != current.interrupt_reason) ||
@@ -233,6 +237,8 @@
         it->referrer_url,
         it->start_time,
         it->end_time,
+        it->etag,
+        it->last_modified,
         it->received_bytes,
         it->total_bytes,
         it->state,
diff --git a/chrome/browser/download/download_history_unittest.cc b/chrome/browser/download/download_history_unittest.cc
index 8ec764b..93fdb73 100644
--- a/chrome/browser/download/download_history_unittest.cc
+++ b/chrome/browser/download/download_history_unittest.cc
@@ -17,10 +17,14 @@
 #include "content/public/test/test_utils.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
+#if !defined(OS_ANDROID)
+#include "chrome/browser/extensions/api/downloads/downloads_api.h"
+#endif
+
 using testing::DoAll;
 using testing::Invoke;
 using testing::Return;
-using testing::ReturnRef;
+using testing::ReturnRefOfCopy;
 using testing::SetArgPointee;
 using testing::WithArg;
 using testing::_;
@@ -40,17 +44,21 @@
   EXPECT_EQ(left.referrer_url.spec(), right.referrer_url.spec());
   EXPECT_EQ(left.start_time.ToTimeT(), right.start_time.ToTimeT());
   EXPECT_EQ(left.end_time.ToTimeT(), right.end_time.ToTimeT());
+  EXPECT_EQ(left.etag, right.etag);
+  EXPECT_EQ(left.last_modified, right.last_modified);
   EXPECT_EQ(left.received_bytes, right.received_bytes);
   EXPECT_EQ(left.total_bytes, right.total_bytes);
   EXPECT_EQ(left.state, right.state);
   EXPECT_EQ(left.danger_type, right.danger_type);
   EXPECT_EQ(left.id, right.id);
   EXPECT_EQ(left.opened, right.opened);
+  EXPECT_EQ(left.by_ext_id, right.by_ext_id);
+  EXPECT_EQ(left.by_ext_name, right.by_ext_name);
 }
 
 typedef DownloadHistory::IdSet IdSet;
 typedef std::vector<history::DownloadRow> InfoVector;
-typedef testing::NiceMock<content::MockDownloadItem> NiceMockDownloadItem;
+typedef testing::StrictMock<content::MockDownloadItem> StrictMockDownloadItem;
 
 class FakeHistoryAdapter : public DownloadHistory::HistoryAdapter {
  public:
@@ -243,6 +251,8 @@
           infos->at(index).referrer_url,
           infos->at(index).start_time,
           infos->at(index).end_time,
+          infos->at(index).etag,
+          infos->at(index).last_modified,
           infos->at(index).received_bytes,
           infos->at(index).total_bytes,
           infos->at(index).state,
@@ -323,9 +333,34 @@
     history_->ExpectDownloadsRemoved(ids);
   }
 
-  // Caller is responsibile for making sure reference arguments lifetime is
-  // greater than the lifetime of the NiceMockDownloadItem() created by this
-  // routine.
+  void InitBasicItem(const base::FilePath::CharType* path,
+                     const char* url_string,
+                     const char* referrer_string,
+                     history::DownloadRow* info) {
+    GURL url(url_string);
+    GURL referrer(referrer_string);
+    std::vector<GURL> url_chain;
+    url_chain.push_back(url);
+    InitItem(static_cast<uint32>(items_.size() + 1),
+             base::FilePath(path),
+             base::FilePath(path),
+             url_chain,
+             referrer,
+             (base::Time::Now() - base::TimeDelta::FromMinutes(10)),
+             (base::Time::Now() - base::TimeDelta::FromMinutes(1)),
+             "Etag",
+             "abc",
+             100,
+             100,
+             content::DownloadItem::COMPLETE,
+             content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
+             content::DOWNLOAD_INTERRUPT_REASON_NONE,
+             false,
+             std::string(),
+             std::string(),
+             info);
+  }
+
   void InitItem(
       uint32 id,
       const base::FilePath& current_path,
@@ -334,16 +369,21 @@
       const GURL& referrer,
       const base::Time& start_time,
       const base::Time& end_time,
+      const std::string& etag,
+      const std::string& last_modified,
       int64 received_bytes,
       int64 total_bytes,
       content::DownloadItem::DownloadState state,
       content::DownloadDangerType danger_type,
       content::DownloadInterruptReason interrupt_reason,
       bool opened,
+      const std::string& by_extension_id,
+      const std::string& by_extension_name,
       history::DownloadRow* info) {
     DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+
     size_t index = items_.size();
-    NiceMockDownloadItem* mock_item = new NiceMockDownloadItem();
+    StrictMockDownloadItem* mock_item = new StrictMockDownloadItem();
     items_.push_back(mock_item);
 
     info->current_path = current_path;
@@ -352,6 +392,8 @@
     info->referrer_url = referrer;
     info->start_time = start_time;
     info->end_time = end_time;
+    info->etag = etag;
+    info->last_modified = last_modified;
     info->received_bytes = received_bytes;
     info->total_bytes = total_bytes;
     info->state = state;
@@ -359,52 +401,64 @@
     info->interrupt_reason = interrupt_reason;
     info->id = id;
     info->opened = opened;
+    info->by_ext_id = by_extension_id;
+    info->by_ext_name = by_extension_name;
 
     EXPECT_CALL(item(index), GetId()).WillRepeatedly(Return(id));
-    EXPECT_CALL(item(index),
-                GetFullPath()).WillRepeatedly(ReturnRef(current_path));
-    EXPECT_CALL(item(index),
-                GetTargetFilePath()).WillRepeatedly(ReturnRef(target_path));
+    EXPECT_CALL(item(index), GetFullPath())
+        .WillRepeatedly(ReturnRefOfCopy(current_path));
+    EXPECT_CALL(item(index), GetTargetFilePath())
+        .WillRepeatedly(ReturnRefOfCopy(target_path));
     DCHECK_LE(1u, url_chain.size());
-    EXPECT_CALL(item(index), GetURL()).WillRepeatedly(ReturnRef(url_chain[0]));
-    EXPECT_CALL(item(index),
-                GetUrlChain()).WillRepeatedly(ReturnRef(url_chain));
-    EXPECT_CALL(item(index), GetMimeType()).WillRepeatedly(Return(
-        "application/octet-stream"));
-    EXPECT_CALL(item(index), GetReferrerUrl()).WillRepeatedly(ReturnRef(
-        referrer));
+    EXPECT_CALL(item(index), GetURL())
+        .WillRepeatedly(ReturnRefOfCopy(url_chain[0]));
+    EXPECT_CALL(item(index), GetUrlChain())
+        .WillRepeatedly(ReturnRefOfCopy(url_chain));
+    EXPECT_CALL(item(index), GetMimeType())
+        .WillRepeatedly(Return("application/octet-stream"));
+    EXPECT_CALL(item(index), GetReferrerUrl())
+        .WillRepeatedly(ReturnRefOfCopy(referrer));
     EXPECT_CALL(item(index), GetStartTime()).WillRepeatedly(Return(start_time));
     EXPECT_CALL(item(index), GetEndTime()).WillRepeatedly(Return(end_time));
+    EXPECT_CALL(item(index), GetETag()).WillRepeatedly(ReturnRefOfCopy(etag));
+    EXPECT_CALL(item(index), GetLastModifiedTime())
+        .WillRepeatedly(ReturnRefOfCopy(last_modified));
     EXPECT_CALL(item(index), GetReceivedBytes())
         .WillRepeatedly(Return(received_bytes));
-    EXPECT_CALL(item(index), GetTotalBytes()).WillRepeatedly(Return(
-        total_bytes));
+    EXPECT_CALL(item(index), GetTotalBytes())
+        .WillRepeatedly(Return(total_bytes));
     EXPECT_CALL(item(index), GetState()).WillRepeatedly(Return(state));
     EXPECT_CALL(item(index), GetDangerType())
         .WillRepeatedly(Return(danger_type));
-    EXPECT_CALL(item(index), GetLastReason()).WillRepeatedly(
-        Return(interrupt_reason));
+    EXPECT_CALL(item(index), GetLastReason())
+        .WillRepeatedly(Return(interrupt_reason));
     EXPECT_CALL(item(index), GetOpened()).WillRepeatedly(Return(opened));
-    EXPECT_CALL(item(index), GetTargetDisposition()).WillRepeatedly(Return(
-          content::DownloadItem::TARGET_DISPOSITION_OVERWRITE));
+    EXPECT_CALL(item(index), GetTargetDisposition())
+        .WillRepeatedly(
+            Return(content::DownloadItem::TARGET_DISPOSITION_OVERWRITE));
     EXPECT_CALL(manager(), GetDownload(id))
         .WillRepeatedly(Return(&item(index)));
-    EXPECT_CALL(item(index), AddObserver(_)).WillOnce(WithArg<0>(Invoke(
-        this, &DownloadHistoryTest::SetItemObserver)));
+    EXPECT_CALL(item(index), AddObserver(_))
+        .WillOnce(WithArg<0>(
+            Invoke(this, &DownloadHistoryTest::SetItemObserver)));
     EXPECT_CALL(item(index), RemoveObserver(_));
+    EXPECT_CALL(item(index), IsTemporary()).WillRepeatedly(Return(false));
+#if !defined(OS_ANDROID)
+    new DownloadedByExtension(&item(index), by_extension_id, by_extension_name);
+#endif
 
     std::vector<content::DownloadItem*> items;
     for (size_t i = 0; i < items_.size(); ++i) {
       items.push_back(&item(i));
     }
     EXPECT_CALL(*manager_.get(), GetAllDownloads(_))
-      .WillRepeatedly(SetArgPointee<0>(items));
+        .WillRepeatedly(SetArgPointee<0>(items));
   }
 
  private:
   base::MessageLoopForUI loop_;
   content::TestBrowserThread ui_thread_;
-  std::vector<NiceMockDownloadItem*> items_;
+  std::vector<StrictMockDownloadItem*> items_;
   scoped_ptr<content::MockDownloadManager> manager_;
   FakeHistoryAdapter* history_;
   scoped_ptr<DownloadHistory> download_history_;
@@ -423,25 +477,10 @@
   // Load a download from history, create the item, OnDownloadCreated,
   // OnDownloadUpdated, OnDownloadRemoved.
   history::DownloadRow info;
-  base::FilePath path(FILE_PATH_LITERAL("/foo/bar.pdf"));
-  GURL url("http://example.com/bar.pdf");
-  GURL referrer("http://example.com/referrer.html");
-  std::vector<GURL> url_chain;
-  url_chain.push_back(url);
-  InitItem(base::RandInt(0, 1 << 20),
-           path,
-           path,
-           url_chain,
-           referrer,
-           (base::Time::Now() - base::TimeDelta::FromMinutes(10)),
-           (base::Time::Now() - base::TimeDelta::FromMinutes(1)),
-           100,
-           100,
-           content::DownloadItem::COMPLETE,
-           content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
-           content::DOWNLOAD_INTERRUPT_REASON_NONE,
-           false,
-           &info);
+  InitBasicItem(FILE_PATH_LITERAL("/foo/bar.pdf"),
+                "http://example.com/bar.pdf",
+                "http://example.com/referrer.html",
+                &info);
   {
     scoped_ptr<InfoVector> infos(new InfoVector());
     infos->push_back(info);
@@ -471,25 +510,10 @@
   ExpectWillQueryDownloads(scoped_ptr<InfoVector>(new InfoVector()));
 
   history::DownloadRow info;
-  base::FilePath path(FILE_PATH_LITERAL("/foo/bar.pdf"));
-  GURL url("http://example.com/bar.pdf");
-  GURL referrer("http://example.com/referrer.html");
-  std::vector<GURL> url_chain;
-  url_chain.push_back(url);
-  InitItem(base::RandInt(0, 1 << 20),
-           path,
-           path,
-           url_chain,
-           referrer,
-           (base::Time::Now() - base::TimeDelta::FromMinutes(10)),
-           (base::Time::Now() - base::TimeDelta::FromMinutes(1)),
-           100,
-           100,
-           content::DownloadItem::COMPLETE,
-           content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
-           content::DOWNLOAD_INTERRUPT_REASON_NONE,
-           false,
-           &info);
+  InitBasicItem(FILE_PATH_LITERAL("/foo/bar.pdf"),
+                "http://example.com/bar.pdf",
+                "http://example.com/referrer.html",
+                &info);
 
   // Pretend the manager just created |item|.
   CallOnDownloadCreated(0);
@@ -509,6 +533,97 @@
   ExpectDownloadsRemoved(ids);
 }
 
+// Test that changes to persisted fields in a DownloadItem triggers database
+// updates.
+TEST_F(DownloadHistoryTest, DownloadHistoryTest_Update) {
+  ExpectWillQueryDownloads(scoped_ptr<InfoVector>(new InfoVector()));
+
+  history::DownloadRow info;
+  InitBasicItem(FILE_PATH_LITERAL("/foo/bar.pdf"),
+                "http://example.com/bar.pdf",
+                "http://example.com/referrer.html",
+                &info);
+  CallOnDownloadCreated(0);
+  ExpectDownloadCreated(info);
+  EXPECT_TRUE(DownloadHistory::IsPersisted(&item(0)));
+
+  base::FilePath new_path(FILE_PATH_LITERAL("/foo/baz.txt"));
+  base::Time new_time(base::Time::Now());
+  std::string new_etag("new etag");
+  std::string new_last_modifed("new last modified");
+
+  // current_path
+  EXPECT_CALL(item(0), GetFullPath()).WillRepeatedly(ReturnRefOfCopy(new_path));
+  info.current_path = new_path;
+  item_observer()->OnDownloadUpdated(&item(0));
+  ExpectDownloadUpdated(info);
+
+  // target_path
+  EXPECT_CALL(item(0), GetTargetFilePath())
+      .WillRepeatedly(ReturnRefOfCopy(new_path));
+  info.target_path = new_path;
+  item_observer()->OnDownloadUpdated(&item(0));
+  ExpectDownloadUpdated(info);
+
+  // end_time
+  EXPECT_CALL(item(0), GetEndTime()).WillRepeatedly(Return(new_time));
+  info.end_time = new_time;
+  item_observer()->OnDownloadUpdated(&item(0));
+  ExpectDownloadUpdated(info);
+
+  // received_bytes
+  EXPECT_CALL(item(0), GetReceivedBytes()).WillRepeatedly(Return(101));
+  info.received_bytes = 101;
+  item_observer()->OnDownloadUpdated(&item(0));
+  ExpectDownloadUpdated(info);
+
+  // total_bytes
+  EXPECT_CALL(item(0), GetTotalBytes()).WillRepeatedly(Return(102));
+  info.total_bytes = 102;
+  item_observer()->OnDownloadUpdated(&item(0));
+  ExpectDownloadUpdated(info);
+
+  // etag
+  EXPECT_CALL(item(0), GetETag()).WillRepeatedly(ReturnRefOfCopy(new_etag));
+  info.etag = new_etag;
+  item_observer()->OnDownloadUpdated(&item(0));
+  ExpectDownloadUpdated(info);
+
+  // last_modified
+  EXPECT_CALL(item(0), GetLastModifiedTime())
+      .WillRepeatedly(ReturnRefOfCopy(new_last_modifed));
+  info.last_modified = new_last_modifed;
+  item_observer()->OnDownloadUpdated(&item(0));
+  ExpectDownloadUpdated(info);
+
+  // state
+  EXPECT_CALL(item(0), GetState())
+      .WillRepeatedly(Return(content::DownloadItem::INTERRUPTED));
+  info.state = content::DownloadItem::INTERRUPTED;
+  item_observer()->OnDownloadUpdated(&item(0));
+  ExpectDownloadUpdated(info);
+
+  // danger_type
+  EXPECT_CALL(item(0), GetDangerType())
+      .WillRepeatedly(Return(content::DOWNLOAD_DANGER_TYPE_DANGEROUS_CONTENT));
+  info.danger_type = content::DOWNLOAD_DANGER_TYPE_DANGEROUS_CONTENT;
+  item_observer()->OnDownloadUpdated(&item(0));
+  ExpectDownloadUpdated(info);
+
+  // interrupt_reason
+  EXPECT_CALL(item(0), GetLastReason())
+      .WillRepeatedly(Return(content::DOWNLOAD_INTERRUPT_REASON_SERVER_FAILED));
+  info.interrupt_reason = content::DOWNLOAD_INTERRUPT_REASON_SERVER_FAILED;
+  item_observer()->OnDownloadUpdated(&item(0));
+  ExpectDownloadUpdated(info);
+
+  // opened
+  EXPECT_CALL(item(0), GetOpened()).WillRepeatedly(Return(true));
+  info.opened = true;
+  item_observer()->OnDownloadUpdated(&item(0));
+  ExpectDownloadUpdated(info);
+}
+
 // Test creating a new item, saving it, removing it by setting it Temporary,
 // changing it without saving it back because it's Temporary, clearing
 // IsTemporary, saving it back, changing it, saving it back because it isn't
@@ -519,25 +634,10 @@
   ExpectWillQueryDownloads(scoped_ptr<InfoVector>(new InfoVector()));
 
   history::DownloadRow info;
-  base::FilePath path(FILE_PATH_LITERAL("/foo/bar.pdf"));
-  GURL url("http://example.com/bar.pdf");
-  GURL referrer("http://example.com/referrer.html");
-  std::vector<GURL> url_chain;
-  url_chain.push_back(url);
-  InitItem(base::RandInt(0, 1 << 20),
-           path,
-           path,
-           url_chain,
-           referrer,
-           (base::Time::Now() - base::TimeDelta::FromMinutes(10)),
-           (base::Time::Now() - base::TimeDelta::FromMinutes(1)),
-           100,
-           100,
-           content::DownloadItem::COMPLETE,
-           content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
-           content::DOWNLOAD_INTERRUPT_REASON_NONE,
-           false,
-           &info);
+  InitBasicItem(FILE_PATH_LITERAL("/foo/bar.pdf"),
+                "http://example.com/bar.pdf",
+                "http://example.com/referrer.html",
+                &info);
 
   // Pretend the manager just created |item|.
   CallOnDownloadCreated(0);
@@ -573,30 +673,14 @@
 }
 
 // Test removing downloads while they're still being added.
-TEST_F(DownloadHistoryTest,
-    DownloadHistoryTest_RemoveWhileAdding) {
+TEST_F(DownloadHistoryTest, DownloadHistoryTest_RemoveWhileAdding) {
   ExpectWillQueryDownloads(scoped_ptr<InfoVector>(new InfoVector()));
 
   history::DownloadRow info;
-  base::FilePath path(FILE_PATH_LITERAL("/foo/bar.pdf"));
-  GURL url("http://example.com/bar.pdf");
-  GURL referrer("http://example.com/referrer.html");
-  std::vector<GURL> url_chain;
-  url_chain.push_back(url);
-  InitItem(base::RandInt(0, 1 << 20),
-           path,
-           path,
-           url_chain,
-           referrer,
-           (base::Time::Now() - base::TimeDelta::FromMinutes(10)),
-           (base::Time::Now() - base::TimeDelta::FromMinutes(1)),
-           100,
-           100,
-           content::DownloadItem::COMPLETE,
-           content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
-           content::DOWNLOAD_INTERRUPT_REASON_NONE,
-           false,
-           &info);
+  InitBasicItem(FILE_PATH_LITERAL("/foo/bar.pdf"),
+                "http://example.com/bar.pdf",
+                "http://example.com/referrer.html",
+                &info);
 
   // Instruct CreateDownload() to not callback to DownloadHistory immediately,
   // but to wait for FinishCreateDownload().
@@ -631,44 +715,14 @@
   // Load a download from history, create the item, OnDownloadCreated,
   // OnDownloadUpdated, OnDownloadRemoved.
   history::DownloadRow info0, info1;
-  base::FilePath path0(FILE_PATH_LITERAL("/foo/bar.pdf"));
-  GURL url0("http://example.com/bar.pdf");
-  GURL referrer0("http://example.com/referrer.html");
-  std::vector<GURL> url0_chain;
-  url0_chain.push_back(url0);
-  InitItem(base::RandInt(0, 1 << 10),
-           path0,
-           path0,
-           url0_chain,
-           referrer0,
-           (base::Time::Now() - base::TimeDelta::FromMinutes(11)),
-           (base::Time::Now() - base::TimeDelta::FromMinutes(2)),
-           100,
-           100,
-           content::DownloadItem::COMPLETE,
-           content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
-           content::DOWNLOAD_INTERRUPT_REASON_NONE,
-           false,
-           &info0);
-  base::FilePath path1(FILE_PATH_LITERAL("/foo/qux.pdf"));
-  GURL url1("http://example.com/qux.pdf");
-  GURL referrer1("http://example.com/referrer.html");
-  std::vector<GURL> url1_chain;
-  url1_chain.push_back(url0);
-  InitItem(item(0).GetId() + base::RandInt(1, 1 << 10),
-           path1,
-           path1,
-           url1_chain,
-           referrer1,
-           (base::Time::Now() - base::TimeDelta::FromMinutes(10)),
-           (base::Time::Now() - base::TimeDelta::FromMinutes(1)),
-           200,
-           200,
-           content::DownloadItem::COMPLETE,
-           content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
-           content::DOWNLOAD_INTERRUPT_REASON_NONE,
-           false,
-           &info1);
+  InitBasicItem(FILE_PATH_LITERAL("/foo/bar.pdf"),
+                "http://example.com/bar.pdf",
+                "http://example.com/referrer.html",
+                &info0);
+  InitBasicItem(FILE_PATH_LITERAL("/foo/qux.pdf"),
+                "http://example.com/qux.pdf",
+                "http://example.com/referrer1.html",
+                &info1);
   {
     scoped_ptr<InfoVector> infos(new InfoVector());
     infos->push_back(info0);
@@ -696,25 +750,10 @@
   ExpectWillQueryDownloads(scoped_ptr<InfoVector>(new InfoVector()));
 
   history::DownloadRow info;
-  base::FilePath path(FILE_PATH_LITERAL("/foo/bar.pdf"));
-  GURL url("http://example.com/bar.pdf");
-  GURL referrer("http://example.com/referrer.html");
-  std::vector<GURL> url_chain;
-  url_chain.push_back(url);
-  InitItem(base::RandInt(0, 1 << 20),
-           path,
-           path,
-           url_chain,
-           referrer,
-           (base::Time::Now() - base::TimeDelta::FromMinutes(10)),
-           (base::Time::Now() - base::TimeDelta::FromMinutes(1)),
-           100,
-           100,
-           content::DownloadItem::COMPLETE,
-           content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
-           content::DOWNLOAD_INTERRUPT_REASON_NONE,
-           false,
-           &info);
+  InitBasicItem(FILE_PATH_LITERAL("/foo/bar.pdf"),
+                "http://example.com/bar.pdf",
+                "http://example.com/referrer.html",
+                &info);
 
   FailCreateDownload();
   // Pretend the manager just created |item|.
@@ -729,32 +768,16 @@
   EXPECT_TRUE(DownloadHistory::IsPersisted(&item(0)));
 }
 
-TEST_F(DownloadHistoryTest,
-    DownloadHistoryTest_UpdateWhileAdding) {
+TEST_F(DownloadHistoryTest, DownloadHistoryTest_UpdateWhileAdding) {
   // Create a fresh item not from history, OnDownloadCreated, OnDownloadUpdated,
   // OnDownloadRemoved.
   ExpectWillQueryDownloads(scoped_ptr<InfoVector>(new InfoVector()));
 
   history::DownloadRow info;
-  base::FilePath path(FILE_PATH_LITERAL("/foo/bar.pdf"));
-  GURL url("http://example.com/bar.pdf");
-  GURL referrer("http://example.com/referrer.html");
-  std::vector<GURL> url_chain;
-  url_chain.push_back(url);
-  InitItem(base::RandInt(0, 1 << 20),
-           path,
-           path,
-           url_chain,
-           referrer,
-           (base::Time::Now() - base::TimeDelta::FromMinutes(10)),
-           (base::Time::Now() - base::TimeDelta::FromMinutes(1)),
-           100,
-           100,
-           content::DownloadItem::COMPLETE,
-           content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
-           content::DOWNLOAD_INTERRUPT_REASON_NONE,
-           false,
-           &info);
+  InitBasicItem(FILE_PATH_LITERAL("/foo/bar.pdf"),
+                "http://example.com/bar.pdf",
+                "http://example.com/referrer.html",
+                &info);
 
   // Instruct CreateDownload() to not callback to DownloadHistory immediately,
   // but to wait for FinishCreateDownload().
diff --git a/chrome/browser/download/download_item_model.cc b/chrome/browser/download/download_item_model.cc
index b1c89fc..83c62f9 100644
--- a/chrome/browser/download/download_item_model.cc
+++ b/chrome/browser/download/download_item_model.cc
@@ -6,12 +6,14 @@
 
 #include "base/i18n/number_formatting.h"
 #include "base/i18n/rtl.h"
+#include "base/metrics/field_trial.h"
 #include "base/strings/string16.h"
 #include "base/strings/sys_string_conversions.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/supports_user_data.h"
 #include "base/time/time.h"
 #include "chrome/browser/download/download_crx_util.h"
+#include "chrome/browser/download/download_util.h"
 #include "chrome/browser/safe_browsing/download_feedback_service.h"
 #include "content/public/browser/download_danger_type.h"
 #include "content/public/browser/download_interrupt_reasons.h"
@@ -304,10 +306,15 @@
   string16 elided_filename =
       ui::ElideFilename(download_->GetFileNameToReportUser(), font, base_width);
   switch (download_->GetDangerType()) {
-    case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_URL:
-      return l10n_util::GetStringUTF16(IDS_PROMPT_MALICIOUS_DOWNLOAD_URL);
-
-    case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE:
+    case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_URL: {
+      std::string trial_condition =
+          base::FieldTrialList::FindFullName(download_util::kFinchTrialName);
+      if (trial_condition.empty())
+        return l10n_util::GetStringUTF16(IDS_PROMPT_MALICIOUS_DOWNLOAD_URL);
+      return download_util::AssembleMalwareFinchString(trial_condition,
+                                                       elided_filename);
+    }
+    case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE: {
       if (download_crx_util::IsExtensionDownload(*download_)) {
         return l10n_util::GetStringUTF16(
             IDS_PROMPT_DANGEROUS_DOWNLOAD_EXTENSION);
@@ -315,25 +322,32 @@
         return l10n_util::GetStringFUTF16(IDS_PROMPT_DANGEROUS_DOWNLOAD,
                                           elided_filename);
       }
-
+    }
     case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_CONTENT:
-    case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_HOST:
-      return l10n_util::GetStringFUTF16(IDS_PROMPT_MALICIOUS_DOWNLOAD_CONTENT,
-                                        elided_filename);
-
-    case content::DOWNLOAD_DANGER_TYPE_UNCOMMON_CONTENT:
+    case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_HOST: {
+      std::string trial_condition =
+          base::FieldTrialList::FindFullName(download_util::kFinchTrialName);
+      if (trial_condition.empty()) {
+        return l10n_util::GetStringFUTF16(IDS_PROMPT_MALICIOUS_DOWNLOAD_CONTENT,
+                                          elided_filename);
+      }
+      return download_util::AssembleMalwareFinchString(trial_condition,
+                                                       elided_filename);
+    }
+    case content::DOWNLOAD_DANGER_TYPE_UNCOMMON_CONTENT: {
       return l10n_util::GetStringFUTF16(IDS_PROMPT_UNCOMMON_DOWNLOAD_CONTENT,
                                         elided_filename);
-
-    case content::DOWNLOAD_DANGER_TYPE_POTENTIALLY_UNWANTED:
+    }
+    case content::DOWNLOAD_DANGER_TYPE_POTENTIALLY_UNWANTED: {
       return l10n_util::GetStringFUTF16(
           IDS_PROMPT_DOWNLOAD_CHANGES_SEARCH_SETTINGS, elided_filename);
-
+    }
     case content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS:
     case content::DOWNLOAD_DANGER_TYPE_MAYBE_DANGEROUS_CONTENT:
     case content::DOWNLOAD_DANGER_TYPE_USER_VALIDATED:
-    case content::DOWNLOAD_DANGER_TYPE_MAX:
+    case content::DOWNLOAD_DANGER_TYPE_MAX: {
       break;
+    }
   }
   NOTREACHED();
   return string16();
diff --git a/chrome/browser/download/download_resource_throttle.cc b/chrome/browser/download/download_resource_throttle.cc
index 7b7b162..1fae14d 100644
--- a/chrome/browser/download/download_resource_throttle.cc
+++ b/chrome/browser/download/download_resource_throttle.cc
@@ -5,7 +5,7 @@
 #include "chrome/browser/download/download_resource_throttle.h"
 
 #include "base/bind.h"
-#include "chrome/browser/download/download_util.h"
+#include "chrome/browser/download/download_stats.h"
 #include "content/public/browser/resource_controller.h"
 
 DownloadResourceThrottle::DownloadResourceThrottle(
@@ -63,9 +63,9 @@
   if (allow) {
     // Presumes all downloads initiated by navigation use this throttle and
     // nothing else does.
-    download_util::RecordDownloadSource(download_util::INITIATED_BY_NAVIGATION);
+    RecordDownloadSource(DOWNLOAD_INITIATED_BY_NAVIGATION);
   } else {
-    download_util::RecordDownloadCount(download_util::BLOCKED_BY_THROTTLING);
+    RecordDownloadCount(CHROME_DOWNLOAD_COUNT_BLOCKED_BY_THROTTLING);
   }
 
   if (request_deferred_) {
diff --git a/chrome/browser/download/download_stats.cc b/chrome/browser/download/download_stats.cc
new file mode 100644
index 0000000..042ac60
--- /dev/null
+++ b/chrome/browser/download/download_stats.cc
@@ -0,0 +1,32 @@
+// 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/download/download_stats.h"
+
+#include "base/metrics/histogram.h"
+
+void RecordDownloadShelfClose(int size, int in_progress, bool autoclose) {
+  static const int kMaxShelfSize = 16;
+  if (autoclose) {
+    UMA_HISTOGRAM_ENUMERATION(
+        "Download.ShelfSizeOnAutoClose", size, kMaxShelfSize);
+    UMA_HISTOGRAM_ENUMERATION(
+        "Download.ShelfInProgressSizeOnAutoClose", in_progress, kMaxShelfSize);
+  } else {
+    UMA_HISTOGRAM_ENUMERATION(
+        "Download.ShelfSizeOnUserClose", size, kMaxShelfSize);
+    UMA_HISTOGRAM_ENUMERATION(
+        "Download.ShelfInProgressSizeOnUserClose", in_progress, kMaxShelfSize);
+  }
+}
+
+void RecordDownloadCount(ChromeDownloadCountTypes type) {
+  UMA_HISTOGRAM_ENUMERATION(
+      "Download.CountsChrome", type, CHROME_DOWNLOAD_COUNT_TYPES_LAST_ENTRY);
+}
+
+void RecordDownloadSource(ChromeDownloadSource source) {
+  UMA_HISTOGRAM_ENUMERATION(
+      "Download.SourcesChrome", source, CHROME_DOWNLOAD_SOURCE_LAST_ENTRY);
+}
diff --git a/chrome/browser/download/download_stats.h b/chrome/browser/download/download_stats.h
new file mode 100644
index 0000000..50d2531
--- /dev/null
+++ b/chrome/browser/download/download_stats.h
@@ -0,0 +1,63 @@
+// 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_DOWNLOAD_DOWNLOAD_STATS_H_
+#define CHROME_BROWSER_DOWNLOAD_DOWNLOAD_STATS_H_
+
+// Record the total number of items and the number of in-progress items showing
+// in the shelf when it closes.  Set |autoclose| to true when the shelf is
+// closing itself, false when the user explicitly closed it.
+void RecordDownloadShelfClose(int size, int in_progress, bool autoclose);
+
+// Used for counting UMA stats. Similar to content's
+// download_stats::DownloadCountTypes but from the chrome layer.
+enum ChromeDownloadCountTypes {
+  // Stale enum values left around os that values passed to UMA don't
+  // change.
+  CHROME_DOWNLOAD_COUNT_UNUSED_0 = 0,
+  CHROME_DOWNLOAD_COUNT_UNUSED_1,
+  CHROME_DOWNLOAD_COUNT_UNUSED_2,
+  CHROME_DOWNLOAD_COUNT_UNUSED_3,
+
+  // A download *would* have been initiated, but it was blocked
+  // by the DownloadThrottlingResourceHandler.
+  CHROME_DOWNLOAD_COUNT_BLOCKED_BY_THROTTLING,
+
+  CHROME_DOWNLOAD_COUNT_TYPES_LAST_ENTRY
+};
+
+// Used for counting UMA stats. Similar to content's
+// download_stats::DownloadInitiattionSources but from the chrome layer.
+enum ChromeDownloadSource {
+  // The download was initiated by navigating to a URL (e.g. by user click).
+  DOWNLOAD_INITIATED_BY_NAVIGATION = 0,
+
+  // The download was initiated by invoking a context menu within a page.
+  DOWNLOAD_INITIATED_BY_CONTEXT_MENU,
+
+  // The download was initiated by the WebStore installer.
+  DOWNLOAD_INITIATED_BY_WEBSTORE_INSTALLER,
+
+  // The download was initiated by the ImageBurner (cros).
+  DOWNLOAD_INITIATED_BY_IMAGE_BURNER,
+
+  // The download was initiated by the plugin installer.
+  DOWNLOAD_INITIATED_BY_PLUGIN_INSTALLER,
+
+  // The download was initiated by the PDF plugin..
+  DOWNLOAD_INITIATED_BY_PDF_SAVE,
+
+  // The download was initiated by chrome.downloads.download().
+  DOWNLOAD_INITIATED_BY_EXTENSION,
+
+  CHROME_DOWNLOAD_SOURCE_LAST_ENTRY,
+};
+
+// Increment one of the above counts.
+void RecordDownloadCount(ChromeDownloadCountTypes type);
+
+// Record initiation of a download from a specific source.
+void RecordDownloadSource(ChromeDownloadSource source);
+
+#endif  // CHROME_BROWSER_DOWNLOAD_DOWNLOAD_STATS_H_
diff --git a/chrome/browser/download/download_util.cc b/chrome/browser/download/download_util.cc
index 8010f97..5b85b2a 100644
--- a/chrome/browser/download/download_util.cc
+++ b/chrome/browser/download/download_util.cc
@@ -13,7 +13,6 @@
 #include "base/i18n/rtl.h"
 #include "base/i18n/time_formatting.h"
 #include "base/lazy_instance.h"
-#include "base/metrics/histogram.h"
 #include "base/path_service.h"
 #include "base/strings/string16.h"
 #include "base/strings/string_number_conversions.h"
@@ -240,33 +239,64 @@
                                     speed_text, amount, time_remaining);
 }
 
-void RecordShelfClose(int size, int in_progress, bool autoclose) {
-  static const int kMaxShelfSize = 16;
-  if (autoclose) {
-    UMA_HISTOGRAM_ENUMERATION("Download.ShelfSizeOnAutoClose",
-                              size,
-                              kMaxShelfSize);
-    UMA_HISTOGRAM_ENUMERATION("Download.ShelfInProgressSizeOnAutoClose",
-                              in_progress,
-                              kMaxShelfSize);
+// Finch trial -----------------------------------------------------------------
+
+const char kFinchTrialName[] = "MalwareDownloadWarning";
+const char kCondition1Control[] = "Condition1Control";
+const char kCondition2Control[] = "Condition2Control";
+const char kCondition3Malicious[] = "Condition3Malicious";
+const char kCondition4Unsafe[] = "Condition4Unsafe";
+const char kCondition5Dangerous[] = "Condition5Dangerous";
+const char kCondition6Harmful[] = "Condition6Harmful";
+const char kCondition7DiscardSecond[] = "Condition7DiscardSecond";
+const char kCondition8DiscardFirst[] = "Condition8DiscardFirst";
+const char kCondition9SafeDiscard[] = "Condition9SafeDiscard";
+const char kCondition10SafeDontRun[] = "Condition10SafeDontRun";
+
+base::string16 AssembleMalwareFinchString(
+    const std::string& trial_condition, const base::string16& elided_filename) {
+  // Sanity check to make sure we have a filename.
+  base::string16 filename;
+  if (elided_filename.empty()) {
+    filename = ASCIIToUTF16("This file");
   } else {
-    UMA_HISTOGRAM_ENUMERATION("Download.ShelfSizeOnUserClose",
-                              size,
-                              kMaxShelfSize);
-    UMA_HISTOGRAM_ENUMERATION("Download.ShelfInProgressSizeOnUserClose",
-                              in_progress,
-                              kMaxShelfSize);
+    filename = ReplaceStringPlaceholders(ASCIIToUTF16("File '$1'"),
+                                         elided_filename,
+                                         NULL);
   }
-}
 
-void RecordDownloadCount(ChromeDownloadCountTypes type) {
-  UMA_HISTOGRAM_ENUMERATION(
-      "Download.CountsChrome", type, CHROME_DOWNLOAD_COUNT_TYPES_LAST_ENTRY);
-}
+  // Set the message text according to the condition.
+  if (trial_condition == kCondition1Control) {
+    return ASCIIToUTF16("This file appears malicious.");
+  }
+  base::string16 message_text;
+  if (trial_condition == kCondition2Control) {
+    message_text = ASCIIToUTF16("$1 appears malicious.");
+  } else if (trial_condition == kCondition3Malicious) {
+    message_text = ASCIIToUTF16("$1 is malicious.");
+  } else if (trial_condition == kCondition4Unsafe) {
+    message_text = ASCIIToUTF16("$1 is unsafe.");
+  } else if (trial_condition == kCondition5Dangerous) {
+    message_text = ASCIIToUTF16("$1 is dangerous.");
+  } else if (trial_condition == kCondition6Harmful) {
+    message_text = ASCIIToUTF16("$1 is harmful.");
+  } else if (trial_condition == kCondition7DiscardSecond) {
+    message_text = ASCIIToUTF16(
+        "$1 is malicious. Discard this file to stay safe.");
+  } else if (trial_condition == kCondition8DiscardFirst) {
+    message_text = ASCIIToUTF16(
+        "Discard this file to stay safe. $1 is malicious.");
+  } else if (trial_condition == kCondition9SafeDiscard) {
+    message_text = ASCIIToUTF16("$1 is malicious. To stay safe, discard it.");
+  } else if (trial_condition == kCondition10SafeDontRun) {
+    message_text = ASCIIToUTF16("$1 is malicious. To stay safe, don't run it.");
+  } else {
+    // We use the second control as a default for other conditions that don't
+    // change the warning string.
+    message_text = ASCIIToUTF16("$1 appears malicious.");
+  }
 
-void RecordDownloadSource(ChromeDownloadSource source) {
-  UMA_HISTOGRAM_ENUMERATION(
-      "Download.SourcesChrome", source, CHROME_DOWNLOAD_SOURCE_LAST_ENTRY);
+  return ReplaceStringPlaceholders(message_text, filename, NULL);
 }
 
 }  // namespace download_util
diff --git a/chrome/browser/download/download_util.h b/chrome/browser/download/download_util.h
index 60288a3..515bd82 100644
--- a/chrome/browser/download/download_util.h
+++ b/chrome/browser/download/download_util.h
@@ -13,6 +13,7 @@
 #include "base/files/file_path.h"
 #include "base/memory/ref_counted.h"
 #include "base/strings/string16.h"
+#include "base/strings/string_util.h"
 #include "ui/gfx/native_widget_types.h"
 
 #if defined(TOOLKIT_VIEWS)
@@ -60,60 +61,27 @@
 // Get the localized status text for an in-progress download.
 string16 GetProgressStatusText(content::DownloadItem* download);
 
-// Record the total number of items and the number of in-progress items showing
-// in the shelf when it closes.  Set |autoclose| to true when the shelf is
-// closing itself, false when the user explicitly closed it.
-void RecordShelfClose(int size, int in_progress, bool autoclose);
+// Summer/Fall 2013 Finch experiment strings -----------------------------------
+// Only deployed to English speakers, don't need translation.
 
-// Used for counting UMA stats. Similar to content's
-// download_stats::DownloadCountTypes but from the chrome layer.
-enum ChromeDownloadCountTypes {
-  // Stale enum values left around os that values passed to UMA don't
-  // change.
-  CHROME_DOWNLOAD_COUNT_UNUSED_0 = 0,
-  CHROME_DOWNLOAD_COUNT_UNUSED_1,
-  CHROME_DOWNLOAD_COUNT_UNUSED_2,
-  CHROME_DOWNLOAD_COUNT_UNUSED_3,
+// Study and condition names.
+extern const char kFinchTrialName[];
+extern const char kCondition1Control[];
+extern const char kCondition2Control[];
+extern const char kCondition3Malicious[];
+extern const char kCondition4Unsafe[];
+extern const char kCondition5Dangerous[];
+extern const char kCondition6Harmful[];
+extern const char kCondition7DiscardSecond[];
+extern const char kCondition8DiscardFirst[];
+extern const char kCondition9SafeDiscard[];
+extern const char kCondition10SafeDontRun[];
 
-  // A download *would* have been initiated, but it was blocked
-  // by the DownloadThrottlingResourceHandler.
-  BLOCKED_BY_THROTTLING,
-
-  CHROME_DOWNLOAD_COUNT_TYPES_LAST_ENTRY
-};
-
-// Used for counting UMA stats. Similar to content's
-// download_stats::DownloadInitiattionSources but from the chrome layer.
-enum ChromeDownloadSource {
-  // The download was initiated by navigating to a URL (e.g. by user click).
-  INITIATED_BY_NAVIGATION = 0,
-
-  // The download was initiated by invoking a context menu within a page.
-  INITIATED_BY_CONTEXT_MENU,
-
-  // The download was initiated by the WebStore installer.
-  INITIATED_BY_WEBSTORE_INSTALLER,
-
-  // The download was initiated by the ImageBurner (cros).
-  INITIATED_BY_IMAGE_BURNER,
-
-  // The download was initiated by the plugin installer.
-  INITIATED_BY_PLUGIN_INSTALLER,
-
-  // The download was initiated by the PDF plugin..
-  INITIATED_BY_PDF_SAVE,
-
-  // The download was initiated by chrome.downloads.download().
-  INITIATED_BY_EXTENSION,
-
-  CHROME_DOWNLOAD_SOURCE_LAST_ENTRY,
-};
-
-// Increment one of the above counts.
-void RecordDownloadCount(ChromeDownloadCountTypes type);
-
-// Record initiation of a download from a specific source.
-void RecordDownloadSource(ChromeDownloadSource source);
+// Helper for getting the appropriate message for a Finch trial.
+// You should only invoke this if you believe you're in the kFinchTrialName
+// finch trial; if you aren't, use the default string and don't invoke this.
+base::string16 AssembleMalwareFinchString(const std::string& trial_condition,
+                                          const string16& elided_filename);
 
 }  // namespace download_util
 
diff --git a/chrome/browser/download/download_util_unittest.cc b/chrome/browser/download/download_util_unittest.cc
new file mode 100644
index 0000000..841260b
--- /dev/null
+++ b/chrome/browser/download/download_util_unittest.cc
@@ -0,0 +1,20 @@
+// 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/download/download_util.h"
+
+#include "base/strings/string16.h"
+#include "base/strings/utf_string_conversions.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+TEST(DownloadUtilTest, FinchStrings) {
+  EXPECT_EQ(
+      ASCIIToUTF16("This file is malicious."),
+      download_util::AssembleMalwareFinchString(
+          download_util::kCondition3Malicious, string16()));
+  EXPECT_EQ(
+      ASCIIToUTF16("File 'malware.exe' is malicious."),
+      download_util::AssembleMalwareFinchString(
+          download_util::kCondition3Malicious, ASCIIToUTF16("malware.exe")));
+}
diff --git a/chrome/browser/drive/fake_drive_service.cc b/chrome/browser/drive/fake_drive_service.cc
index 74b8f2b..5fc49e3 100644
--- a/chrome/browser/drive/fake_drive_service.cc
+++ b/chrome/browser/drive/fake_drive_service.cc
@@ -216,7 +216,12 @@
 bool FakeDriveService::LoadAccountMetadataForWapi(
     const std::string& relative_path) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-  account_metadata_value_ = test_util::LoadJSONFile(relative_path);
+
+  // Load JSON data, which must be a dictionary.
+  scoped_ptr<base::Value> value = test_util::LoadJSONFile(relative_path);
+  CHECK_EQ(base::Value::TYPE_DICTIONARY, value->GetType());
+  account_metadata_value_.reset(
+      static_cast<base::DictionaryValue*>(value.release()));
 
   // Update the largest_changestamp_.
   scoped_ptr<AccountMetadata> account_metadata =
@@ -248,6 +253,16 @@
   return app_info_value_;
 }
 
+void FakeDriveService::SetQuotaValue(int64 used, int64 total) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK(account_metadata_value_);
+
+  account_metadata_value_->SetString("entry.gd$quotaBytesUsed.$t",
+                                     base::Int64ToString16(used));
+  account_metadata_value_->SetString("entry.gd$quotaBytesTotal.$t",
+                                     base::Int64ToString16(total));
+}
+
 GURL FakeDriveService::GetFakeLinkUrl(const std::string& resource_id) {
   return GURL("https://fake_server/" + net::EscapePath(resource_id));
 }
diff --git a/chrome/browser/drive/fake_drive_service.h b/chrome/browser/drive/fake_drive_service.h
index b2eb5fc..994bc53 100644
--- a/chrome/browser/drive/fake_drive_service.h
+++ b/chrome/browser/drive/fake_drive_service.h
@@ -52,6 +52,9 @@
     share_url_base_ = share_url_base;
   }
 
+  // Changes the quota fields returned from GetAboutResource().
+  void SetQuotaValue(int64 used, int64 total);
+
   // Returns the largest changestamp, which starts from 0 by default. See
   // also comments at LoadAccountMetadataForWapi().
   int64 largest_changestamp() const { return largest_changestamp_; }
@@ -270,7 +273,7 @@
   GURL GetNewUploadSessionUrl();
 
   scoped_ptr<base::DictionaryValue> resource_list_value_;
-  scoped_ptr<base::Value> account_metadata_value_;
+  scoped_ptr<base::DictionaryValue> account_metadata_value_;
   scoped_ptr<base::Value> app_info_value_;
   std::map<GURL, UploadSession> upload_sessions_;
   int64 largest_changestamp_;
diff --git a/chrome/browser/extensions/DEPS b/chrome/browser/extensions/DEPS
index 290e2e5..d16e654 100644
--- a/chrome/browser/extensions/DEPS
+++ b/chrome/browser/extensions/DEPS
@@ -8,6 +8,7 @@
   "+apps/launcher.h",
   "+apps/native_app_window.h",
   "+apps/shell_window.h",
+  "+apps/shell_window_registry.h",
 
   # TODO(tfarina): Remove all these. crbug.com/125846.
   # DO NOT ADD ANY MORE ITEMS TO THE LIST BELOW!
diff --git a/chrome/browser/extensions/activity_log/activity_actions.cc b/chrome/browser/extensions/activity_log/activity_actions.cc
index 1d79225..4baca4c 100644
--- a/chrome/browser/extensions/activity_log/activity_actions.cc
+++ b/chrome/browser/extensions/activity_log/activity_actions.cc
@@ -11,9 +11,9 @@
 #include "base/logging.h"
 #include "base/memory/singleton.h"
 #include "base/strings/string_number_conversions.h"
+#include "base/strings/string_util.h"
 #include "base/strings/stringprintf.h"
 #include "chrome/browser/extensions/activity_log/activity_action_constants.h"
-#include "chrome/browser/extensions/activity_log/api_name_constants.h"
 #include "chrome/browser/extensions/activity_log/fullstream_ui_policy.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/common/chrome_switches.h"
@@ -36,63 +36,6 @@
   return value_as_text;
 }
 
-// Sets up the hashmap for mapping extension strings to "ints". The hashmap is
-// only set up once because it's quite long; the value is then cached.
-class APINameMap {
- public:
-  APINameMap() {
-    SetupMap();
-  }
-
-  // activity_log_api_name_constants.h lists all known API calls as of 5/17.
-  // This code maps each of those API calls (and events) to short strings
-  // (integers converted to strings). They're all strings because (1) sqlite
-  // databases are all strings underneath anyway and (2) the Lookup function
-  // will simply return the original api_call string if we don't have it in our
-  // lookup table.
-  void SetupMap() {
-    for (size_t i = 0;
-         i < arraysize(activity_log_api_name_constants::kNames);
-         ++i) {
-      std::string name =
-          std::string(activity_log_api_name_constants::kNames[i]);
-      std::string num = base::IntToString(i);
-      names_to_nums_[name] = num;
-      nums_to_names_[num] = name;
-    }
-  }
-
-  static APINameMap* GetInstance() {
-    return Singleton<APINameMap>::get();
-  }
-
-  // This matches an api call to a number, if it's in the lookup table. If not,
-  // it returns the original api call.
-  const std::string& ApiToShortname(const std::string& api_call) {
-    std::map<std::string, std::string>::iterator it =
-        names_to_nums_.find(api_call);
-    if (it == names_to_nums_.end())
-      return api_call;
-    else
-      return it->second;
-  }
-
-  // This matches a number to an API call -- it's the opposite of
-  // ApiToShortname.
-  const std::string& ShortnameToApi(const std::string& shortname) {
-    std::map<std::string, std::string>::iterator it =
-        nums_to_names_.find(shortname);
-    if (it == nums_to_names_.end())
-      return shortname;
-    else
-      return it->second;
-  }
-
- private:
-  std::map<std::string, std::string> names_to_nums_;  // <name, number label>
-  std::map<std::string, std::string> nums_to_names_;  // <number label, name>
-};
-
 }  // namespace
 
 namespace extensions {
@@ -163,6 +106,30 @@
   return other_.get();
 }
 
+std::string Action::SerializePageUrl() const {
+  return (page_incognito() ? constants::kIncognitoUrl : "") + page_url().spec();
+}
+
+void Action::ParsePageUrl(const std::string& url) {
+  set_page_incognito(StartsWithASCII(url, constants::kIncognitoUrl, true));
+  if (page_incognito())
+    set_page_url(GURL(url.substr(strlen(constants::kIncognitoUrl))));
+  else
+    set_page_url(GURL(url));
+}
+
+std::string Action::SerializeArgUrl() const {
+  return (arg_incognito() ? constants::kIncognitoUrl : "") + arg_url().spec();
+}
+
+void Action::ParseArgUrl(const std::string& url) {
+  set_arg_incognito(StartsWithASCII(url, constants::kIncognitoUrl, true));
+  if (arg_incognito())
+    set_arg_url(GURL(url.substr(strlen(constants::kIncognitoUrl))));
+  else
+    set_arg_url(GURL(url));
+}
+
 scoped_ptr<ExtensionActivity> Action::ConvertToExtensionActivity() {
   scoped_ptr<ExtensionActivity> result(new ExtensionActivity);
 
@@ -246,7 +213,7 @@
   return result.Pass();
 }
 
-std::string Action::PrintForDebug() {
+std::string Action::PrintForDebug() const {
   std::string result = "ID=" + extension_id() + " CATEGORY=";
   switch (action_type_) {
     case ACTION_API_CALL:
diff --git a/chrome/browser/extensions/activity_log/activity_actions.h b/chrome/browser/extensions/activity_log/activity_actions.h
index 6782b83..8e3e31c 100644
--- a/chrome/browser/extensions/activity_log/activity_actions.h
+++ b/chrome/browser/extensions/activity_log/activity_actions.h
@@ -98,12 +98,20 @@
   void set_other(scoped_ptr<DictionaryValue> other);
   DictionaryValue* mutable_other();
 
+  // Helper methods for serializing and deserializing URLs into strings.  If
+  // the URL is marked as incognito, then the string is prefixed with
+  // kIncognitoUrl ("<incognito>").
+  std::string SerializePageUrl() const;
+  void ParsePageUrl(const std::string& url);
+  std::string SerializeArgUrl() const;
+  void ParseArgUrl(const std::string& url);
+
   // Flatten the activity's type-specific fields into an ExtensionActivity.
   scoped_ptr<api::activity_log_private::ExtensionActivity>
       ConvertToExtensionActivity();
 
   // Print an action as a regular string for debugging purposes.
-  std::string PrintForDebug();
+  virtual std::string PrintForDebug() const;
 
  protected:
   virtual ~Action();
diff --git a/chrome/browser/extensions/activity_log/activity_database.cc b/chrome/browser/extensions/activity_log/activity_database.cc
index 810c758..7679d15 100644
--- a/chrome/browser/extensions/activity_log/activity_database.cc
+++ b/chrome/browser/extensions/activity_log/activity_database.cc
@@ -91,8 +91,10 @@
   SoftFailureClose();
 }
 
-void ActivityDatabase::NotifyAction() {
-  if (valid_db_ && !batch_mode_) {
+void ActivityDatabase::AdviseFlush(int size) {
+  if (!valid_db_)
+    return;
+  if (!batch_mode_ || size == kFlushImmediately) {
     if (!delegate_->FlushDatabase(&db_))
       SoftFailureClose();
   }
diff --git a/chrome/browser/extensions/activity_log/activity_database.h b/chrome/browser/extensions/activity_log/activity_database.h
index ea2cff9..30b32f7 100644
--- a/chrome/browser/extensions/activity_log/activity_database.h
+++ b/chrome/browser/extensions/activity_log/activity_database.h
@@ -75,10 +75,13 @@
 
     // Initializes the database schema; this gives a policy a chance to create
     // or update database tables as needed.  Should return true on success.
+    // Will be called from within a database transaction.
     virtual bool InitDatabase(sql::Connection* db) = 0;
 
     // Requests that the policy flush any pending actions to the database.
-    // Should return true on success or false on a database error.
+    // Should return true on success or false on a database error.  Will not be
+    // called from a transaction (the implementation may wish to use a
+    // transaction for the flush).
     virtual bool FlushDatabase(sql::Connection* db) = 0;
 
     // Called if the database encounters a permanent error; the policy should
@@ -93,6 +96,9 @@
     virtual void OnDatabaseClose() = 0;
   };
 
+  // Value to be passed to AdviseFlush below to force a database flush.
+  static const int kFlushImmediately = -1;
+
   // Need to call Init to actually use the ActivityDatabase.  The Delegate
   // provides hooks for an ActivityLogPolicy to control the database schema and
   // reads/writes.
@@ -106,11 +112,13 @@
   void Close();
 
   // Inform the database that there may be additional data which could be
-  // written out.
-  // TODO(mvrable): Add a method to force a database flush, or perhaps pass
-  // hints to the database about how much data is queued up so the database can
-  // flush before the timeout if there is a large amount of data?
-  void NotifyAction();
+  // written out.  The size parameter should indicate (approximately) how many
+  // records are queued to be written; the database may use this information to
+  // schedule a flush early if too much data is queueing up.  A value of
+  // kFlushImmediately will force an immediate call into
+  // Delegate::FlushDatabase(); otherwise, it is up to the database to
+  // determine when to flush.
+  void AdviseFlush(int size);
 
   // Turns off batch I/O writing mode. This should only be used in unit tests,
   // browser tests, or in our special --enable-extension-activity-log-testing
@@ -188,6 +196,7 @@
   friend class ActivityLogDatabasePolicy;
   FRIEND_TEST_ALL_PREFIXES(ActivityDatabaseTest, BatchModeOff);
   FRIEND_TEST_ALL_PREFIXES(ActivityDatabaseTest, BatchModeOn);
+  FRIEND_TEST_ALL_PREFIXES(ActivityDatabaseTest, BatchModeFlush);
   DISALLOW_COPY_AND_ASSIGN(ActivityDatabase);
 };
 
diff --git a/chrome/browser/extensions/activity_log/activity_database_unittest.cc b/chrome/browser/extensions/activity_log/activity_database_unittest.cc
index b8f9d91..5894999 100644
--- a/chrome/browser/extensions/activity_log/activity_database_unittest.cc
+++ b/chrome/browser/extensions/activity_log/activity_database_unittest.cc
@@ -103,7 +103,7 @@
 void ActivityDatabaseTestPolicy::Record(ActivityDatabase* db,
                                         scoped_refptr<Action> action) {
   queue_.push_back(action);
-  db->NotifyAction();
+  db->AdviseFlush(queue_.size());
 }
 
 class ActivityDatabaseTest : public ChromeRenderViewHostTestHarness {
@@ -151,7 +151,8 @@
     std::string sql_str = "SELECT COUNT(*) FROM " +
                           std::string(ActivityDatabaseTestPolicy::kTableName) +
                           " WHERE api_name LIKE ?";
-    sql::Statement statement(db->GetUniqueStatement(sql_str.c_str()));
+    sql::Statement statement(db->GetCachedStatement(
+        sql::StatementID(SQL_FROM_HERE), sql_str.c_str()));
     statement.BindString(0, api_name_pattern);
     if (!statement.Step())
       return -1;
@@ -246,6 +247,27 @@
   activity_db->Close();
 }
 
+TEST_F(ActivityDatabaseTest, BatchModeFlush) {
+  base::ScopedTempDir temp_dir;
+  base::FilePath db_file;
+  ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
+  db_file = temp_dir.path().AppendASCII("ActivityFlush.db");
+  base::DeleteFile(db_file, false);
+
+  // Record some actions
+  ActivityDatabase* activity_db = OpenDatabase(db_file);
+  activity_db->SetBatchModeForTesting(true);
+  scoped_refptr<Action> action = CreateAction(base::Time::Now(), "brewster");
+  Record(activity_db, action);
+  ASSERT_EQ(0, CountActions(&activity_db->db_, "brewster"));
+
+  // Request an immediate database flush.
+  activity_db->AdviseFlush(ActivityDatabase::kFlushImmediately);
+  ASSERT_EQ(1, CountActions(&activity_db->db_, "brewster"));
+
+  activity_db->Close();
+}
+
 // Check that nothing explodes if the DB isn't initialized.
 TEST_F(ActivityDatabaseTest, InitFailure) {
   base::ScopedTempDir temp_dir;
diff --git a/chrome/browser/extensions/activity_log/activity_log.cc b/chrome/browser/extensions/activity_log/activity_log.cc
index 2b81ed5..bc973e7 100644
--- a/chrome/browser/extensions/activity_log/activity_log.cc
+++ b/chrome/browser/extensions/activity_log/activity_log.cc
@@ -14,7 +14,8 @@
 #include "base/strings/utf_string_conversions.h"
 #include "base/threading/thread_checker.h"
 #include "chrome/browser/extensions/activity_log/activity_action_constants.h"
-#include "chrome/browser/extensions/activity_log/stream_noargs_ui_policy.h"
+#include "chrome/browser/extensions/activity_log/counting_policy.h"
+#include "chrome/browser/extensions/activity_log/fullstream_ui_policy.h"
 #include "chrome/browser/extensions/api/activity_log_private/activity_log_private_api.h"
 #include "chrome/browser/extensions/extension_service.h"
 #include "chrome/browser/extensions/extension_system.h"
@@ -240,8 +241,8 @@
       case ActivityLogPolicy::POLICY_FULLSTREAM:
         policy_ = new FullStreamUIPolicy(profile_);
         break;
-      case ActivityLogPolicy::POLICY_NOARGS:
-        policy_ = new StreamWithoutArgsUIPolicy(profile_);
+      case ActivityLogPolicy::POLICY_COUNTS:
+        policy_ = new CountingPolicy(profile_);
         break;
       default:
         NOTREACHED();
@@ -302,7 +303,7 @@
   if (testing_mode_)
     SetDefaultPolicy(ActivityLogPolicy::POLICY_FULLSTREAM);
   else
-    SetDefaultPolicy(ActivityLogPolicy::POLICY_NOARGS);
+    SetDefaultPolicy(ActivityLogPolicy::POLICY_COUNTS);
 }
 
 void ActivityLog::Shutdown() {
diff --git a/chrome/browser/extensions/activity_log/activity_log_policy.cc b/chrome/browser/extensions/activity_log/activity_log_policy.cc
index 3e8b889..c02da5e 100644
--- a/chrome/browser/extensions/activity_log/activity_log_policy.cc
+++ b/chrome/browser/extensions/activity_log/activity_log_policy.cc
@@ -7,9 +7,12 @@
 #include <stdint.h>
 
 #include "base/files/file_path.h"
+#include "base/json/json_string_value_serializer.h"
 #include "base/logging.h"
+#include "base/strings/stringprintf.h"
 #include "base/time/clock.h"
 #include "base/time/time.h"
+#include "chrome/browser/extensions/activity_log/activity_action_constants.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/common/extensions/extension.h"
 #include "content/public/browser/browser_thread.h"
@@ -17,12 +20,25 @@
 
 using content::BrowserThread;
 
+namespace constants = activity_log_constants;
+
+namespace {
+// Obsolete database tables: these should be dropped from the database if
+// found.
+const char* kObsoleteTables[] = {"activitylog_apis", "activitylog_blocked",
+                                 "activitylog_urls"};
+}  // namespace
+
 namespace extensions {
 
-ActivityLogPolicy::ActivityLogPolicy(Profile* profile) : testing_clock_(NULL) {}
+ActivityLogPolicy::ActivityLogPolicy(Profile* profile) {}
 
 ActivityLogPolicy::~ActivityLogPolicy() {}
 
+void ActivityLogPolicy::SetClockForTesting(scoped_ptr<base::Clock> clock) {
+  testing_clock_.reset(clock.release());
+}
+
 base::Time ActivityLogPolicy::Now() const {
   if (testing_clock_)
     return testing_clock_->Now();
@@ -30,10 +46,6 @@
     return base::Time::Now();
 }
 
-std::string ActivityLogPolicy::GetKey(KeyType) const {
-  return std::string();
-}
-
 ActivityLogDatabasePolicy::ActivityLogDatabasePolicy(
     Profile* profile,
     const base::FilePath& database_name)
@@ -49,4 +61,111 @@
   return db_->GetSqlConnection();
 }
 
+// static
+std::string ActivityLogPolicy::Util::Serialize(const base::Value* value) {
+  std::string value_as_text;
+  if (!value) {
+    value_as_text = "";
+  } else {
+    JSONStringValueSerializer serializer(&value_as_text);
+    serializer.SerializeAndOmitBinaryValues(*value);
+  }
+  return value_as_text;
+}
+
+// static
+void ActivityLogPolicy::Util::StripPrivacySensitiveFields(
+    scoped_refptr<Action> action) {
+  // Clear incognito URLs/titles.
+  if (action->page_incognito()) {
+    action->set_page_url(GURL());
+    action->set_page_title("");
+  }
+  if (action->arg_incognito()) {
+    action->set_arg_url(GURL());
+  }
+
+  // Strip query parameters, username/password, etc., from URLs.
+  if (action->page_url().is_valid() || action->arg_url().is_valid()) {
+    url_canon::Replacements<char> url_sanitizer;
+    url_sanitizer.ClearUsername();
+    url_sanitizer.ClearPassword();
+    url_sanitizer.ClearQuery();
+    url_sanitizer.ClearRef();
+
+    if (action->page_url().is_valid())
+      action->set_page_url(action->page_url().ReplaceComponents(url_sanitizer));
+    if (action->arg_url().is_valid())
+      action->set_arg_url(action->arg_url().ReplaceComponents(url_sanitizer));
+  }
+
+  // Clear WebRequest details; only keep a record of which types of
+  // modifications were performed.
+  if (action->action_type() == Action::ACTION_WEB_REQUEST) {
+    DictionaryValue* details = NULL;
+    if (action->mutable_other()->GetDictionary(constants::kActionWebRequest,
+                                               &details)) {
+      DictionaryValue::Iterator details_iterator(*details);
+      while (!details_iterator.IsAtEnd()) {
+        details->SetBoolean(details_iterator.key(), true);
+        details_iterator.Advance();
+      }
+    }
+  }
+}
+
+// static
+void ActivityLogPolicy::Util::StripArguments(
+    const std::set<std::string>& api_whitelist,
+    scoped_refptr<Action> action) {
+  if (action->action_type() != Action::ACTION_API_CALL &&
+      action->action_type() != Action::ACTION_API_EVENT &&
+      action->action_type() != Action::ACTION_API_BLOCKED)
+    return;
+
+  if (api_whitelist.find(action->api_name()) == api_whitelist.end())
+    action->set_args(scoped_ptr<ListValue>());
+}
+
+// static
+base::Time ActivityLogPolicy::Util::AddDays(const base::Time& base_date,
+                                            int days) {
+  // To allow for time zone changes, add an additional partial day then round
+  // down to midnight.
+  return (base_date + base::TimeDelta::FromDays(days) +
+          base::TimeDelta::FromHours(4)).LocalMidnight();
+}
+
+// static
+void ActivityLogPolicy::Util::ComputeDatabaseTimeBounds(const base::Time& now,
+                                                        int days_ago,
+                                                        int64* early_bound,
+                                                        int64* late_bound) {
+  base::Time morning_midnight = now.LocalMidnight();
+  if (days_ago == 0) {
+      *early_bound = morning_midnight.ToInternalValue();
+      *late_bound = base::Time::Max().ToInternalValue();
+  } else {
+      base::Time early_time = Util::AddDays(morning_midnight, -days_ago);
+      base::Time late_time = Util::AddDays(early_time, 1);
+      *early_bound = early_time.ToInternalValue();
+      *late_bound = late_time.ToInternalValue();
+  }
+}
+
+// static
+bool ActivityLogPolicy::Util::DropObsoleteTables(sql::Connection* db) {
+  for (size_t i = 0; i < arraysize(kObsoleteTables); i++) {
+    const char* table_name = kObsoleteTables[i];
+    if (db->DoesTableExist(table_name)) {
+      std::string drop_statement =
+          base::StringPrintf("DROP TABLE %s", table_name);
+      if (!db->Execute(drop_statement.c_str())) {
+        return false;
+      }
+    }
+  }
+  return true;
+}
+
 }  // namespace extensions
diff --git a/chrome/browser/extensions/activity_log/activity_log_policy.h b/chrome/browser/extensions/activity_log/activity_log_policy.h
index e8421dc..ebfdf4e 100644
--- a/chrome/browser/extensions/activity_log/activity_log_policy.h
+++ b/chrome/browser/extensions/activity_log/activity_log_policy.h
@@ -5,6 +5,7 @@
 #ifndef CHROME_BROWSER_EXTENSIONS_ACTIVITY_LOG_ACTIVITY_LOG_POLICY_H_
 #define CHROME_BROWSER_EXTENSIONS_ACTIVITY_LOG_ACTIVITY_LOG_POLICY_H_
 
+#include <set>
 #include <string>
 
 #include "base/bind.h"
@@ -51,23 +52,10 @@
  public:
   enum PolicyType {
     POLICY_FULLSTREAM,
-    POLICY_NOARGS,
+    POLICY_COUNTS,
     POLICY_INVALID,
   };
 
-  // For all subclasses, add all the key types they might support here.
-  // The actual key is returned by calling GetKey(KeyType).  The subclasses
-  // are free to return an empty string for keys they don't support.
-  // For every key added here, you should update the GetKey member function
-  // for at least one policy.
-  enum KeyType {
-    PARAM_KEY_REASON,      // Why an action was blocked
-    PARAM_KEY_DOM_ACTION,  // Getter, Setter, Method,...
-    PARAM_KEY_URL_TITLE,
-    PARAM_KEY_DETAILS_STRING,
-    PARAM_KEY_EXTRA,
-  };
-
   // Parameters are the profile and the thread that will be used to execute
   // the callback when ReadData is called.
   // TODO(felt,dbabic)  Since only ReadData uses thread_id, it would be
@@ -99,10 +87,52 @@
       const base::Callback
           <void(scoped_ptr<Action::ActionVector>)>& callback) = 0;
 
-  virtual std::string GetKey(KeyType key_id) const;
-
   // For unit testing only.
-  void SetClockForTesting(base::Clock* clock) { testing_clock_ = clock; }
+  void SetClockForTesting(scoped_ptr<base::Clock> clock);
+
+  // A collection of methods that are useful for implementing policies.  These
+  // are all static methods; the ActivityLogPolicy::Util class cannot be
+  // instantiated.  This is nested within ActivityLogPolicy to make calling
+  // these methods more convenient from within a policy, but they are public.
+  class Util {
+   public:
+    // Serialize a Value as a JSON string.  Returns an empty string if value is
+    // null.
+    static std::string Serialize(const base::Value* value);
+
+    // Removes potentially privacy-sensitive data that should not be logged.
+    // This should generally be called on an Action before logging, unless
+    // debugging flags are enabled.  Modifies the Action object in place; if
+    // the action might be shared with other users, it is up to the caller to
+    // call ->Clone() first.
+    static void StripPrivacySensitiveFields(scoped_refptr<Action> action);
+
+    // Strip arguments from most API actions, preserving actions only for a
+    // whitelisted set.  Modifies the Action object in-place.
+    static void StripArguments(const std::set<std::string>& api_whitelist,
+                               scoped_refptr<Action> action);
+
+    // Given a base day (timestamp at local midnight), computes the timestamp
+    // at midnight the given number of days before or after.
+    static base::Time AddDays(const base::Time& base_date, int days);
+
+    // Compute the time bounds that should be used for a database query to
+    // cover a time range days_ago days in the past, relative to the specified
+    // time.
+    static void ComputeDatabaseTimeBounds(const base::Time& now,
+                                          int days_ago,
+                                          int64* early_bound,
+                                          int64* late_bound);
+
+    // Deletes obsolete database tables from an activity log database.  This
+    // can be used in InitDatabase() methods of ActivityLogDatabasePolicy
+    // subclasses to clean up data from old versions of the activity logging
+    // code.  Returns true on success, false on database error.
+    static bool DropObsoleteTables(sql::Connection* db);
+
+   private:
+    DISALLOW_IMPLICIT_CONSTRUCTORS(Util);
+  };
 
  protected:
   // An ActivityLogPolicy is not directly destroyed.  Instead, call Close()
@@ -118,7 +148,7 @@
   // Support for a mock clock for testing purposes.  This is used by ReadData
   // to determine the date for "today" when when interpreting date ranges to
   // fetch.  This has no effect on batching of writes to the database.
-  base::Clock* testing_clock_;
+  scoped_ptr<base::Clock> testing_clock_;
 
   DISALLOW_COPY_AND_ASSIGN(ActivityLogPolicy);
 };
diff --git a/chrome/browser/extensions/activity_log/activity_log_policy_unittest.cc b/chrome/browser/extensions/activity_log/activity_log_policy_unittest.cc
new file mode 100644
index 0000000..7b0e078
--- /dev/null
+++ b/chrome/browser/extensions/activity_log/activity_log_policy_unittest.cc
@@ -0,0 +1,102 @@
+// 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/values.h"
+#include "chrome/browser/extensions/activity_log/activity_action_constants.h"
+#include "chrome/browser/extensions/activity_log/activity_actions.h"
+#include "chrome/browser/extensions/activity_log/activity_log_policy.h"
+#include "chrome/browser/extensions/activity_log/web_request_constants.h"
+#include "chrome/common/extensions/value_builder.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace extensions {
+
+class ActivityLogPolicyUtilTest : public testing::Test {};
+
+// Test that incognito values are stripped, and non-incognito ones aren't.
+TEST_F(ActivityLogPolicyUtilTest, StripPrivacySensitive) {
+  scoped_refptr<Action> action =
+      new Action("punky",
+                 base::Time::Now(),
+                 Action::ACTION_API_CALL,
+                 "tabs.executeScript");
+  action->mutable_args()->AppendString("woof");
+  action->set_page_url(GURL("http://www.google.com/"));
+  action->set_page_incognito(true);
+  action->set_page_title("private");
+  action->set_arg_url(GURL("http://www.youtube.com/?privatekey"));
+
+  ASSERT_EQ("<incognito>http://www.google.com/", action->SerializePageUrl());
+
+  ActivityLogPolicy::Util::StripPrivacySensitiveFields(action);
+
+  ASSERT_FALSE(action->page_url().is_valid());
+  ASSERT_EQ("<incognito>", action->SerializePageUrl());
+  ASSERT_EQ("", action->page_title());
+  ASSERT_EQ("http://www.youtube.com/", action->arg_url().spec());
+}
+
+// Test that WebRequest details are stripped for privacy.
+TEST_F(ActivityLogPolicyUtilTest, StripPrivacySensitiveWebRequest) {
+  scoped_refptr<Action> action = new Action(
+      "punky", base::Time::Now(), Action::ACTION_WEB_REQUEST, "webRequest");
+  action->mutable_other()->Set(
+      activity_log_constants::kActionWebRequest,
+      DictionaryBuilder()
+          .Set(activity_log_web_request_constants::kNewUrlKey,
+               "http://www.youtube.com/")
+          .Set(activity_log_web_request_constants::kAddedRequestHeadersKey,
+               ListBuilder().Append("arg"))
+          .Build().release());
+
+  ActivityLogPolicy::Util::StripPrivacySensitiveFields(action);
+
+  ASSERT_EQ(
+      "{\"web_request\":{\"added_request_headers\":true,\"new_url\":true}}",
+      ActivityLogPolicy::Util::Serialize(action->other()));
+}
+
+// Test that argument values are stripped as appropriate.
+TEST_F(ActivityLogPolicyUtilTest, StripArguments) {
+  std::set<std::string> whitelist;
+  whitelist.insert("tabs.executeScript");
+
+  // API is in whitelist; not stripped.
+  scoped_refptr<Action> action =
+      new Action("punky",
+                 base::Time::Now(),
+                 Action::ACTION_API_CALL,
+                 "tabs.executeScript");
+  action->mutable_args()->AppendString("woof");
+  ActivityLogPolicy::Util::StripArguments(whitelist, action);
+  ASSERT_EQ("[\"woof\"]", ActivityLogPolicy::Util::Serialize(action->args()));
+
+  // Not in whitelist: stripped.
+  action = new Action(
+      "punky", base::Time::Now(), Action::ACTION_API_CALL, "tabs.create");
+  action->mutable_args()->AppendString("woof");
+  ActivityLogPolicy::Util::StripArguments(whitelist, action);
+  ASSERT_EQ("", ActivityLogPolicy::Util::Serialize(action->args()));
+
+  // Not an API type: not stripped.
+  action = new Action(
+      "punky", base::Time::Now(), Action::ACTION_DOM_ACCESS, "tabs.create");
+  action->mutable_args()->AppendString("woof");
+  ActivityLogPolicy::Util::StripArguments(whitelist, action);
+  ASSERT_EQ("[\"woof\"]", ActivityLogPolicy::Util::Serialize(action->args()));
+}
+
+// Test parsing of URLs serialized to strings.
+TEST_F(ActivityLogPolicyUtilTest, ParseUrls) {
+  scoped_refptr<Action> action =
+      new Action("punky",
+                 base::Time::Now(),
+                 Action::ACTION_API_CALL,
+                 "tabs.executeScript");
+  action->ParsePageUrl("<incognito>http://www.google.com/");
+  EXPECT_EQ("http://www.google.com/", action->page_url().spec());
+  EXPECT_TRUE(action->page_incognito());
+}
+
+}  // namespace extensions
diff --git a/chrome/browser/extensions/activity_log/activity_log_unittest.cc b/chrome/browser/extensions/activity_log/activity_log_unittest.cc
index 118cb4d..25c9cea 100644
--- a/chrome/browser/extensions/activity_log/activity_log_unittest.cc
+++ b/chrome/browser/extensions/activity_log/activity_log_unittest.cc
@@ -81,7 +81,7 @@
     if (log_arguments)
       activity_log->SetDefaultPolicy(ActivityLogPolicy::POLICY_FULLSTREAM);
     else
-      activity_log->SetDefaultPolicy(ActivityLogPolicy::POLICY_NOARGS);
+      activity_log->SetDefaultPolicy(ActivityLogPolicy::POLICY_COUNTS);
   }
 
   static void Arguments_Prerender(
diff --git a/chrome/browser/extensions/activity_log/api_name_constants.h b/chrome/browser/extensions/activity_log/api_name_constants.h
deleted file mode 100644
index d745b66..0000000
--- a/chrome/browser/extensions/activity_log/api_name_constants.h
+++ /dev/null
@@ -1,214 +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.
-
-// Constants used in api_actions.cc.
-
-#ifndef CHROME_BROWSER_EXTENSIONS_ACTIVITY_LOG_API_NAME_CONSTANTS_H_
-#define CHROME_BROWSER_EXTENSIONS_ACTIVITY_LOG_API_NAME_CONSTANTS_H_
-
-namespace activity_log_api_name_constants {
-
-// All of the chrome.* API names and events. ADD TO THE END. Do not remove any!
-const char* const kNames[] = {
-    "alarms.clear", "alarms.clearAll", "alarms.create", "alarms.get",
-    "alarms.getAll", "alarms.onAlarm", "app.runtime.onLaunched",
-    "app.runtime.onRestarted", "app.window.create", "app.window.current",
-    "app.window.onBoundsChanged", "app.window.onClosed",
-    "app.window.onFullscreened", "app.window.onMaximized",
-    "app.window.onMinimized", "app.window.onRestored", "bluetooth.connect",
-    "bluetooth.disconnect", "bluetooth.getAdapterState",
-    "bluetooth.getDevices", "bluetooth.getLocalOutOfBandPairingData",
-    "bluetooth.getServices", "bluetooth.onAdapterStateChanged",
-    "bluetooth.read", "bluetooth.setOutOfBandPairingData",
-    "bluetooth.startDiscovery", "bluetooth.stopDiscovery", "bluetooth.write",
-    "bookmarks.create", "bookmarks.get", "bookmarks.getChildren",
-    "bookmarks.getRecent", "bookmarks.getSubTree", "bookmarks.getTree",
-    "bookmarks.move", "bookmarks.onChanged", "bookmarks.onChildrenReordered",
-    "bookmarks.onCreated", "bookmarks.onImportBegan",
-    "bookmarks.onImportEnded", "bookmarks.onMoved", "bookmarks.onRemoved",
-    "bookmarks.remove", "bookmarks.removeTree", "bookmarks.search",
-    "bookmarks.update", "browserAction.disable", "browserAction.enable",
-    "browserAction.getBadgeBackgroundColor", "browserAction.getBadgeText",
-    "browserAction.getPopup", "browserAction.getTitle",
-    "browserAction.onClicked", "browserAction.setBadgeBackgroundColor",
-    "browserAction.setBadgeText", "browserAction.setIcon",
-    "browserAction.setPopup", "browserAction.setTitle", "browsingData.remove",
-    "browsingData.removeAppcache", "browsingData.removeCache",
-    "browsingData.removeCookies", "browsingData.removeDownloads",
-    "browsingData.removeFileSystems", "browsingData.removeFormData",
-    "browsingData.removeHistory", "browsingData.removeIndexedDB",
-    "browsingData.removeLocalStorage", "browsingData.removePasswords",
-    "browsingData.removePluginData", "browsingData.removeWebSQL",
-    "browsingData.settings", "commands.getAll", "commands.onCommand",
-    "contextMenus.create", "contextMenus.onClicked", "contextMenus.remove",
-    "contextMenus.removeAll", "contextMenus.update", "cookies.get",
-    "cookies.getAll", "cookies.getAllCookieStores", "cookies.onChanged",
-    "cookies.remove", "cookies.set", "debugger.attach", "debugger.detach",
-    "debugger.getTargets", "debugger.onDetach", "debugger.onEvent",
-    "debugger.sendCommand", "declarativeContent.onPageChanged",
-    "declarativeWebRequest.onMessage", "declarativeWebRequest.onRequest",
-    "devtools.inspectedWindow.eval", "devtools.inspectedWindow.getResources",
-    "devtools.inspectedWindow.onResourceAdded",
-    "devtools.inspectedWindow.onResourceContentCommitted",
-    "devtools.inspectedWindow.reload", "devtools.network.getHAR",
-    "devtools.network.onNavigated", "devtools.network.onRequestFinished",
-    "devtools.panels.create", "devtools.panels.setOpenResourceHandler",
-    "downloads.acceptDanger", "downloads.cancel", "downloads.download",
-    "downloads.drag", "downloads.erase", "downloads.getFileIcon",
-    "downloads.onChanged", "downloads.onCreated",
-    "downloads.onDeterminingFilename", "downloads.onErased", "downloads.open",
-    "downloads.pause", "downloads.resume", "downloads.search",
-    "downloads.show", "experimental.devtools.audits.addCategory",
-    "experimental.devtools.console.addMessage",
-    "experimental.devtools.console.getMessages",
-    "experimental.devtools.console.onMessageAdded",
-    "experimental.discovery.clearAllSuggestions",
-    "experimental.discovery.removeSuggestion",
-    "experimental.discovery.suggest", "experimental.history.getMostVisited",
-    "experimental.identity.getAuthToken",
-    "experimental.identity.launchWebAuthFlow", "infobars.show",
-    "removed.experimental.mediaGalleries.assembleMediaFile",
-    "removed.experimental.mediaGalleries.extractEmbeddedThumbnails",
-    "experimental.processes.getProcessIdForTab",
-    "experimental.processes.getProcessInfo",
-    "experimental.processes.onCreated", "experimental.processes.onExited",
-    "experimental.processes.onUnresponsive",
-    "experimental.processes.onUpdated",
-    "experimental.processes.onUpdatedWithMemory",
-    "experimental.processes.terminate",
-    "experimental.record.captureURLs", "experimental.record.replayURLs",
-    "experimental.speechInput.isRecording", "experimental.speechInput.onError",
-    "experimental.speechInput.onResult", "experimental.speechInput.onSoundEnd",
-    "experimental.speechInput.onSoundStart", "experimental.speechInput.start",
-    "experimental.speechInput.stop", "experimental.systemInfo.cpu.get" ,
-    "experimental.systemInfo.cpu.onUpdated",
-    "experimental.systemInfo.display.get",
-    "experimental.systemInfo.memory.get", "experimental.systemInfo.storage.get",
-     "experimental.systemInfo.storage.onAttached",
-    "experimental.systemInfo.storage.onAvailableCapacityChanged",
-    "experimental.systemInfo.storage.onDetached",
-    "extension.getBackgroundPage", "extension.getURL", "extension.getViews",
-    "extension.isAllowedFileSchemeAccess",
-    "extension.isAllowedIncognitoAccess", "extension.setUpdateUrlData",
-    "fileBrowserHandler.onExecute", "fileBrowserHandler.selectFile",
-    "fileSystem.chooseEntry", "fileSystem.getDisplayPath",
-    "fileSystem.getEntryById", "fileSystem.getEntryId",
-    "fileSystem.getWritableEntry", "fileSystem.isWritableEntry",
-    "fontSettings.clearDefaultFixedFontSize",
-    "fontSettings.clearDefaultFontSize", "fontSettings.clearFont",
-    "fontSettings.clearMinimumFontSize",
-    "fontSettings.getDefaultFixedFontSize", "fontSettings.getDefaultFontSize",
-    "fontSettings.getFont", "fontSettings.getFontList",
-    "fontSettings.getMinimumFontSize",
-    "fontSettings.onDefaultFixedFontSizeChanged",
-    "fontSettings.onDefaultFontSizeChanged", "fontSettings.onFontChanged",
-    "fontSettings.onMinimumFontSizeChanged",
-    "fontSettings.setDefaultFixedFontSize", "fontSettings.setDefaultFontSize",
-    "fontSettings.setFont", "fontSettings.setMinimumFontSize",
-    "history.addUrl", "history.deleteAll", "history.deleteRange",
-    "history.deleteUrl", "history.getVisits", "history.onVisitRemoved",
-    "history.onVisited", "history.search", "i18n.getAcceptLanguages",
-    "i18n.getMessage", "idle.onStateChanged", "idle.queryState",
-    "idle.setDetectionInterval", "input.ime.clearComposition",
-    "input.ime.commitText", "input.ime.deleteSurroundingText",
-    "input.ime.keyEventHandled", "input.ime.onActivate", "input.ime.onBlur",
-    "input.ime.onCandidateClicked", "input.ime.onDeactivated",
-    "input.ime.onFocus", "input.ime.onInputContextUpdate",
-    "input.ime.onKeyEvent", "input.ime.onMenuItemActivated",
-    "input.ime.onSurroundingTextChanged",
-    "input.ime.setCandidateWindowProperties", "input.ime.setCandidates",
-    "input.ime.setComposition", "input.ime.setCursorPosition",
-    "input.ime.setMenuItems", "input.ime.updateMenuItems", "management.get",
-    "management.getAll", "management.getPermissionWarningsById",
-    "management.getPermissionWarningsByManifest", "management.launchApp",
-    "management.onDisabled", "management.onEnabled", "management.onInstalled",
-    "management.onUninstalled", "management.setEnabled",
-    "management.uninstall", "management.uninstallSelf",
-    "mediaGalleries.getMediaFileSystemMetadata",
-    "mediaGalleries.getMediaFileSystems", "notifications.clear",
-    "notifications.create", "notifications.onButtonClicked",
-    "notifications.onClicked", "notifications.onClosed",
-    "notifications.onDisplayed", "notifications.update",
-    "omnibox.onInputCancelled", "omnibox.onInputChanged",
-    "omnibox.onInputEntered", "omnibox.onInputStarted",
-    "omnibox.setDefaultSuggestion", "pageAction.getPopup",
-    "pageAction.getTitle", "pageAction.hide", "pageAction.onClicked",
-    "pageAction.setIcon", "pageAction.setPopup", "pageAction.setTitle",
-    "pageAction.show", "pageCapture.saveAsMHTML", "permissions.contains",
-    "permissions.getAll", "permissions.onAdded", "permissions.onRemoved",
-    "permissions.remove", "permissions.request", "power.releaseKeepAwake",
-    "power.requestKeepAwake", "proxy.onProxyError",
-    "pushMessaging.getChannelId", "pushMessaging.onMessage", "runtime.connect",
-    "runtime.getBackgroundPage", "runtime.getManifest", "runtime.getURL",
-    "runtime.onBrowserUpdateAvailable", "runtime.onConnect",
-    "runtime.onConnectExternal", "runtime.onInstalled", "runtime.onMessage",
-    "runtime.onMessageExternal", "runtime.onStartup", "runtime.onSuspend",
-    "runtime.onSuspendCanceled", "runtime.onUpdateAvailable", "runtime.reload",
-    "runtime.requestUpdateCheck", "runtime.sendMessage",
-    "scriptBadge.getAttention", "scriptBadge.getPopup",
-    "scriptBadge.onClicked", "scriptBadge.setPopup", "serial.close",
-    "serial.flush", "serial.getControlSignals", "serial.getPorts",
-    "serial.open", "serial.read", "serial.setControlSignals", "serial.write",
-    "sessionRestore.getRecentlyClosed", "sessionRestore.restore",
-    "socket.accept", "socket.bind", "socket.connect", "socket.create",
-    "socket.destroy", "socket.disconnect", "socket.getInfo",
-    "socket.getNetworkList", "socket.listen", "socket.read", "socket.recvFrom",
-    "socket.sendTo", "socket.setKeepAlive", "socket.setNoDelay",
-    "socket.write", "storage.onChanged",
-    "syncFileSystem.getConflictResolutionPolicy",
-    "syncFileSystem.getFileStatus", "syncFileSystem.getFileStatuses",
-    "syncFileSystem.getUsageAndQuota", "syncFileSystem.onFileStatusChanged",
-    "syncFileSystem.onServiceStatusChanged",
-    "syncFileSystem.requestFileSystem",
-    "syncFileSystem.setConflictResolutionPolicy", "tabCapture.capture",
-    "tabCapture.getCapturedTabs", "tabCapture.onStatusChanged",
-    "tabs.captureVisibleTab", "tabs.connect", "tabs.create",
-    "tabs.detectLanguage", "tabs.duplicate", "tabs.executeScript", "tabs.get",
-    "tabs.getCurrent", "tabs.highlight", "tabs.insertCSS", "tabs.move",
-    "tabs.onActivated", "tabs.onAttached", "tabs.onCreated", "tabs.onDetached",
-    "tabs.onHighlighted", "tabs.onMoved", "tabs.onRemoved", "tabs.onReplaced",
-    "tabs.onUpdated", "tabs.query", "tabs.reload", "tabs.remove",
-    "tabs.sendMessage", "tabs.update", "topSites.get", "tts.getVoices",
-    "tts.isSpeaking", "tts.speak", "tts.stop", "ttsEngine.onSpeak",
-    "ttsEngine.onStop", "usb.bulkTransfer", "usb.claimInterface",
-    "usb.closeDevice", "usb.controlTransfer", "usb.findDevices",
-    "usb.interruptTransfer", "usb.isochronousTransfer", "usb.releaseInterface",
-    "usb.setInterfaceAlternateSetting", "webNavigation.getAllFrames",
-    "webNavigation.getFrame", "webNavigation.onBeforeNavigate",
-    "webNavigation.onCommitted", "webNavigation.onCompleted",
-    "webNavigation.onCreatedNavigationTarget",
-    "webNavigation.onDOMContentLoaded", "webNavigation.onErrorOccurred",
-    "webNavigation.onHistoryStateUpdated",
-    "webNavigation.onReferenceFragmentUpdated", "webNavigation.onTabReplaced",
-    "webRequest.handlerBehaviorChanged", "webRequest.onAuthRequired",
-    "webRequest.onBeforeRedirect", "webRequest.onBeforeRequest",
-    "webRequest.onBeforeSendHeaders", "webRequest.onCompleted",
-    "webRequest.onErrorOccurred", "webRequest.onHeadersReceived",
-    "webRequest.onResponseStarted", "webRequest.onSendHeaders",
-    "webstore.install", "windows.create", "windows.get", "windows.getAll",
-    "windows.getCurrent", "windows.getLastFocused", "windows.onCreated",
-    "windows.onFocusChanged", "windows.onRemoved", "windows.remove",
-    "windows.update",
-    "tabs.getSelected", "tabs.sendRequest",
-    "systemInfo.cpu.get", "systemInfo.memory.get",
-    "runtime.onRestartRequired",
-    "system.cpu.getInfo",
-    "system.display.getInfo",
-    "system.display.onDisplayChanged",
-    "system.display.setDisplayProperties",
-    "system.memory.getInfo",
-    "system.storage.getInfo",
-    "system.storage.onAttached",
-    "system.storage.onDetached",
-    "system.storage.ejectDevice",
-    "system.storage.addAvailableCapacityWatch",
-    "system.storage.removeAvailableCapacityWatch",
-    "system.storage.getAllAvailableCapacityWatches",
-    "system.storage.removeAllAvailableCapacityWatches",
-    "system.storage.onAvailableCapacityChanged"
-};
-
-}  // namespace activity_log_api_name_constants
-
-#endif  // CHROME_BROWSER_EXTENSIONS_ACTIVITY_LOG_API_NAME_CONSTANTS_H_
diff --git a/chrome/browser/extensions/activity_log/counting_policy.cc b/chrome/browser/extensions/activity_log/counting_policy.cc
new file mode 100644
index 0000000..e99fade
--- /dev/null
+++ b/chrome/browser/extensions/activity_log/counting_policy.cc
@@ -0,0 +1,505 @@
+// 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.
+
+// A policy for storing activity log data to a database that performs
+// aggregation to reduce the size of the database.  The database layout is
+// nearly the same as FullStreamUIPolicy, which stores a complete log, with a
+// few changes:
+//   - a "count" column is added to track how many log records were merged
+//     together into this row
+//   - the "time" column measures the most recent time that the current row was
+//     updated
+// When writing a record, if a row already exists where all other columns
+// (extension_id, action_type, api_name, args, urls, etc.) all match, and the
+// previous time falls within today (the current time), then the count field on
+// the old row is incremented.  Otherwise, a new row is written.
+//
+// For many text columns, repeated strings are compressed by moving string
+// storage to a separate table ("string_ids") and storing only an identifier in
+// the logging table.  For example, if the api_name_x column contained the
+// value 4 and the string_ids table contained a row with primary key 4 and
+// value 'tabs.query', then the api_name field should be taken to have the
+// value 'tabs.query'.  Each column ending with "_x" is compressed in this way.
+// All lookups are to the string_ids table, except for the page_url_x and
+// arg_url_x columns, which are converted via the url_ids table (this
+// separation of URL values is to help simplify history clearing).
+//
+// The activitylog_uncompressed view allows for simpler reading of the activity
+// log contents with identifiers already translated to string values.
+
+#include "chrome/browser/extensions/activity_log/counting_policy.h"
+
+#include <map>
+#include <string>
+#include <vector>
+
+#include "base/callback.h"
+#include "base/files/file_path.h"
+#include "base/json/json_reader.h"
+#include "base/json/json_string_value_serializer.h"
+#include "base/strings/string_util.h"
+#include "base/strings/stringprintf.h"
+#include "chrome/common/chrome_constants.h"
+
+using content::BrowserThread;
+
+namespace {
+
+// Delay between cleaning passes (to delete old action records) through the
+// database.
+const int kCleaningDelayInHours = 12;
+
+// We should log the arguments to these API calls.  Be careful when
+// constructing this whitelist to not keep arguments that might compromise
+// privacy by logging too much data to the activity log.
+//
+// TODO(mvrable): The contents of this whitelist should be reviewed and
+// expanded as needed.
+const char* kAlwaysLog[] = {"extension.connect", "extension.sendMessage",
+                            "tabs.executeScript", "tabs.insertCSS"};
+
+// Columns in the main database table.  See the file-level comment for a
+// discussion of how data is stored and the meanings of the _x columns.
+const char* kTableContentFields[] = {
+    "count", "extension_id_x", "time", "action_type", "api_name_x", "args_x",
+    "page_url_x", "page_title_x", "arg_url_x", "other_x"};
+const char* kTableFieldTypes[] = {
+    "INTEGER NOT NULL DEFAULT 1", "INTEGER NOT NULL", "INTEGER", "INTEGER",
+    "INTEGER", "INTEGER", "INTEGER", "INTEGER", "INTEGER",
+    "INTEGER"};
+
+// Miscellaneous SQL commands for initializing the database; these should be
+// idempotent.
+static const char kPolicyMiscSetup[] =
+    // The activitylog_uncompressed view performs string lookups for simpler
+    // access to the log data.
+    "DROP VIEW IF EXISTS activitylog_uncompressed;\n"
+    "CREATE VIEW activitylog_uncompressed AS\n"
+    "SELECT count,\n"
+    "    x1.value AS extension_id,\n"
+    "    time,\n"
+    "    action_type,\n"
+    "    x2.value AS api_name,\n"
+    "    x3.value AS args,\n"
+    "    x4.value AS page_url,\n"
+    "    x5.value AS page_title,\n"
+    "    x6.value AS arg_url,\n"
+    "    x7.value AS other\n"
+    "FROM activitylog_compressed\n"
+    "    LEFT JOIN string_ids AS x1 ON (x1.id = extension_id_x)\n"
+    "    LEFT JOIN string_ids AS x2 ON (x2.id = api_name_x)\n"
+    "    LEFT JOIN string_ids AS x3 ON (x3.id = args_x)\n"
+    "    LEFT JOIN url_ids    AS x4 ON (x4.id = page_url_x)\n"
+    "    LEFT JOIN string_ids AS x5 ON (x5.id = page_title_x)\n"
+    "    LEFT JOIN url_ids    AS x6 ON (x6.id = arg_url_x)\n"
+    "    LEFT JOIN string_ids AS x7 ON (x7.id = other_x);\n"
+    // An index on all fields except count and time: all the fields that aren't
+    // changed when incrementing a count.  This should accelerate finding the
+    // rows to update (at worst several rows will need to be checked to find
+    // the one in the right time range).
+    "CREATE INDEX IF NOT EXISTS activitylog_compressed_index\n"
+    "ON activitylog_compressed(extension_id_x, action_type, api_name_x,\n"
+    "    args_x, page_url_x, page_title_x, arg_url_x, other_x)";
+
+// SQL statements to clean old, unused entries out of the string and URL id
+// tables.
+static const char kStringTableCleanup[] =
+    "DELETE FROM string_ids WHERE id NOT IN\n"
+    "(SELECT extension_id_x FROM activitylog_compressed\n"
+    " UNION SELECT api_name_x FROM activitylog_compressed\n"
+    " UNION SELECT args_x FROM activitylog_compressed\n"
+    " UNION SELECT page_title_x FROM activitylog_compressed\n"
+    " UNION SELECT other_x FROM activitylog_compressed)";
+static const char kUrlTableCleanup[] =
+    "DELETE FROM url_ids WHERE id NOT IN\n"
+    "(SELECT page_url_x FROM activitylog_compressed\n"
+    " UNION SELECT arg_url_x FROM activitylog_compressed)";
+
+}  // namespace
+
+namespace extensions {
+
+// A specialized Action subclass which is used to represent an action read from
+// the database with a corresponding count.
+class CountedAction : public Action {
+ public:
+  CountedAction(const std::string& extension_id,
+                const base::Time& time,
+                const ActionType action_type,
+                const std::string& api_name)
+      : Action(extension_id, time, action_type, api_name) {}
+
+  // Number of merged records for this action.
+  int count() const { return count_; }
+  void set_count(int count) { count_ = count; }
+
+  virtual std::string PrintForDebug() const OVERRIDE;
+
+ protected:
+  virtual ~CountedAction() {}
+
+ private:
+  int count_;
+};
+
+std::string CountedAction::PrintForDebug() const {
+  return base::StringPrintf(
+      "%s COUNT=%d", Action::PrintForDebug().c_str(), count());
+}
+
+const char* CountingPolicy::kTableName = "activitylog_compressed";
+const char* CountingPolicy::kReadViewName = "activitylog_uncompressed";
+
+CountingPolicy::CountingPolicy(Profile* profile)
+    : ActivityLogDatabasePolicy(
+          profile,
+          base::FilePath(chrome::kExtensionActivityLogFilename)),
+      string_table_("string_ids"),
+      url_table_("url_ids"),
+      retention_time_(base::TimeDelta::FromHours(60)) {
+  for (size_t i = 0; i < arraysize(kAlwaysLog); i++) {
+    api_arg_whitelist_.insert(kAlwaysLog[i]);
+  }
+}
+
+CountingPolicy::~CountingPolicy() {}
+
+bool CountingPolicy::InitDatabase(sql::Connection* db) {
+  if (!Util::DropObsoleteTables(db))
+    return false;
+
+  if (!string_table_.Initialize(db))
+    return false;
+  if (!url_table_.Initialize(db))
+    return false;
+
+  // Create the unified activity log entry table.
+  if (!ActivityDatabase::InitializeTable(db,
+                                         kTableName,
+                                         kTableContentFields,
+                                         kTableFieldTypes,
+                                         arraysize(kTableContentFields)))
+    return false;
+
+  // Create a view for easily accessing the uncompressed form of the data, and
+  // any necessary indexes if needed.
+  return db->Execute(kPolicyMiscSetup);
+}
+
+void CountingPolicy::ProcessAction(scoped_refptr<Action> action) {
+  ScheduleAndForget(this, &CountingPolicy::QueueAction, action);
+}
+
+void CountingPolicy::QueueAction(scoped_refptr<Action> action) {
+  if (activity_database()->is_db_valid()) {
+    action = action->Clone();
+    Util::StripPrivacySensitiveFields(action);
+    Util::StripArguments(api_arg_whitelist_, action);
+    queued_actions_.push_back(action);
+    activity_database()->AdviseFlush(queued_actions_.size());
+  }
+}
+
+bool CountingPolicy::FlushDatabase(sql::Connection* db) {
+  // Columns that must match exactly for database rows to be coalesced.
+  static const char* matched_columns[] = {
+      "extension_id_x", "action_type", "api_name_x", "args_x", "page_url_x",
+      "page_title_x", "arg_url_x", "other_x"};
+  Action::ActionVector queue;
+  queue.swap(queued_actions_);
+
+  // Whether to clean old records out of the activity log database.  Do this
+  // much less frequently than database flushes since it is expensive, but
+  // always check on the first database flush (since there might be a large
+  // amount of data to clear).
+  bool clean_database = (last_database_cleaning_time_.is_null() ||
+                         Now() - last_database_cleaning_time_ >
+                             base::TimeDelta::FromHours(kCleaningDelayInHours));
+
+  if (queue.empty() && !clean_database)
+    return true;
+
+  sql::Transaction transaction(db);
+  if (!transaction.Begin())
+    return false;
+
+  std::string insert_str =
+      "INSERT INTO " + std::string(kTableName) + "(count, time";
+  std::string update_str =
+      "UPDATE " + std::string(kTableName) +
+      " SET count = count + 1, time = max(?, time)"
+      " WHERE time >= ? AND time < ?";
+
+  for (size_t i = 0; i < arraysize(matched_columns); i++) {
+    insert_str =
+        base::StringPrintf("%s, %s", insert_str.c_str(), matched_columns[i]);
+    update_str = base::StringPrintf(
+        "%s AND %s IS ?", update_str.c_str(), matched_columns[i]);
+  }
+  insert_str += ") VALUES (1, ?";
+  for (size_t i = 0; i < arraysize(matched_columns); i++) {
+    insert_str += ", ?";
+  }
+  insert_str += ")";
+
+  Action::ActionVector::size_type i;
+  for (i = 0; i != queue.size(); ++i) {
+    const Action& action = *queue[i];
+
+    base::Time day_start = action.time().LocalMidnight();
+    base::Time next_day = Util::AddDays(day_start, 1);
+
+    // The contents in values must match up with fields in matched_columns.  A
+    // value of -1 is used to encode a null database value.
+    int64 id;
+    std::vector<int64> matched_values;
+
+    if (!string_table_.StringToInt(db, action.extension_id(), &id))
+      return false;
+    matched_values.push_back(id);
+
+    matched_values.push_back(static_cast<int>(action.action_type()));
+
+    if (!string_table_.StringToInt(db, action.api_name(), &id))
+      return false;
+    matched_values.push_back(id);
+
+    if (action.args()) {
+      std::string args = Util::Serialize(action.args());
+      // TODO(mvrable): For now, truncate long argument lists.  This is a
+      // workaround for excessively-long values coming from DOM logging.  When
+      // the V8ValueConverter is fixed to return more reasonable values, we can
+      // drop the truncation.
+      if (args.length() > 10000) {
+        args = "[\"<too_large>\"]";
+      }
+      if (!string_table_.StringToInt(db, args, &id))
+        return false;
+      matched_values.push_back(id);
+    } else {
+      matched_values.push_back(-1);
+    }
+
+    std::string page_url_string = action.SerializePageUrl();
+    if (!page_url_string.empty()) {
+      if (!url_table_.StringToInt(db, page_url_string, &id))
+        return false;
+      matched_values.push_back(id);
+    } else {
+      matched_values.push_back(-1);
+    }
+
+    // TODO(mvrable): Create a title_table_?
+    if (!action.page_title().empty()) {
+      if (!string_table_.StringToInt(db, action.page_title(), &id))
+        return false;
+      matched_values.push_back(id);
+    } else {
+      matched_values.push_back(-1);
+    }
+
+    std::string arg_url_string = action.SerializeArgUrl();
+    if (!arg_url_string.empty()) {
+      if (!url_table_.StringToInt(db, arg_url_string, &id))
+        return false;
+      matched_values.push_back(id);
+    } else {
+      matched_values.push_back(-1);
+    }
+
+    if (action.other()) {
+      if (!string_table_.StringToInt(db, Util::Serialize(action.other()), &id))
+        return false;
+      matched_values.push_back(id);
+    } else {
+      matched_values.push_back(-1);
+    }
+
+    // Assume there is an existing row for this action, and try to update the
+    // count.
+    sql::Statement update_statement(db->GetCachedStatement(
+        sql::StatementID(SQL_FROM_HERE), update_str.c_str()));
+    update_statement.BindInt64(0, action.time().ToInternalValue());
+    update_statement.BindInt64(1, day_start.ToInternalValue());
+    update_statement.BindInt64(2, next_day.ToInternalValue());
+    for (size_t j = 0; j < matched_values.size(); j++) {
+      if (matched_values[j] == -1)
+        update_statement.BindNull(j + 3);
+      else
+        update_statement.BindInt64(j + 3, matched_values[j]);
+    }
+    if (!update_statement.Run())
+      return false;
+
+    // Check if the update succeeded (was the count of updated rows non-zero)?
+    // If it failed because no matching row existed, fall back to inserting a
+    // new record.
+    if (db->GetLastChangeCount() > 0) {
+      if (db->GetLastChangeCount() > 1) {
+        LOG(WARNING) << "Found and updated multiple rows in the activity log "
+                     << "database; counts may be off!";
+      }
+      continue;
+    }
+    sql::Statement insert_statement(db->GetCachedStatement(
+        sql::StatementID(SQL_FROM_HERE), insert_str.c_str()));
+    insert_statement.BindInt64(0, action.time().ToInternalValue());
+    for (size_t j = 0; j < matched_values.size(); j++) {
+      if (matched_values[j] == -1)
+        update_statement.BindNull(j + 1);
+      else
+        insert_statement.BindInt64(j + 1, matched_values[j]);
+    }
+    if (!insert_statement.Run())
+      return false;
+  }
+
+  if (clean_database) {
+    base::Time cutoff = (Now() - retention_time()).LocalMidnight();
+    if (!CleanOlderThan(db, cutoff))
+      return false;
+    last_database_cleaning_time_ = Now();
+  }
+
+  if (!transaction.Commit())
+    return false;
+
+  return true;
+}
+
+scoped_ptr<Action::ActionVector> CountingPolicy::DoReadData(
+    const std::string& extension_id,
+    const int days_ago) {
+  // Ensure data is flushed to the database first so that we query over all
+  // data.
+  activity_database()->AdviseFlush(ActivityDatabase::kFlushImmediately);
+
+  DCHECK_GE(days_ago, 0);
+  scoped_ptr<Action::ActionVector> actions(new Action::ActionVector());
+
+  sql::Connection* db = GetDatabaseConnection();
+  if (!db) {
+    return actions.Pass();
+  }
+
+  int64 early_bound;
+  int64 late_bound;
+  Util::ComputeDatabaseTimeBounds(Now(), days_ago, &early_bound, &late_bound);
+  std::string query_str = base::StringPrintf(
+      "SELECT time, action_type, api_name, args, page_url, page_title, "
+      "arg_url, other, count "
+      "FROM %s WHERE extension_id=? AND time>? AND time<=? "
+      "ORDER BY time DESC",
+      kReadViewName);
+  sql::Statement query(db->GetCachedStatement(SQL_FROM_HERE,
+                                              query_str.c_str()));
+  query.BindString(0, extension_id);
+  query.BindInt64(1, early_bound);
+  query.BindInt64(2, late_bound);
+
+  while (query.is_valid() && query.Step()) {
+    scoped_refptr<CountedAction> action =
+        new CountedAction(extension_id,
+                          base::Time::FromInternalValue(query.ColumnInt64(0)),
+                          static_cast<Action::ActionType>(query.ColumnInt(1)),
+                          query.ColumnString(2));
+
+    if (query.ColumnType(3) != sql::COLUMN_TYPE_NULL) {
+      scoped_ptr<Value> parsed_value(
+          base::JSONReader::Read(query.ColumnString(3)));
+      if (parsed_value && parsed_value->IsType(Value::TYPE_LIST)) {
+        action->set_args(
+            make_scoped_ptr(static_cast<ListValue*>(parsed_value.release())));
+      } else {
+        LOG(WARNING) << "Unable to parse args: '" << query.ColumnString(3)
+                     << "'";
+      }
+    }
+
+    action->ParsePageUrl(query.ColumnString(4));
+    action->set_page_title(query.ColumnString(5));
+    action->ParseArgUrl(query.ColumnString(6));
+
+    if (query.ColumnType(7) != sql::COLUMN_TYPE_NULL) {
+      scoped_ptr<Value> parsed_value(
+          base::JSONReader::Read(query.ColumnString(7)));
+      if (parsed_value && parsed_value->IsType(Value::TYPE_DICTIONARY)) {
+        action->set_other(make_scoped_ptr(
+            static_cast<DictionaryValue*>(parsed_value.release())));
+      } else {
+        LOG(WARNING) << "Unable to parse other: '" << query.ColumnString(7)
+                     << "'";
+      }
+    }
+
+    action->set_count(query.ColumnInt(8));
+
+    actions->push_back(action);
+  }
+
+  return actions.Pass();
+}
+
+void CountingPolicy::ReadData(
+    const std::string& extension_id,
+    const int day,
+    const base::Callback<void(scoped_ptr<Action::ActionVector>)>& callback) {
+  BrowserThread::PostTaskAndReplyWithResult(
+      BrowserThread::DB,
+      FROM_HERE,
+      base::Bind(&CountingPolicy::DoReadData,
+                 base::Unretained(this),
+                 extension_id,
+                 day),
+      callback);
+}
+
+void CountingPolicy::OnDatabaseFailure() {
+  queued_actions_.clear();
+}
+
+void CountingPolicy::OnDatabaseClose() {
+  delete this;
+}
+
+// Cleans old records from the activity log database.
+bool CountingPolicy::CleanOlderThan(sql::Connection* db,
+                                    const base::Time& cutoff) {
+  std::string clean_statement =
+      "DELETE FROM " + std::string(kTableName) + " WHERE time < ?";
+  sql::Statement cleaner(db->GetCachedStatement(sql::StatementID(SQL_FROM_HERE),
+                                                clean_statement.c_str()));
+  cleaner.BindInt64(0, cutoff.ToInternalValue());
+  if (!cleaner.Run())
+    return false;
+  return CleanStringTables(db);
+}
+
+// Cleans unused interned strings from the database.  This should be run after
+// deleting rows from the main log table to clean out stale values.
+bool CountingPolicy::CleanStringTables(sql::Connection* db) {
+  sql::Statement cleaner1(db->GetCachedStatement(
+      sql::StatementID(SQL_FROM_HERE), kStringTableCleanup));
+  if (!cleaner1.Run())
+    return false;
+  if (db->GetLastChangeCount() > 0)
+    string_table_.ClearCache();
+
+  sql::Statement cleaner2(db->GetCachedStatement(
+      sql::StatementID(SQL_FROM_HERE), kUrlTableCleanup));
+  if (!cleaner2.Run())
+    return false;
+  if (db->GetLastChangeCount() > 0)
+    url_table_.ClearCache();
+
+  return true;
+}
+
+void CountingPolicy::Close() {
+  // The policy object should have never been created if there's no DB thread.
+  DCHECK(BrowserThread::IsMessageLoopValid(BrowserThread::DB));
+  ScheduleAndForget(activity_database(), &ActivityDatabase::Close);
+}
+
+}  // namespace extensions
diff --git a/chrome/browser/extensions/activity_log/counting_policy.h b/chrome/browser/extensions/activity_log/counting_policy.h
new file mode 100644
index 0000000..5981bca
--- /dev/null
+++ b/chrome/browser/extensions/activity_log/counting_policy.h
@@ -0,0 +1,100 @@
+// 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_EXTENSIONS_ACTIVITY_LOG_COUNTING_POLICY_H_
+#define CHROME_BROWSER_EXTENSIONS_ACTIVITY_LOG_COUNTING_POLICY_H_
+
+#include <string>
+
+#include "base/containers/hash_tables.h"
+#include "chrome/browser/extensions/activity_log/activity_database.h"
+#include "chrome/browser/extensions/activity_log/activity_log_policy.h"
+#include "chrome/browser/extensions/activity_log/database_string_table.h"
+
+namespace extensions {
+
+// A policy for logging the stream of actions, but without arguments.
+class CountingPolicy : public ActivityLogDatabasePolicy {
+ public:
+  explicit CountingPolicy(Profile* profile);
+  virtual ~CountingPolicy();
+
+  virtual void ProcessAction(scoped_refptr<Action> action) OVERRIDE;
+
+  virtual void ReadData(
+      const std::string& extension_id,
+      const int day,
+      const base::Callback
+          <void(scoped_ptr<Action::ActionVector>)>& callback) OVERRIDE;
+
+  virtual void Close() OVERRIDE;
+
+  // Gets or sets the amount of time that old records are kept in the database.
+  const base::TimeDelta& retention_time() const { return retention_time_; }
+  void set_retention_time(const base::TimeDelta& delta) {
+    retention_time_ = delta;
+  }
+
+  // The main database table, and the name for a read-only view that
+  // decompresses string values for easier parsing.
+  static const char* kTableName;
+  static const char* kReadViewName;
+
+ protected:
+  // The ActivityDatabase::Delegate interface.  These are always called from
+  // the database thread.
+  virtual bool InitDatabase(sql::Connection* db) OVERRIDE;
+  virtual bool FlushDatabase(sql::Connection* db) OVERRIDE;
+  virtual void OnDatabaseFailure() OVERRIDE;
+  virtual void OnDatabaseClose() OVERRIDE;
+
+ private:
+  // Adds an Action to those to be written out; this is an internal method used
+  // by ProcessAction and is called on the database thread.
+  void QueueAction(scoped_refptr<Action> action);
+
+  // Internal method to read data from the database; called on the database
+  // thread.
+  scoped_ptr<Action::ActionVector> DoReadData(
+      const std::string& extension_id,
+      const int days_ago);
+
+  // Cleans old records from the activity log database.
+  bool CleanOlderThan(sql::Connection* db, const base::Time& cutoff);
+
+  // Cleans unused interned strings from the database.  This should be run
+  // after deleting rows from the main log table to clean out stale values.
+  bool CleanStringTables(sql::Connection* db);
+
+  // API calls for which complete arguments should be logged.
+  std::set<std::string> api_arg_whitelist_;
+
+  // Tables for mapping strings to integers for shrinking database storage
+  // requirements.  URLs are kept in a separate table from other strings to
+  // make history clearing simpler.
+  DatabaseStringTable string_table_;
+  DatabaseStringTable url_table_;
+
+  // Tracks any pending updates to be written to the database, if write
+  // batching is turned on.  Should only be accessed from the database thread.
+  // TODO(mvrable): Do in-memory aggregation as well.
+  Action::ActionVector queued_actions_;
+
+  // The amount of time old activity log records should be kept in the
+  // database.  This time is subtracted from the current time, rounded down to
+  // midnight, and rows older than this are deleted from the database when
+  // cleaning runs.
+  base::TimeDelta retention_time_;
+
+  // The time at which old activity log records were last cleaned out of the
+  // database (only tracked for this browser session).  Old records are deleted
+  // on the first database flush, and then every 12 hours subsequently.
+  base::Time last_database_cleaning_time_;
+
+  FRIEND_TEST_ALL_PREFIXES(CountingPolicyTest, MergingAndExpiring);
+};
+
+}  // namespace extensions
+
+#endif  // CHROME_BROWSER_EXTENSIONS_ACTIVITY_LOG_COUNTING_POLICY_H_
diff --git a/chrome/browser/extensions/activity_log/counting_policy_unittest.cc b/chrome/browser/extensions/activity_log/counting_policy_unittest.cc
new file mode 100644
index 0000000..748b528
--- /dev/null
+++ b/chrome/browser/extensions/activity_log/counting_policy_unittest.cc
@@ -0,0 +1,407 @@
+// 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/cancelable_callback.h"
+#include "base/command_line.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/run_loop.h"
+#include "base/strings/stringprintf.h"
+#include "base/synchronization/waitable_event.h"
+#include "base/test/simple_test_clock.h"
+#include "chrome/browser/extensions/activity_log/activity_log.h"
+#include "chrome/browser/extensions/activity_log/counting_policy.h"
+#include "chrome/browser/extensions/extension_service.h"
+#include "chrome/browser/extensions/test_extension_system.h"
+#include "chrome/common/chrome_constants.h"
+#include "chrome/common/chrome_switches.h"
+#include "chrome/common/extensions/extension_builder.h"
+#include "chrome/test/base/chrome_render_view_host_test_harness.h"
+#include "chrome/test/base/testing_profile.h"
+#include "content/public/test/test_browser_thread_bundle.h"
+#include "sql/statement.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+#if defined(OS_CHROMEOS)
+#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"
+#endif
+
+namespace extensions {
+
+class CountingPolicyTest : public testing::Test {
+ public:
+  CountingPolicyTest()
+      : thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP),
+        saved_cmdline_(CommandLine::NO_PROGRAM) {
+#if defined OS_CHROMEOS
+    test_user_manager_.reset(new chromeos::ScopedTestUserManager());
+#endif
+    CommandLine command_line(CommandLine::NO_PROGRAM);
+    saved_cmdline_ = *CommandLine::ForCurrentProcess();
+    profile_.reset(new TestingProfile());
+    CommandLine::ForCurrentProcess()->AppendSwitch(
+        switches::kEnableExtensionActivityLogging);
+    CommandLine::ForCurrentProcess()->AppendSwitch(
+        switches::kEnableExtensionActivityLogTesting);
+    extension_service_ = static_cast<TestExtensionSystem*>(
+        ExtensionSystem::Get(profile_.get()))->CreateExtensionService
+            (&command_line, base::FilePath(), false);
+  }
+
+  virtual ~CountingPolicyTest() {
+#if defined OS_CHROMEOS
+    test_user_manager_.reset();
+#endif
+    base::RunLoop().RunUntilIdle();
+    profile_.reset(NULL);
+    base::RunLoop().RunUntilIdle();
+    // Restore the original command line and undo the affects of SetUp().
+    *CommandLine::ForCurrentProcess() = saved_cmdline_;
+  }
+
+  // A helper function to call ReadData on a policy object and wait for the
+  // results to be processed.
+  void CheckReadData(
+      ActivityLogPolicy* policy,
+      const std::string& extension_id,
+      const int day,
+      const base::Callback<void(scoped_ptr<Action::ActionVector>)>& checker) {
+    // Submit a request to the policy to read back some data, and call the
+    // checker function when results are available.  This will happen on the
+    // database thread.
+    policy->ReadData(
+        extension_id,
+        day,
+        base::Bind(&CountingPolicyTest::CheckWrapper,
+                   checker,
+                   base::MessageLoop::current()->QuitClosure()));
+
+    // Set up a timeout that will trigger after 5 seconds; if we haven't
+    // received any results by then assume that the test is broken.
+    base::CancelableClosure timeout(
+        base::Bind(&CountingPolicyTest::TimeoutCallback));
+    base::MessageLoop::current()->PostDelayedTask(
+        FROM_HERE, timeout.callback(), base::TimeDelta::FromSeconds(5));
+
+    // Wait for results; either the checker or the timeout callbacks should
+    // cause the main loop to exit.
+    base::MessageLoop::current()->Run();
+
+    timeout.Cancel();
+  }
+
+  static void CheckWrapper(
+      const base::Callback<void(scoped_ptr<Action::ActionVector>)>& checker,
+      const base::Closure& done,
+      scoped_ptr<Action::ActionVector> results) {
+    checker.Run(results.Pass());
+    done.Run();
+  }
+
+  static void TimeoutCallback() {
+    base::MessageLoop::current()->QuitWhenIdle();
+    FAIL() << "Policy test timed out waiting for results";
+  }
+
+  static void Arguments_Stripped(scoped_ptr<Action::ActionVector> i) {
+    scoped_refptr<Action> last = i->front();
+    std::string args =
+        "ID=odlameecjipmbmbejkplpemijjgpljce CATEGORY=api_call "
+        "API=extension.connect ARGS=[\"hello\",\"world\"] COUNT=1";
+    ASSERT_EQ(args, last->PrintForDebug());
+  }
+
+  static void Arguments_GetTodaysActions(
+      scoped_ptr<Action::ActionVector> actions) {
+    std::string api_stripped_print =
+        "ID=punky CATEGORY=api_call API=brewster COUNT=2";
+    std::string api_print =
+        "ID=punky CATEGORY=api_call API=extension.sendMessage "
+        "ARGS=[\"not\",\"stripped\"] COUNT=1";
+    std::string dom_print =
+        "ID=punky CATEGORY=dom_access API=lets ARGS=[\"vamoose\"] "
+        "PAGE_URL=http://www.google.com/ COUNT=1";
+    ASSERT_EQ(3, static_cast<int>(actions->size()));
+    ASSERT_EQ(dom_print, actions->at(0)->PrintForDebug());
+    ASSERT_EQ(api_print, actions->at(1)->PrintForDebug());
+    ASSERT_EQ(api_stripped_print, actions->at(2)->PrintForDebug());
+  }
+
+  static void Arguments_GetOlderActions(
+      scoped_ptr<Action::ActionVector> actions) {
+    std::string api_print =
+        "ID=punky CATEGORY=api_call API=brewster COUNT=1";
+    std::string dom_print =
+        "ID=punky CATEGORY=dom_access API=lets ARGS=[\"vamoose\"] "
+        "PAGE_URL=http://www.google.com/ COUNT=1";
+    ASSERT_EQ(2, static_cast<int>(actions->size()));
+    ASSERT_EQ(dom_print, actions->at(0)->PrintForDebug());
+    ASSERT_EQ(api_print, actions->at(1)->PrintForDebug());
+  }
+
+  static void Arguments_CheckMergeCount(
+      int count,
+      scoped_ptr<Action::ActionVector> actions) {
+    std::string api_print = base::StringPrintf(
+        "ID=punky CATEGORY=api_call API=brewster COUNT=%d", count);
+    if (count > 0) {
+      ASSERT_EQ(1u, actions->size());
+      ASSERT_EQ(api_print, actions->at(0)->PrintForDebug());
+    } else {
+      ASSERT_EQ(0u, actions->size());
+    }
+  }
+
+ protected:
+  ExtensionService* extension_service_;
+  scoped_ptr<TestingProfile> profile_;
+  content::TestBrowserThreadBundle thread_bundle_;
+  // Used to preserve a copy of the original command line.
+  // The test framework will do this itself as well. However, by then,
+  // it is too late to call ActivityLog::RecomputeLoggingIsEnabled() in
+  // TearDown().
+  CommandLine saved_cmdline_;
+
+#if defined OS_CHROMEOS
+  chromeos::ScopedTestDeviceSettingsService test_device_settings_service_;
+  chromeos::ScopedTestCrosSettings test_cros_settings_;
+  scoped_ptr<chromeos::ScopedTestUserManager> test_user_manager_;
+#endif
+};
+
+TEST_F(CountingPolicyTest, Construct) {
+  ActivityLogPolicy* policy = new CountingPolicy(profile_.get());
+  scoped_refptr<const Extension> extension =
+      ExtensionBuilder()
+          .SetManifest(DictionaryBuilder()
+                       .Set("name", "Test extension")
+                       .Set("version", "1.0.0")
+                       .Set("manifest_version", 2))
+          .Build();
+  extension_service_->AddExtension(extension.get());
+  scoped_ptr<base::ListValue> args(new base::ListValue());
+  scoped_refptr<Action> action = new Action(extension->id(),
+                                            base::Time::Now(),
+                                            Action::ACTION_API_CALL,
+                                            "tabs.testMethod");
+  action->set_args(args.Pass());
+  policy->ProcessAction(action);
+  policy->Close();
+}
+
+TEST_F(CountingPolicyTest, LogWithStrippedArguments) {
+  ActivityLogPolicy* policy = new CountingPolicy(profile_.get());
+  scoped_refptr<const Extension> extension =
+      ExtensionBuilder()
+          .SetManifest(DictionaryBuilder()
+                       .Set("name", "Test extension")
+                       .Set("version", "1.0.0")
+                       .Set("manifest_version", 2))
+          .Build();
+  extension_service_->AddExtension(extension.get());
+
+  scoped_ptr<base::ListValue> args(new base::ListValue());
+  args->Set(0, new base::StringValue("hello"));
+  args->Set(1, new base::StringValue("world"));
+  scoped_refptr<Action> action = new Action(extension->id(),
+                                            base::Time::Now(),
+                                            Action::ACTION_API_CALL,
+                                            "extension.connect");
+  action->set_args(args.Pass());
+
+  policy->ProcessAction(action);
+  CheckReadData(policy,
+                extension->id(),
+                0,
+                base::Bind(&CountingPolicyTest::Arguments_Stripped));
+  policy->Close();
+}
+
+TEST_F(CountingPolicyTest, GetTodaysActions) {
+  CountingPolicy* policy = new CountingPolicy(profile_.get());
+  // Disable row expiration for this test by setting a time before any actions
+  // we generate.
+  policy->set_retention_time(base::TimeDelta::FromDays(14));
+
+  // Use a mock clock to ensure that events are not recorded on the wrong day
+  // when the test is run close to local midnight.  Note: Ownership is passed
+  // to the policy, but we still keep a pointer locally.  The policy will take
+  // care of destruction; this is safe since the policy outlives all our
+  // accesses to the mock clock.
+  base::SimpleTestClock* mock_clock = new base::SimpleTestClock();
+  mock_clock->SetNow(base::Time::Now().LocalMidnight() +
+                     base::TimeDelta::FromHours(12));
+  policy->SetClockForTesting(scoped_ptr<base::Clock>(mock_clock));
+
+  // Record some actions
+  scoped_refptr<Action> action =
+      new Action("punky",
+                 mock_clock->Now() - base::TimeDelta::FromMinutes(40),
+                 Action::ACTION_API_CALL,
+                 "brewster");
+  action->mutable_args()->AppendString("woof");
+  policy->ProcessAction(action);
+
+  action = new Action("punky",
+                      mock_clock->Now() - base::TimeDelta::FromMinutes(30),
+                      Action::ACTION_API_CALL,
+                      "brewster");
+  action->mutable_args()->AppendString("meow");
+  policy->ProcessAction(action);
+
+  action = new Action("punky",
+                      mock_clock->Now() - base::TimeDelta::FromMinutes(20),
+                      Action::ACTION_API_CALL,
+                      "extension.sendMessage");
+  action->mutable_args()->AppendString("not");
+  action->mutable_args()->AppendString("stripped");
+  policy->ProcessAction(action);
+
+  action =
+      new Action("punky", mock_clock->Now(), Action::ACTION_DOM_ACCESS, "lets");
+  action->mutable_args()->AppendString("vamoose");
+  action->set_page_url(GURL("http://www.google.com"));
+  policy->ProcessAction(action);
+
+  action = new Action(
+      "scoobydoo", mock_clock->Now(), Action::ACTION_DOM_ACCESS, "lets");
+  action->mutable_args()->AppendString("vamoose");
+  action->set_page_url(GURL("http://www.google.com"));
+  policy->ProcessAction(action);
+
+  CheckReadData(
+      policy,
+      "punky",
+      0,
+      base::Bind(&CountingPolicyTest::Arguments_GetTodaysActions));
+  policy->Close();
+}
+
+// Check that we can read back less recent actions in the db.
+TEST_F(CountingPolicyTest, GetOlderActions) {
+  CountingPolicy* policy = new CountingPolicy(profile_.get());
+  policy->set_retention_time(base::TimeDelta::FromDays(14));
+
+  // Use a mock clock to ensure that events are not recorded on the wrong day
+  // when the test is run close to local midnight.
+  base::SimpleTestClock* mock_clock = new base::SimpleTestClock();
+  mock_clock->SetNow(base::Time::Now().LocalMidnight() +
+                     base::TimeDelta::FromHours(12));
+  policy->SetClockForTesting(scoped_ptr<base::Clock>(mock_clock));
+
+  // Record some actions
+  scoped_refptr<Action> action =
+      new Action("punky",
+                 mock_clock->Now() - base::TimeDelta::FromDays(3) -
+                     base::TimeDelta::FromMinutes(40),
+                 Action::ACTION_API_CALL,
+                 "brewster");
+  action->mutable_args()->AppendString("woof");
+  policy->ProcessAction(action);
+
+  action = new Action("punky",
+                      mock_clock->Now() - base::TimeDelta::FromDays(3),
+                      Action::ACTION_DOM_ACCESS,
+                      "lets");
+  action->mutable_args()->AppendString("vamoose");
+  action->set_page_url(GURL("http://www.google.com"));
+  policy->ProcessAction(action);
+
+  action = new Action("punky",
+                      mock_clock->Now(),
+                      Action::ACTION_DOM_ACCESS,
+                      "lets");
+  action->mutable_args()->AppendString("too new");
+  action->set_page_url(GURL("http://www.google.com"));
+  policy->ProcessAction(action);
+
+  action = new Action("punky",
+                      mock_clock->Now() - base::TimeDelta::FromDays(7),
+                      Action::ACTION_DOM_ACCESS,
+                      "lets");
+  action->mutable_args()->AppendString("too old");
+  action->set_page_url(GURL("http://www.google.com"));
+  policy->ProcessAction(action);
+
+  CheckReadData(
+      policy,
+      "punky",
+      3,
+      base::Bind(&CountingPolicyTest::Arguments_GetOlderActions));
+
+  policy->Close();
+}
+
+// Check that merging of actions only occurs within the same day, not across
+// days, and that old data can be expired from the database.
+TEST_F(CountingPolicyTest, MergingAndExpiring) {
+  CountingPolicy* policy = new CountingPolicy(profile_.get());
+  // Initially disable expiration by setting a retention time before any
+  // actions we generate.
+  policy->set_retention_time(base::TimeDelta::FromDays(14));
+
+  // Use a mock clock to ensure that events are not recorded on the wrong day
+  // when the test is run close to local midnight.
+  base::SimpleTestClock* mock_clock = new base::SimpleTestClock();
+  mock_clock->SetNow(base::Time::Now().LocalMidnight() +
+                    base::TimeDelta::FromHours(12));
+  policy->SetClockForTesting(scoped_ptr<base::Clock>(mock_clock));
+
+  // The first two actions should be merged; the last one is on a separate day
+  // and should not be.
+  scoped_refptr<Action> action =
+      new Action("punky",
+                 mock_clock->Now() - base::TimeDelta::FromDays(3) -
+                     base::TimeDelta::FromMinutes(40),
+                 Action::ACTION_API_CALL,
+                 "brewster");
+  policy->ProcessAction(action);
+
+  action = new Action("punky",
+                      mock_clock->Now() - base::TimeDelta::FromDays(3) -
+                          base::TimeDelta::FromMinutes(20),
+                      Action::ACTION_API_CALL,
+                      "brewster");
+  policy->ProcessAction(action);
+
+  action = new Action("punky",
+                      mock_clock->Now() - base::TimeDelta::FromDays(2) -
+                          base::TimeDelta::FromMinutes(20),
+                      Action::ACTION_API_CALL,
+                      "brewster");
+  policy->ProcessAction(action);
+
+  CheckReadData(policy,
+                "punky",
+                3,
+                base::Bind(&CountingPolicyTest::Arguments_CheckMergeCount, 2));
+  CheckReadData(policy,
+                "punky",
+                2,
+                base::Bind(&CountingPolicyTest::Arguments_CheckMergeCount, 1));
+
+  // Clean actions before midnight two days ago.  Force expiration to run by
+  // clearing last_database_cleaning_time_ and submitting a new action.
+  policy->set_retention_time(base::TimeDelta::FromDays(2));
+  policy->last_database_cleaning_time_ = base::Time();
+  action = new Action("punky",
+                      mock_clock->Now(),
+                      Action::ACTION_API_CALL,
+                      "brewster");
+  policy->ProcessAction(action);
+
+  CheckReadData(policy,
+                "punky",
+                3,
+                base::Bind(&CountingPolicyTest::Arguments_CheckMergeCount, 0));
+  CheckReadData(policy,
+                "punky",
+                2,
+                base::Bind(&CountingPolicyTest::Arguments_CheckMergeCount, 1));
+
+  policy->Close();
+}
+
+}  // namespace extensions
diff --git a/chrome/browser/extensions/activity_log/database_string_table.cc b/chrome/browser/extensions/activity_log/database_string_table.cc
new file mode 100644
index 0000000..c9e832e
--- /dev/null
+++ b/chrome/browser/extensions/activity_log/database_string_table.cc
@@ -0,0 +1,103 @@
+// 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/extensions/activity_log/database_string_table.h"
+
+#include "base/strings/stringprintf.h"
+#include "sql/connection.h"
+#include "sql/statement.h"
+
+using base::StringPrintf;
+
+namespace extensions {
+
+DatabaseStringTable::DatabaseStringTable(const std::string& table)
+    : table_(table) {}
+
+DatabaseStringTable::~DatabaseStringTable() {}
+
+bool DatabaseStringTable::Initialize(sql::Connection* connection) {
+  if (!connection->DoesTableExist(table_.c_str())) {
+    return connection->Execute(StringPrintf(
+        "CREATE TABLE %s (id INTEGER PRIMARY KEY, value TEXT NOT NULL); "
+        "CREATE UNIQUE INDEX %s_index ON %s(value)",
+        table_.c_str(),
+        table_.c_str(),
+        table_.c_str()).c_str());
+  } else {
+    return true;
+  }
+}
+
+bool DatabaseStringTable::StringToInt(sql::Connection* connection,
+                                      const std::string& value,
+                                      int64* id) {
+  std::map<std::string, int64>::const_iterator lookup =
+      value_to_id_.find(value);
+  if (lookup != value_to_id_.end()) {
+    *id = lookup->second;
+    return true;
+  }
+
+  // Operate on the assumption that the cache does a good job on
+  // frequently-used strings--if there is a cache miss, first act on the
+  // assumption that the string is not in the database either.
+  sql::Statement update(connection->GetUniqueStatement(
+      StringPrintf("INSERT OR IGNORE INTO %s(value) VALUES (?)", table_.c_str())
+          .c_str()));
+  update.BindString(0, value);
+  if (!update.Run())
+    return false;
+
+  if (connection->GetLastChangeCount() == 1) {
+    *id = connection->GetLastInsertRowId();
+    id_to_value_[*id] = value;
+    value_to_id_[value] = *id;
+    return true;
+  }
+
+  // The specified string may have already existed in the database, in which
+  // case the insert above will have been ignored.  If this happens, do a
+  // lookup to find the old value.
+  sql::Statement query(connection->GetUniqueStatement(
+      StringPrintf("SELECT id FROM %s WHERE value = ?", table_.c_str())
+          .c_str()));
+  query.BindString(0, value);
+  if (!query.Step())
+    return false;
+  *id = query.ColumnInt64(0);
+  id_to_value_[*id] = value;
+  value_to_id_[value] = *id;
+  return true;
+}
+
+bool DatabaseStringTable::IntToString(sql::Connection* connection,
+                                      int64 id,
+                                      std::string* value) {
+  std::map<int64, std::string>::const_iterator lookup =
+      id_to_value_.find(id);
+  if (lookup != id_to_value_.end()) {
+    *value = lookup->second;
+    return true;
+  }
+
+  sql::Statement query(connection->GetUniqueStatement(
+      StringPrintf("SELECT value FROM %s WHERE id = ?", table_.c_str())
+          .c_str()));
+  query.BindInt64(0, id);
+  if (!query.Step())
+    return false;
+
+  *value = query.ColumnString(0);
+  id_to_value_[id] = *value;
+  value_to_id_[*value] = id;
+  return true;
+}
+
+void DatabaseStringTable::ClearCache() {
+  id_to_value_.clear();
+  value_to_id_.clear();
+}
+
+}  // namespace extensions
diff --git a/chrome/browser/extensions/activity_log/database_string_table.h b/chrome/browser/extensions/activity_log/database_string_table.h
new file mode 100644
index 0000000..9677fae
--- /dev/null
+++ b/chrome/browser/extensions/activity_log/database_string_table.h
@@ -0,0 +1,71 @@
+// 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_EXTENSIONS_ACTIVITY_LOG_DATABASE_STRING_TABLE_H_
+#define CHROME_BROWSER_EXTENSIONS_ACTIVITY_LOG_DATABASE_STRING_TABLE_H_
+
+#include <map>
+#include <string>
+
+#include "base/basictypes.h"
+
+namespace sql {
+class Connection;
+}  // namespace sql
+
+namespace extensions {
+
+// A class for maintaining a persistent mapping between strings and integers.
+// This is used to help compress the contents of the activity log database on
+// disk by replacing repeated strings by smaller integers.
+//
+// The mapping from integers to strings is maintained in a database table, but
+// the mapping is also cached in memory.
+//
+// The database table used to store the strings is configurable, but its layout
+// is fixed: it always consists of just two columns, "id" and "value".
+//
+// All calls to DatabaseStringTable must occur on the database thread.
+class DatabaseStringTable {
+ public:
+  explicit DatabaseStringTable(const std::string& table);
+
+  ~DatabaseStringTable();
+
+  // Initialize the database table.  This will create the table if it does not
+  // exist.  Returns true on success; false on error.
+  bool Initialize(sql::Connection* connection);
+
+  // Interns a string in the database table and sets *id to the corresponding
+  // integer.  If the string already exists, the existing number is returned;
+  // otherwise, new database row is inserted with the new string.  Returns true
+  // on success and false on database error.
+  bool StringToInt(sql::Connection* connection,
+                   const std::string& value,
+                   int64* id);
+
+  // Looks up an integer value and converts it to a string (which is stored in
+  // *value).  Returns true on success.  A false return does not necessarily
+  // indicate a database error; it might simply be that the value cannot be
+  // found.
+  bool IntToString(sql::Connection* connection, int64 id, std::string* value);
+
+  // Clear the in-memory cache; this should be called if the underlying
+  // database table has been manipulated and the cache may be stale.
+  void ClearCache();
+
+ private:
+  // In-memory caches of recently accessed values.
+  std::map<int64, std::string> id_to_value_;
+  std::map<std::string, int64> value_to_id_;
+
+  // The name of the database table where the mapping is stored.
+  std::string table_;
+
+  DISALLOW_COPY_AND_ASSIGN(DatabaseStringTable);
+};
+
+}  // namespace extensions
+
+#endif  // CHROME_BROWSER_EXTENSIONS_ACTIVITY_LOG_DATABASE_STRING_TABLE_H_
diff --git a/chrome/browser/extensions/activity_log/database_string_table_unittest.cc b/chrome/browser/extensions/activity_log/database_string_table_unittest.cc
new file mode 100644
index 0000000..2024827
--- /dev/null
+++ b/chrome/browser/extensions/activity_log/database_string_table_unittest.cc
@@ -0,0 +1,133 @@
+// 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/files/scoped_temp_dir.h"
+#include "chrome/browser/extensions/activity_log/database_string_table.h"
+#include "sql/connection.h"
+#include "sql/statement.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace extensions {
+
+class DatabaseStringTableTest : public testing::Test {
+ protected:
+  virtual void SetUp() OVERRIDE {
+    ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
+    base::FilePath db_file = temp_dir_.path().AppendASCII("StringTable.db");
+
+    ASSERT_TRUE(db_.Open(db_file));
+  }
+
+  virtual void TearDown() OVERRIDE {
+    db_.Close();
+  }
+
+  base::ScopedTempDir temp_dir_;
+  sql::Connection db_;
+};
+
+// Check that initializing the database works.
+TEST_F(DatabaseStringTableTest, Init) {
+  DatabaseStringTable table("test");
+  table.Initialize(&db_);
+  ASSERT_TRUE(db_.DoesTableExist("test"));
+  ASSERT_TRUE(db_.DoesIndexExist("test_index"));
+}
+
+// Insert a new mapping into the table, then verify the table contents.
+TEST_F(DatabaseStringTableTest, Insert) {
+  DatabaseStringTable table("test");
+  table.Initialize(&db_);
+  int64 id;
+  ASSERT_TRUE(table.StringToInt(&db_, "abc", &id));
+
+  sql::Statement query(
+      db_.GetUniqueStatement("SELECT id FROM test WHERE value = 'abc'"));
+  ASSERT_TRUE(query.Step());
+  int64 raw_id = query.ColumnInt64(0);
+  ASSERT_EQ(id, raw_id);
+}
+
+// Check that different strings are mapped to different values, and the same
+// string is mapped to the same value repeatably.
+TEST_F(DatabaseStringTableTest, InsertMultiple) {
+  DatabaseStringTable table("test");
+  table.Initialize(&db_);
+
+  int64 id1;
+  int64 id2;
+  ASSERT_TRUE(table.StringToInt(&db_, "string1", &id1));
+  ASSERT_TRUE(table.StringToInt(&db_, "string2", &id2));
+  ASSERT_NE(id1, id2);
+
+  int64 id1a;
+  ASSERT_TRUE(table.StringToInt(&db_, "string1", &id1a));
+  ASSERT_EQ(id1, id1a);
+}
+
+// Check that values can be read back from the database even after the
+// in-memory cache is cleared.
+TEST_F(DatabaseStringTableTest, CacheCleared) {
+  DatabaseStringTable table("test");
+  table.Initialize(&db_);
+
+  int64 id1;
+  ASSERT_TRUE(table.StringToInt(&db_, "string1", &id1));
+
+  table.ClearCache();
+
+  int64 id2;
+  ASSERT_TRUE(table.StringToInt(&db_, "string1", &id2));
+  ASSERT_EQ(id1, id2);
+}
+
+// Check that direct database modifications are picked up after the cache is
+// cleared.
+TEST_F(DatabaseStringTableTest, DatabaseModified) {
+  DatabaseStringTable table("test");
+  table.Initialize(&db_);
+
+  int64 id1;
+  ASSERT_TRUE(table.StringToInt(&db_, "modified", &id1));
+
+  ASSERT_TRUE(
+      db_.Execute("UPDATE test SET id = id + 1 WHERE value = 'modified'"));
+
+  int64 id2;
+  ASSERT_TRUE(table.StringToInt(&db_, "modified", &id2));
+  ASSERT_EQ(id1, id2);
+
+  table.ClearCache();
+
+  int64 id3;
+  ASSERT_TRUE(table.StringToInt(&db_, "modified", &id3));
+  ASSERT_EQ(id1 + 1, id3);
+}
+
+// Check that looking up an unknown id returns an error.
+TEST_F(DatabaseStringTableTest, BadLookup) {
+  DatabaseStringTable table("test");
+  table.Initialize(&db_);
+  std::string value;
+  ASSERT_FALSE(table.IntToString(&db_, 1, &value));
+}
+
+// Check looking up an inserted value, both cached and not cached.
+TEST_F(DatabaseStringTableTest, Lookup) {
+  DatabaseStringTable table("test");
+  table.Initialize(&db_);
+  int64 id;
+  ASSERT_TRUE(table.StringToInt(&db_, "abc", &id));
+
+  std::string value;
+  ASSERT_TRUE(table.IntToString(&db_, id, &value));
+  ASSERT_EQ("abc", value);
+
+  table.ClearCache();
+  value = "";
+  ASSERT_TRUE(table.IntToString(&db_, id, &value));
+  ASSERT_EQ("abc", value);
+}
+
+}  // namespace extensions
diff --git a/chrome/browser/extensions/activity_log/fullstream_ui_policy.cc b/chrome/browser/extensions/activity_log/fullstream_ui_policy.cc
index 24f5494..94f6371 100644
--- a/chrome/browser/extensions/activity_log/fullstream_ui_policy.cc
+++ b/chrome/browser/extensions/activity_log/fullstream_ui_policy.cc
@@ -31,32 +31,6 @@
 
 namespace constants = activity_log_constants;
 
-namespace {
-
-// Key strings for passing parameters to the ProcessAction member function.
-const char kKeyReason[] =         "fsuip.reason";
-const char kKeyDomainAction[] =   "fsuip.domact";
-const char kKeyURLTitle[] =       "fsuip.urltitle";
-const char kKeyDetailsString[] =  "fsuip.details";
-
-// Obsolete database tables: these should be dropped from the database if
-// found.
-const char* kObsoleteTables[] = {"activitylog_apis", "activitylog_blocked",
-                                 "activitylog_urls"};
-
-std::string Serialize(const base::Value* value) {
-  std::string value_as_text;
-  if (!value) {
-    value_as_text = "null";
-  } else {
-    JSONStringValueSerializer serializer(&value_as_text);
-    serializer.SerializeAndOmitBinaryValues(*value);
-  }
-  return value_as_text;
-}
-
-}  // namespace
-
 namespace extensions {
 
 const char* FullStreamUIPolicy::kTableName = "activitylog_full";
@@ -68,7 +42,8 @@
   "LONGVARCHAR NOT NULL", "INTEGER", "INTEGER", "LONGVARCHAR", "LONGVARCHAR",
   "LONGVARCHAR", "LONGVARCHAR", "LONGVARCHAR", "LONGVARCHAR"
 };
-const int FullStreamUIPolicy::kTableFieldCount = arraysize(kTableContentFields);
+const int FullStreamUIPolicy::kTableFieldCount =
+    arraysize(FullStreamUIPolicy::kTableContentFields);
 
 FullStreamUIPolicy::FullStreamUIPolicy(Profile* profile)
     : ActivityLogDatabasePolicy(
@@ -78,17 +53,8 @@
 FullStreamUIPolicy::~FullStreamUIPolicy() {}
 
 bool FullStreamUIPolicy::InitDatabase(sql::Connection* db) {
-  // Drop old database tables.
-  for (size_t i = 0; i < arraysize(kObsoleteTables); i++) {
-    const char* table_name = kObsoleteTables[i];
-    if (db->DoesTableExist(table_name)) {
-      std::string drop_statement =
-          base::StringPrintf("DROP TABLE %s", table_name);
-      if (!db->Execute(drop_statement.c_str())) {
-        return false;
-      }
-    }
-  }
+  if (!Util::DropObsoleteTables(db))
+    return false;
 
   // Create the unified activity log entry table.
   return ActivityDatabase::InitializeTable(db,
@@ -113,13 +79,6 @@
   sql::Statement statement(db->GetCachedStatement(
       sql::StatementID(SQL_FROM_HERE), sql_str.c_str()));
 
-  url_canon::Replacements<char> url_sanitizer;
-  if (!CommandLine::ForCurrentProcess()->HasSwitch(
-          switches::kEnableExtensionActivityLogTesting)) {
-    url_sanitizer.ClearQuery();
-    url_sanitizer.ClearRef();
-  }
-
   Action::ActionVector::size_type i;
   for (i = 0; i != queued_actions_.size(); ++i) {
     const Action& action = *queued_actions_[i];
@@ -129,29 +88,21 @@
     statement.BindInt(2, static_cast<int>(action.action_type()));
     statement.BindString(3, action.api_name());
     if (action.args()) {
-      statement.BindString(4, Serialize(action.args()));
+      statement.BindString(4, Util::Serialize(action.args()));
     }
-    if (action.page_url().is_valid()) {
-      if (action.page_incognito()) {
-        statement.BindString(5, constants::kIncognitoUrl);
-      } else {
-        statement.BindString(
-            5, action.page_url().ReplaceComponents(url_sanitizer).spec());
-      }
+    std::string page_url_string = action.SerializePageUrl();
+    if (!page_url_string.empty()) {
+      statement.BindString(5, page_url_string);
     }
-    if (!action.page_title().empty() && !action.page_incognito()) {
+    if (!action.page_title().empty()) {
       statement.BindString(6, action.page_title());
     }
-    if (action.arg_url().is_valid()) {
-      if (action.arg_incognito()) {
-        statement.BindString(7, constants::kIncognitoUrl);
-      } else {
-        statement.BindString(
-            7, action.arg_url().ReplaceComponents(url_sanitizer).spec());
-      }
+    std::string arg_url_string = action.SerializePageUrl();
+    if (!arg_url_string.empty()) {
+      statement.BindString(5, arg_url_string);
     }
     if (action.other()) {
-      statement.BindString(8, Serialize(action.other()));
+      statement.BindString(8, Util::Serialize(action.other()));
     }
 
     if (!statement.Run()) {
@@ -170,6 +121,10 @@
 scoped_ptr<Action::ActionVector> FullStreamUIPolicy::DoReadData(
     const std::string& extension_id,
     const int days_ago) {
+  // Ensure data is flushed to the database first so that we query over all
+  // data.
+  activity_database()->AdviseFlush(ActivityDatabase::kFlushImmediately);
+
   DCHECK_GE(days_ago, 0);
   scoped_ptr<Action::ActionVector> actions(new Action::ActionVector());
 
@@ -178,21 +133,9 @@
     return actions.Pass();
   }
 
-  // Compute the time bounds for that day.
-  base::Time morning_midnight = Now().LocalMidnight();
-  int64 early_bound = 0;
-  int64 late_bound = 0;
-  if (days_ago == 0) {
-      early_bound = morning_midnight.ToInternalValue();
-      late_bound = base::Time::Max().ToInternalValue();
-  } else {
-      base::Time early_time = morning_midnight -
-          base::TimeDelta::FromDays(days_ago);
-      base::Time late_time = morning_midnight -
-          base::TimeDelta::FromDays(days_ago-1);
-      early_bound = early_time.ToInternalValue();
-      late_bound = late_time.ToInternalValue();
-  }
+  int64 early_bound;
+  int64 late_bound;
+  Util::ComputeDatabaseTimeBounds(Now(), days_ago, &early_bound, &late_bound);
   std::string query_str = base::StringPrintf(
       "SELECT time, action_type, api_name, args, page_url, page_title, "
       "arg_url, other "
@@ -223,13 +166,9 @@
       }
     }
 
-    GURL page_url(query.ColumnString(4));
-    action->set_page_url(page_url);
-
+    action->ParsePageUrl(query.ColumnString(4));
     action->set_page_title(query.ColumnString(5));
-
-    GURL arg_url(query.ColumnString(6));
-    action->set_arg_url(arg_url);
+    action->ParseArgUrl(query.ColumnString(6));
 
     if (query.ColumnType(7) != sql::COLUMN_TYPE_NULL) {
       scoped_ptr<Value> parsed_value(
@@ -277,22 +216,6 @@
       callback);
 }
 
-std::string FullStreamUIPolicy::GetKey(ActivityLogPolicy::KeyType key_ty) const
-{
-  switch (key_ty) {
-    case PARAM_KEY_REASON:
-      return std::string(kKeyReason);
-    case PARAM_KEY_DOM_ACTION:
-      return std::string(kKeyDomainAction);
-    case PARAM_KEY_URL_TITLE:
-      return std::string(kKeyURLTitle);
-    case PARAM_KEY_DETAILS_STRING:
-      return std::string(kKeyDetailsString);
-    default:
-      return std::string();
-  }
-}
-
 scoped_refptr<Action> FullStreamUIPolicy::ProcessArguments(
     scoped_refptr<Action> action) const {
   return action;
@@ -310,7 +233,7 @@
 void FullStreamUIPolicy::QueueAction(scoped_refptr<Action> action) {
   if (activity_database()->is_db_valid()) {
     queued_actions_.push_back(action);
-    activity_database()->NotifyAction();
+    activity_database()->AdviseFlush(queued_actions_.size());
   }
 }
 
diff --git a/chrome/browser/extensions/activity_log/fullstream_ui_policy.h b/chrome/browser/extensions/activity_log/fullstream_ui_policy.h
index 49a8b70..4f50d54 100644
--- a/chrome/browser/extensions/activity_log/fullstream_ui_policy.h
+++ b/chrome/browser/extensions/activity_log/fullstream_ui_policy.h
@@ -16,6 +16,11 @@
 
 // A policy for logging the full stream of actions, including all arguments.
 // It's mostly intended to be used in testing and analysis.
+//
+// NOTE: The FullStreamUIPolicy deliberately keeps almost all information,
+// including some data that could be privacy sensitive (full URLs including
+// incognito URLs, full headers when WebRequest is used, etc.).  It should not
+// be used during normal browsing if users care about privacy.
 class FullStreamUIPolicy : public ActivityLogDatabasePolicy {
  public:
   // For more info about these member functions, see the super class.
@@ -34,9 +39,6 @@
       const base::Callback
           <void(scoped_ptr<Action::ActionVector>)>& callback) OVERRIDE;
 
-  // Returns the actual key for a given key type
-  virtual std::string GetKey(ActivityLogPolicy::KeyType key_id) const OVERRIDE;
-
   virtual void Close() OVERRIDE;
 
   // Database table schema.
@@ -50,8 +52,8 @@
   // ActivityDatabase class for an overall discussion of how cleanup works.
   virtual ~FullStreamUIPolicy();
 
-  // The ActivityDatabase::PolicyDelegate interface.  These are always called
-  // from the database thread.
+  // The ActivityDatabase::Delegate interface.  These are always called from
+  // the database thread.
   virtual bool InitDatabase(sql::Connection* db) OVERRIDE;
   virtual bool FlushDatabase(sql::Connection* db) OVERRIDE;
   virtual void OnDatabaseFailure() OVERRIDE;
diff --git a/chrome/browser/extensions/activity_log/fullstream_ui_policy_unittest.cc b/chrome/browser/extensions/activity_log/fullstream_ui_policy_unittest.cc
index 0421357..2c453a8 100644
--- a/chrome/browser/extensions/activity_log/fullstream_ui_policy_unittest.cc
+++ b/chrome/browser/extensions/activity_log/fullstream_ui_policy_unittest.cc
@@ -247,29 +247,32 @@
   ActivityLogPolicy* policy = new FullStreamUIPolicy(profile_.get());
 
   // Use a mock clock to ensure that events are not recorded on the wrong day
-  // when the test is run close to local midnight.
-  base::SimpleTestClock mock_clock;
-  mock_clock.SetNow(base::Time::Now().LocalMidnight() +
-                    base::TimeDelta::FromHours(12));
-  policy->SetClockForTesting(&mock_clock);
+  // when the test is run close to local midnight.  Note: Ownership is passed
+  // to the policy, but we still keep a pointer locally.  The policy will take
+  // care of destruction; this is safe since the policy outlives all our
+  // accesses to the mock clock.
+  base::SimpleTestClock* mock_clock = new base::SimpleTestClock();
+  mock_clock->SetNow(base::Time::Now().LocalMidnight() +
+                     base::TimeDelta::FromHours(12));
+  policy->SetClockForTesting(scoped_ptr<base::Clock>(mock_clock));
 
   // Record some actions
   scoped_refptr<Action> action =
       new Action("punky",
-                 mock_clock.Now() - base::TimeDelta::FromMinutes(40),
+                 mock_clock->Now() - base::TimeDelta::FromMinutes(40),
                  Action::ACTION_API_CALL,
                  "brewster");
   action->mutable_args()->AppendString("woof");
   policy->ProcessAction(action);
 
   action =
-      new Action("punky", mock_clock.Now(), Action::ACTION_DOM_ACCESS, "lets");
+      new Action("punky", mock_clock->Now(), Action::ACTION_DOM_ACCESS, "lets");
   action->mutable_args()->AppendString("vamoose");
   action->set_page_url(GURL("http://www.google.com"));
   policy->ProcessAction(action);
 
   action = new Action(
-      "scoobydoo", mock_clock.Now(), Action::ACTION_DOM_ACCESS, "lets");
+      "scoobydoo", mock_clock->Now(), Action::ACTION_DOM_ACCESS, "lets");
   action->mutable_args()->AppendString("vamoose");
   action->set_page_url(GURL("http://www.google.com"));
   policy->ProcessAction(action);
@@ -288,15 +291,15 @@
 
   // Use a mock clock to ensure that events are not recorded on the wrong day
   // when the test is run close to local midnight.
-  base::SimpleTestClock mock_clock;
-  mock_clock.SetNow(base::Time::Now().LocalMidnight() +
-                    base::TimeDelta::FromHours(12));
-  policy->SetClockForTesting(&mock_clock);
+  base::SimpleTestClock* mock_clock = new base::SimpleTestClock();
+  mock_clock->SetNow(base::Time::Now().LocalMidnight() +
+                     base::TimeDelta::FromHours(12));
+  policy->SetClockForTesting(scoped_ptr<base::Clock>(mock_clock));
 
   // Record some actions
   scoped_refptr<Action> action =
       new Action("punky",
-                 mock_clock.Now() - base::TimeDelta::FromDays(3) -
+                 mock_clock->Now() - base::TimeDelta::FromDays(3) -
                      base::TimeDelta::FromMinutes(40),
                  Action::ACTION_API_CALL,
                  "brewster");
@@ -304,7 +307,7 @@
   policy->ProcessAction(action);
 
   action = new Action("punky",
-                      mock_clock.Now() - base::TimeDelta::FromDays(3),
+                      mock_clock->Now() - base::TimeDelta::FromDays(3),
                       Action::ACTION_DOM_ACCESS,
                       "lets");
   action->mutable_args()->AppendString("vamoose");
@@ -312,7 +315,7 @@
   policy->ProcessAction(action);
 
   action = new Action("punky",
-                      mock_clock.Now(),
+                      mock_clock->Now(),
                       Action::ACTION_DOM_ACCESS,
                       "lets");
   action->mutable_args()->AppendString("too new");
@@ -320,7 +323,7 @@
   policy->ProcessAction(action);
 
   action = new Action("punky",
-                      mock_clock.Now() - base::TimeDelta::FromDays(7),
+                      mock_clock->Now() - base::TimeDelta::FromDays(7),
                       Action::ACTION_DOM_ACCESS,
                       "lets");
   action->mutable_args()->AppendString("too old");
diff --git a/chrome/browser/extensions/activity_log/stream_noargs_ui_policy.cc b/chrome/browser/extensions/activity_log/stream_noargs_ui_policy.cc
deleted file mode 100644
index 6ec8916..0000000
--- a/chrome/browser/extensions/activity_log/stream_noargs_ui_policy.cc
+++ /dev/null
@@ -1,63 +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/extensions/activity_log/stream_noargs_ui_policy.h"
-
-#include "base/json/json_string_value_serializer.h"
-#include "chrome/browser/extensions/activity_log/activity_action_constants.h"
-
-namespace constants = activity_log_constants;
-
-namespace {
-
-// We should log the arguments to these API calls.  Be careful when
-// constructing this whitelist to not keep arguments that might compromise
-// privacy by logging too much data to the activity log.
-//
-// TODO(mvrable): The contents of this whitelist should be reviewed and
-// expanded as needed.
-const char* kAlwaysLog[] = {"extension.connect", "extension.sendMessage",
-                            "tabs.executeScript", "tabs.insertCSS"};
-
-}  // namespace
-
-namespace extensions {
-
-StreamWithoutArgsUIPolicy::StreamWithoutArgsUIPolicy(Profile* profile)
-    : FullStreamUIPolicy(profile) {
-  for (size_t i = 0; i < arraysize(kAlwaysLog); i++) {
-    arg_whitelist_api_.insert(kAlwaysLog[i]);
-  }
-}
-
-StreamWithoutArgsUIPolicy::~StreamWithoutArgsUIPolicy() {}
-
-scoped_refptr<Action> StreamWithoutArgsUIPolicy::ProcessArguments(
-    scoped_refptr<Action> action) const {
-  if (action->action_type() == Action::ACTION_DOM_ACCESS ||
-      action->action_type() == Action::ACTION_DOM_EVENT ||
-      arg_whitelist_api_.find(action->api_name()) != arg_whitelist_api_.end()) {
-    // No stripping of arguments
-  } else {
-    // Do not modify the Action in-place, as there might be other users.
-    action = action->Clone();
-    action->set_args(scoped_ptr<ListValue>());
-
-    // Strip details of the web request modifications (for privacy reasons).
-    if (action->action_type() == Action::ACTION_WEB_REQUEST) {
-      DictionaryValue* details = NULL;
-      if (action->mutable_other()->GetDictionary(constants::kActionWebRequest,
-                                                 &details)) {
-        DictionaryValue::Iterator details_iterator(*details);
-        while (!details_iterator.IsAtEnd()) {
-          details->SetBoolean(details_iterator.key(), true);
-          details_iterator.Advance();
-        }
-      }
-    }
-  }
-  return action;
-}
-
-}  // namespace extensions
diff --git a/chrome/browser/extensions/activity_log/stream_noargs_ui_policy.h b/chrome/browser/extensions/activity_log/stream_noargs_ui_policy.h
deleted file mode 100644
index addbacd..0000000
--- a/chrome/browser/extensions/activity_log/stream_noargs_ui_policy.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_EXTENSIONS_ACTIVITY_LOG_STREAM_NOARGS_UI_POLICY_H_
-#define CHROME_BROWSER_EXTENSIONS_ACTIVITY_LOG_STREAM_NOARGS_UI_POLICY_H_
-
-#include <string>
-
-#include "base/containers/hash_tables.h"
-#include "chrome/browser/extensions/activity_log/fullstream_ui_policy.h"
-
-namespace extensions {
-
-// A policy for logging the stream of actions, but without arguments.
-class StreamWithoutArgsUIPolicy : public FullStreamUIPolicy {
- public:
-  explicit StreamWithoutArgsUIPolicy(Profile* profile);
-  virtual ~StreamWithoutArgsUIPolicy();
-
- protected:
-  // Clears the args field of the action (except for some DOM events and a
-  // small whitelisted set of api_names).  For WEB_REQUEST actions, keeps keys
-  // but removes values from the "web_request" dictionary in other.
-  virtual scoped_refptr<Action> ProcessArguments(
-      scoped_refptr<Action> action) const OVERRIDE;
-
- private:
-  base::hash_set<std::string> arg_whitelist_api_;
-};
-
-}  // namespace extensions
-
-#endif  // CHROME_BROWSER_EXTENSIONS_ACTIVITY_LOG_STREAM_NOARGS_UI_POLICY_H_
diff --git a/chrome/browser/extensions/activity_log/stream_noargs_ui_policy_unittest.cc b/chrome/browser/extensions/activity_log/stream_noargs_ui_policy_unittest.cc
deleted file mode 100644
index 5c5207a..0000000
--- a/chrome/browser/extensions/activity_log/stream_noargs_ui_policy_unittest.cc
+++ /dev/null
@@ -1,173 +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/command_line.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/run_loop.h"
-#include "base/synchronization/waitable_event.h"
-#include "chrome/browser/extensions/activity_log/activity_log.h"
-#include "chrome/browser/extensions/activity_log/stream_noargs_ui_policy.h"
-#include "chrome/browser/extensions/extension_service.h"
-#include "chrome/browser/extensions/test_extension_system.h"
-#include "chrome/common/chrome_constants.h"
-#include "chrome/common/chrome_switches.h"
-#include "chrome/common/extensions/extension_builder.h"
-#include "chrome/test/base/chrome_render_view_host_test_harness.h"
-#include "chrome/test/base/testing_profile.h"
-#include "content/public/test/test_browser_thread_bundle.h"
-#include "sql/statement.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-#if defined(OS_CHROMEOS)
-#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"
-#endif
-
-namespace extensions {
-
-class StreamWithoutArgsUIPolicyTest : public testing::Test {
- public:
-  StreamWithoutArgsUIPolicyTest()
-      : thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP),
-        saved_cmdline_(CommandLine::NO_PROGRAM) {
-#if defined OS_CHROMEOS
-    test_user_manager_.reset(new chromeos::ScopedTestUserManager());
-#endif
-    CommandLine command_line(CommandLine::NO_PROGRAM);
-    saved_cmdline_ = *CommandLine::ForCurrentProcess();
-    profile_.reset(new TestingProfile());
-    CommandLine::ForCurrentProcess()->AppendSwitch(
-        switches::kEnableExtensionActivityLogging);
-    CommandLine::ForCurrentProcess()->AppendSwitch(
-        switches::kEnableExtensionActivityLogTesting);
-    extension_service_ = static_cast<TestExtensionSystem*>(
-        ExtensionSystem::Get(profile_.get()))->CreateExtensionService
-            (&command_line, base::FilePath(), false);
-  }
-
-  virtual ~StreamWithoutArgsUIPolicyTest() {
-#if defined OS_CHROMEOS
-    test_user_manager_.reset();
-#endif
-    base::RunLoop().RunUntilIdle();
-    profile_.reset(NULL);
-    base::RunLoop().RunUntilIdle();
-    // Restore the original command line and undo the affects of SetUp().
-    *CommandLine::ForCurrentProcess() = saved_cmdline_;
-  }
-
-  static void RetrieveActions_LogAndFetchActions(
-      scoped_ptr<std::vector<scoped_refptr<Action> > > i) {
-    ASSERT_EQ(2, static_cast<int>(i->size()));
-  }
-
-  static void Arguments_Missing(
-      scoped_ptr<std::vector<scoped_refptr<Action> > > i) {
-    scoped_refptr<Action> last = i->front();
-    std::string noargs =
-        "ID=odlameecjipmbmbejkplpemijjgpljce CATEGORY=api_call "
-        "API=tabs.testMethod";
-    ASSERT_EQ(noargs, last->PrintForDebug());
-  }
-
- protected:
-  ExtensionService* extension_service_;
-  scoped_ptr<TestingProfile> profile_;
-  content::TestBrowserThreadBundle thread_bundle_;
-  // Used to preserve a copy of the original command line.
-  // The test framework will do this itself as well. However, by then,
-  // it is too late to call ActivityLog::RecomputeLoggingIsEnabled() in
-  // TearDown().
-  CommandLine saved_cmdline_;
-
-#if defined OS_CHROMEOS
-  chromeos::ScopedTestDeviceSettingsService test_device_settings_service_;
-  chromeos::ScopedTestCrosSettings test_cros_settings_;
-  scoped_ptr<chromeos::ScopedTestUserManager> test_user_manager_;
-#endif
-};
-
-TEST_F(StreamWithoutArgsUIPolicyTest, Construct) {
-  ActivityLogPolicy* policy = new StreamWithoutArgsUIPolicy(profile_.get());
-  scoped_refptr<const Extension> extension =
-      ExtensionBuilder()
-          .SetManifest(DictionaryBuilder()
-                       .Set("name", "Test extension")
-                       .Set("version", "1.0.0")
-                       .Set("manifest_version", 2))
-          .Build();
-  extension_service_->AddExtension(extension.get());
-  scoped_ptr<base::ListValue> args(new base::ListValue());
-  scoped_refptr<Action> action = new Action(extension->id(),
-                                            base::Time::Now(),
-                                            Action::ACTION_API_CALL,
-                                            "tabs.testMethod");
-  action->set_args(args.Pass());
-  policy->ProcessAction(action);
-  policy->Close();
-}
-
-TEST_F(StreamWithoutArgsUIPolicyTest, LogAndFetchActions) {
-  ActivityLogPolicy* policy = new StreamWithoutArgsUIPolicy(profile_.get());
-  scoped_refptr<const Extension> extension =
-      ExtensionBuilder()
-          .SetManifest(DictionaryBuilder()
-                       .Set("name", "Test extension")
-                       .Set("version", "1.0.0")
-                       .Set("manifest_version", 2))
-          .Build();
-  extension_service_->AddExtension(extension.get());
-  GURL gurl("http://www.google.com");
-
-  // Write some API calls
-  scoped_refptr<Action> action_api = new Action(extension->id(),
-                                                base::Time::Now(),
-                                                Action::ACTION_API_CALL,
-                                                "tabs.testMethod");
-  action_api->set_args(make_scoped_ptr(new base::ListValue()));
-  policy->ProcessAction(action_api);
-
-  scoped_refptr<Action> action_dom = new Action(extension->id(),
-                                                base::Time::Now(),
-                                                Action::ACTION_DOM_ACCESS,
-                                                "document.write");
-  action_dom->set_args(make_scoped_ptr(new base::ListValue()));
-  action_dom->set_page_url(gurl);
-  policy->ProcessAction(action_dom);
-
-  policy->ReadData(extension->id(), 0,
-      base::Bind(
-          StreamWithoutArgsUIPolicyTest::RetrieveActions_LogAndFetchActions));
-
-  policy->Close();
-}
-
-TEST_F(StreamWithoutArgsUIPolicyTest, LogWithoutArguments) {
-  ActivityLogPolicy* policy = new StreamWithoutArgsUIPolicy(profile_.get());
-  scoped_refptr<const Extension> extension =
-      ExtensionBuilder()
-          .SetManifest(DictionaryBuilder()
-                       .Set("name", "Test extension")
-                       .Set("version", "1.0.0")
-                       .Set("manifest_version", 2))
-          .Build();
-  extension_service_->AddExtension(extension.get());
-
-  scoped_ptr<base::ListValue> args(new base::ListValue());
-  args->Set(0, new base::StringValue("hello"));
-  args->Set(1, new base::StringValue("world"));
-  scoped_refptr<Action> action = new Action(extension->id(),
-                                            base::Time::Now(),
-                                            Action::ACTION_API_CALL,
-                                            "tabs.testMethod");
-  action->set_args(args.Pass());
-
-  policy->ProcessAction(action);
-  policy->ReadData(extension->id(), 0,
-      base::Bind(StreamWithoutArgsUIPolicyTest::Arguments_Missing));
-  policy->Close();
-}
-
-}  // namespace extensions
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 eabfc1c..dcda353 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
@@ -6,11 +6,11 @@
 
 #include "apps/native_app_window.h"
 #include "apps/shell_window.h"
+#include "apps/shell_window_registry.h"
 #include "base/command_line.h"
-#include "chrome/browser/extensions/shell_window_registry.h"
 #include "chrome/common/extensions/api/app_current_window_internal.h"
 #include "chrome/common/extensions/api/app_window.h"
-#include "chrome/common/extensions/features/feature.h"
+#include "chrome/common/extensions/features/feature_channel.h"
 #include "extensions/common/switches.h"
 
 using apps::ShellWindow;
@@ -32,7 +32,8 @@
 }  // namespace
 
 bool AppCurrentWindowInternalExtensionFunction::RunImpl() {
-  ShellWindowRegistry* registry = ShellWindowRegistry::Get(profile());
+  apps::ShellWindowRegistry* registry =
+      apps::ShellWindowRegistry::Get(profile());
   DCHECK(registry);
   content::RenderViewHost* rvh = render_view_host();
   if (!rvh)
@@ -123,7 +124,7 @@
 
 bool AppCurrentWindowInternalSetIconFunction::RunWithWindow(
     ShellWindow* window) {
-  if (Feature::GetCurrentChannel() > chrome::VersionInfo::CHANNEL_DEV &&
+  if (GetCurrentChannel() > chrome::VersionInfo::CHANNEL_DEV &&
       GetExtension()->location() != extensions::Manifest::COMPONENT) {
     error_ = kDevChannelOnly;
     return false;
diff --git a/chrome/browser/extensions/api/app_window/app_window_api.cc b/chrome/browser/extensions/api/app_window/app_window_api.cc
index a172a5a..7fa2492 100644
--- a/chrome/browser/extensions/api/app_window/app_window_api.cc
+++ b/chrome/browser/extensions/api/app_window/app_window_api.cc
@@ -7,17 +7,17 @@
 #include "apps/app_window_contents.h"
 #include "apps/native_app_window.h"
 #include "apps/shell_window.h"
+#include "apps/shell_window_registry.h"
 #include "base/command_line.h"
 #include "base/time/time.h"
 #include "base/values.h"
 #include "chrome/browser/app_mode/app_mode_utils.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/devtools/devtools_window.h"
-#include "chrome/browser/extensions/shell_window_registry.h"
 #include "chrome/browser/extensions/window_controller.h"
 #include "chrome/browser/ui/apps/chrome_shell_window_delegate.h"
 #include "chrome/common/extensions/api/app_window.h"
-#include "chrome/common/extensions/features/feature.h"
+#include "chrome/common/extensions/features/feature_channel.h"
 #include "content/public/browser/notification_registrar.h"
 #include "content/public/browser/notification_types.h"
 #include "content/public/browser/render_process_host.h"
@@ -150,7 +150,7 @@
       create_params.window_key = *options->id;
 
       if (!options->singleton || *options->singleton) {
-        ShellWindow* window = ShellWindowRegistry::Get(profile())->
+        ShellWindow* window = apps::ShellWindowRegistry::Get(profile())->
             GetShellWindowForAppAndKey(extension_id(),
                                        create_params.window_key);
         if (window) {
@@ -207,7 +207,7 @@
         create_params.bounds.set_y(*bounds->top.get());
     }
 
-    if (Feature::GetCurrentChannel() <= chrome::VersionInfo::CHANNEL_DEV ||
+    if (GetCurrentChannel() <= chrome::VersionInfo::CHANNEL_DEV ||
         GetExtension()->location() == extensions::Manifest::COMPONENT) {
       if (options->type == extensions::api::app_window::WINDOW_TYPE_PANEL) {
           create_params.window_type = ShellWindow::WINDOW_TYPE_PANEL;
@@ -318,7 +318,8 @@
   SetCreateResultFromShellWindow(shell_window, result);
   SetResult(result);
 
-  if (ShellWindowRegistry::Get(profile())->HadDevToolsAttached(created_view)) {
+  if (apps::ShellWindowRegistry::Get(profile())->
+          HadDevToolsAttached(created_view)) {
     new DevToolsRestorer(this, created_view);
     return true;
   }
diff --git a/chrome/browser/extensions/api/app_window/app_window_apitest.cc b/chrome/browser/extensions/api/app_window/app_window_apitest.cc
index aee3c9c..a4f3909 100644
--- a/chrome/browser/extensions/api/app_window/app_window_apitest.cc
+++ b/chrome/browser/extensions/api/app_window/app_window_apitest.cc
@@ -4,11 +4,11 @@
 
 #include "apps/native_app_window.h"
 #include "apps/shell_window.h"
+#include "apps/shell_window_registry.h"
 #include "base/run_loop.h"
 #include "base/strings/string_number_conversions.h"
 #include "chrome/browser/extensions/extension_test_message_listener.h"
 #include "chrome/browser/extensions/platform_app_browsertest_util.h"
-#include "chrome/browser/extensions/shell_window_registry.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/test/base/testing_profile.h"
 #include "ui/base/base_window.h"
@@ -23,15 +23,15 @@
 namespace {
 
 class TestShellWindowRegistryObserver
-    : public extensions::ShellWindowRegistry::Observer {
+    : public apps::ShellWindowRegistry::Observer {
  public:
   explicit TestShellWindowRegistryObserver(Profile* profile)
       : profile_(profile),
         icon_updates_(0) {
-    extensions::ShellWindowRegistry::Get(profile_)->AddObserver(this);
+    apps::ShellWindowRegistry::Get(profile_)->AddObserver(this);
   }
   virtual ~TestShellWindowRegistryObserver() {
-    extensions::ShellWindowRegistry::Get(profile_)->RemoveObserver(this);
+    apps::ShellWindowRegistry::Get(profile_)->RemoveObserver(this);
   }
 
   // Overridden from ShellWindowRegistry::Observer:
diff --git a/chrome/browser/extensions/api/content_settings/content_settings_store.cc b/chrome/browser/extensions/api/content_settings/content_settings_store.cc
index ebae984..ff58296 100644
--- a/chrome/browser/extensions/api/content_settings/content_settings_store.cc
+++ b/chrome/browser/extensions/api/content_settings/content_settings_store.cc
@@ -349,7 +349,7 @@
 
 bool ContentSettingsStore::OnCorrectThread() {
   // If there is no UI thread, we're most likely in a unit test.
-  return !BrowserThread::IsWellKnownThread(BrowserThread::UI) ||
+  return !BrowserThread::IsThreadInitialized(BrowserThread::UI) ||
          BrowserThread::CurrentlyOn(BrowserThread::UI);
 }
 
diff --git a/chrome/browser/extensions/api/declarative_content/declarative_content_apitest.cc b/chrome/browser/extensions/api/declarative_content/declarative_content_apitest.cc
index dc3bead..363d987 100644
--- a/chrome/browser/extensions/api/declarative_content/declarative_content_apitest.cc
+++ b/chrome/browser/extensions/api/declarative_content/declarative_content_apitest.cc
@@ -8,7 +8,7 @@
 #include "chrome/browser/extensions/extension_tab_util.h"
 #include "chrome/browser/extensions/extension_test_message_listener.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
-#include "chrome/common/extensions/features/feature.h"
+#include "chrome/common/extensions/features/feature_channel.h"
 #include "content/public/test/browser_test_utils.h"
 
 namespace extensions {
@@ -23,7 +23,7 @@
   }
   virtual ~DeclarativeContentApiTest() {}
 
-  extensions::Feature::ScopedCurrentChannel current_channel_;
+  extensions::ScopedCurrentChannel current_channel_;
 };
 
 IN_PROC_BROWSER_TEST_F(DeclarativeContentApiTest, Overview) {
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 986598c..a7d8732 100644
--- a/chrome/browser/extensions/api/developer_private/developer_private_api.cc
+++ b/chrome/browser/extensions/api/developer_private/developer_private_api.cc
@@ -8,6 +8,7 @@
 #include "apps/app_restore_service.h"
 #include "apps/saved_files_service.h"
 #include "apps/shell_window.h"
+#include "apps/shell_window_registry.h"
 #include "base/base64.h"
 #include "base/command_line.h"
 #include "base/file_util.h"
@@ -27,7 +28,6 @@
 #include "chrome/browser/extensions/extension_service.h"
 #include "chrome/browser/extensions/extension_system.h"
 #include "chrome/browser/extensions/management_policy.h"
-#include "chrome/browser/extensions/shell_window_registry.h"
 #include "chrome/browser/extensions/unpacked_installer.h"
 #include "chrome/browser/extensions/updater/extension_updater.h"
 #include "chrome/browser/platform_util.h"
@@ -67,6 +67,7 @@
 #include "webkit/common/blob/shareable_file_reference.h"
 
 using apps::ShellWindow;
+using apps::ShellWindowRegistry;
 using content::RenderViewHost;
 
 namespace extensions {
diff --git a/chrome/browser/extensions/api/downloads/downloads_api.cc b/chrome/browser/extensions/api/downloads/downloads_api.cc
index 1bfc27b..9f7dc63 100644
--- a/chrome/browser/extensions/api/downloads/downloads_api.cc
+++ b/chrome/browser/extensions/api/downloads/downloads_api.cc
@@ -36,6 +36,7 @@
 #include "chrome/browser/download/download_service.h"
 #include "chrome/browser/download/download_service_factory.h"
 #include "chrome/browser/download/download_shelf.h"
+#include "chrome/browser/download/download_stats.h"
 #include "chrome/browser/download/download_util.h"
 #include "chrome/browser/extensions/event_names.h"
 #include "chrome/browser/extensions/event_router.h"
@@ -44,6 +45,8 @@
 #include "chrome/browser/extensions/extension_prefs.h"
 #include "chrome/browser/extensions/extension_service.h"
 #include "chrome/browser/extensions/extension_system.h"
+#include "chrome/browser/extensions/extension_warning_service.h"
+#include "chrome/browser/extensions/extension_warning_set.h"
 #include "chrome/browser/icon_loader.h"
 #include "chrome/browser/icon_manager.h"
 #include "chrome/browser/platform_util.h"
@@ -592,6 +595,7 @@
             extensions::api::downloads::FILENAME_CONFLICT_ACTION_UNIQUIFY),
         determined_conflict_action_(
             extensions::api::downloads::FILENAME_CONFLICT_ACTION_UNIQUIFY) {
+    DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
     download_item->SetUserData(kKey, this);
   }
 
@@ -613,6 +617,7 @@
   void set_filename_change_callbacks(
       const base::Closure& no_change,
       const ExtensionDownloadsEventRouter::FilenameChangedCallback& change) {
+    DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
     filename_no_change_ = no_change;
     filename_change_ = change;
     determined_filename_ = creator_suggested_filename_;
@@ -622,6 +627,7 @@
   }
 
   void ClearPendingDeterminers() {
+    DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
     determined_filename_.clear();
     determined_conflict_action_ =
       extensions::api::downloads::FILENAME_CONFLICT_ACTION_UNIQUIFY;
@@ -633,6 +639,7 @@
   }
 
   void DeterminerRemoved(const std::string& extension_id) {
+    DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
     for (DeterminerInfoVector::iterator iter = determiners_.begin();
          iter != determiners_.end();) {
       if (iter->extension_id == extension_id) {
@@ -648,6 +655,7 @@
 
   void AddPendingDeterminer(const std::string& extension_id,
                             const base::Time& installed) {
+    DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
     for (size_t index = 0; index < determiners_.size(); ++index) {
       if (determiners_[index].extension_id == extension_id) {
         DCHECK(false) << extension_id;
@@ -658,6 +666,7 @@
   }
 
   bool DeterminerAlreadyReported(const std::string& extension_id) {
+    DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
     for (size_t index = 0; index < determiners_.size(); ++index) {
       if (determiners_[index].extension_id == extension_id) {
         return determiners_[index].reported;
@@ -669,6 +678,7 @@
   void CreatorSuggestedFilename(
       const base::FilePath& filename,
       extensions::api::downloads::FilenameConflictAction conflict_action) {
+    DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
     creator_suggested_filename_ = filename;
     creator_conflict_action_ = conflict_action;
   }
@@ -683,6 +693,7 @@
   }
 
   void ResetCreatorSuggestion() {
+    DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
     creator_suggested_filename_.clear();
     creator_conflict_action_ =
       extensions::api::downloads::FILENAME_CONFLICT_ACTION_UNIQUIFY;
@@ -692,9 +703,11 @@
   // |extension_id| has already reported. The caller is responsible for
   // validating |filename|.
   bool DeterminerCallback(
+      Profile* profile,
       const std::string& extension_id,
       const base::FilePath& filename,
       extensions::api::downloads::FilenameConflictAction conflict_action) {
+    DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
     bool found_info = false;
     for (size_t index = 0; index < determiners_.size(); ++index) {
       if (determiners_[index].extension_id == extension_id) {
@@ -705,12 +718,25 @@
         // Do not use filename if another determiner has already overridden the
         // filename and they take precedence. Extensions that were installed
         // later take precedence over previous extensions.
-        if (!filename.empty() &&
-            (determiner_.extension_id.empty() ||
-             (determiners_[index].install_time > determiner_.install_time))) {
-          determined_filename_ = filename;
-          determined_conflict_action_ = conflict_action;
-          determiner_ = determiners_[index];
+        if (!filename.empty()) {
+          extensions::ExtensionWarningSet warnings;
+          std::string winner_extension_id;
+          ExtensionDownloadsEventRouter::DetermineFilenameInternal(
+              filename,
+              conflict_action,
+              determiners_[index].extension_id,
+              determiners_[index].install_time,
+              determiner_.extension_id,
+              determiner_.install_time,
+              &winner_extension_id,
+              &determined_filename_,
+              &determined_conflict_action_,
+              &warnings);
+          if (!warnings.empty())
+            extensions::ExtensionWarningService::NotifyWarningsOnUI(
+                profile, warnings);
+          if (winner_extension_id == determiners_[index].extension_id)
+            determiner_ = determiners_[index];
         }
         break;
       }
@@ -1003,7 +1029,7 @@
   DownloadManager* manager = BrowserContext::GetDownloadManager(
       current_profile);
   manager->DownloadUrl(download_params.Pass());
-  download_util::RecordDownloadSource(download_util::INITIATED_BY_EXTENSION);
+  RecordDownloadSource(DOWNLOAD_INITIATED_BY_EXTENSION);
   RecordApiFunctions(DOWNLOADS_FUNCTION_DOWNLOAD);
   return true;
 }
@@ -1558,6 +1584,50 @@
   }
 }
 
+void ExtensionDownloadsEventRouter::DetermineFilenameInternal(
+    const base::FilePath& filename,
+    extensions::api::downloads::FilenameConflictAction conflict_action,
+    const std::string& suggesting_extension_id,
+    const base::Time& suggesting_install_time,
+    const std::string& incumbent_extension_id,
+    const base::Time& incumbent_install_time,
+    std::string* winner_extension_id,
+    base::FilePath* determined_filename,
+    extensions::api::downloads::FilenameConflictAction*
+      determined_conflict_action,
+    extensions::ExtensionWarningSet* warnings) {
+  DCHECK(!filename.empty());
+  DCHECK(!suggesting_extension_id.empty());
+
+  if (incumbent_extension_id.empty()) {
+    *winner_extension_id = suggesting_extension_id;
+    *determined_filename = filename;
+    *determined_conflict_action = conflict_action;
+    return;
+  }
+
+  if (suggesting_install_time < incumbent_install_time) {
+    *winner_extension_id = incumbent_extension_id;
+    warnings->insert(
+        extensions::ExtensionWarning::CreateDownloadFilenameConflictWarning(
+            suggesting_extension_id,
+            incumbent_extension_id,
+            filename,
+            *determined_filename));
+    return;
+  }
+
+  *winner_extension_id = suggesting_extension_id;
+  warnings->insert(
+      extensions::ExtensionWarning::CreateDownloadFilenameConflictWarning(
+          incumbent_extension_id,
+          suggesting_extension_id,
+          *determined_filename,
+          filename));
+  *determined_filename = filename;
+  *determined_conflict_action = conflict_action;
+}
+
 bool ExtensionDownloadsEventRouter::DetermineFilename(
     Profile* profile,
     bool include_incognito,
@@ -1591,7 +1661,8 @@
               base::FilePath());
   // If the invalid filename check is moved to before DeterminerCallback(), then
   // it will block forever waiting for this ext_id to report.
-  if (Fault(!data->DeterminerCallback(ext_id, filename, conflict_action),
+  if (Fault(!data->DeterminerCallback(
+                profile, ext_id, filename, conflict_action),
             errors::kUnexpectedDeterminer, error) ||
       Fault((!const_filename.empty() && !valid_filename),
             errors::kInvalidFilename, error))
@@ -1790,6 +1861,7 @@
     int type,
     const content::NotificationSource& source,
     const content::NotificationDetails& details) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
   switch (type) {
     case chrome::NOTIFICATION_EXTENSION_UNLOADED: {
       extensions::UnloadedExtensionInfo* unloaded =
diff --git a/chrome/browser/extensions/api/downloads/downloads_api.h b/chrome/browser/extensions/api/downloads/downloads_api.h
index a6fda46..e7db6d0 100644
--- a/chrome/browser/extensions/api/downloads/downloads_api.h
+++ b/chrome/browser/extensions/api/downloads/downloads_api.h
@@ -17,6 +17,7 @@
 #include "chrome/browser/download/download_path_reservation_tracker.h"
 #include "chrome/browser/extensions/event_router.h"
 #include "chrome/browser/extensions/extension_function.h"
+#include "chrome/browser/extensions/extension_warning_set.h"
 #include "chrome/common/extensions/api/downloads.h"
 #include "content/public/browser/download_item.h"
 #include "content/public/browser/download_manager.h"
@@ -298,6 +299,21 @@
       DownloadPathReservationTracker::FilenameConflictAction)>
     FilenameChangedCallback;
 
+  // The logic for how to handle conflicting filename suggestions from multiple
+  // extensions is split out here for testing.
+  static void DetermineFilenameInternal(
+      const base::FilePath& filename,
+      extensions::api::downloads::FilenameConflictAction conflict_action,
+      const std::string& suggesting_extension_id,
+      const base::Time& suggesting_install_time,
+      const std::string& incumbent_extension_id,
+      const base::Time& incumbent_install_time,
+      std::string* winner_extension_id,
+      base::FilePath* determined_filename,
+      extensions::api::downloads::FilenameConflictAction*
+        determined_conflict_action,
+      extensions::ExtensionWarningSet* warnings);
+
   // A downloads.onDeterminingFilename listener has returned. If the extension
   // wishes to override the download's filename, then |filename| will be
   // non-empty. |filename| will be interpreted as a relative path, appended to
diff --git a/chrome/browser/extensions/api/downloads/downloads_api_browsertest.cc b/chrome/browser/extensions/api/downloads/downloads_api_browsertest.cc
index 82a5f6f..e5962af 100644
--- a/chrome/browser/extensions/api/downloads/downloads_api_browsertest.cc
+++ b/chrome/browser/extensions/api/downloads/downloads_api_browsertest.cc
@@ -427,6 +427,7 @@
           downloads_directory().Append(history_info[i].filename),
           url_chain, GURL(),    // URL Chain, referrer
           current, current,  // start_time, end_time
+          std::string(), std::string(), // etag, last_modified
           1, 1,              // received_bytes, total_bytes
           history_info[i].state,  // state
           content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
@@ -3496,3 +3497,73 @@
 #include "content/public/browser/download_interrupt_reason_values.h"
 #undef INTERRUPT_REASON
 }
+
+TEST(ExtensionDetermineDownloadFilenameInternal,
+     ExtensionDetermineDownloadFilenameInternal) {
+
+  std::string winner_id;
+  base::FilePath filename;
+  extensions::api::downloads::FilenameConflictAction conflict_action =
+    api::FILENAME_CONFLICT_ACTION_UNIQUIFY;
+  extensions::ExtensionWarningSet warnings;
+
+  // Empty incumbent determiner
+  warnings.clear();
+  ExtensionDownloadsEventRouter::DetermineFilenameInternal(
+      base::FilePath(FILE_PATH_LITERAL("a")),
+      api::FILENAME_CONFLICT_ACTION_OVERWRITE,
+      "suggester",
+      base::Time::Now(),
+      "",
+      base::Time(),
+      &winner_id,
+      &filename,
+      &conflict_action,
+      &warnings);
+  EXPECT_EQ("suggester", winner_id);
+  EXPECT_EQ(FILE_PATH_LITERAL("a"), filename.value());
+  EXPECT_EQ(api::FILENAME_CONFLICT_ACTION_OVERWRITE, conflict_action);
+  EXPECT_TRUE(warnings.empty());
+
+  // Incumbent wins
+  warnings.clear();
+  ExtensionDownloadsEventRouter::DetermineFilenameInternal(
+      base::FilePath(FILE_PATH_LITERAL("b")),
+      api::FILENAME_CONFLICT_ACTION_PROMPT,
+      "suggester",
+      base::Time::Now() - base::TimeDelta::FromDays(1),
+      "incumbent",
+      base::Time::Now(),
+      &winner_id,
+      &filename,
+      &conflict_action,
+      &warnings);
+  EXPECT_EQ("incumbent", winner_id);
+  EXPECT_EQ(FILE_PATH_LITERAL("a"), filename.value());
+  EXPECT_EQ(api::FILENAME_CONFLICT_ACTION_OVERWRITE, conflict_action);
+  EXPECT_FALSE(warnings.empty());
+  EXPECT_EQ(extensions::ExtensionWarning::kDownloadFilenameConflict,
+            warnings.begin()->warning_type());
+  EXPECT_EQ("suggester", warnings.begin()->extension_id());
+
+  // Suggester wins
+  warnings.clear();
+  ExtensionDownloadsEventRouter::DetermineFilenameInternal(
+      base::FilePath(FILE_PATH_LITERAL("b")),
+      api::FILENAME_CONFLICT_ACTION_PROMPT,
+      "suggester",
+      base::Time::Now(),
+      "incumbent",
+      base::Time::Now() - base::TimeDelta::FromDays(1),
+      &winner_id,
+      &filename,
+      &conflict_action,
+      &warnings);
+  EXPECT_EQ("suggester", winner_id);
+  EXPECT_EQ(FILE_PATH_LITERAL("b"), filename.value());
+  EXPECT_EQ(api::FILENAME_CONFLICT_ACTION_PROMPT, conflict_action);
+  EXPECT_FALSE(warnings.empty());
+  EXPECT_EQ(extensions::ExtensionWarning::kDownloadFilenameConflict,
+            warnings.begin()->warning_type());
+  EXPECT_EQ("incumbent", warnings.begin()->extension_id());
+}
diff --git a/chrome/browser/extensions/api/extension_action/script_badge_apitest.cc b/chrome/browser/extensions/api/extension_action/script_badge_apitest.cc
index c30884d..fd7264a 100644
--- a/chrome/browser/extensions/api/extension_action/script_badge_apitest.cc
+++ b/chrome/browser/extensions/api/extension_action/script_badge_apitest.cc
@@ -15,7 +15,7 @@
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/common/extensions/extension.h"
-#include "chrome/common/extensions/features/feature.h"
+#include "chrome/common/extensions/features/feature_channel.h"
 #include "chrome/test/base/ui_test_utils.h"
 #include "content/public/browser/web_contents.h"
 #include "net/dns/mock_host_resolver.h"
@@ -36,7 +36,7 @@
   }
 
  private:
-  extensions::Feature::ScopedCurrentChannel trunk_;
+  extensions::ScopedCurrentChannel trunk_;
 };
 
 IN_PROC_BROWSER_TEST_F(ScriptBadgeApiTest, Basics) {
diff --git a/chrome/browser/extensions/api/feedback_private/feedback_service_chromeos.cc b/chrome/browser/extensions/api/feedback_private/feedback_service_chromeos.cc
index ba3e1f2..19d6595 100644
--- a/chrome/browser/extensions/api/feedback_private/feedback_service_chromeos.cc
+++ b/chrome/browser/extensions/api/feedback_private/feedback_service_chromeos.cc
@@ -8,7 +8,7 @@
 #include "base/memory/weak_ptr.h"
 #include "base/values.h"
 #include "chrome/browser/chromeos/login/user_manager.h"
-#include "chrome/browser/chromeos/system_logs/system_logs_fetcher.h"
+#include "chrome/browser/chromeos/system_logs/about_system_logs_fetcher.h"
 
 using extensions::api::feedback_private::SystemInformation;
 
@@ -55,7 +55,8 @@
     const GetSystemInformationCallback& callback) {
   system_information_callback_ = callback;
 
-  chromeos::SystemLogsFetcher* fetcher = new chromeos::SystemLogsFetcher();
+  chromeos::AboutSystemLogsFetcher* fetcher =
+      new chromeos::AboutSystemLogsFetcher();
   fetcher->Fetch(base::Bind(&FeedbackServiceImpl::ProcessSystemLogs,
                             AsWeakPtr()));
 }
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 fe66380..7ebf9e2 100644
--- a/chrome/browser/extensions/api/file_system/file_system_api.cc
+++ b/chrome/browser/extensions/api/file_system/file_system_api.cc
@@ -6,6 +6,7 @@
 
 #include "apps/saved_files_service.h"
 #include "apps/shell_window.h"
+#include "apps/shell_window_registry.h"
 #include "base/bind.h"
 #include "base/file_util.h"
 #include "base/files/file_path.h"
@@ -20,7 +21,6 @@
 #include "chrome/browser/extensions/api/file_handlers/app_file_handler_util.h"
 #include "chrome/browser/extensions/extension_service.h"
 #include "chrome/browser/extensions/extension_system.h"
-#include "chrome/browser/extensions/shell_window_registry.h"
 #include "chrome/browser/platform_util.h"
 #include "chrome/browser/ui/chrome_select_file_policy.h"
 #include "chrome/common/chrome_paths.h"
@@ -741,7 +741,8 @@
   // platform-app only.
   content::WebContents* web_contents = NULL;
   if (extension_->is_platform_app()) {
-    ShellWindowRegistry* registry = ShellWindowRegistry::Get(profile());
+    apps::ShellWindowRegistry* registry =
+        apps::ShellWindowRegistry::Get(profile());
     DCHECK(registry);
     ShellWindow* shell_window = registry->GetShellWindowForRenderViewHost(
         render_view_host());
diff --git a/chrome/browser/extensions/api/identity/web_auth_flow.cc b/chrome/browser/extensions/api/identity/web_auth_flow.cc
index 7f3ba05..977f1f1 100644
--- a/chrome/browser/extensions/api/identity/web_auth_flow.cc
+++ b/chrome/browser/extensions/api/identity/web_auth_flow.cc
@@ -59,7 +59,7 @@
   WebContentsObserver::Observe(NULL);
 
   if (!shell_window_key_.empty()) {
-    ShellWindowRegistry::Get(profile_)->RemoveObserver(this);
+    apps::ShellWindowRegistry::Get(profile_)->RemoveObserver(this);
 
     if (shell_window_ && shell_window_->web_contents())
       shell_window_->web_contents()->Close();
@@ -67,13 +67,12 @@
 }
 
 void WebAuthFlow::Start() {
-  ShellWindowRegistry::Get(profile_)->AddObserver(this);
+  apps::ShellWindowRegistry::Get(profile_)->AddObserver(this);
 
   // Attach a random ID string to the window so we can recoginize it
   // in OnShellWindowAdded.
   std::string random_bytes;
   crypto::RandBytes(WriteInto(&random_bytes, 33), 32);
-  std::string key;
   bool success = base::Base64Encode(random_bytes, &shell_window_key_);
   DCHECK(success);
 
diff --git a/chrome/browser/extensions/api/identity/web_auth_flow.h b/chrome/browser/extensions/api/identity/web_auth_flow.h
index 077b1f0..e1a9852 100644
--- a/chrome/browser/extensions/api/identity/web_auth_flow.h
+++ b/chrome/browser/extensions/api/identity/web_auth_flow.h
@@ -7,7 +7,7 @@
 
 #include <string>
 
-#include "chrome/browser/extensions/shell_window_registry.h"
+#include "apps/shell_window_registry.h"
 #include "content/public/browser/notification_observer.h"
 #include "content/public/browser/notification_registrar.h"
 #include "content/public/browser/web_contents_observer.h"
@@ -45,7 +45,7 @@
 // a window. If a window would be required, the flow fails.
 class WebAuthFlow : public content::NotificationObserver,
                     public content::WebContentsObserver,
-                    public ShellWindowRegistry::Observer {
+                    public apps::ShellWindowRegistry::Observer {
  public:
   enum Mode {
     INTERACTIVE,  // Show UI to the user if necessary.
@@ -91,7 +91,7 @@
  private:
   friend class ::WebAuthFlowTest;
 
-  // ShellWindowRegistry::Observer implementation.
+  // ::ShellWindowRegistry::Observer implementation.
   virtual void OnShellWindowAdded(apps::ShellWindow* shell_window) OVERRIDE;
   virtual void OnShellWindowIconChanged(apps::ShellWindow* shell_window)
       OVERRIDE;
diff --git a/chrome/browser/extensions/api/input/input.cc b/chrome/browser/extensions/api/input/input.cc
index b4d264f..9d0b3cb 100644
--- a/chrome/browser/extensions/api/input/input.cc
+++ b/chrome/browser/extensions/api/input/input.cc
@@ -38,10 +38,27 @@
   return false;
 }
 
+bool MoveCursorFunction::RunImpl() {
+#if defined(USE_ASH)
+  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+
+  int swipe_direction;
+  int modifier_flags;
+  EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &swipe_direction));
+  EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(1, &modifier_flags));
+
+  return keyboard::MoveCursor(swipe_direction, modifier_flags,
+                              ash::Shell::GetPrimaryRootWindow());
+#endif
+  error_ = kNotYetImplementedError;
+  return false;
+}
+
 InputAPI::InputAPI(Profile* profile) {
   ExtensionFunctionRegistry* registry =
       ExtensionFunctionRegistry::GetInstance();
   registry->RegisterFunction<InsertTextInputFunction>();
+  registry->RegisterFunction<MoveCursorFunction>();
 }
 
 InputAPI::~InputAPI() {
diff --git a/chrome/browser/extensions/api/input/input.h b/chrome/browser/extensions/api/input/input.h
index 4cdf3fa..ab5bddb 100644
--- a/chrome/browser/extensions/api/input/input.h
+++ b/chrome/browser/extensions/api/input/input.h
@@ -26,6 +26,19 @@
   virtual bool RunImpl() OVERRIDE;
 };
 
+class  MoveCursorFunction : public SyncExtensionFunction {
+ public:
+  DECLARE_EXTENSION_FUNCTION(
+      "experimental.input.virtualKeyboard.moveCursor",
+      EXPERIMENTAL_INPUT_VIRTUALKEYBOARD_MOVECURSOR);
+
+ protected:
+  virtual ~MoveCursorFunction() {}
+
+  // ExtensionFunction.
+  virtual bool RunImpl() OVERRIDE;
+};
+
 class InputAPI : public ProfileKeyedAPI {
  public:
   explicit InputAPI(Profile* profile);
diff --git a/chrome/browser/extensions/api/log_private/log_private_api.h b/chrome/browser/extensions/api/log_private/log_private_api.h
index f6f8911..d9a110f 100644
--- a/chrome/browser/extensions/api/log_private/log_private_api.h
+++ b/chrome/browser/extensions/api/log_private/log_private_api.h
@@ -7,7 +7,7 @@
 
 #include <string>
 
-#include "chrome/browser/chromeos/system_logs/system_logs_fetcher.h"
+#include "chrome/browser/chromeos/system_logs/about_system_logs_fetcher.h"
 #include "chrome/browser/extensions/api/log_private/filter_handler.h"
 #include "chrome/browser/extensions/api/log_private/log_parser.h"
 #include "chrome/browser/extensions/extension_function.h"
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 055c4ac..2e6e343 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
@@ -11,7 +11,6 @@
 #include "base/logging.h"
 #include "base/memory/linked_ptr.h"
 #include "base/memory/scoped_ptr.h"
-#include "chrome/browser/chromeos/system_logs/system_logs_fetcher.h"
 #include "chrome/browser/extensions/api/log_private/filter_handler.h"
 #include "chrome/browser/extensions/api/log_private/log_parser.h"
 #include "chrome/browser/extensions/api/log_private/syslog_parser.h"
@@ -62,7 +61,8 @@
   EXTENSION_FUNCTION_VALIDATE(params.get());
   filter_handler_.reset(new FilterHandler(params->filter));
 
-  chromeos::SystemLogsFetcher* fetcher = new chromeos::SystemLogsFetcher();
+  chromeos::AboutSystemLogsFetcher* fetcher =
+      new chromeos::AboutSystemLogsFetcher();
   fetcher->Fetch(
       base::Bind(&LogPrivateGetHistoricalFunction::OnSystemLogsLoaded, this));
   return true;
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 25a47d2..cc5fe09 100644
--- a/chrome/browser/extensions/api/media_galleries/media_galleries_api.cc
+++ b/chrome/browser/extensions/api/media_galleries/media_galleries_api.cc
@@ -11,13 +11,13 @@
 #include <vector>
 
 #include "apps/shell_window.h"
+#include "apps/shell_window_registry.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/platform_file.h"
 #include "base/stl_util.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/values.h"
 #include "chrome/browser/browser_process.h"
-#include "chrome/browser/extensions/shell_window_registry.h"
 #include "chrome/browser/media_galleries/media_file_system_registry.h"
 #include "chrome/browser/media_galleries/media_galleries_dialog_controller.h"
 #include "chrome/browser/storage_monitor/storage_monitor.h"
@@ -214,7 +214,7 @@
     // If there is no WebContentsModalDialogManager, then this contents is
     // probably the background page for an app. Try to find a shell window to
     // host the dialog.
-    ShellWindow* window = ShellWindowRegistry::Get(profile())->
+    ShellWindow* window = apps::ShellWindowRegistry::Get(profile())->
         GetCurrentShellWindowForApp(GetExtension()->id());
     if (window) {
       contents = window->web_contents();
diff --git a/chrome/browser/extensions/api/messaging/message_service.cc b/chrome/browser/extensions/api/messaging/message_service.cc
index 65f74ed..00e40f7 100644
--- a/chrome/browser/extensions/api/messaging/message_service.cc
+++ b/chrome/browser/extensions/api/messaging/message_service.cc
@@ -34,6 +34,8 @@
 #include "content/public/browser/notification_service.h"
 #include "content/public/browser/render_process_host.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/site_instance.h"
 #include "content/public/browser/web_contents.h"
 #include "url/gurl.h"
@@ -321,8 +323,14 @@
   channel->opener.reset(new ExtensionMessagePort(source, MSG_ROUTING_CONTROL,
                                                  source_extension_id));
 
+  // Get handle of the native view and pass it to the native messaging host.
+  gfx::NativeView native_view =
+      content::RenderWidgetHost::FromID(source_process_id, source_routing_id)->
+          GetView()->GetNativeView();
+
   scoped_ptr<NativeMessageProcessHost> native_process =
       NativeMessageProcessHost::Create(
+          native_view,
           base::WeakPtr<NativeMessageProcessHost::Client>(
               weak_factory_.GetWeakPtr()),
           source_extension_id, native_app_name, receiver_port_id);
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 749cb43..40535eb 100644
--- a/chrome/browser/extensions/api/messaging/native_message_process_host.cc
+++ b/chrome/browser/extensions/api/messaging/native_message_process_host.cc
@@ -8,6 +8,7 @@
 #include "base/files/file_path.h"
 #include "base/logging.h"
 #include "base/platform_file.h"
+#include "base/threading/sequenced_worker_pool.h"
 #include "base/values.h"
 #include "chrome/browser/extensions/api/messaging/native_messaging_host_manifest.h"
 #include "chrome/browser/extensions/api/messaging/native_process_launcher.h"
@@ -77,13 +78,14 @@
 
 // static
 scoped_ptr<NativeMessageProcessHost> NativeMessageProcessHost::Create(
+    gfx::NativeView native_view,
     base::WeakPtr<Client> weak_client_ui,
     const std::string& source_extension_id,
     const std::string& native_host_name,
     int destination_port) {
   return CreateWithLauncher(weak_client_ui, source_extension_id,
                             native_host_name, destination_port,
-                            NativeProcessLauncher::CreateDefault());
+                            NativeProcessLauncher::CreateDefault(native_view));
 }
 
 // static
@@ -136,10 +138,18 @@
   }
 
   read_file_ = read_file;
+
+  scoped_refptr<base::TaskRunner> task_runner(
+      content::BrowserThread::GetBlockingPool()->
+          GetTaskRunnerWithShutdownBehavior(
+              base::SequencedWorkerPool::SKIP_ON_SHUTDOWN));
+
   read_stream_.reset(new net::FileStream(
-      read_file, base::PLATFORM_FILE_READ | base::PLATFORM_FILE_ASYNC, NULL));
+      read_file, base::PLATFORM_FILE_READ | base::PLATFORM_FILE_ASYNC, NULL,
+      task_runner));
   write_stream_.reset(new net::FileStream(
-      write_file, base::PLATFORM_FILE_WRITE | base::PLATFORM_FILE_ASYNC, NULL));
+      write_file, base::PLATFORM_FILE_WRITE | base::PLATFORM_FILE_ASYNC, NULL,
+      task_runner));
 
   WaitRead();
   DoWrite();
diff --git a/chrome/browser/extensions/api/messaging/native_message_process_host.h b/chrome/browser/extensions/api/messaging/native_message_process_host.h
index 8458b28..a6638a4 100644
--- a/chrome/browser/extensions/api/messaging/native_message_process_host.h
+++ b/chrome/browser/extensions/api/messaging/native_message_process_host.h
@@ -14,6 +14,7 @@
 #include "base/process/process.h"
 #include "chrome/browser/extensions/api/messaging/native_process_launcher.h"
 #include "content/public/browser/browser_thread.h"
+#include "ui/gfx/native_widget_types.h"
 
 namespace net {
 
@@ -52,6 +53,7 @@
   virtual ~NativeMessageProcessHost();
 
   static scoped_ptr<NativeMessageProcessHost> Create(
+      gfx::NativeView native_view,
       base::WeakPtr<Client> weak_client_ui,
       const std::string& source_extension_id,
       const std::string& native_host_name,
diff --git a/chrome/browser/extensions/api/messaging/native_message_process_host_unittest.cc b/chrome/browser/extensions/api/messaging/native_message_process_host_unittest.cc
index 8653d10..f92d930 100644
--- a/chrome/browser/extensions/api/messaging/native_message_process_host_unittest.cc
+++ b/chrome/browser/extensions/api/messaging/native_message_process_host_unittest.cc
@@ -26,7 +26,7 @@
 #include "chrome/common/chrome_switches.h"
 #include "chrome/common/chrome_version_info.h"
 #include "chrome/common/extensions/extension.h"
-#include "chrome/common/extensions/features/feature.h"
+#include "chrome/common/extensions/features/feature_channel.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/test/test_browser_thread_bundle.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -144,7 +144,7 @@
 
   // Force the channel to be dev.
   base::ScopedTempDir temp_dir_;
-  Feature::ScopedCurrentChannel current_channel_;
+  ScopedCurrentChannel current_channel_;
   scoped_ptr<NativeMessageProcessHost> native_message_process_host_;
   base::FilePath user_data_dir_;
   scoped_ptr<base::RunLoop> read_message_run_loop_;
@@ -218,7 +218,7 @@
       switches::kNativeMessagingHosts, hosts_option);
 
   native_message_process_host_ = NativeMessageProcessHost::Create(
-      AsWeakPtr(), kTestNativeMessagingExtensionId,
+      gfx::NativeView(), AsWeakPtr(), kTestNativeMessagingExtensionId,
       kTestNativeMessagingHostName, 0);
   ASSERT_TRUE(native_message_process_host_.get());
 
diff --git a/chrome/browser/extensions/api/messaging/native_process_launcher.cc b/chrome/browser/extensions/api/messaging/native_process_launcher.cc
index 2186e1e..0f8992e 100644
--- a/chrome/browser/extensions/api/messaging/native_process_launcher.cc
+++ b/chrome/browser/extensions/api/messaging/native_process_launcher.cc
@@ -11,6 +11,7 @@
 #include "base/logging.h"
 #include "base/memory/ref_counted.h"
 #include "base/path_service.h"
+#include "base/strings/string_number_conversions.h"
 #include "base/strings/string_split.h"
 #include "base/threading/sequenced_worker_pool.h"
 #include "chrome/browser/extensions/api/messaging/native_messaging_host_manifest.h"
@@ -23,7 +24,9 @@
 
 namespace {
 
-const char kNativeHostsDirectoryName[] = "native_hosts";
+// Name of the command line switch used to pass handle of the native view to
+// the native messaging host.
+const char kParentWindowSwitchName[] = "parent-window";
 
 base::FilePath GetHostManifestPathFromCommandLine(
     const std::string& native_host_name) {
@@ -51,7 +54,7 @@
 // Default implementation on NativeProcessLauncher interface.
 class NativeProcessLauncherImpl : public NativeProcessLauncher {
  public:
-  NativeProcessLauncherImpl();
+  explicit NativeProcessLauncherImpl(gfx::NativeView native_view);
   virtual ~NativeProcessLauncherImpl();
 
   virtual void Launch(const GURL& origin,
@@ -61,7 +64,7 @@
  private:
   class Core : public base::RefCountedThreadSafe<Core> {
    public:
-    Core();
+    explicit Core(gfx::NativeView native_view);
     void Launch(const GURL& origin,
                 const std::string& native_host_name,
                 LaunchedCallback callback);
@@ -85,6 +88,9 @@
 
     bool detached_;
 
+    // Handle of the native view corrsponding to the extension.
+    gfx::NativeView native_view_;
+
     DISALLOW_COPY_AND_ASSIGN(Core);
   };
 
@@ -93,8 +99,9 @@
   DISALLOW_COPY_AND_ASSIGN(NativeProcessLauncherImpl);
 };
 
-NativeProcessLauncherImpl::Core::Core()
-    : detached_(false) {
+NativeProcessLauncherImpl::Core::Core(gfx::NativeView native_view)
+    : detached_(false),
+      native_view_(native_view) {
 }
 
 NativeProcessLauncherImpl::Core::~Core() {
@@ -182,6 +189,14 @@
   CommandLine command_line(host_path);
   command_line.AppendArg(origin.spec());
 
+  // Pass handle of the native view window to the native messaging host. This
+  // way the host will be able to create properly focused UI windows.
+#if defined(OS_WIN)
+  int64 window_handle = reinterpret_cast<intptr_t>(native_view_);
+  command_line.AppendSwitchASCII(kParentWindowSwitchName,
+                                 base::Int64ToString(window_handle));
+#endif  // !defined(OS_WIN)
+
   base::PlatformFile read_file;
   base::PlatformFile write_file;
   if (NativeProcessLauncher::LaunchNativeProcess(
@@ -230,8 +245,9 @@
                  this, callback, RESULT_SUCCESS, read_file, write_file));
 }
 
-NativeProcessLauncherImpl::NativeProcessLauncherImpl()
-  : core_(new Core()) {
+NativeProcessLauncherImpl::NativeProcessLauncherImpl(
+    gfx::NativeView native_view)
+  : core_(new Core(native_view)) {
 }
 
 NativeProcessLauncherImpl::~NativeProcessLauncherImpl() {
@@ -247,8 +263,10 @@
 }  // namespace
 
 // static
-scoped_ptr<NativeProcessLauncher> NativeProcessLauncher::CreateDefault() {
-  return scoped_ptr<NativeProcessLauncher>(new NativeProcessLauncherImpl());
+scoped_ptr<NativeProcessLauncher> NativeProcessLauncher::CreateDefault(
+    gfx::NativeView native_view) {
+  return scoped_ptr<NativeProcessLauncher>(
+      new NativeProcessLauncherImpl(native_view));
 }
 
 }  // namespace extensions
diff --git a/chrome/browser/extensions/api/messaging/native_process_launcher.h b/chrome/browser/extensions/api/messaging/native_process_launcher.h
index 5ab1fce..d2107eb 100644
--- a/chrome/browser/extensions/api/messaging/native_process_launcher.h
+++ b/chrome/browser/extensions/api/messaging/native_process_launcher.h
@@ -9,6 +9,7 @@
 #include "base/memory/scoped_ptr.h"
 #include "base/platform_file.h"
 #include "base/process/process.h"
+#include "ui/gfx/native_widget_types.h"
 
 class CommandLine;
 class GURL;
@@ -36,7 +37,8 @@
                                base::PlatformFile read_file,
                                base::PlatformFile write_file)> LaunchedCallback;
 
-  static scoped_ptr<NativeProcessLauncher> CreateDefault();
+  static scoped_ptr<NativeProcessLauncher> CreateDefault(
+      gfx::NativeView native_view);
 
   NativeProcessLauncher() {}
   virtual ~NativeProcessLauncher() {}
diff --git a/chrome/browser/extensions/api/metrics_private/metrics_apitest.cc b/chrome/browser/extensions/api/metrics_private/metrics_apitest.cc
index 1794fc2..d31559a 100644
--- a/chrome/browser/extensions/api/metrics_private/metrics_apitest.cc
+++ b/chrome/browser/extensions/api/metrics_private/metrics_apitest.cc
@@ -8,6 +8,7 @@
 #include "base/metrics/histogram.h"
 #include "base/metrics/statistics_recorder.h"
 #include "chrome/browser/extensions/extension_apitest.h"
+#include "chrome/common/metrics/variations/variations_associated_data.h"
 #include "content/public/browser/user_metrics.h"
 
 namespace {
@@ -129,6 +130,12 @@
 
   base::FieldTrialList::CreateFieldTrial("apitestfieldtrial2", "group1");
 
+  std::map<std::string, std::string> params;
+  params["a"] = "aa";
+  params["b"] = "bb";
+  ASSERT_TRUE(chrome_variations::AssociateVariationParams(
+      "apitestfieldtrial2", "group1", params));
+
   ASSERT_TRUE(RunComponentExtensionTest("metrics")) << message_;
 
   observer.ValidateUserActions(g_user_actions, arraysize(g_user_actions));
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 f65d80e..8aa2b1b 100644
--- a/chrome/browser/extensions/api/metrics_private/metrics_private_api.cc
+++ b/chrome/browser/extensions/api/metrics_private/metrics_private_api.cc
@@ -12,6 +12,7 @@
 #include "chrome/browser/browser_process.h"
 #include "chrome/common/extensions/api/metrics_private.h"
 #include "chrome/common/extensions/extension.h"
+#include "chrome/common/metrics/variations/variations_associated_data.h"
 #include "chrome/common/pref_names.h"
 #include "content/public/browser/user_metrics.h"
 
@@ -23,6 +24,7 @@
 
 namespace GetIsCrashReportingEnabled =
     api::metrics_private::GetIsCrashReportingEnabled;
+namespace GetVariationParams = api::metrics_private::GetVariationParams;
 namespace GetFieldTrial = api::metrics_private::GetFieldTrial;
 namespace RecordUserAction = api::metrics_private::RecordUserAction;
 namespace RecordValue = api::metrics_private::RecordValue;
@@ -76,6 +78,22 @@
   return true;
 }
 
+bool MetricsPrivateGetVariationParamsFunction::RunImpl() {
+  scoped_ptr<GetVariationParams::Params> params(
+      GetVariationParams::Params::Create(*args_));
+  EXTENSION_FUNCTION_VALIDATE(params.get());
+
+  GetVariationParams::Results::Params result;
+  if (!chrome_variations::GetVariationParams(
+      params->name, &result.additional_properties)) {
+    SetError("Variation parameters are unavailable.");
+    return false;
+  }
+
+  SetResult(result.ToValue().release());
+  return true;
+}
+
 bool MetricsPrivateRecordUserActionFunction::RunImpl() {
   scoped_ptr<RecordUserAction::Params> params(
       RecordUserAction::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 7679aa2..86ff32c 100644
--- a/chrome/browser/extensions/api/metrics_private/metrics_private_api.h
+++ b/chrome/browser/extensions/api/metrics_private/metrics_private_api.h
@@ -37,6 +37,18 @@
   virtual bool RunImpl() OVERRIDE;
 };
 
+class MetricsPrivateGetVariationParamsFunction : public SyncExtensionFunction {
+ public:
+  DECLARE_EXTENSION_FUNCTION("metricsPrivate.getVariationParams",
+                             METRICSPRIVATE_GETVARIATIONPARAMS)
+
+ protected:
+  virtual ~MetricsPrivateGetVariationParamsFunction() {}
+
+  // ExtensionFunction:
+  virtual bool RunImpl() OVERRIDE;
+};
+
 class MetricsPrivateRecordUserActionFunction : public SyncExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("metricsPrivate.recordUserAction",
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 22b7fde..546c878 100644
--- a/chrome/browser/extensions/api/system_info/system_info_api.cc
+++ b/chrome/browser/extensions/api/system_info/system_info_api.cc
@@ -29,7 +29,6 @@
 
 namespace extensions {
 
-using api::system_storage::StorageFreeSpaceChangeInfo;
 using api::system_storage::StorageUnitInfo;
 using content::BrowserThread;
 
@@ -39,14 +38,9 @@
   return event_name == event_names::kOnDisplayChanged;
 }
 
-bool IsAvailableCapacityChangedEvent(const std::string& event_name) {
-  return event_name == event_names::kOnStorageAvailableCapacityChanged;
-}
-
 // Event router for systemInfo API. It is a singleton instance shared by
 // multiple profiles.
 class SystemInfoEventRouter : public gfx::DisplayObserver,
-                              public StorageFreeSpaceObserver,
                               public chrome::RemovableStorageObserver {
  public:
   static SystemInfoEventRouter* GetInstance();
@@ -59,11 +53,6 @@
   void RemoveEventListener(const std::string& event_name);
 
  private:
-  // StorageFreeSpaceObserver:
-  virtual void OnFreeSpaceChanged(const std::string& id,
-                                  double new_value,
-                                  double old_value) OVERRIDE;
-
   // gfx::DisplayObserver:
   virtual void OnDisplayBoundsChanged(const gfx::Display& display) OVERRIDE;
   virtual void OnDisplayAdded(const gfx::Display& new_display) OVERRIDE;
@@ -80,11 +69,6 @@
   void DispatchEvent(const std::string& event_name,
       scoped_ptr<base::ListValue> args);
 
-  // The callbacks of querying storage info to start and stop watching the
-  // storages. Called from UI thread.
-  void StartWatchingStorages(bool success);
-  void StopWatchingStorages(bool success);
-
   // Called to dispatch the systemInfo.display.onDisplayChanged event.
   void OnDisplayChanged();
 
@@ -103,33 +87,15 @@
 }
 
 SystemInfoEventRouter::SystemInfoEventRouter() {
-  StorageInfoProvider::Get()->AddObserver(this);
   chrome::StorageMonitor::GetInstance()->AddObserver(this);
 }
 
 SystemInfoEventRouter::~SystemInfoEventRouter() {
-  StorageInfoProvider::Get()->RemoveObserver(this);
   if (chrome::StorageMonitor* storage_monitor =
           chrome::StorageMonitor::GetInstance())
     storage_monitor->RemoveObserver(this);
 }
 
-void SystemInfoEventRouter::StartWatchingStorages(bool success) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-  if (!success)
-    return;
-
-  StorageInfoProvider::Get()->StartWatchingAllStorages();
-}
-
-void SystemInfoEventRouter::StopWatchingStorages(bool success) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-  if (!success)
-    return;
-
-  StorageInfoProvider::Get()->StopWatchingAllStorages();
-}
-
 void SystemInfoEventRouter::AddEventListener(const std::string& event_name) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
 
@@ -137,15 +103,6 @@
   if (watching_event_set_.count(event_name) > 1)
     return;
 
-  // Start watching the |event_name| event if the first event listener arrives.
-  // For systemInfo.storage event.
-  if (IsAvailableCapacityChangedEvent(event_name)) {
-    StorageInfoProvider::Get()->StartQueryInfo(
-        base::Bind(&SystemInfoEventRouter::StartWatchingStorages,
-                   base::Unretained(this)));
-    return;
-  }
-
   // For systemInfo.display event.
   if (IsDisplayChangedEvent(event_name)) {
 #if defined(USE_ASH)
@@ -166,14 +123,6 @@
   if (watching_event_set_.count(event_name) > 0)
     return;
 
-  // In case of the last event listener is removed, we need to stop watching
-  // it to avoid unnecessary overhead.
-  if (IsAvailableCapacityChangedEvent(event_name)) {
-    StorageInfoProvider::Get()->StartQueryInfo(
-        base::Bind(&SystemInfoEventRouter::StopWatchingStorages,
-                   base::Unretained(this)));
-  }
-
   if (IsDisplayChangedEvent(event_name)) {
 #if defined(USE_ASH)
     ash::Shell::GetScreen()->RemoveObserver(this);
@@ -181,19 +130,6 @@
   }
 }
 
-// Called on UI thread since the observer is added from UI thread.
-void SystemInfoEventRouter::OnFreeSpaceChanged(
-    const std::string& transient_id, double new_value, double old_value) {
-  StorageFreeSpaceChangeInfo info;
-  info.id = transient_id;
-  info.available_capacity = static_cast<double>(new_value);
-
-  scoped_ptr<base::ListValue> args(new base::ListValue());
-  args->Append(info.ToValue().release());
-
-  DispatchEvent(event_names::kOnStorageAvailableCapacityChanged, args.Pass());
-}
-
 void SystemInfoEventRouter::OnRemovableStorageAttached(
     const chrome::StorageInfo& info) {
   StorageUnitInfo unit;
@@ -248,8 +184,6 @@
 
 SystemInfoAPI::SystemInfoAPI(Profile* profile) : profile_(profile) {
   ExtensionSystem::Get(profile_)->event_router()->RegisterObserver(
-      this, event_names::kOnStorageAvailableCapacityChanged);
-  ExtensionSystem::Get(profile_)->event_router()->RegisterObserver(
       this, event_names::kOnStorageAttached);
   ExtensionSystem::Get(profile_)->event_router()->RegisterObserver(
       this, event_names::kOnStorageDetached);
diff --git a/chrome/browser/extensions/api/system_storage/storage_api_test_util.cc b/chrome/browser/extensions/api/system_storage/storage_api_test_util.cc
new file mode 100644
index 0000000..b5b6c98
--- /dev/null
+++ b/chrome/browser/extensions/api/system_storage/storage_api_test_util.cc
@@ -0,0 +1,29 @@
+// 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/extensions/api/system_storage/storage_api_test_util.h"
+
+#include "base/strings/utf_string_conversions.h"
+
+namespace extensions {
+namespace test {
+
+const struct TestStorageUnitInfo kRemovableStorageData = {
+    "dcim:device:001", "/media/usb1", 4098, 1000
+};
+
+chrome::StorageInfo BuildStorageInfoFromTestStorageUnitInfo(
+    const TestStorageUnitInfo& unit) {
+  return chrome::StorageInfo(
+      unit.device_id,
+      UTF8ToUTF16(unit.name),
+      base::FilePath::StringType(), /* no location */
+      string16(), /* no storage label */
+      string16(), /* no storage vendor */
+      string16(), /* no storage model */
+      unit.capacity);
+}
+
+}  // namespace test
+}  // namespace extensions
diff --git a/chrome/browser/extensions/api/system_storage/storage_api_test_util.h b/chrome/browser/extensions/api/system_storage/storage_api_test_util.h
new file mode 100644
index 0000000..d47aee8
--- /dev/null
+++ b/chrome/browser/extensions/api/system_storage/storage_api_test_util.h
@@ -0,0 +1,33 @@
+// 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_EXTENSIONS_API_SYSTEM_STORAGE_STORAGE_API_TEST_UTIL_H_
+#define CHROME_BROWSER_EXTENSIONS_API_SYSTEM_STORAGE_STORAGE_API_TEST_UTIL_H_
+
+#include <vector>
+
+#include "chrome/browser/extensions/api/system_storage/storage_info_provider.h"
+#include "chrome/browser/storage_monitor/storage_info.h"
+
+namespace extensions {
+namespace test {
+
+struct TestStorageUnitInfo {
+  const char* device_id;
+  const char* name;
+  // Total amount of the storage device space, in bytes.
+  double capacity;
+  // The available amount of the storage space, in bytes.
+  double available_capacity;
+};
+
+extern const struct TestStorageUnitInfo kRemovableStorageData;
+
+chrome::StorageInfo BuildStorageInfoFromTestStorageUnitInfo(
+    const TestStorageUnitInfo& unit);
+
+}  // namespace test
+}  // namespace extensions
+
+#endif  // CHROME_BROWSER_EXTENSIONS_API_SYSTEM_STORAGE_STORAGE_API_TEST_UTIL_H_
diff --git a/chrome/browser/extensions/api/system_storage/storage_free_space_observer.h b/chrome/browser/extensions/api/system_storage/storage_free_space_observer.h
deleted file mode 100644
index f861c97..0000000
--- a/chrome/browser/extensions/api/system_storage/storage_free_space_observer.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_EXTENSIONS_API_SYSTEM_STORAGE_STORAGE_FREE_SPACE_OBSERVER_H_
-#define CHROME_BROWSER_EXTENSIONS_API_SYSTEM_STORAGE_STORAGE_FREE_SPACE_OBSERVER_H_
-
-#include <string>
-
-namespace extensions {
-
-// Observes the storage free space changes.
-//
-// StorageInfoProvider class maintains a StorageFreeSpaceObserver list for
-// storage devices' free space change event.
-class StorageFreeSpaceObserver {
- public:
-  // Called when the storage free space changes.
-  virtual void OnFreeSpaceChanged(const std::string& transient_id,
-                                  double old_value, /* in bytes */
-                                  double new_value  /* in bytes */) = 0;
- protected:
-  virtual ~StorageFreeSpaceObserver() {}
-};
-
-}  // namespace extensions
-
-#endif  // CHROME_BROWSER_EXTENSIONS_API_SYSTEM_STORAGE_STORAGE_FREE_SPACE_OBSERVER_H_
-
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 2f1b874..fd4208b 100644
--- a/chrome/browser/extensions/api/system_storage/storage_info_provider.cc
+++ b/chrome/browser/extensions/api/system_storage/storage_info_provider.cc
@@ -34,21 +34,11 @@
 
 }  // namespace systeminfo
 
-const int kDefaultPollingIntervalMs = 1000;
-const char kWatchingTokenName[] = "_storage_info_watching_token_";
-
 // Static member intialization.
 base::LazyInstance<scoped_refptr<StorageInfoProvider> >
     StorageInfoProvider::provider_ = LAZY_INSTANCE_INITIALIZER;
 
-StorageInfoProvider::StorageInfoProvider()
-    : observers_(new ObserverListThreadSafe<StorageFreeSpaceObserver>()),
-      watching_interval_(kDefaultPollingIntervalMs) {
-}
-
-StorageInfoProvider::StorageInfoProvider(size_t watching_interval)
-    : observers_(new ObserverListThreadSafe<StorageFreeSpaceObserver>()),
-      watching_interval_(watching_interval) {
+StorageInfoProvider::StorageInfoProvider() {
 }
 
 StorageInfoProvider::~StorageInfoProvider() {
@@ -98,170 +88,6 @@
   }
 }
 
-void StorageInfoProvider::AddObserver(StorageFreeSpaceObserver* obs) {
-  observers_->AddObserver(obs);
-}
-
-void StorageInfoProvider::RemoveObserver(StorageFreeSpaceObserver* obs) {
-  observers_->RemoveObserver(obs);
-}
-
-void StorageInfoProvider::StartWatching(const std::string& transient_id) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-
-  BrowserThread::PostBlockingPoolSequencedTask(
-      kWatchingTokenName,
-      FROM_HERE,
-      base::Bind(&StorageInfoProvider::AddWatchedStorageOnBlockingPool,
-                 this, transient_id));
-}
-
-void StorageInfoProvider::StopWatching(const std::string& transient_id) {
-  base::FilePath mount_path;
-  BrowserThread::PostBlockingPoolSequencedTask(
-      kWatchingTokenName,
-      FROM_HERE,
-      base::Bind(&StorageInfoProvider::RemoveWatchedStorageOnBlockingPool,
-                 this, transient_id));
-}
-
-void StorageInfoProvider::StartWatchingAllStorages() {
-  for (StorageUnitInfoList::const_iterator it = info_.begin();
-       it != info_.end(); ++it) {
-    StartWatching((*it)->id);
-  }
-}
-
-void StorageInfoProvider::StopWatchingAllStorages() {
-  for (StorageUnitInfoList::const_iterator it = info_.begin();
-       it != info_.end(); ++it) {
-    StopWatching((*it)->id);
-  }
-}
-
-int64 StorageInfoProvider::GetStorageFreeSpaceFromTransientId(
-    const std::string& transient_id) {
-  std::vector<chrome::StorageInfo> storage_list =
-      StorageMonitor::GetInstance()->GetAllAvailableStorages();
-
-  std::string device_id =
-      StorageMonitor::GetInstance()->GetDeviceIdForTransientId(
-          transient_id);
-
-  // Lookup the matched storage info by |device_id|.
-  for (std::vector<chrome::StorageInfo>::const_iterator it =
-       storage_list.begin();
-       it != storage_list.end(); ++it) {
-    if (device_id == it->device_id())
-      return base::SysInfo::AmountOfFreeDiskSpace(
-          base::FilePath(it->location()));
-  }
-
-  return -1;
-}
-
-void StorageInfoProvider::AddWatchedStorageOnBlockingPool(
-    const std::string& transient_id) {
-  DCHECK(BrowserThread::GetBlockingPool()->RunsTasksOnCurrentThread());
-  // If the storage |transient_id| is already being watched.
-  if (ContainsKey(storage_transient_id_to_size_map_, transient_id))
-    return;
-
-  int64 available_bytes = GetStorageFreeSpaceFromTransientId(transient_id);
-  if (available_bytes < 0)
-    return;
-
-  storage_transient_id_to_size_map_[transient_id] = available_bytes;
-
-  // If it is the first storage to be watched, we need to start the watching
-  // timer.
-  if (storage_transient_id_to_size_map_.size() == 1) {
-    BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
-        base::Bind(&StorageInfoProvider::StartWatchingTimerOnUIThread, this));
-  }
-}
-
-void StorageInfoProvider::RemoveWatchedStorageOnBlockingPool(
-    const std::string& transient_id) {
-  DCHECK(BrowserThread::GetBlockingPool()->RunsTasksOnCurrentThread());
-  if (storage_transient_id_to_size_map_.erase(transient_id) == 0)
-    return;
-
-  // Stop watching timer if there is no storage to be watched.
-  if (storage_transient_id_to_size_map_.empty()) {
-    BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
-        base::Bind(&StorageInfoProvider::StopWatchingTimerOnUIThread, this));
-  }
-}
-
-void StorageInfoProvider::CheckWatchedStorages() {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-  std::vector<chrome::StorageInfo> storage_list =
-      StorageMonitor::GetInstance()->GetAllAvailableStorages();
-
-  for (std::vector<chrome::StorageInfo>::iterator it = storage_list.begin();
-       it != storage_list.end(); ++it) {
-    BrowserThread::PostBlockingPoolSequencedTask(
-        kWatchingTokenName,
-        FROM_HERE,
-        base::Bind(&StorageInfoProvider::CheckWatchedStorageOnBlockingPool,
-                   this,
-                   StorageMonitor::GetInstance()->GetTransientIdForDeviceId(
-                       it->device_id())));
-  }
-}
-
-void StorageInfoProvider::CheckWatchedStorageOnBlockingPool(
-    const std::string& transient_id) {
-  DCHECK(BrowserThread::GetBlockingPool()->RunsTasksOnCurrentThread());
-  if (!ContainsKey(storage_transient_id_to_size_map_, transient_id))
-    return;
-
-  double new_available_bytes = GetStorageFreeSpaceFromTransientId(transient_id);
-  double old_available_bytes = storage_transient_id_to_size_map_[transient_id];
-
-  // No free space change.
-  if (new_available_bytes == old_available_bytes)
-    return;
-
-  if (new_available_bytes < 0) {
-    // In case we can't establish the new free space value from |transient_id|,
-    // the |transient_id| is currently not available, so we need to remove it
-    // from |storage_transient_id_to_size_map_|.
-    storage_transient_id_to_size_map_.erase(transient_id);
-    if (storage_transient_id_to_size_map_.size() == 0) {
-      BrowserThread::PostTask(
-          BrowserThread::UI, FROM_HERE,
-          base::Bind(&StorageInfoProvider::StopWatchingTimerOnUIThread, this));
-    }
-    return;
-  }
-
-  // Ignore free space change event if the old available capacity is 0.
-  if (old_available_bytes > 0) {
-    observers_->Notify(&StorageFreeSpaceObserver::OnFreeSpaceChanged,
-                       transient_id,
-                       old_available_bytes,
-                       new_available_bytes);
-  }
-  storage_transient_id_to_size_map_[transient_id] = new_available_bytes;
-}
-
-void StorageInfoProvider::StartWatchingTimerOnUIThread() {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-  // Start the watching timer if it is not running.
-  if (!watching_timer_.IsRunning()) {
-    watching_timer_.Start(FROM_HERE,
-        base::TimeDelta::FromMilliseconds(watching_interval_),
-        this, &StorageInfoProvider::CheckWatchedStorages);
-  }
-}
-
-void StorageInfoProvider::StopWatchingTimerOnUIThread() {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-  watching_timer_.Stop();
-}
-
 // static
 StorageInfoProvider* StorageInfoProvider::Get() {
   if (provider_.Get().get() == NULL)
diff --git a/chrome/browser/extensions/api/system_storage/storage_info_provider.h b/chrome/browser/extensions/api/system_storage/storage_info_provider.h
index 2dc96f5..859ea87 100644
--- a/chrome/browser/extensions/api/system_storage/storage_info_provider.h
+++ b/chrome/browser/extensions/api/system_storage/storage_info_provider.h
@@ -12,7 +12,6 @@
 #include "base/observer_list_threadsafe.h"
 #include "base/timer/timer.h"
 #include "chrome/browser/extensions/api/system_info/system_info_provider.h"
-#include "chrome/browser/extensions/api/system_storage/storage_free_space_observer.h"
 #include "chrome/browser/storage_monitor/removable_storage_observer.h"
 #include "chrome/browser/storage_monitor/storage_info.h"
 #include "chrome/common/extensions/api/system_storage.h"
@@ -39,34 +38,17 @@
   // Get the single shared instance of StorageInfoProvider.
   static StorageInfoProvider* Get();
 
-  // Add and remove observer, both can be called from any thread.
-  void AddObserver(StorageFreeSpaceObserver* obs);
-  void RemoveObserver(StorageFreeSpaceObserver* obs);
-
-  // Start and stop watching the given storage |transient_id|.
-  void StartWatching(const std::string& transient_id);
-  void StopWatching(const std::string& transient_id);
-
-  // Start and stop watching all available storages.
-  void StartWatchingAllStorages();
-  void StopWatchingAllStorages();
-
   // SystemInfoProvider implementations
   virtual void PrepareQueryOnUIThread() OVERRIDE;
   virtual void InitializeProvider(const base::Closure& do_query_info_callback)
       OVERRIDE;
 
-  // Get the amount of storage free space from |transient_id|, or -1 on failure.
-  virtual int64 GetStorageFreeSpaceFromTransientId(
-      const std::string& transient_id);
-
   const StorageUnitInfoList& storage_unit_info_list() const;
 
   static void InitializeForTesting(scoped_refptr<StorageInfoProvider> provider);
 
  protected:
   StorageInfoProvider();
-  explicit StorageInfoProvider(size_t watching_interval);
 
   virtual ~StorageInfoProvider();
 
@@ -83,49 +65,11 @@
   StorageUnitInfoList info_;
 
  private:
-  typedef std::map<std::string, double> StorageTransientIdToSizeMap;
-
   // SystemInfoProvider implementations.
   // Override to query the available capacity of all known storage devices on
   // the blocking pool, including fixed and removable devices.
   virtual bool QueryInfo() OVERRIDE;
 
-  // Query the new attached removable storage info on the blocking pool.
-  void QueryAttachedStorageInfoOnBlockingPool(const std::string& transient_id);
-
-  // Posts a task to check for free space changes on the blocking pool.
-  // Should be called on the UI thread.
-  void CheckWatchedStorages();
-
-  // Check if the free space changes for the watched storages by iterating over
-  // the |storage_transient_id_to_size_map_|. It is called on blocking pool.
-  void CheckWatchedStorageOnBlockingPool(const std::string& transient_id);
-
-  // Add the storage identified by |transient_id| into watching list.
-  void AddWatchedStorageOnBlockingPool(const std::string& transient_id);
-  // Remove the storage identified by |transient_id| from watching list.
-  void RemoveWatchedStorageOnBlockingPool(const std::string& transient_id);
-
-  void StartWatchingTimerOnUIThread();
-  // Force to stop the watching timer or there is no any one storage to be
-  // watched. It is called on UI thread.
-  void StopWatchingTimerOnUIThread();
-
-  // Mapping of the storage being watched and the recent free space value. It
-  // is maintained on the blocking pool.
-  StorageTransientIdToSizeMap storage_transient_id_to_size_map_;
-
-  // The timer used for watching the storage free space changes periodically.
-  base::RepeatingTimer<StorageInfoProvider> watching_timer_;
-
-  // The thread-safe observer list that observe the changes happening on the
-  // storages.
-  scoped_refptr<ObserverListThreadSafe<StorageFreeSpaceObserver> > observers_;
-
-  // The time interval for watching the free space change, in milliseconds.
-  // Only changed for testing purposes.
-  size_t watching_interval_;
-
   static base::LazyInstance<scoped_refptr<StorageInfoProvider> > provider_;
 
   DISALLOW_COPY_AND_ASSIGN(StorageInfoProvider);
diff --git a/chrome/browser/extensions/api/system_storage/storage_info_provider_unittest.cc b/chrome/browser/extensions/api/system_storage/storage_info_provider_unittest.cc
deleted file mode 100644
index 27896be..0000000
--- a/chrome/browser/extensions/api/system_storage/storage_info_provider_unittest.cc
+++ /dev/null
@@ -1,304 +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.
-
-// StorageInfoProvider unit tests.
-
-#include "base/message_loop/message_loop.h"
-#include "base/stl_util.h"
-#include "chrome/browser/extensions/api/system_storage/storage_info_provider.h"
-#include "chrome/browser/extensions/api/system_storage/test_storage_info_provider.h"
-#include "chrome/browser/storage_monitor/storage_monitor.h"
-#include "chrome/browser/storage_monitor/test_storage_monitor.h"
-#include "content/public/test/test_browser_thread.h"
-#include "content/public/test/test_utils.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace extensions {
-
-using api::system_storage::ParseStorageUnitType;
-using api::system_storage::StorageUnitInfo;
-using api::system_storage::StorageUnitType;
-using base::MessageLoop;
-using chrome::test::TestStorageMonitor;
-using chrome::StorageMonitor;
-using content::BrowserThread;
-using content::RunAllPendingInMessageLoop;
-using content::RunMessageLoop;
-using test::TestStorageUnitInfo;
-using testing::Return;
-using testing::_;
-
-const struct TestStorageUnitInfo kTestingData[] = {
-  {"path:device:001", "C:", 1000, 10, 0},
-  {"path:device:002", "d:", 2000, 10, 1},
-  {"path:device:003", "/home", 3000, 10, 2},
-  {"path:device:004", "/", 4000, 10, 3}
-};
-
-// The watching interval for unit test is 1 milliseconds.
-const size_t kWatchingIntervalMs = 1u;
-// The number of times of checking watched storages.
-const int kCheckTimes = 10;
-
-class MockStorageObserver : public StorageFreeSpaceObserver {
- public:
-  MockStorageObserver() {}
-  virtual ~MockStorageObserver() {}
-
-  MOCK_METHOD3(OnFreeSpaceChanged, void(const std::string&,
-     double, double));
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(MockStorageObserver);
-};
-
-const int kMaxCheckWatchStorageTimes = 10;
-
-// A testing observer used to provide the statistics of how many times
-// that the storage free space has been changed and check the change against
-// our expectation.
-class TestStorageObserver : public StorageFreeSpaceObserver {
- public:
-  TestStorageObserver() : change_times_(0) {
-    for (size_t i = 0; i < arraysize(kTestingData); ++i)
-      testing_data_.push_back(kTestingData[i]);
-  }
-
-  virtual ~TestStorageObserver() {}
-
-  virtual void OnFreeSpaceChanged(const std::string& transient_id,
-                                  double old_value,
-                                  double new_value) OVERRIDE {
-    // The observer is added on UI thread, so the callback should be also
-    // called on UI thread.
-    ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::UI));
-    std::string device_id =
-        StorageMonitor::GetInstance()->GetDeviceIdForTransientId(transient_id);
-    size_t i = 0;
-    for (; i < testing_data_.size(); ++i) {
-      if (testing_data_[i].device_id == device_id) {
-        EXPECT_DOUBLE_EQ(new_value-old_value, testing_data_[i].change_step);
-        ++change_times_;
-        break;
-      }
-    }
-
-    ASSERT_TRUE(i != testing_data_.size());
-  }
-
- private:
-  // A copy of |kTestingData|.
-  std::vector<TestStorageUnitInfo> testing_data_;
-  int change_times_;
-};
-
-class UnitTestStorageInfoProvider : public test::TestStorageInfoProvider {
- public :
-  UnitTestStorageInfoProvider(const struct TestStorageUnitInfo* testing_data,
-                              size_t n)
-      : TestStorageInfoProvider(testing_data, n),
-        check_watch_storage_times_(0) {}
-
- protected:
-  virtual ~UnitTestStorageInfoProvider() {}
-
- private:
-  virtual int64 GetStorageFreeSpaceFromTransientId(
-      const std::string& transient_id) OVERRIDE {
-    int64 available_capacity = -1;
-    std::string device_id =
-        StorageMonitor::GetInstance()->GetDeviceIdForTransientId(transient_id);
-    for (size_t i = 0; i < testing_data_.size(); ++i) {
-      if (testing_data_[i].device_id == device_id) {
-        available_capacity = testing_data_[i].available_capacity;
-        // We simulate free space change by increasing the |available_capacity|
-        // with a fixed change step.
-        testing_data_[i].available_capacity += testing_data_[i].change_step;
-
-        // Add up the counting variable.
-        ++check_watch_storage_times_;
-
-        // Post a quit task to UI thread for test result verification
-        // if |check_watch_storage_times_| is greater than the threshold value
-        // |kMaxCheckWatchStorageTimes|.
-        if (check_watch_storage_times_ > kMaxCheckWatchStorageTimes) {
-          BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
-                MessageLoop::QuitClosure());
-          check_watch_storage_times_ = 0;
-        }
-
-        break;
-      }
-    }
-    return available_capacity;
-  }
-
-  int check_watch_storage_times_;
-};
-
-class StorageInfoProviderTest : public testing::Test {
- public:
-  StorageInfoProviderTest();
-  virtual ~StorageInfoProviderTest();
-
- protected:
-  virtual void SetUp() OVERRIDE;
-  virtual void TearDown() OVERRIDE;
-
-  void SetUpAllMockStorageDevices() {
-    for (size_t i = 0; i < arraysize(kTestingData); ++i) {
-      StorageMonitor::GetInstance()->receiver()->ProcessAttach(
-          extensions::test::BuildStorageInfoFromTestStorageUnitInfo(
-              kTestingData[i]));
-    }
-  }
-
-  // Run message loop and flush blocking pool to make sure there is no pending
-  // tasks on blocking pool.
-  static void RunLoopAndFlushBlockingPool();
-  static void RunAllPendingAndFlushBlockingPool();
-
-  base::MessageLoop message_loop_;
-  content::TestBrowserThread ui_thread_;
-  scoped_refptr<UnitTestStorageInfoProvider> storage_info_provider_;
-};
-
-StorageInfoProviderTest::StorageInfoProviderTest()
-    : message_loop_(base::MessageLoop::TYPE_UI),
-      ui_thread_(BrowserThread::UI, &message_loop_) {
-}
-
-StorageInfoProviderTest::~StorageInfoProviderTest() {
-}
-
-void StorageInfoProviderTest::SetUp() {
-  ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::UI));
-  chrome::test::TestStorageMonitor::CreateAndInstall();
-  SetUpAllMockStorageDevices();
-  storage_info_provider_ = new UnitTestStorageInfoProvider(
-      kTestingData, arraysize(kTestingData));
-}
-
-void StorageInfoProviderTest::TearDown() {
-  RunAllPendingAndFlushBlockingPool();
-}
-
-void StorageInfoProviderTest::RunLoopAndFlushBlockingPool() {
-  RunMessageLoop();
-  content::BrowserThread::GetBlockingPool()->FlushForTesting();
-}
-
-void StorageInfoProviderTest::RunAllPendingAndFlushBlockingPool() {
-  RunAllPendingInMessageLoop();
-  content::BrowserThread::GetBlockingPool()->FlushForTesting();
-}
-
-TEST_F(StorageInfoProviderTest, WatchingNoChangedStorage) {
-  // Case 1: watching a storage that the free space is not changed.
-  MockStorageObserver observer;
-  storage_info_provider_->AddObserver(&observer);
-  std::string transient_id =
-      StorageMonitor::GetInstance()->GetTransientIdForDeviceId(
-          kTestingData[0].device_id);
-  storage_info_provider_->StartWatching(transient_id);
-  EXPECT_CALL(observer, OnFreeSpaceChanged(transient_id, _, _))
-      .Times(0);
-
-  RunLoopAndFlushBlockingPool();
-
-  storage_info_provider_->RemoveObserver(&observer);
-  storage_info_provider_->StopWatching(transient_id);
-  RunAllPendingAndFlushBlockingPool();
-}
-
-TEST_F(StorageInfoProviderTest, WatchingOneStorage) {
-  // Case 2: only watching one storage.
-  TestStorageObserver observer;
-  storage_info_provider_->AddObserver(&observer);
-  std::string transient_id =
-    StorageMonitor::GetInstance()->GetTransientIdForDeviceId(
-        kTestingData[1].device_id);
-  storage_info_provider_->StartWatching(transient_id);
-  RunLoopAndFlushBlockingPool();
-
-  storage_info_provider_->StopWatching(transient_id);
-  // Give a chance to run StopWatching task on the blocking pool.
-  RunAllPendingAndFlushBlockingPool();
-
-  MockStorageObserver mock_observer;
-  storage_info_provider_->AddObserver(&mock_observer);
-  // The watched storage won't get free space change notification.
-  EXPECT_CALL(mock_observer,
-      OnFreeSpaceChanged(transient_id, _, _)).Times(0);
-  RunAllPendingAndFlushBlockingPool();
-
-  storage_info_provider_->RemoveObserver(&observer);
-  storage_info_provider_->RemoveObserver(&mock_observer);
-}
-
-TEST_F(StorageInfoProviderTest, WatchingMultipleStorages) {
-  // Case 2: watching multiple storages. We ignore the first entry in
-  // |kTestingData| since its change_step is zero.
-  TestStorageObserver observer;
-  storage_info_provider_->AddObserver(&observer);
-
-  for (size_t k = 1; k < arraysize(kTestingData); ++k) {
-    std::string transient_id =
-        StorageMonitor::GetInstance()->GetTransientIdForDeviceId(
-            kTestingData[k].device_id);
-    storage_info_provider_->StartWatching(transient_id);
-  }
-  RunLoopAndFlushBlockingPool();
-
-  // Stop watching the first storage.
-  storage_info_provider_->StopWatching(
-      StorageMonitor::GetInstance()->GetTransientIdForDeviceId(
-          kTestingData[1].device_id));
-  RunAllPendingAndFlushBlockingPool();
-
-  MockStorageObserver mock_observer;
-  storage_info_provider_->AddObserver(&mock_observer);
-  for (size_t k = 2; k < arraysize(kTestingData); ++k) {
-    std::string transient_id =
-        StorageMonitor::GetInstance()->GetTransientIdForDeviceId(
-            kTestingData[k].device_id);
-    EXPECT_CALL(mock_observer,
-        OnFreeSpaceChanged(transient_id,  _, _))
-        .WillRepeatedly(Return());
-  }
-
-  // After stopping watching, the observer won't get change notification.
-  EXPECT_CALL(mock_observer,
-      OnFreeSpaceChanged(
-          StorageMonitor::GetInstance()->GetTransientIdForDeviceId(
-              kTestingData[1].device_id),
-          _, _))
-          .Times(0);
-  RunLoopAndFlushBlockingPool();
-
-  for (size_t k = 1; k < arraysize(kTestingData); ++k) {
-    std::string transient_id =
-        StorageMonitor::GetInstance()->GetTransientIdForDeviceId(
-            kTestingData[k].device_id);
-    storage_info_provider_->StopWatching(transient_id);
-  }
-  RunAllPendingAndFlushBlockingPool();
-  storage_info_provider_->RemoveObserver(&observer);
-  storage_info_provider_->RemoveObserver(&mock_observer);
-}
-
-TEST_F(StorageInfoProviderTest, WatchingInvalidStorage) {
-  // Case 3: watching an invalid storage.
-  std::string invalid_device_id("invalid_id");
-  MockStorageObserver mock_observer;
-  storage_info_provider_->AddObserver(&mock_observer);
-  storage_info_provider_->StartWatching(invalid_device_id);
-  EXPECT_CALL(mock_observer,
-      OnFreeSpaceChanged(invalid_device_id, _, _)).Times(0);
-  RunAllPendingAndFlushBlockingPool();
-  storage_info_provider_->RemoveObserver(&mock_observer);
-}
-
-} // namespace extensions
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 db28ad8..cf640ab 100644
--- a/chrome/browser/extensions/api/system_storage/system_storage_api.cc
+++ b/chrome/browser/extensions/api/system_storage/system_storage_api.cc
@@ -92,56 +92,4 @@
   SendResponse(true);
 }
 
-SystemStorageAddAvailableCapacityWatchFunction::
-    SystemStorageAddAvailableCapacityWatchFunction() {
-}
-
-SystemStorageAddAvailableCapacityWatchFunction::
-    ~SystemStorageAddAvailableCapacityWatchFunction() {
-}
-
-bool SystemStorageAddAvailableCapacityWatchFunction::RunImpl() {
-  // TODO(Haojian): Implement the addAvailableCapacityWatch API.
-  return false;
-}
-
-SystemStorageRemoveAvailableCapacityWatchFunction::
-    SystemStorageRemoveAvailableCapacityWatchFunction() {
-}
-
-SystemStorageRemoveAvailableCapacityWatchFunction::
-    ~SystemStorageRemoveAvailableCapacityWatchFunction() {
-}
-
-bool SystemStorageRemoveAvailableCapacityWatchFunction::RunImpl() {
-  // TODO(Haojian): Implement the removeAvailableCapacityWatch API.
-  return false;
-}
-
-SystemStorageGetAllAvailableCapacityWatchesFunction
-    ::SystemStorageGetAllAvailableCapacityWatchesFunction() {
-}
-
-SystemStorageGetAllAvailableCapacityWatchesFunction
-    ::~SystemStorageGetAllAvailableCapacityWatchesFunction() {
-}
-
-bool SystemStorageGetAllAvailableCapacityWatchesFunction::RunImpl() {
-  // TODO(Haojian): Implement the getAllAvailableCapacityWatches API.
-  return false;
-}
-
-SystemStorageRemoveAllAvailableCapacityWatchesFunction::
-    SystemStorageRemoveAllAvailableCapacityWatchesFunction() {
-}
-
-SystemStorageRemoveAllAvailableCapacityWatchesFunction::
-    ~SystemStorageRemoveAllAvailableCapacityWatchesFunction() {
-}
-
-bool SystemStorageRemoveAllAvailableCapacityWatchesFunction::RunImpl() {
-  // TODO(Haojian): Implement the removeAllAvailableCapacityWatches api.
-  return false;
-}
-
 }  // namespace extensions
diff --git a/chrome/browser/extensions/api/system_storage/system_storage_api.h b/chrome/browser/extensions/api/system_storage/system_storage_api.h
index ba17536..0c346f9 100644
--- a/chrome/browser/extensions/api/system_storage/system_storage_api.h
+++ b/chrome/browser/extensions/api/system_storage/system_storage_api.h
@@ -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.
+
 #ifndef CHROME_BROWSER_EXTENSIONS_API_SYSTEM_STORAGE_SYSTEM_STORAGE_API_H_
 #define CHROME_BROWSER_EXTENSIONS_API_SYSTEM_STORAGE_SYSTEM_STORAGE_API_H_
 
@@ -43,54 +44,6 @@
   void HandleResponse(chrome::StorageMonitor::EjectStatus status);
 };
 
-class SystemStorageAddAvailableCapacityWatchFunction
-    : public AsyncExtensionFunction {
- public:
-  DECLARE_EXTENSION_FUNCTION("system.storage.addAvailableCapacityWatch",
-                             SYSTEM_STORAGE_ADDAVAILABLECAPACITYWATCH);
-  SystemStorageAddAvailableCapacityWatchFunction();
-
- private:
-  virtual ~SystemStorageAddAvailableCapacityWatchFunction();
-  virtual bool RunImpl() OVERRIDE;
-};
-
-class SystemStorageRemoveAvailableCapacityWatchFunction
-    : public SyncExtensionFunction {
- public:
-  DECLARE_EXTENSION_FUNCTION("system.storage.removeAvailableCapacityWatch",
-                             SYSTEM_STORAGE_REMOVEAVAILABLECAPACITYWATCH);
-  SystemStorageRemoveAvailableCapacityWatchFunction();
-
- private:
-  virtual ~SystemStorageRemoveAvailableCapacityWatchFunction();
-  virtual bool RunImpl() OVERRIDE;
-};
-
-class SystemStorageGetAllAvailableCapacityWatchesFunction
-    : public SyncExtensionFunction {
- public:
-  DECLARE_EXTENSION_FUNCTION("system.storage.getAllAvailableCapacityWatches",
-                             SYSTEM_STORAGE_GETALLAVAILABLECAPACITYWATCHES);
-  SystemStorageGetAllAvailableCapacityWatchesFunction();
-
- private:
-  virtual ~SystemStorageGetAllAvailableCapacityWatchesFunction();
-  virtual bool RunImpl() OVERRIDE;
-};
-
-class SystemStorageRemoveAllAvailableCapacityWatchesFunction
-    : public SyncExtensionFunction {
- public:
-  DECLARE_EXTENSION_FUNCTION("system.storage.removeAllAvailableCapacityWatches",
-                             SYSTEM_STORAGE_REMOVEALLAVAILABLECAPACITYWATCHES);
-  SystemStorageRemoveAllAvailableCapacityWatchesFunction();
-
- private:
-  virtual ~SystemStorageRemoveAllAvailableCapacityWatchesFunction();
-  virtual bool RunImpl() OVERRIDE;
-};
-
 }  // namespace extensions
 
 #endif  // CHROME_BROWSER_EXTENSIONS_API_SYSTEM_STORAGE_SYSTEM_STORAGE_API_H_
diff --git a/chrome/browser/extensions/api/system_storage/system_storage_apitest.cc b/chrome/browser/extensions/api/system_storage/system_storage_apitest.cc
index a56461e..5cd4fe3 100644
--- a/chrome/browser/extensions/api/system_storage/system_storage_apitest.cc
+++ b/chrome/browser/extensions/api/system_storage/system_storage_apitest.cc
@@ -6,8 +6,8 @@
 
 #include "base/message_loop/message_loop.h"
 #include "base/strings/utf_string_conversions.h"
+#include "chrome/browser/extensions/api/system_storage/storage_api_test_util.h"
 #include "chrome/browser/extensions/api/system_storage/storage_info_provider.h"
-#include "chrome/browser/extensions/api/system_storage/test_storage_info_provider.h"
 #include "chrome/browser/extensions/extension_apitest.h"
 #include "chrome/browser/extensions/extension_test_message_listener.h"
 #include "chrome/browser/storage_monitor/storage_info.h"
@@ -17,18 +17,14 @@
 namespace {
 
 using chrome::StorageMonitor;
-using extensions::api::system_storage::ParseStorageUnitType;
-using extensions::api::system_storage::StorageUnitInfo;
-using extensions::StorageInfoProvider;
 using extensions::StorageUnitInfoList;
 using extensions::test::TestStorageUnitInfo;
-using extensions::test::TestStorageInfoProvider;
 using extensions::test::kRemovableStorageData;
 
 const struct TestStorageUnitInfo kTestingData[] = {
-  {"dcim:device:001", "0xbeaf", 4098, 1000, 0},
-  {"path:device:002", "/home", 4098, 1000, 10},
-  {"path:device:003", "/data", 10000, 1000, 4097}
+  {"dcim:device:001", "0xbeaf", 4098, 1000},
+  {"path:device:002", "/home", 4098, 1000},
+  {"path:device:003", "/data", 10000, 1000}
 };
 
 }  // namespace
@@ -70,10 +66,6 @@
 
 IN_PROC_BROWSER_TEST_F(SystemStorageApiTest, Storage) {
   SetUpAllMockStorageDevices();
-  TestStorageInfoProvider* provider =
-      new TestStorageInfoProvider(kTestingData,
-                                  arraysize(kTestingData));
-  StorageInfoProvider::InitializeForTesting(provider);
   std::vector<linked_ptr<ExtensionTestMessageListener> > device_ids_listeners;
   for (size_t i = 0; i < arraysize(kTestingData); ++i) {
     linked_ptr<ExtensionTestMessageListener> listener(
diff --git a/chrome/browser/extensions/api/system_storage/system_storage_eject_apitest.cc b/chrome/browser/extensions/api/system_storage/system_storage_eject_apitest.cc
index c91ca29..764fdbb 100644
--- a/chrome/browser/extensions/api/system_storage/system_storage_eject_apitest.cc
+++ b/chrome/browser/extensions/api/system_storage/system_storage_eject_apitest.cc
@@ -7,8 +7,8 @@
 #include "base/files/file_path.h"
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
+#include "chrome/browser/extensions/api/system_storage/storage_api_test_util.h"
 #include "chrome/browser/extensions/api/system_storage/storage_info_provider.h"
-#include "chrome/browser/extensions/api/system_storage/test_storage_info_provider.h"
 #include "chrome/browser/extensions/extension_apitest.h"
 #include "chrome/browser/extensions/extension_process_manager.h"
 #include "chrome/browser/extensions/extension_system.h"
@@ -23,7 +23,6 @@
 namespace {
 
 using extensions::test::TestStorageUnitInfo;
-using extensions::test::TestStorageInfoProvider;
 using extensions::test::kRemovableStorageData;
 
 }  // namespace
diff --git a/chrome/browser/extensions/api/system_storage/test_storage_info_provider.cc b/chrome/browser/extensions/api/system_storage/test_storage_info_provider.cc
deleted file mode 100644
index 3a3e0eb..0000000
--- a/chrome/browser/extensions/api/system_storage/test_storage_info_provider.cc
+++ /dev/null
@@ -1,63 +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/extensions/api/system_storage/test_storage_info_provider.h"
-
-#include "base/strings/utf_string_conversions.h"
-#include "chrome/browser/storage_monitor/storage_monitor.h"
-
-namespace extensions {
-namespace test {
-
-using api::system_storage::ParseStorageUnitType;
-using api::system_storage::StorageUnitInfo;
-
-// Watching interval for testing.
-const size_t kTestingIntervalMS = 10;
-
-const struct TestStorageUnitInfo kRemovableStorageData = {
-    "dcim:device:001", "/media/usb1", 4098, 1000, 1
-};
-
-chrome::StorageInfo BuildStorageInfoFromTestStorageUnitInfo(
-    const TestStorageUnitInfo& unit) {
-  return chrome::StorageInfo(
-      unit.device_id,
-      UTF8ToUTF16(unit.name),
-      base::FilePath::StringType(), /* no location */
-      string16(), /* no storage label */
-      string16(), /* no storage vendor */
-      string16(), /* no storage model */
-      unit.capacity);
-}
-
-TestStorageInfoProvider::TestStorageInfoProvider(
-    const struct TestStorageUnitInfo* testing_data, size_t n)
-        : StorageInfoProvider(kTestingIntervalMS),
-          testing_data_(testing_data, testing_data + n) {
-}
-
-TestStorageInfoProvider::~TestStorageInfoProvider() {
-}
-
-int64 TestStorageInfoProvider::GetStorageFreeSpaceFromTransientId(
-    const std::string& transient_id) {
-  int64 available_capacity = -1;
-  std::string device_id =
-      chrome::StorageMonitor::GetInstance()->GetDeviceIdForTransientId(
-          transient_id);
-  for (size_t i = 0; i < testing_data_.size(); ++i) {
-    if (testing_data_[i].device_id == device_id) {
-      available_capacity = testing_data_[i].available_capacity;
-      // We simulate free space change by increasing the |available_capacity|
-      // with a fixed change step.
-      testing_data_[i].available_capacity += testing_data_[i].change_step;
-      break;
-    }
-  }
-  return available_capacity;
-}
-
-}  // namespace test
-}  // namespace extensions
diff --git a/chrome/browser/extensions/api/system_storage/test_storage_info_provider.h b/chrome/browser/extensions/api/system_storage/test_storage_info_provider.h
deleted file mode 100644
index 7a390b7..0000000
--- a/chrome/browser/extensions/api/system_storage/test_storage_info_provider.h
+++ /dev/null
@@ -1,51 +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_EXTENSIONS_API_SYSTEM_STORAGE_TEST_STORAGE_INFO_PROVIDER_H_
-#define CHROME_BROWSER_EXTENSIONS_API_SYSTEM_STORAGE_TEST_STORAGE_INFO_PROVIDER_H_
-
-#include <vector>
-
-#include "chrome/browser/extensions/api/system_storage/storage_info_provider.h"
-#include "chrome/browser/storage_monitor/storage_info.h"
-
-namespace extensions {
-namespace test {
-
-struct TestStorageUnitInfo {
-  const char* device_id;
-  const char* name;
-  // Total amount of the storage device space, in bytes.
-  double capacity;
-  // The available amount of the storage space, in bytes.
-  double available_capacity;
-  // The change step of available capacity for simulating the free space change.
-  // Each querying operation will increase the |available_capacity| with this
-  // value.
-  int change_step;
-};
-
-extern const struct TestStorageUnitInfo kRemovableStorageData;
-
-chrome::StorageInfo BuildStorageInfoFromTestStorageUnitInfo(
-    const TestStorageUnitInfo& unit);
-
-class TestStorageInfoProvider : public extensions::StorageInfoProvider {
- public:
-  TestStorageInfoProvider(const struct TestStorageUnitInfo* testing_data,
-                          size_t n);
-
- protected:
-  virtual ~TestStorageInfoProvider();
-
-  // StorageInfoProvider implementations.
-  virtual int64 GetStorageFreeSpaceFromTransientId(
-      const std::string& transient_id) OVERRIDE;
-
-  std::vector<struct TestStorageUnitInfo> testing_data_;
-};
-
-}  // namespace test
-}  // namespace extensions
-#endif  // CHROME_BROWSER_EXTENSIONS_API_SYSTEM_STORAGE_TEST_STORAGE_INFO_PROVIDER_H_
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 34f7803..25f17c4 100644
--- a/chrome/browser/extensions/api/tab_capture/tab_capture_api.cc
+++ b/chrome/browser/extensions/api/tab_capture/tab_capture_api.cc
@@ -21,10 +21,10 @@
 #include "chrome/browser/ui/browser_finder.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
 #include "chrome/common/chrome_switches.h"
-#include "chrome/common/extensions/features/base_feature_provider.h"
-#include "chrome/common/extensions/features/simple_feature.h"
+#include "chrome/common/extensions/features/feature.h"
 #include "content/public/browser/render_process_host.h"
 #include "content/public/browser/render_view_host.h"
+#include "extensions/common/features/feature_provider.h"
 
 using extensions::api::tab_capture::MediaStreamConstraint;
 
@@ -80,7 +80,7 @@
           active_tab_permission_granter()->IsGranted(extension) &&
       CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
           switches::kWhitelistedExtensionID) != extension_id &&
-      !BaseFeatureProvider::GetPermissionFeatures()->GetFeature("tabCapture")->
+      !FeatureProvider::GetByName("permission")->GetFeature("tabCapture")->
           IsIdInWhitelist(extension_id)) {
     error_ = kGrantError;
     return false;
diff --git a/chrome/browser/extensions/api/tabs/tabs_api.cc b/chrome/browser/extensions/api/tabs/tabs_api.cc
index cbe4a0d..d574db9 100644
--- a/chrome/browser/extensions/api/tabs/tabs_api.cc
+++ b/chrome/browser/extensions/api/tabs/tabs_api.cc
@@ -93,9 +93,9 @@
 #endif  // OS_WIN
 
 #if defined(USE_ASH)
+#include "apps/shell_window_registry.h"
 #include "ash/ash_switches.h"
 #include "chrome/browser/extensions/api/tabs/ash_panel_contents.h"
-#include "chrome/browser/extensions/shell_window_registry.h"
 #endif
 
 using apps::ShellWindow;
diff --git a/chrome/browser/extensions/api/usb/usb_api.cc b/chrome/browser/extensions/api/usb/usb_api.cc
index a6c8ae8..878e362 100644
--- a/chrome/browser/extensions/api/usb/usb_api.cc
+++ b/chrome/browser/extensions/api/usb/usb_api.cc
@@ -89,7 +89,7 @@
 static const int kMaxPackets = 4 * 1024 * 1024;
 static const int kMaxPacketLength = 64 * 1024;
 
-static UsbDeviceHandle* device_for_test_ = NULL;
+static UsbDevice* device_for_test_ = NULL;
 
 static bool ConvertDirectionToApi(const UsbEndpointDirection& input,
                                   Direction* output) {
@@ -410,7 +410,7 @@
 
 UsbFindDevicesFunction::~UsbFindDevicesFunction() {}
 
-void UsbFindDevicesFunction::SetDeviceForTest(UsbDeviceHandle* device) {
+void UsbFindDevicesFunction::SetDeviceForTest(UsbDevice* device) {
   device_for_test_ = device;
 }
 
@@ -426,7 +426,7 @@
   if (device_for_test_) {
     UsbDeviceResource* const resource = new UsbDeviceResource(
         extension_->id(),
-        device_for_test_);
+        device_for_test_->Open());
 
     Device device;
     result_->Append(PopulateDevice(manager_->Add(resource), 0, 0));
@@ -472,23 +472,26 @@
                             this)));
 }
 
-
 void UsbFindDevicesFunction::OnEnumerationCompleted(
     ScopedDeviceVector devices) {
+  for (size_t i = 0; i < devices->size(); ++i) {
+    scoped_refptr<UsbDeviceHandle> device_handle =
+      devices->at(i)->Open();
+    if (device_handle)
+      device_handles_.push_back(device_handle);
+  }
+
   BrowserThread::PostTask(
       BrowserThread::IO,
       FROM_HERE,
-      base::Bind(&UsbFindDevicesFunction::OnCompleted,
-                 this,
-                 base::Passed(devices.Pass())));
+      base::Bind(&UsbFindDevicesFunction::OnCompleted, this));
 }
 
-void UsbFindDevicesFunction::OnCompleted(
-    ScopedDeviceVector devices) {
-  for (size_t i = 0; i < devices->size(); ++i) {
-    UsbDeviceHandle* const device = devices->at(i).get();
+void UsbFindDevicesFunction::OnCompleted() {
+  for (size_t i = 0; i < device_handles_.size(); ++i) {
+    UsbDeviceHandle* const device_handle = device_handles_[i].get();
     UsbDeviceResource* const resource =
-        new UsbDeviceResource(extension_->id(), device);
+        new UsbDeviceResource(extension_->id(), device_handle);
 
     result_->Append(PopulateDevice(manager_->Add(resource),
                                    parameters_->options.vendor_id,
@@ -521,8 +524,8 @@
   BrowserThread::PostTaskAndReplyWithResult(
       BrowserThread::FILE,
       FROM_HERE,
-      base::Bind(&UsbDeviceHandle::ListInterfaces,
-                 resource->device(),
+      base::Bind(&UsbDevice::ListInterfaces,
+                 resource->device()->device(),
                  config_),
       base::Bind(&UsbListInterfacesFunction::OnCompleted, this));
 }
@@ -652,10 +655,10 @@
       FROM_HERE,
       base::Bind(&UsbDeviceHandle::Close, resource->device()),
       base::Bind(&UsbCloseDeviceFunction::OnCompleted, this));
-  RemoveUsbDeviceResource(parameters_->device.handle);
 }
 
 void UsbCloseDeviceFunction::OnCompleted() {
+  RemoveUsbDeviceResource(parameters_->device.handle);
   AsyncWorkCompleted();
 }
 
diff --git a/chrome/browser/extensions/api/usb/usb_api.h b/chrome/browser/extensions/api/usb/usb_api.h
index 65c713e..2f779ff 100644
--- a/chrome/browser/extensions/api/usb/usb_api.h
+++ b/chrome/browser/extensions/api/usb/usb_api.h
@@ -11,6 +11,7 @@
 #include "base/memory/ref_counted.h"
 #include "chrome/browser/extensions/api/api_function.h"
 #include "chrome/browser/extensions/api/api_resource_manager.h"
+#include "chrome/browser/usb/usb_device.h"
 #include "chrome/browser/usb/usb_device_handle.h"
 #include "chrome/common/extensions/api/usb.h"
 #include "net/base/io_buffer.h"
@@ -63,7 +64,7 @@
 
   UsbFindDevicesFunction();
 
-  static void SetDeviceForTest(UsbDeviceHandle* device);
+  static void SetDeviceForTest(UsbDevice* device);
 
  protected:
   virtual ~UsbFindDevicesFunction();
@@ -72,21 +73,25 @@
   virtual void AsyncWorkStart() OVERRIDE;
 
  private:
-  typedef scoped_ptr<std::vector<scoped_refptr<UsbDeviceHandle> > >
+  typedef scoped_ptr<std::vector<scoped_refptr<UsbDevice> > >
       ScopedDeviceVector;
 
+  // This should be run on the FILE thread.
   // Wait for GetDeviceService to return and start enumeration on FILE thread.
   void EnumerateDevices(uint16_t vendor_id,
                         uint16_t product_id,
                         int interface_id,
                         UsbService* service);
+
   // Relay the result on IO thread to OnCompleted.
   void OnEnumerationCompleted(ScopedDeviceVector devices);
 
+  // This should be run on the IO thread.
   // Create ApiResources and reply.
-  void OnCompleted(ScopedDeviceVector devices);
+  void OnCompleted();
 
   scoped_ptr<base::ListValue> result_;
+  std::vector<scoped_refptr<UsbDeviceHandle> > device_handles_;
   scoped_ptr<extensions::api::usb::FindDevices::Params> parameters_;
 };
 
@@ -271,11 +276,11 @@
   virtual void AsyncWorkStart() OVERRIDE;
 
  private:
-  // FILE thread.
+  // This should be run on the FILE thread.
   void OnStartResest(UsbDeviceResource* resource);
   void OnCompletedFileThread(bool success);
 
-  // IO thread.
+  // This should be run on the IO thread.
   void OnCompleted(bool success);
   void OnError();
 
diff --git a/chrome/browser/extensions/api/usb/usb_apitest.cc b/chrome/browser/extensions/api/usb/usb_apitest.cc
index af0039c..3af2e2e 100644
--- a/chrome/browser/extensions/api/usb/usb_apitest.cc
+++ b/chrome/browser/extensions/api/usb/usb_apitest.cc
@@ -5,12 +5,14 @@
 #include "chrome/browser/extensions/api/usb/usb_api.h"
 #include "chrome/browser/extensions/extension_apitest.h"
 #include "chrome/browser/ui/browser.h"
+#include "content/public/browser/browser_thread.h"
 #include "net/base/io_buffer.h"
 #include "testing/gmock/include/gmock/gmock.h"
 
 using testing::AnyNumber;
 using testing::_;
 using testing::Return;
+using content::BrowserThread;
 
 namespace {
 
@@ -27,6 +29,7 @@
 #pragma warning(push)
 #pragma warning(disable:4373)
 #endif
+
 class MockUsbDeviceHandle : public UsbDeviceHandle {
  public:
   MockUsbDeviceHandle() : UsbDeviceHandle() {}
@@ -54,11 +57,36 @@
 
   MOCK_METHOD0(ResetDevice, bool());
 
-  MOCK_METHOD1(ListInterfaces, bool(UsbConfigDescriptor* config));
+  void set_device(UsbDevice* device) { device_ = device; }
 
  protected:
   virtual ~MockUsbDeviceHandle() {}
 };
+
+class MockUsbDevice : public UsbDevice {
+ public:
+  explicit MockUsbDevice(MockUsbDeviceHandle* mock_handle)
+     : UsbDevice(),
+       mock_handle_(mock_handle) {
+    mock_handle->set_device(this);
+  }
+
+  virtual scoped_refptr<UsbDeviceHandle> Open() OVERRIDE {
+    return mock_handle_;
+  }
+
+  virtual bool Close(scoped_refptr<UsbDeviceHandle> handle) OVERRIDE {
+    EXPECT_TRUE(false) << "Should not be reached";
+    return false;
+  }
+
+  MOCK_METHOD1(ListInterfaces, bool(UsbConfigDescriptor* config));
+
+ private:
+  MockUsbDeviceHandle* mock_handle_;
+  virtual ~MockUsbDevice() {}
+};
+
 #if defined(OS_WIN)
 #pragma warning(pop)
 #endif
@@ -66,22 +94,24 @@
 class UsbApiTest : public ExtensionApiTest {
  public:
   virtual void SetUpOnMainThread() OVERRIDE {
-    mock_device_ = new MockUsbDeviceHandle();
+    mock_device_handle_ = new MockUsbDeviceHandle();
+    mock_device_ = new MockUsbDevice(mock_device_handle_.get());
     extensions::UsbFindDevicesFunction::SetDeviceForTest(mock_device_.get());
   }
 
  protected:
-  scoped_refptr<MockUsbDeviceHandle> mock_device_;
+  scoped_refptr<MockUsbDeviceHandle> mock_device_handle_;
+  scoped_refptr<MockUsbDevice> mock_device_;
 };
 
 }  // namespace
 
 IN_PROC_BROWSER_TEST_F(UsbApiTest, DeviceHandling) {
-  EXPECT_CALL(*mock_device_.get(), Close()).Times(AnyNumber());
-  EXPECT_CALL(*mock_device_.get(), ResetDevice())
+  EXPECT_CALL(*mock_device_handle_.get(), Close()).Times(AnyNumber());
+  EXPECT_CALL(*mock_device_handle_.get(), ResetDevice())
       .WillOnce(Return(true))
       .WillOnce(Return(false));
-  EXPECT_CALL(*mock_device_.get(),
+  EXPECT_CALL(*mock_device_handle_.get(),
               InterruptTransfer(USB_DIRECTION_OUTBOUND, 2, _, 1, _, _))
       .WillOnce(InvokeUsbTransferCallback<5>(USB_TRANSFER_COMPLETED));
   ASSERT_TRUE(RunExtensionTest("usb/device_handling"));
@@ -90,12 +120,12 @@
 IN_PROC_BROWSER_TEST_F(UsbApiTest, ListInterfaces) {
   EXPECT_CALL(*mock_device_.get(), ListInterfaces(_))
       .WillOnce(Return(false));
-  EXPECT_CALL(*mock_device_.get(), Close()).Times(AnyNumber());
+  EXPECT_CALL(*mock_device_handle_.get(), Close()).Times(AnyNumber());
   ASSERT_TRUE(RunExtensionTest("usb/list_interfaces"));
 }
 
 IN_PROC_BROWSER_TEST_F(UsbApiTest, TransferEvent) {
-  EXPECT_CALL(*mock_device_.get(),
+  EXPECT_CALL(*mock_device_handle_.get(),
               ControlTransfer(USB_DIRECTION_OUTBOUND,
                               UsbDeviceHandle::STANDARD,
                               UsbDeviceHandle::DEVICE,
@@ -107,36 +137,36 @@
                               _,
                               _))
       .WillOnce(InvokeUsbTransferCallback<9>(USB_TRANSFER_COMPLETED));
-  EXPECT_CALL(*mock_device_.get(),
+  EXPECT_CALL(*mock_device_handle_.get(),
               BulkTransfer(USB_DIRECTION_OUTBOUND, 1, _, 1, _, _))
       .WillOnce(InvokeUsbTransferCallback<5>(USB_TRANSFER_COMPLETED));
-  EXPECT_CALL(*mock_device_.get(),
+  EXPECT_CALL(*mock_device_handle_.get(),
               InterruptTransfer(USB_DIRECTION_OUTBOUND, 2, _, 1, _, _))
       .WillOnce(InvokeUsbTransferCallback<5>(USB_TRANSFER_COMPLETED));
-  EXPECT_CALL(*mock_device_.get(),
+  EXPECT_CALL(*mock_device_handle_.get(),
               IsochronousTransfer(USB_DIRECTION_OUTBOUND, 3, _, 1, 1, 1, _, _))
       .WillOnce(InvokeUsbTransferCallback<7>(USB_TRANSFER_COMPLETED));
-  EXPECT_CALL(*mock_device_.get(), Close()).Times(AnyNumber());
+  EXPECT_CALL(*mock_device_handle_.get(), Close()).Times(AnyNumber());
   ASSERT_TRUE(RunExtensionTest("usb/transfer_event"));
 }
 
 IN_PROC_BROWSER_TEST_F(UsbApiTest, ZeroLengthTransfer) {
-  EXPECT_CALL(*mock_device_.get(), BulkTransfer(_, _, _, 0, _, _))
+  EXPECT_CALL(*mock_device_handle_.get(), BulkTransfer(_, _, _, 0, _, _))
       .WillOnce(InvokeUsbTransferCallback<5>(USB_TRANSFER_COMPLETED));
-  EXPECT_CALL(*mock_device_.get(), Close()).Times(AnyNumber());
+  EXPECT_CALL(*mock_device_handle_.get(), Close()).Times(AnyNumber());
   ASSERT_TRUE(RunExtensionTest("usb/zero_length_transfer"));
 }
 
 IN_PROC_BROWSER_TEST_F(UsbApiTest, TransferFailure) {
-  EXPECT_CALL(*mock_device_.get(), BulkTransfer(_, _, _, _, _, _))
+  EXPECT_CALL(*mock_device_handle_.get(), BulkTransfer(_, _, _, _, _, _))
       .WillOnce(InvokeUsbTransferCallback<5>(USB_TRANSFER_COMPLETED))
       .WillOnce(InvokeUsbTransferCallback<5>(USB_TRANSFER_ERROR))
       .WillOnce(InvokeUsbTransferCallback<5>(USB_TRANSFER_TIMEOUT));
-  EXPECT_CALL(*mock_device_.get(), Close()).Times(AnyNumber());
+  EXPECT_CALL(*mock_device_handle_.get(), Close()).Times(AnyNumber());
   ASSERT_TRUE(RunExtensionTest("usb/transfer_failure"));
 }
 
 IN_PROC_BROWSER_TEST_F(UsbApiTest, InvalidLengthTransfer) {
-  EXPECT_CALL(*mock_device_.get(), Close()).Times(AnyNumber());
+  EXPECT_CALL(*mock_device_handle_.get(), Close()).Times(AnyNumber());
   ASSERT_TRUE(RunExtensionTest("usb/invalid_length_transfer"));
 }
diff --git a/chrome/browser/extensions/api/usb/usb_device_resource.cc b/chrome/browser/extensions/api/usb/usb_device_resource.cc
index 685d24d..f086300 100644
--- a/chrome/browser/extensions/api/usb/usb_device_resource.cc
+++ b/chrome/browser/extensions/api/usb/usb_device_resource.cc
@@ -13,6 +13,9 @@
 #include "chrome/browser/extensions/api/api_resource.h"
 #include "chrome/browser/usb/usb_device_handle.h"
 #include "chrome/common/extensions/api/usb.h"
+#include "content/public/browser/browser_thread.h"
+
+using content::BrowserThread;
 
 namespace extensions {
 
@@ -31,6 +34,9 @@
                                      scoped_refptr<UsbDeviceHandle> device)
     : ApiResource(owner_extension_id), device_(device) {}
 
-UsbDeviceResource::~UsbDeviceResource() {}
+UsbDeviceResource::~UsbDeviceResource() {
+  BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
+                          base::Bind(&UsbDeviceHandle::Close, device_));
+}
 
 }  // namespace extensions
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 590c681..73c80f1 100644
--- a/chrome/browser/extensions/api/web_navigation/web_navigation_api.cc
+++ b/chrome/browser/extensions/api/web_navigation/web_navigation_api.cc
@@ -37,6 +37,8 @@
 
 namespace extensions {
 
+#if !defined(OS_ANDROID)
+
 namespace helpers = web_navigation_api_helpers;
 namespace keys = web_navigation_api_constants;
 
@@ -858,4 +860,6 @@
   ExtensionSystem::Get(profile_)->event_router()->UnregisterObserver(this);
 }
 
+#endif  // OS_ANDROID
+
 }  // namespace extensions
diff --git a/chrome/browser/extensions/api/webstore_private/webstore_private_api.cc b/chrome/browser/extensions/api/webstore_private/webstore_private_api.cc
index f108480..07cc111 100644
--- a/chrome/browser/extensions/api/webstore_private/webstore_private_api.cc
+++ b/chrome/browser/extensions/api/webstore_private/webstore_private_api.cc
@@ -571,10 +571,12 @@
   if (approval_->enable_launcher)
     AppListService::Get()->EnableAppList(profile());
 
-  if (apps::IsAppLauncherEnabled()) {
+  if (apps::IsAppLauncherEnabled() && approval_->manifest->is_app()) {
     // Show the app list to show download is progressing. Don't show the app
     // list on first app install so users can be trained to open it themselves.
-    if (approval_->manifest->is_app() && !approval_->enable_launcher)
+    if (approval_->enable_launcher)
+      AppListService::Get()->CreateForProfile(profile());
+    else
       AppListService::Get()->ShowForProfile(profile());
   }
 
diff --git a/chrome/browser/extensions/crx_installer.cc b/chrome/browser/extensions/crx_installer.cc
index a80d1e0..68d715b 100644
--- a/chrome/browser/extensions/crx_installer.cc
+++ b/chrome/browser/extensions/crx_installer.cc
@@ -72,23 +72,31 @@
 }  // namespace
 
 // static
+scoped_refptr<CrxInstaller> CrxInstaller::CreateSilent(
+    ExtensionService* frontend) {
+  return new CrxInstaller(frontend->AsWeakPtr(),
+                          scoped_ptr<ExtensionInstallPrompt>(),
+                          NULL);
+}
+
+// static
 scoped_refptr<CrxInstaller> CrxInstaller::Create(
     ExtensionService* frontend,
-    ExtensionInstallPrompt* client) {
-  return new CrxInstaller(frontend->AsWeakPtr(), client, NULL);
+    scoped_ptr<ExtensionInstallPrompt> client) {
+  return new CrxInstaller(frontend->AsWeakPtr(), client.Pass(), NULL);
 }
 
 // static
 scoped_refptr<CrxInstaller> CrxInstaller::Create(
     ExtensionService* service,
-    ExtensionInstallPrompt* client,
+    scoped_ptr<ExtensionInstallPrompt> client,
     const WebstoreInstaller::Approval* approval) {
-  return new CrxInstaller(service->AsWeakPtr(), client, approval);
+  return new CrxInstaller(service->AsWeakPtr(), client.Pass(), approval);
 }
 
 CrxInstaller::CrxInstaller(
     base::WeakPtr<ExtensionService> service_weak,
-    ExtensionInstallPrompt* client,
+    scoped_ptr<ExtensionInstallPrompt> client,
     const WebstoreInstaller::Approval* approval)
     : install_directory_(service_weak->install_directory()),
       install_source_(Manifest::INTERNAL),
@@ -97,7 +105,8 @@
       delete_source_(false),
       create_app_shortcut_(false),
       service_weak_(service_weak),
-      client_(client),
+      // See header file comment on |client_| for why we use a raw pointer here.
+      client_(client.release()),
       apps_require_extension_mime_type_(false),
       allow_silent_install_(false),
       install_cause_(extension_misc::INSTALL_CAUSE_UNSET),
@@ -560,13 +569,6 @@
     ExtensionService::RecordPermissionMessagesHistogram(
         extension(), histogram_name.c_str());
 
-    // Kill the theme loading bubble.
-    content::NotificationService* service =
-        content::NotificationService::current();
-    service->Notify(chrome::NOTIFICATION_NO_THEME_DETECTED,
-                    content::Source<CrxInstaller>(this),
-                    content::NotificationService::NoDetails());
-
     NotifyCrxInstallComplete(false);
   }
 
diff --git a/chrome/browser/extensions/crx_installer.h b/chrome/browser/extensions/crx_installer.h
index 6f71868..d2bcbbb 100644
--- a/chrome/browser/extensions/crx_installer.h
+++ b/chrome/browser/extensions/crx_installer.h
@@ -76,18 +76,21 @@
     NumOffStoreInstallAllowReasons
   };
 
-  // Extensions will be installed into service->install_directory(),
-  // then registered with |service|. Any install UI will be displayed
-  // using |client|. Pass NULL for |client| for silent install
+  // Extensions will be installed into service->install_directory(), then
+  // registered with |service|. This does a silent install - see below for
+  // other options.
+  static scoped_refptr<CrxInstaller> CreateSilent(ExtensionService* service);
+
+  // Same as above, but use |client| to generate a confirmation prompt.
   static scoped_refptr<CrxInstaller> Create(
       ExtensionService* service,
-      ExtensionInstallPrompt* client);
+      scoped_ptr<ExtensionInstallPrompt> client);
 
   // Same as the previous method, except use the |approval| to bypass the
   // prompt. Note that the caller retains ownership of |approval|.
   static scoped_refptr<CrxInstaller> Create(
       ExtensionService* service,
-      ExtensionInstallPrompt* client,
+      scoped_ptr<ExtensionInstallPrompt> client,
       const WebstoreInstaller::Approval* approval);
 
   // Install the crx in |source_file|.
@@ -199,7 +202,7 @@
   friend class ExtensionCrxInstallerTest;
 
   CrxInstaller(base::WeakPtr<ExtensionService> service_weak,
-               ExtensionInstallPrompt* client,
+               scoped_ptr<ExtensionInstallPrompt> client,
                const WebstoreInstaller::Approval* approval);
   virtual ~CrxInstaller();
 
diff --git a/chrome/browser/extensions/crx_installer_browsertest.cc b/chrome/browser/extensions/crx_installer_browsertest.cc
index 112772f..c288691 100644
--- a/chrome/browser/extensions/crx_installer_browsertest.cc
+++ b/chrome/browser/extensions/crx_installer_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/memory/ref_counted.h"
 #include "chrome/browser/download/download_crx_util.h"
 #include "chrome/browser/extensions/crx_installer.h"
 #include "chrome/browser/extensions/extension_browsertest.h"
@@ -29,19 +30,54 @@
 
 namespace {
 
-// Observer waits for exactly one download to finish.
+class MockInstallPrompt;
+
+// This class holds information about things that happen with a
+// MockInstallPrompt. We create the MockInstallPrompt but need to pass
+// ownership of it to CrxInstaller, so it isn't safe to hang this data on
+// MockInstallPrompt itself becuase we can't guarantee it's lifetime.
+class MockPromptProxy :
+      public base::RefCountedThreadSafe<MockPromptProxy> {
+ public:
+  explicit MockPromptProxy(content::WebContents* web_contents);
+
+  bool did_succeed() const { return !extension_id_.empty(); }
+  const std::string& extension_id() { return extension_id_; }
+  bool confirmation_requested() const { return confirmation_requested_; }
+  const string16& error() const { return error_; }
+
+  // To have any effect, this should be called before CreatePrompt.
+  void set_record_oauth2_grant(bool record_oauth2_grant) {
+    record_oauth2_grant_.reset(new bool(record_oauth2_grant));
+  }
+
+  void set_extension_id(const std::string& id) { extension_id_ = id; }
+  void set_confirmation_requested() { confirmation_requested_ = true; }
+  void set_error(const string16& error) { error_ = error; }
+
+  scoped_ptr<ExtensionInstallPrompt> CreatePrompt();
+
+ private:
+  friend class base::RefCountedThreadSafe<MockPromptProxy>;
+  virtual ~MockPromptProxy();
+
+  // Data used to create a prompt.
+  content::WebContents* web_contents_;
+  scoped_ptr<bool> record_oauth2_grant_;
+
+  // Data reported back to us by the prompt we created.
+  bool confirmation_requested_;
+  std::string extension_id_;
+  string16 error_;
+};
 
 class MockInstallPrompt : public ExtensionInstallPrompt {
  public:
-  explicit MockInstallPrompt(content::WebContents* web_contents) :
+  MockInstallPrompt(content::WebContents* web_contents,
+                    MockPromptProxy* proxy) :
       ExtensionInstallPrompt(web_contents),
-      confirmation_requested_(false),
-      extension_(NULL) {}
+      proxy_(proxy) {}
 
-  bool did_succeed() const { return !!extension_; }
-  const Extension* extension() const { return extension_; }
-  bool confirmation_requested() const { return confirmation_requested_; }
-  const string16& error() const { return error_; }
   void set_record_oauth2_grant(bool record) { record_oauth2_grant_ = record; }
 
   // Overriding some of the ExtensionInstallUI API.
@@ -49,27 +85,43 @@
       Delegate* delegate,
       const Extension* extension,
       const ShowDialogCallback& show_dialog_callback) OVERRIDE {
-    confirmation_requested_ = true;
+    proxy_->set_confirmation_requested();
     delegate->InstallUIProceed();
   }
   virtual void OnInstallSuccess(const Extension* extension,
                                 SkBitmap* icon) OVERRIDE {
-    extension_ = extension;
+    proxy_->set_extension_id(extension->id());
     base::MessageLoopForUI::current()->Quit();
   }
   virtual void OnInstallFailure(const CrxInstallerError& error) OVERRIDE {
-    error_ = error.message();
+    proxy_->set_error(error.message());
     base::MessageLoopForUI::current()->Quit();
   }
 
  private:
-  bool confirmation_requested_;
-  string16 error_;
-  const Extension* extension_;
+  scoped_refptr<MockPromptProxy> proxy_;
 };
 
-MockInstallPrompt* CreateMockInstallPromptForBrowser(Browser* browser) {
-  return new MockInstallPrompt(
+
+MockPromptProxy::MockPromptProxy(content::WebContents* web_contents) :
+    web_contents_(web_contents),
+    confirmation_requested_(false) {
+}
+
+MockPromptProxy::~MockPromptProxy() {}
+
+scoped_ptr<ExtensionInstallPrompt> MockPromptProxy::CreatePrompt() {
+  scoped_ptr<MockInstallPrompt> prompt(
+      new MockInstallPrompt(web_contents_, this));
+  if (record_oauth2_grant_.get())
+    prompt->set_record_oauth2_grant(*record_oauth2_grant_.get());
+  return prompt.PassAs<ExtensionInstallPrompt>();
+}
+
+
+scoped_refptr<MockPromptProxy> CreateMockPromptProxyForBrowser(
+    Browser* browser) {
+  return new MockPromptProxy(
       browser->tab_strip_model()->GetActiveWebContents());
 }
 
@@ -82,7 +134,7 @@
   scoped_refptr<CrxInstaller> InstallWithPrompt(
       const std::string& ext_relpath,
       const std::string& id,
-      MockInstallPrompt* mock_install_prompt) {
+      scoped_refptr<MockPromptProxy> mock_install_prompt) {
     ExtensionService* service = extensions::ExtensionSystem::Get(
         browser()->profile())->extension_service();
     base::FilePath ext_path = test_data_dir_.AppendASCII(ext_relpath);
@@ -103,7 +155,7 @@
 
     scoped_refptr<CrxInstaller> installer(
         CrxInstaller::Create(service,
-                             mock_install_prompt, /* ownership transferred */
+                             mock_install_prompt->CreatePrompt(),
                              approval.get()       /* keep ownership */));
     installer->set_allow_silent_install(true);
     installer->set_is_gallery_install(true);
@@ -124,15 +176,16 @@
     ExtensionService* service = extensions::ExtensionSystem::Get(
         browser()->profile())->extension_service();
 
-    MockInstallPrompt* mock_prompt =
-        CreateMockInstallPromptForBrowser(browser());
+    scoped_refptr<MockPromptProxy> mock_prompt =
+        CreateMockPromptProxyForBrowser(browser());
+
     mock_prompt->set_record_oauth2_grant(record_oauth2_grant);
     scoped_refptr<CrxInstaller> installer =
         InstallWithPrompt("browsertest/scopes", std::string(), mock_prompt);
 
     scoped_refptr<PermissionSet> permissions =
         service->extension_prefs()->GetGrantedPermissions(
-            mock_prompt->extension()->id());
+            mock_prompt->extension_id());
     ASSERT_TRUE(permissions.get());
   }
 
@@ -171,8 +224,8 @@
       browser()->profile())->extension_service();
 
   // Even whitelisted extensions with NPAPI should not prompt.
-  MockInstallPrompt* mock_prompt =
-      CreateMockInstallPromptForBrowser(browser());
+  scoped_refptr<MockPromptProxy> mock_prompt =
+      CreateMockPromptProxyForBrowser(browser());
   scoped_refptr<CrxInstaller> installer =
       InstallWithPrompt("uitest/plugins", id, mock_prompt);
   EXPECT_FALSE(mock_prompt->confirmation_requested());
@@ -225,9 +278,10 @@
   std::string crx_path_string(crx_path.value().begin(), crx_path.value().end());
   GURL url = GURL(std::string("file:///").append(crx_path_string));
 
-  MockInstallPrompt* mock_prompt =
-      CreateMockInstallPromptForBrowser(browser());
-  download_crx_util::SetMockInstallPromptForTesting(mock_prompt);
+  scoped_refptr<MockPromptProxy> mock_prompt =
+      CreateMockPromptProxyForBrowser(browser());
+  download_crx_util::SetMockInstallPromptForTesting(
+      mock_prompt->CreatePrompt());
 
   LOG(ERROR) << "PackAndInstallExtension: Getting download manager";
   content::DownloadManager* download_manager =
@@ -278,10 +332,11 @@
   const bool kTestData[] = {false, true};
 
   for (size_t i = 0; i < arraysize(kTestData); ++i) {
-    MockInstallPrompt* mock_prompt =
-        CreateMockInstallPromptForBrowser(browser());
+    scoped_refptr<MockPromptProxy> mock_prompt =
+        CreateMockPromptProxyForBrowser(browser());
+
     scoped_refptr<CrxInstaller> crx_installer(
-        CrxInstaller::Create(service, mock_prompt));
+        CrxInstaller::Create(service, mock_prompt->CreatePrompt()));
     crx_installer->set_install_cause(
         extension_misc::INSTALL_CAUSE_USER_DOWNLOAD);
 
diff --git a/chrome/browser/extensions/error_console/error_console.cc b/chrome/browser/extensions/error_console/error_console.cc
index 94eedd8..cff063c 100644
--- a/chrome/browser/extensions/error_console/error_console.cc
+++ b/chrome/browser/extensions/error_console/error_console.cc
@@ -4,12 +4,14 @@
 
 #include "chrome/browser/extensions/error_console/error_console.h"
 
-#include <algorithm>
+#include <list>
 
+#include "base/lazy_instance.h"
+#include "base/stl_util.h"
 #include "chrome/browser/chrome_notification_types.h"
-#include "chrome/browser/extensions/error_console/extension_error.h"
 #include "chrome/browser/extensions/extension_system.h"
 #include "chrome/browser/profiles/profile.h"
+#include "chrome/common/extensions/extension.h"
 #include "content/public/browser/notification_details.h"
 #include "content/public/browser/notification_service.h"
 #include "content/public/browser/notification_source.h"
@@ -17,6 +19,29 @@
 
 namespace extensions {
 
+namespace {
+
+const size_t kMaxErrorsPerExtension = 100;
+
+// Iterate through an error list and remove and delete all errors which were
+// from an incognito context.
+void DeleteIncognitoErrorsFromList(ErrorConsole::ErrorList* list) {
+  ErrorConsole::ErrorList::iterator iter = list->begin();
+  while (iter != list->end()) {
+    if ((*iter)->from_incognito()) {
+      delete *iter;
+      iter = list->erase(iter);
+    } else {
+      ++iter;
+    }
+  }
+}
+
+base::LazyInstance<ErrorConsole::ErrorList> g_empty_error_list =
+    LAZY_INSTANCE_INITIALIZER;
+
+}  // namespace
+
 void ErrorConsole::Observer::OnErrorConsoleDestroyed() {
 }
 
@@ -24,10 +49,14 @@
   registrar_.Add(this,
                  chrome::NOTIFICATION_PROFILE_DESTROYED,
                  content::NotificationService::AllBrowserContextsAndSources());
+  registrar_.Add(this,
+                 chrome::NOTIFICATION_EXTENSION_UNINSTALLED,
+                 content::Source<Profile>(profile_));
 }
 
 ErrorConsole::~ErrorConsole() {
   FOR_EACH_OBSERVER(Observer, observers_, OnErrorConsoleDestroyed());
+  RemoveAllErrors();
 }
 
 // static
@@ -35,31 +64,28 @@
   return ExtensionSystem::Get(profile)->error_console();
 }
 
-void ErrorConsole::ReportError(scoped_ptr<ExtensionError> error) {
+void ErrorConsole::ReportError(scoped_ptr<const ExtensionError> scoped_error) {
   DCHECK(thread_checker_.CalledOnValidThread());
-  errors_.push_back(error.release());
-  FOR_EACH_OBSERVER(Observer, observers_, OnErrorAdded(errors_.back()));
-}
 
-ErrorConsole::WeakErrorList ErrorConsole::GetErrorsForExtension(
-    const std::string& extension_id) const {
-  WeakErrorList result;
-  for (ErrorList::const_iterator iter = errors_.begin();
-       iter != errors_.end(); ++iter) {
-    if ((*iter)->extension_id() == extension_id)
-      result.push_back(*iter);
+  const ExtensionError* error = scoped_error.release();
+  // If there are too many errors for an extension already, limit ourselves to
+  // the most recent ones.
+  ErrorList* error_list = &errors_[error->extension_id()];
+  if (error_list->size() >= kMaxErrorsPerExtension) {
+    delete error_list->front();
+    error_list->pop_front();
   }
-  return result;
+  error_list->push_back(error);
+
+  FOR_EACH_OBSERVER(Observer, observers_, OnErrorAdded(error));
 }
 
-void ErrorConsole::RemoveError(const ExtensionError* error) {
-  ErrorList::iterator iter = std::find(errors_.begin(), errors_.end(), error);
-  CHECK(iter != errors_.end());
-  errors_.erase(iter);
-}
-
-void ErrorConsole::RemoveAllErrors() {
-  errors_.clear();
+const ErrorConsole::ErrorList& ErrorConsole::GetErrorsForExtension(
+    const std::string& extension_id) const {
+  ErrorMap::const_iterator iter = errors_.find(extension_id);
+  if (iter != errors_.end())
+    return iter->second;
+  return g_empty_error_list.Get();
 }
 
 void ErrorConsole::AddObserver(Observer* observer) {
@@ -73,19 +99,26 @@
 }
 
 void ErrorConsole::RemoveIncognitoErrors() {
-  WeakErrorList to_remove;
-  for (ErrorList::const_iterator iter = errors_.begin();
+  for (ErrorMap::iterator iter = errors_.begin();
        iter != errors_.end(); ++iter) {
-    if ((*iter)->from_incognito())
-      to_remove.push_back(*iter);
+    DeleteIncognitoErrorsFromList(&(iter->second));
   }
+}
 
-  for (WeakErrorList::const_iterator iter = to_remove.begin();
-       iter != to_remove.end(); ++iter) {
-    RemoveError(*iter);
+void ErrorConsole::RemoveErrorsForExtension(const std::string& extension_id) {
+  ErrorMap::iterator iter = errors_.find(extension_id);
+  if (iter != errors_.end()) {
+    STLDeleteContainerPointers(iter->second.begin(), iter->second.end());
+    errors_.erase(iter);
   }
 }
 
+void ErrorConsole::RemoveAllErrors() {
+  for (ErrorMap::iterator iter = errors_.begin(); iter != errors_.end(); ++iter)
+    STLDeleteContainerPointers(iter->second.begin(), iter->second.end());
+  errors_.clear();
+}
+
 void ErrorConsole::Observe(int type,
                            const content::NotificationSource& source,
                            const content::NotificationDetails& details) {
@@ -98,6 +131,12 @@
         RemoveIncognitoErrors();
       break;
     }
+    case chrome::NOTIFICATION_EXTENSION_UNINSTALLED:
+      // No need to check the profile here, since we registered to only receive
+      // notifications from our own.
+      RemoveErrorsForExtension(
+          content::Details<Extension>(details).ptr()->id());
+      break;
     default:
       NOTREACHED();
   }
diff --git a/chrome/browser/extensions/error_console/error_console.h b/chrome/browser/extensions/error_console/error_console.h
index 80b2f96..c60bda9 100644
--- a/chrome/browser/extensions/error_console/error_console.h
+++ b/chrome/browser/extensions/error_console/error_console.h
@@ -5,16 +5,17 @@
 #ifndef CHROME_BROWSER_EXTENSIONS_ERROR_CONSOLE_ERROR_CONSOLE_H_
 #define CHROME_BROWSER_EXTENSIONS_ERROR_CONSOLE_ERROR_CONSOLE_H_
 
-#include <vector>
+#include <deque>
+#include <map>
 
 #include "base/gtest_prod_util.h"
 #include "base/memory/scoped_ptr.h"
-#include "base/memory/scoped_vector.h"
 #include "base/observer_list.h"
 #include "base/strings/string16.h"
 #include "base/threading/thread_checker.h"
 #include "content/public/browser/notification_observer.h"
 #include "content/public/browser/notification_registrar.h"
+#include "extensions/browser/extension_error.h"
 
 namespace content {
 class NotificationDetails;
@@ -26,17 +27,16 @@
 
 namespace extensions {
 class ErrorConsoleUnitTest;
-class ExtensionError;
 
 // The ErrorConsole is a central object to which all extension errors are
 // reported. This includes errors detected in extensions core, as well as
 // runtime Javascript errors.
 // This class is owned by ExtensionSystem, making it, in effect, a
 // BrowserContext-keyed service.
-class ErrorConsole : content::NotificationObserver {
+class ErrorConsole : public content::NotificationObserver {
  public:
-  typedef ScopedVector<ExtensionError> ErrorList;
-  typedef std::vector<const ExtensionError*> WeakErrorList;
+  typedef std::deque<const ExtensionError*> ErrorList;
+  typedef std::map<std::string, ErrorList> ErrorMap;
 
   class Observer {
    public:
@@ -55,24 +55,18 @@
   static ErrorConsole* Get(Profile* profile);
 
   // Report an extension error, and add it to the list.
-  void ReportError(scoped_ptr<ExtensionError> error);
+  void ReportError(scoped_ptr<const ExtensionError> error);
 
   // Get a collection of weak pointers to all errors relating to the extension
   // with the given |extension_id|.
-  WeakErrorList GetErrorsForExtension(const std::string& extension_id) const;
-
-  // Remove an error from the list of observed errors.
-  void RemoveError(const ExtensionError* error);
-
-  // Remove all errors from the list of observed errors.
-  void RemoveAllErrors();
+  const ErrorList& GetErrorsForExtension(const std::string& extension_id) const;
 
   // Add or remove observers of the ErrorConsole to be notified of any errors
   // added.
   void AddObserver(Observer* observer);
   void RemoveObserver(Observer* observer);
 
-  const ErrorList& errors() { return errors_; }
+  const ErrorMap& errors() { return errors_; }
 
  private:
   FRIEND_TEST_ALL_PREFIXES(ErrorConsoleUnitTest, AddAndRemoveErrors);
@@ -81,6 +75,12 @@
   // the incognito profile is destroyed.
   void RemoveIncognitoErrors();
 
+  // Remove all errors relating to a particular |extension_id|.
+  void RemoveErrorsForExtension(const std::string& extension_id);
+
+  // Remove all errors for all extensions.
+  void RemoveAllErrors();
+
   // content::NotificationObserver implementation.
   virtual void Observe(int type,
                        const content::NotificationSource& source,
@@ -93,7 +93,7 @@
   ObserverList<Observer> observers_;
 
   // The errors which we have received so far.
-  ErrorList errors_;
+  ErrorMap errors_;
 
   // The profile with which the ErrorConsole is associated. Only collect errors
   // from extensions and RenderViews associated with this Profile (and it's
diff --git a/chrome/browser/extensions/error_console/error_console_unittest.cc b/chrome/browser/extensions/error_console/error_console_unittest.cc
index 0d27ff2..62b5320 100644
--- a/chrome/browser/extensions/error_console/error_console_unittest.cc
+++ b/chrome/browser/extensions/error_console/error_console_unittest.cc
@@ -4,12 +4,16 @@
 
 #include "chrome/browser/extensions/error_console/error_console.h"
 
+#include "base/json/json_writer.h"
+#include "base/logging.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/strings/string16.h"
+#include "base/strings/string_number_conversions.h"
 #include "base/strings/utf_string_conversions.h"
-#include "chrome/browser/extensions/error_console/extension_error.h"
 #include "chrome/test/base/testing_profile.h"
-#include "extensions/common/id_util.h"
+#include "content/public/common/url_constants.h"
+#include "extensions/browser/extension_error.h"
+#include "extensions/common/constants.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 using base::string16;
@@ -19,12 +23,32 @@
 
 namespace {
 
-scoped_ptr<ExtensionError> CreateNewManifestError(bool from_incognito) {
-  return scoped_ptr<ExtensionError>(
-      new ManifestParsingError(from_incognito,
-                               UTF8ToUTF16("source"),
-                               UTF8ToUTF16("message"),
-                               0u /* line number */ ));
+const char kExecutionContextURLKey[] = "executionContextURL";
+const char kStackTraceKey[] = "stackTrace";
+
+string16 CreateErrorDetails(const std::string& extension_id) {
+  base::DictionaryValue value;
+  value.SetString(
+      kExecutionContextURLKey,
+      std::string(kExtensionScheme) +
+          content::kStandardSchemeSeparator +
+          extension_id);
+  value.Set(kStackTraceKey, new ListValue);
+  std::string json_utf8;
+  base::JSONWriter::Write(&value, &json_utf8);
+  return UTF8ToUTF16(json_utf8);
+}
+
+scoped_ptr<const ExtensionError> CreateNewRuntimeError(
+    bool from_incognito,
+    const std::string& extension_id,
+    const string16& message) {
+  return scoped_ptr<const ExtensionError>(new JavascriptRuntimeError(
+      from_incognito,
+      UTF8ToUTF16("source"),
+      message,
+      logging::LOG_INFO,
+      CreateErrorDetails(extension_id)));
 }
 
 }  // namespace
@@ -49,26 +73,81 @@
 
   const size_t kNumTotalErrors = 6;
   const size_t kNumNonIncognitoErrors = 3;
+  const char kId[] = "id";
   // Populate with both incognito and non-incognito errors (evenly distributed).
-  for (size_t i = 0; i < kNumTotalErrors; ++i)
-    error_console_->ReportError(CreateNewManifestError(i % 2 == 0));
+  for (size_t i = 0; i < kNumTotalErrors; ++i) {
+    error_console_->ReportError(
+        CreateNewRuntimeError(i % 2 == 0, kId, string16()));
+  }
 
-  ASSERT_EQ(kNumTotalErrors, error_console_->errors().size());
+  // There should only be one entry in the map, since errors are stored in lists
+  // keyed by extension id.
+  ASSERT_EQ(1u, error_console_->errors().size());
+
+  ASSERT_EQ(kNumTotalErrors, error_console_->GetErrorsForExtension(kId).size());
 
   // Remove the incognito errors; three errors should remain, and all should
   // be from non-incognito contexts.
   error_console_->RemoveIncognitoErrors();
-  ASSERT_EQ(kNumNonIncognitoErrors, error_console_->errors().size());
-  for (size_t i = 0; i < error_console_->errors().size(); ++i)
-    ASSERT_FALSE(error_console_->errors()[i]->from_incognito());
+  const ErrorConsole::ErrorList& errors =
+      error_console_->GetErrorsForExtension(kId);
+  ASSERT_EQ(kNumNonIncognitoErrors, errors.size());
+  for (size_t i = 0; i < errors.size(); ++i)
+    ASSERT_FALSE(errors[i]->from_incognito());
 
-  // Remove an error by address.
-  error_console_->RemoveError(error_console_->errors()[1]);
-  ASSERT_EQ(kNumNonIncognitoErrors - 1, error_console_->errors().size());
+  // Add another error for a different extension id.
+  const char kSecondId[] = "id2";
+  error_console_->ReportError(
+      CreateNewRuntimeError(false, kSecondId, string16()));
 
-  // Remove all remaining errors.
+  // There should be two entries now, one for each id, and there should be one
+  // error for the second extension.
+  ASSERT_EQ(2u, error_console_->errors().size());
+  ASSERT_EQ(1u, error_console_->GetErrorsForExtension(kSecondId).size());
+
+  // Remove all errors for the second id.
+  error_console_->RemoveErrorsForExtension(kSecondId);
+  ASSERT_EQ(1u, error_console_->errors().size());
+  ASSERT_EQ(0u, error_console_->GetErrorsForExtension(kSecondId).size());
+  // First extension should be unaffected.
+  ASSERT_EQ(kNumNonIncognitoErrors,
+            error_console_->GetErrorsForExtension(kId).size());
+
+  // Remove remaining errors.
   error_console_->RemoveAllErrors();
   ASSERT_EQ(0u, error_console_->errors().size());
+  ASSERT_EQ(0u, error_console_->GetErrorsForExtension(kId).size());
+}
+
+// Test that if we add enough errors, only the most recent
+// kMaxErrorsPerExtension are kept.
+TEST_F(ErrorConsoleUnitTest, ExcessiveErrorsGetCropped) {
+  ASSERT_EQ(0u, error_console_->errors().size());
+
+  // This constant matches one of the same name in error_console.cc.
+  const size_t kMaxErrorsPerExtension = 100;
+  const size_t kNumExtraErrors = 5;
+  const char kId[] = "id";
+
+  // Add new errors, with each error's message set to its number.
+  for (size_t i = 0; i < kMaxErrorsPerExtension + kNumExtraErrors; ++i) {
+    error_console_->ReportError(
+        CreateNewRuntimeError(false, kId, base::UintToString16(i)));
+  }
+
+  ASSERT_EQ(1u, error_console_->errors().size());
+
+  const ErrorConsole::ErrorList& errors =
+      error_console_->GetErrorsForExtension(kId);
+  ASSERT_EQ(kMaxErrorsPerExtension, errors.size());
+
+  // We should have popped off errors in the order they arrived, so the
+  // first stored error should be the 6th reported (zero-based)...
+  ASSERT_EQ(errors.front()->message(),
+            base::UintToString16(kNumExtraErrors));
+  // ..and the last stored should be the 105th reported.
+  ASSERT_EQ(errors.back()->message(),
+            base::UintToString16(kMaxErrorsPerExtension + kNumExtraErrors - 1));
 }
 
 }  // namespace extensions
diff --git a/chrome/browser/extensions/extension_bindings_apitest.cc b/chrome/browser/extensions/extension_bindings_apitest.cc
index 1eb5f90..61b5799 100644
--- a/chrome/browser/extensions/extension_bindings_apitest.cc
+++ b/chrome/browser/extensions/extension_bindings_apitest.cc
@@ -9,11 +9,18 @@
 #include "chrome/browser/extensions/extension_host.h"
 #include "chrome/browser/extensions/extension_process_manager.h"
 #include "chrome/browser/extensions/extension_system.h"
+#include "chrome/browser/extensions/extension_test_message_listener.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/test/base/ui_test_utils.h"
 #include "content/public/test/browser_test_utils.h"
 
-IN_PROC_BROWSER_TEST_F(ExtensionApiTest, ExceptionInHandlerShouldNotCrash) {
+namespace extensions {
+namespace {
+
+class ExtensionBindingsApiTest : public ExtensionApiTest {};
+
+IN_PROC_BROWSER_TEST_F(ExtensionBindingsApiTest,
+                       ExceptionInHandlerShouldNotCrash) {
   ASSERT_TRUE(RunExtensionSubtest(
       "bindings/exception_in_handler_should_not_crash",
       "page.html")) << message_;
@@ -21,6 +28,7 @@
 
 // Tests that an error raised during an async function still fires
 // the callback, but sets chrome.runtime.lastError.
+// FIXME should be in ExtensionBindingsApiTest.
 IN_PROC_BROWSER_TEST_F(ExtensionBrowserTest, LastError) {
   ASSERT_TRUE(LoadExtension(
       test_data_dir_.AppendASCII("browsertest").AppendASCII("last_error")));
@@ -36,8 +44,38 @@
   EXPECT_TRUE(result);
 }
 
-IN_PROC_BROWSER_TEST_F(ExtensionApiTest, InternalAPIsNotOnChromeObject) {
+// Regression test that we don't delete our own bindings with about:blank
+// iframes.
+IN_PROC_BROWSER_TEST_F(ExtensionBindingsApiTest, AboutBlankIframe) {
+  ResultCatcher catcher;
+  ExtensionTestMessageListener listener("load", true);
+
+  ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII("bindings")
+                                          .AppendASCII("about_blank_iframe")));
+
+  ASSERT_TRUE(listener.WaitUntilSatisfied());
+
+  const Extension* extension = LoadExtension(
+        test_data_dir_.AppendASCII("bindings")
+                      .AppendASCII("internal_apis_not_on_chrome_object"));
+  ASSERT_TRUE(extension);
+  listener.Reply(extension->id());
+
+  ASSERT_TRUE(catcher.GetNextResult()) << message_;
+}
+
+IN_PROC_BROWSER_TEST_F(ExtensionBindingsApiTest,
+                       InternalAPIsNotOnChromeObject) {
   ASSERT_TRUE(RunExtensionSubtest(
       "bindings/internal_apis_not_on_chrome_object",
       "page.html")) << message_;
 }
+
+// Tests that we don't override events when bindings are re-injected.
+// Regression test for http://crbug.com/269149.
+IN_PROC_BROWSER_TEST_F(ExtensionBindingsApiTest, EventOverriding) {
+  ASSERT_TRUE(RunExtensionTest("bindings/event_overriding")) << message_;
+}
+
+}  // namespace
+}  // namespace extensions
diff --git a/chrome/browser/extensions/extension_browsertest.cc b/chrome/browser/extensions/extension_browsertest.cc
index 05e426c..2ebf2dc 100644
--- a/chrome/browser/extensions/extension_browsertest.cc
+++ b/chrome/browser/extensions/extension_browsertest.cc
@@ -406,15 +406,15 @@
   size_t num_before = service->extensions()->size();
 
   {
-    ExtensionInstallPrompt* install_ui = NULL;
+    scoped_ptr<ExtensionInstallPrompt> install_ui;
     if (ui_type == INSTALL_UI_TYPE_CANCEL) {
-      install_ui = new MockAbortExtensionInstallPrompt();
+      install_ui.reset(new MockAbortExtensionInstallPrompt());
     } else if (ui_type == INSTALL_UI_TYPE_NORMAL) {
-      install_ui = new ExtensionInstallPrompt(
-          browser->tab_strip_model()->GetActiveWebContents());
+      install_ui.reset(new ExtensionInstallPrompt(
+          browser->tab_strip_model()->GetActiveWebContents()));
     } else if (ui_type == INSTALL_UI_TYPE_AUTO_CONFIRM) {
-      install_ui = new MockAutoConfirmExtensionInstallPrompt(
-          browser->tab_strip_model()->GetActiveWebContents());
+      install_ui.reset(new MockAutoConfirmExtensionInstallPrompt(
+          browser->tab_strip_model()->GetActiveWebContents()));
     }
 
     // TODO(tessamac): Update callers to always pass an unpacked extension
@@ -427,7 +427,7 @@
       return NULL;
 
     scoped_refptr<extensions::CrxInstaller> installer(
-        extensions::CrxInstaller::Create(service, install_ui));
+        extensions::CrxInstaller::Create(service, install_ui.Pass()));
     installer->set_expected_id(id);
     installer->set_is_gallery_install(from_webstore);
     installer->set_install_source(install_source);
@@ -534,6 +534,8 @@
   content::NotificationRegistrar registrar;
   registrar.Add(this, content::NOTIFICATION_LOAD_STOP,
                 content::NotificationService::AllSources());
+  registrar.Add(this, content::NOTIFICATION_WEB_CONTENTS_DESTROYED,
+                content::NotificationService::AllSources());
 
   ExtensionProcessManager* manager =
       extensions::ExtensionSystem::Get(profile())->process_manager();
@@ -751,7 +753,8 @@
     }
 
     case content::NOTIFICATION_LOAD_STOP:
-      VLOG(1) << "Got LOAD_STOP notification.";
+    case content::NOTIFICATION_WEB_CONTENTS_DESTROYED:
+      VLOG(1) << "Got LOAD_STOP or WEB_CONTENTS_DESTROYED notification.";
       base::MessageLoopForUI::current()->Quit();
       break;
 
diff --git a/chrome/browser/extensions/extension_browsertest.h b/chrome/browser/extensions/extension_browsertest.h
index 2640696..cc715e7 100644
--- a/chrome/browser/extensions/extension_browsertest.h
+++ b/chrome/browser/extensions/extension_browsertest.h
@@ -16,7 +16,7 @@
 #include "chrome/browser/ui/browser.h"
 #include "chrome/common/extensions/extension.h"
 #include "chrome/common/extensions/feature_switch.h"
-#include "chrome/common/extensions/features/feature.h"
+#include "chrome/common/extensions/features/feature_channel.h"
 #include "chrome/common/extensions/manifest.h"
 #include "chrome/test/base/in_process_browser_test.h"
 #include "content/public/browser/notification_details.h"
@@ -297,7 +297,7 @@
   int target_visible_page_action_count_;
 
   // Make the current channel "dev" for the duration of the test.
-  extensions::Feature::ScopedCurrentChannel current_channel_;
+  extensions::ScopedCurrentChannel current_channel_;
 
   // Disable external install UI.
   extensions::FeatureSwitch::ScopedOverride
diff --git a/chrome/browser/extensions/extension_function_histogram_value.h b/chrome/browser/extensions/extension_function_histogram_value.h
index 3408bd6..1defcb8 100644
--- a/chrome/browser/extensions/extension_function_histogram_value.h
+++ b/chrome/browser/extensions/extension_function_histogram_value.h
@@ -574,10 +574,10 @@
   FILEBROWSERPRIVATE_GETSHAREURL,
   SYSTEM_STORAGE_GETINFO,
   SYSTEM_STORAGE_EJECTDEVICE,
-  SYSTEM_STORAGE_ADDAVAILABLECAPACITYWATCH,
-  SYSTEM_STORAGE_REMOVEAVAILABLECAPACITYWATCH,
-  SYSTEM_STORAGE_GETALLAVAILABLECAPACITYWATCHES,
-  SYSTEM_STORAGE_REMOVEALLAVAILABLECAPACITYWATCHES,
+  DELETED_SYSTEM_STORAGE_ADDAVAILABLECAPACITYWATCH,
+  DELETED_SYSTEM_STORAGE_REMOVEAVAILABLECAPACITYWATCH,
+  DELETED_SYSTEM_STORAGE_GETALLAVAILABLECAPACITYWATCHES,
+  DELETED_SYSTEM_STORAGE_REMOVEALLAVAILABLECAPACITYWATCHES,
   DOWNLOADS_REMOVEFILE,
   DOWNLOADS_SHOWDEFAULTFOLDER,
   INFOBARS_SHOW,
@@ -588,6 +588,8 @@
   RECOVERYPRIVATE_DESTROYPARTITIONS,
   FEEDBACKPRIVATE_GETSTRINGS,
   LOGPRIVATE_GETHISTORICAL,
+  EXPERIMENTAL_INPUT_VIRTUALKEYBOARD_MOVECURSOR,
+  METRICSPRIVATE_GETVARIATIONPARAMS,
   ENUM_BOUNDARY // Last entry: Add new entries above.
 };
 
diff --git a/chrome/browser/extensions/extension_functional_browsertest.cc b/chrome/browser/extensions/extension_functional_browsertest.cc
index 25ceba5..38a8650 100644
--- a/chrome/browser/extensions/extension_functional_browsertest.cc
+++ b/chrome/browser/extensions/extension_functional_browsertest.cc
@@ -27,7 +27,7 @@
         content::NotificationService::AllSources());
 
     scoped_refptr<extensions::CrxInstaller> installer(
-        extensions::CrxInstaller::Create(service, NULL));
+        extensions::CrxInstaller::CreateSilent(service));
     installer->set_is_gallery_install(false);
     installer->set_allow_silent_install(true);
     installer->set_install_source(Manifest::INTERNAL);
diff --git a/chrome/browser/extensions/extension_messages_apitest.cc b/chrome/browser/extensions/extension_messages_apitest.cc
index 466ca2f..7726d6e 100644
--- a/chrome/browser/extensions/extension_messages_apitest.cc
+++ b/chrome/browser/extensions/extension_messages_apitest.cc
@@ -342,10 +342,8 @@
   EXPECT_EQ(COULD_NOT_ESTABLISH_CONNECTION_ERROR,
             CanConnectAndSendMessages(not_connectable->id()));
 
-  // Unloading the extension is the same as it never existing - so the bindings
-  // will no longer exist.
   DisableExtension(chromium_connectable->id());
-  EXPECT_EQ(NAMESPACE_NOT_DEFINED,
+  EXPECT_EQ(COULD_NOT_ESTABLISH_CONNECTION_ERROR,
             CanConnectAndSendMessages(chromium_connectable->id()));
 
   EnableExtension(chromium_connectable->id());
diff --git a/chrome/browser/extensions/extension_service.cc b/chrome/browser/extensions/extension_service.cc
index 4deba6c..325bea2 100644
--- a/chrome/browser/extensions/extension_service.cc
+++ b/chrome/browser/extensions/extension_service.cc
@@ -59,7 +59,6 @@
 #include "chrome/browser/extensions/management_policy.h"
 #include "chrome/browser/extensions/pending_extension_manager.h"
 #include "chrome/browser/extensions/permissions_updater.h"
-#include "chrome/browser/extensions/shell_window_registry.h"
 #include "chrome/browser/extensions/unpacked_installer.h"
 #include "chrome/browser/extensions/update_observer.h"
 #include "chrome/browser/extensions/updater/extension_updater.h"
@@ -80,7 +79,7 @@
 #include "chrome/common/extensions/extension_manifest_constants.h"
 #include "chrome/common/extensions/extension_messages.h"
 #include "chrome/common/extensions/feature_switch.h"
-#include "chrome/common/extensions/features/feature.h"
+#include "chrome/common/extensions/features/feature_channel.h"
 #include "chrome/common/extensions/incognito_handler.h"
 #include "chrome/common/extensions/manifest.h"
 #include "chrome/common/extensions/manifest_handlers/app_isolation_info.h"
@@ -627,11 +626,12 @@
 
   // We want a silent install only for non-pending extensions and
   // pending extensions that have install_silently set.
-  ExtensionInstallPrompt* client = NULL;
+  scoped_ptr<ExtensionInstallPrompt> client;
   if (pending_extension_info && !pending_extension_info->install_silently())
-    client = ExtensionInstallUI::CreateInstallPromptWithProfile(profile_);
+    client.reset(ExtensionInstallUI::CreateInstallPromptWithProfile(profile_));
 
-  scoped_refptr<CrxInstaller> installer(CrxInstaller::Create(this, client));
+  scoped_refptr<CrxInstaller> installer(
+      CrxInstaller::Create(this, client.Pass()));
   installer->set_expected_id(id);
   if (pending_extension_info) {
     installer->set_install_source(pending_extension_info->install_source());
@@ -2035,13 +2035,17 @@
   }
 
   bool is_extension_upgrade = false;
-  if (const Extension* old = GetInstalledExtension(extension->id())) {
-    is_extension_upgrade = true;
-    DCHECK_NE(extension, old);
+  bool is_extension_installed = false;
+  const Extension* old = GetInstalledExtension(extension->id());
+  if (old) {
+    is_extension_installed = true;
+    int version_compare_result =
+        extension->version()->CompareTo(*(old->version()));
+    is_extension_upgrade = version_compare_result > 0;
     // Other than for unpacked extensions, CrxInstaller should have guaranteed
     // that we aren't downgrading.
     if (!Manifest::IsUnpackedLocation(extension->location()))
-      CHECK_GE(extension->version()->CompareTo(*(old->version())), 0);
+      CHECK_GE(version_compare_result, 0);
   }
   SetBeingUpgraded(extension, is_extension_upgrade);
 
@@ -2056,9 +2060,9 @@
 
   // Check if the extension's privileges have changed and mark the
   // extension disabled if necessary.
-  CheckPermissionsIncrease(extension, is_extension_upgrade);
+  CheckPermissionsIncrease(extension, is_extension_installed);
 
-  if (is_extension_upgrade && !reloading) {
+  if (is_extension_installed && !reloading) {
     // To upgrade an extension in place, unload the old one and then load the
     // new one.  ReloadExtension disables the extension, which is sufficient.
     UnloadExtension(extension->id(), extension_misc::UNLOAD_REASON_UPDATE);
@@ -2161,7 +2165,7 @@
 }
 
 void ExtensionService::CheckPermissionsIncrease(const Extension* extension,
-                                                bool is_extension_upgrade) {
+                                                bool is_extension_installed) {
   UpdateActivePermissions(extension);
 
   // We keep track of all permissions the user has granted each extension.
@@ -2188,7 +2192,7 @@
   int disable_reasons = extension_prefs_->GetDisableReasons(extension->id());
 
   bool auto_grant_permission =
-      (!is_extension_upgrade && extension->was_installed_by_default()) ||
+      (!is_extension_installed && extension->was_installed_by_default()) ||
       chrome::IsRunningInForcedAppMode();
   // Silently grant all active permissions to default apps only on install.
   // After install they should behave like other apps.
@@ -2216,7 +2220,7 @@
         extension->GetActivePermissions().get(), extension->GetType());
   }
 
-  if (is_extension_upgrade) {
+  if (is_extension_installed) {
     // If the extension was already disabled, suppress any alerts for becoming
     // disabled on permissions increase.
     bool previously_disabled =
@@ -2725,7 +2729,7 @@
   }
 
   // no client (silent install)
-  scoped_refptr<CrxInstaller> installer(CrxInstaller::Create(this, NULL));
+  scoped_refptr<CrxInstaller> installer(CrxInstaller::CreateSilent(this));
   installer->set_install_source(location);
   installer->set_expected_id(id);
   installer->set_expected_version(*version);
@@ -2815,7 +2819,7 @@
 
       // Extensions need to know the channel for API restrictions.
       process->Send(new ExtensionMsg_SetChannel(
-          extensions::Feature::GetCurrentChannel()));
+          extensions::GetCurrentChannel()));
 
       // Platform apps need to know the system font.
       scoped_ptr<base::DictionaryValue> fonts(new base::DictionaryValue);
diff --git a/chrome/browser/extensions/extension_service.h b/chrome/browser/extensions/extension_service.h
index 8932576..d6a837b 100644
--- a/chrome/browser/extensions/extension_service.h
+++ b/chrome/browser/extensions/extension_service.h
@@ -766,7 +766,7 @@
   // Disables the extension if the privilege level has increased
   // (e.g., due to an upgrade).
   void CheckPermissionsIncrease(const extensions::Extension* extension,
-                                bool is_upgrade);
+                                bool is_extension_installed);
 
   // Helper that updates the active extension list used for crash reporting.
   void UpdateActiveExtensionsInCrashReporter();
diff --git a/chrome/browser/extensions/extension_service_unittest.cc b/chrome/browser/extensions/extension_service_unittest.cc
index bf6c949..c0d461e 100644
--- a/chrome/browser/extensions/extension_service_unittest.cc
+++ b/chrome/browser/extensions/extension_service_unittest.cc
@@ -91,7 +91,6 @@
 #include "content/public/browser/render_process_host.h"
 #include "content/public/browser/storage_partition.h"
 #include "content/public/common/content_constants.h"
-#include "content/public/test/test_browser_thread.h"
 #include "content/public/test/test_utils.h"
 #include "extensions/common/constants.h"
 #include "extensions/common/extension_resource.h"
@@ -440,15 +439,10 @@
 
 // Our message loop may be used in tests which require it to be an IO loop.
 ExtensionServiceTestBase::ExtensionServiceTestBase()
-    : loop_(base::MessageLoop::TYPE_IO),
+    : thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP),
       service_(NULL),
       management_policy_(NULL),
-      expected_extensions_count_(0),
-      ui_thread_(BrowserThread::UI, &loop_),
-      db_thread_(BrowserThread::DB, &loop_),
-      file_thread_(BrowserThread::FILE, &loop_),
-      file_user_blocking_thread_(BrowserThread::FILE_USER_BLOCKING, &loop_),
-      io_thread_(BrowserThread::IO, &loop_) {
+      expected_extensions_count_(0) {
   base::FilePath test_data_dir;
   if (!PathService::Get(chrome::DIR_TEST_DATA, &test_data_dir)) {
     ADD_FAILURE();
@@ -458,13 +452,7 @@
 }
 
 ExtensionServiceTestBase::~ExtensionServiceTestBase() {
-  // Drop our reference to ExtensionService and TestingProfile, so that they
-  // can be destroyed while BrowserThreads and MessageLoop are still around
-  // (they are used in the destruction process).
   service_ = NULL;
-  base::MessageLoop::current()->RunUntilIdle();
-  profile_.reset(NULL);
-  base::MessageLoop::current()->RunUntilIdle();
 }
 
 void ExtensionServiceTestBase::InitializeExtensionService(
@@ -476,7 +464,7 @@
   // TestingPrefServiceSyncable instance.
   if (!params.pref_file.empty()) {
     builder.WithUserFilePrefs(params.pref_file,
-                              loop_.message_loop_proxy().get());
+                              base::MessageLoopProxy::current().get());
     scoped_refptr<user_prefs::PrefRegistrySyncable> registry(
         new user_prefs::PrefRegistrySyncable);
     scoped_ptr<PrefServiceSyncable> prefs(
@@ -500,7 +488,8 @@
       CommandLine::ForCurrentProcess(),
       params.extensions_install_dir,
       params.autoupdate_enabled);
-  service_->SetFileTaskRunnerForTesting(loop_.message_loop_proxy().get());
+  service_->SetFileTaskRunnerForTesting(
+      base::MessageLoopProxy::current().get());
   service_->set_extensions_enabled(true);
   service_->set_show_extensions_prompts(false);
   service_->set_install_updates_when_idle_for_test(false);
@@ -694,8 +683,8 @@
   }
 
   // Create a CrxInstaller and start installation. To allow the install
-  // to happen, use loop_.RunUntilIdle();. Most tests will not use this
-  // method directly.  Instead, use InstallCrx(), which waits for
+  // to happen, use base::RunLoop().RunUntilIdle();. Most tests will not use
+  // this method directly.  Instead, use InstallCrx(), which waits for
   // the crx to be installed and does extra error checking.
   void StartCRXInstall(const base::FilePath& crx_path) {
     StartCRXInstall(crx_path, Extension::NO_FLAGS);
@@ -704,7 +693,7 @@
   void StartCRXInstall(const base::FilePath& crx_path, int creation_flags) {
     ASSERT_TRUE(base::PathExists(crx_path))
         << "Path does not exist: "<< crx_path.value().c_str();
-    scoped_refptr<CrxInstaller> installer(CrxInstaller::Create(service_, NULL));
+    scoped_refptr<CrxInstaller> installer(CrxInstaller::CreateSilent(service_));
     installer->set_creation_flags(creation_flags);
     if (!(creation_flags & Extension::WAS_INSTALLED_BY_DEFAULT)) {
       installer->set_allow_silent_install(true);
@@ -790,7 +779,7 @@
     EXPECT_TRUE(base::PathExists(crx_path))
         << "Path does not exist: "<< crx_path.value().c_str();
     // no client (silent install)
-    scoped_refptr<CrxInstaller> installer(CrxInstaller::Create(service_, NULL));
+    scoped_refptr<CrxInstaller> installer(CrxInstaller::CreateSilent(service_));
     installer->set_install_source(install_location);
     installer->InstallCrx(crx_path);
 
@@ -911,7 +900,7 @@
           chrome::NOTIFICATION_CRX_INSTALLER_DONE,
           content::Source<extensions::CrxInstaller>(installer)).Wait();
     } else {
-      loop_.RunUntilIdle();
+      base::RunLoop().RunUntilIdle();
     }
 
     std::vector<string16> errors = GetErrors();
@@ -994,7 +983,7 @@
 
     // The extension should not be in the service anymore.
     EXPECT_FALSE(service_->GetInstalledExtension(id));
-    loop_.RunUntilIdle();
+    base::RunLoop().RunUntilIdle();
 
     // The directory should be gone.
     EXPECT_FALSE(base::PathExists(extension_path));
@@ -1399,7 +1388,7 @@
   // be called, call it manually instead.
   service_->GarbageCollectExtensions();
   // Wait for GarbageCollectExtensions task to complete.
-  loop_.RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
 
   base::FileEnumerator dirs(extensions_install_dir_, false,
                             base::FileEnumerator::DIRECTORIES);
@@ -1437,7 +1426,7 @@
 
   service_->GarbageCollectExtensions();
   // Wait for GarbageCollectExtensions task to complete.
-  loop_.RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
 
   // Verify that the pending update for the first extension didn't get
   // deleted.
@@ -1475,7 +1464,7 @@
   // be called, call it manually instead.
   service_->GarbageCollectExtensions();
   // Wait for GarbageCollectExtensions task to complete.
-  loop_.RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
 
   // Verify that the pending update for the first extension got installed.
   EXPECT_FALSE(base::PathExists(extensions_install_dir_.AppendASCII(
@@ -1511,7 +1500,7 @@
 
   service_->Init();
   // Wait for GarbageCollectExtensions task to complete.
-  loop_.RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
 
   // These extensions are used by the extensions we test below, they must be
   // installed.
@@ -1751,7 +1740,7 @@
   service_->OnExternalExtensionFileFound(good_crx, &version,
                                          path, Manifest::EXTERNAL_PREF,
                                          Extension::NO_FLAGS, false);
-  loop_.RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
   ASSERT_TRUE(NULL == service_->GetExtensionById(good_crx, false));
   ValidateIntegerPref(good_crx, "location",
                       Extension::EXTERNAL_EXTENSION_UNINSTALLED);
@@ -1762,7 +1751,7 @@
   service_->OnExternalExtensionFileFound(good_crx, &version,
                                          path, Manifest::EXTERNAL_PREF,
                                          Extension::NO_FLAGS, false);
-  loop_.RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
   ASSERT_TRUE(NULL == service_->GetExtensionById(good_crx, false));
   ValidateIntegerPref(good_crx, "location",
                       Extension::EXTERNAL_EXTENSION_UNINSTALLED);
@@ -1879,13 +1868,13 @@
              .AppendASCII("user_script_basic.user.js");
 
   ASSERT_TRUE(base::PathExists(path));
-  scoped_refptr<CrxInstaller> installer(CrxInstaller::Create(service_, NULL));
+  scoped_refptr<CrxInstaller> installer(CrxInstaller::CreateSilent(service_));
   installer->set_allow_silent_install(true);
   installer->InstallUserScript(
       path,
       GURL("http://www.aaronboodman.com/scripts/user_script_basic.user.js"));
 
-  loop_.RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
   std::vector<string16> errors = GetErrors();
   EXPECT_TRUE(installed_) << "Nothing was installed.";
   EXPECT_FALSE(was_update_) << path.value();
@@ -1909,10 +1898,10 @@
   service_->set_browser_terminating_for_test(true);
 
   base::FilePath path = data_dir_.AppendASCII("good.crx");
-  scoped_refptr<CrxInstaller> installer(CrxInstaller::Create(service_, NULL));
+  scoped_refptr<CrxInstaller> installer(CrxInstaller::CreateSilent(service_));
   installer->set_allow_silent_install(true);
   installer->InstallCrx(path);
-  loop_.RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
 
   EXPECT_FALSE(installed_) << "Extension installed during shutdown.";
   ASSERT_EQ(0u, loaded_.size()) << "Extension loaded during shutdown.";
@@ -2402,7 +2391,7 @@
       .AppendASCII("theme_i18n");
 
   extensions::UnpackedInstaller::Create(service_)->Load(extension_path);
-  loop_.RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
   EXPECT_EQ(0u, GetErrors().size());
   ASSERT_EQ(1u, loaded_.size());
   EXPECT_EQ(1u, service_->extensions()->size());
@@ -2444,7 +2433,7 @@
   base::CopyFile(manifest_no_key, manifest_path);
   extensions::UnpackedInstaller::Create(service_)->Load(extension_path);
 
-  loop_.RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
   EXPECT_EQ(0u, GetErrors().size());
   ASSERT_EQ(1u, loaded_.size());
   EXPECT_EQ(1u, service_->extensions()->size());
@@ -2488,7 +2477,7 @@
   // Load extension.
   InitializeEmptyExtensionService();
   extensions::UnpackedInstaller::Create(service_)->Load(extension_path);
-  loop_.RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
 
   EXPECT_TRUE(GetErrors().empty());
   ASSERT_EQ(1u, loaded_.size());
@@ -2831,7 +2820,7 @@
 
   base::FilePath path = data_dir_.AppendASCII("good.crx");
   UpdateExtension(good_crx, path, UPDATED);
-  loop_.RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
 
   ASSERT_EQ(0u, service_->extensions()->size());
   ASSERT_FALSE(installed_);
@@ -2936,7 +2925,7 @@
   ASSERT_TRUE(serializer.Serialize(manifest));
 
   extensions::UnpackedInstaller::Create(service_)->Load(extension_path);
-  loop_.RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
 
   EXPECT_EQ(0u, GetErrors().size());
   ASSERT_EQ(1u, loaded_.size());
@@ -2950,7 +2939,7 @@
   ASSERT_TRUE(serializer.Serialize(manifest));
 
   extensions::UnpackedInstaller::Create(service_)->Load(extension_path);
-  loop_.RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
 
   EXPECT_EQ(0u, GetErrors().size());
   ASSERT_EQ(1u, loaded_.size());
@@ -2986,7 +2975,7 @@
   // The extension that has a plugin should not install.
   extensions::UnpackedInstaller::Create(service_)->Load(
       extension_with_plugin_path);
-  loop_.RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
   EXPECT_EQ(0u, GetErrors().size());
   EXPECT_EQ(0u, loaded_.size());
   EXPECT_EQ(0u, service_->extensions()->size());
@@ -2996,7 +2985,7 @@
   ExtensionErrorReporter::GetInstance()->ClearErrors();
   extensions::UnpackedInstaller::Create(service_)->Load(
       extension_no_plugin_path);
-  loop_.RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
   EXPECT_EQ(0u, GetErrors().size());
   EXPECT_EQ(1u, loaded_.size());
   EXPECT_EQ(1u, service_->extensions()->size());
@@ -3011,7 +3000,7 @@
   ExtensionErrorReporter::GetInstance()->ClearErrors();
   extensions::UnpackedInstaller::Create(service_)->Load(
       extension_with_plugin_path);
-  loop_.RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
   EXPECT_EQ(0u, GetErrors().size());
   EXPECT_EQ(2u, loaded_.size());
   EXPECT_EQ(2u, service_->extensions()->size());
@@ -3034,7 +3023,7 @@
       "cancel");
 
   service_->ReloadExtension(good1);
-  loop_.RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
   EXPECT_EQ(1u, loaded_.size());
   EXPECT_EQ(2u, service_->extensions()->size());
   EXPECT_EQ(0u, service_->disabled_extensions()->size());
@@ -3277,7 +3266,7 @@
                                                                     "v1");
 
   // Make sure pref is updated
-  loop_.RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
 
   // blacklist is set for good0,1,2
   ValidateBooleanPref(good0, "blacklist", true);
@@ -3314,7 +3303,7 @@
                                                                      "v1");
 
   // Make sure pref is updated
-  loop_.RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
 
   // Now, the good_crx is blacklisted.
   ValidateBooleanPref(good_crx, "blacklist", true);
@@ -3326,7 +3315,7 @@
                                                                      "v2");
 
   // Make sure pref is updated
-  loop_.RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
   // blacklist value should not be set for good_crx
   EXPECT_FALSE(IsPrefExist(good_crx, "blacklist"));
 }
@@ -3375,7 +3364,7 @@
                                                                     "v1");
 
   // Make sure pref is updated
-  loop_.RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
 
   // The good_crx is blacklisted and the whitelist doesn't negate it.
   ValidateBooleanPref(good_crx, "blacklist", true);
@@ -3401,7 +3390,7 @@
                                                                     "v1");
 
   // Make sure pref is updated
-  loop_.RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
 
   ValidateBooleanPref(good1, "blacklist", true);
 
@@ -3471,7 +3460,7 @@
   }
 
   // Extension should not be running now.
-  loop_.RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
   EXPECT_EQ(0u, service_->extensions()->size());
 }
 
@@ -3515,7 +3504,7 @@
     ListValue* blacklist = update.Get();
     blacklist->Append(Value::CreateStringValue(good0));
   }
-  loop_.RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
   ASSERT_EQ(1u, service_->extensions()->size());
   EXPECT_TRUE(service_->GetExtensionById(good0, false));
 }
@@ -3564,7 +3553,7 @@
     ListValue* blacklist = update.Get();
     blacklist->Append(Value::CreateStringValue(good0));
   }
-  loop_.RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
   ASSERT_EQ(1u, service_->extensions()->size());
   EXPECT_TRUE(service_->GetExtensionById(good_crx, false));
 }
@@ -3907,7 +3896,7 @@
       .AppendASCII(extension_id)
       .AppendASCII("1.0.0.0");
   extensions::UnpackedInstaller::Create(service_)->Load(ext);
-  loop_.RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
 
   EXPECT_EQ(1u, service_->extensions()->size());
   EXPECT_EQ(0u, service_->disabled_extensions()->size());
@@ -3924,7 +3913,7 @@
   service_->ReloadExtension(extension_id);
 
   // Finish reloading
-  loop_.RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
 
   // Extension should be enabled again.
   EXPECT_EQ(1u, service_->extensions()->size());
@@ -4062,7 +4051,7 @@
   base::FilePath path = data_dir_.AppendASCII("requirements")
                            .AppendASCII("v2_bad_requirements");
   extensions::UnpackedInstaller::Create(service_)->Load(path);
-  loop_.RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
   EXPECT_EQ(1u, GetErrors().size());
   EXPECT_EQ(0u, service_->extensions()->size());
 }
@@ -4112,14 +4101,14 @@
        ext_url, "dummy=value", options,
        base::Bind(&ExtensionCookieCallback::SetCookieCallback,
                   base::Unretained(&callback)));
-  loop_.RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
   EXPECT_TRUE(callback.result_);
 
   cookie_monster->GetAllCookiesForURLAsync(
       ext_url,
       base::Bind(&ExtensionCookieCallback::GetAllCookiesCallback,
                  base::Unretained(&callback)));
-  loop_.RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
   EXPECT_EQ(1U, callback.list_.size());
 
   // Open a database.
@@ -4160,14 +4149,14 @@
 
   // Uninstall the extension.
   service_->UninstallExtension(good_crx, false, NULL);
-  loop_.RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
 
   // Check that the cookie is gone.
   cookie_monster->GetAllCookiesForURLAsync(
        ext_url,
        base::Bind(&ExtensionCookieCallback::GetAllCookiesCallback,
                   base::Unretained(&callback)));
-  loop_.RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
   EXPECT_EQ(0U, callback.list_.size());
 
   // The database should have vanished as well.
@@ -4228,14 +4217,14 @@
        origin1, "dummy=value", options,
        base::Bind(&ExtensionCookieCallback::SetCookieCallback,
                   base::Unretained(&callback)));
-  loop_.RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
   EXPECT_TRUE(callback.result_);
 
   cookie_monster->GetAllCookiesForURLAsync(
       origin1,
       base::Bind(&ExtensionCookieCallback::GetAllCookiesCallback,
                  base::Unretained(&callback)));
-  loop_.RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
   EXPECT_EQ(1U, callback.list_.size());
 
   // Open a database.
@@ -4286,7 +4275,7 @@
        origin1,
        base::Bind(&ExtensionCookieCallback::GetAllCookiesCallback,
                   base::Unretained(&callback)));
-  loop_.RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
   EXPECT_EQ(1U, callback.list_.size());
 
   // Now uninstall the other. Storage should be cleared for the apps.
@@ -4300,7 +4289,7 @@
        origin1,
        base::Bind(&ExtensionCookieCallback::GetAllCookiesCallback,
                   base::Unretained(&callback)));
-  loop_.RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
   EXPECT_EQ(0U, callback.list_.size());
 
   // The database should have vanished as well.
@@ -4326,7 +4315,7 @@
       .AppendASCII("behllobkkfkfnphdnhnkndlbkcpglgmj")
       .AppendASCII("1.0.0.0");
   extensions::UnpackedInstaller::Create(service_)->Load(ext1);
-  loop_.RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
   EXPECT_EQ(0u, GetErrors().size());
   ASSERT_EQ(1u, loaded_.size());
   EXPECT_EQ(Manifest::UNPACKED, loaded_[0]->location());
@@ -4340,7 +4329,7 @@
       .AppendASCII("cccccccccccccccccccccccccccccccc")
       .AppendASCII("1");
   extensions::UnpackedInstaller::Create(service_)->Load(no_manifest);
-  loop_.RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
   EXPECT_EQ(1u, GetErrors().size());
   ASSERT_EQ(1u, loaded_.size());
   EXPECT_EQ(1u, service_->extensions()->size());
@@ -4349,7 +4338,7 @@
   std::string id = loaded_[0]->id();
   EXPECT_FALSE(unloaded_id_.length());
   service_->UninstallExtension(id, false, NULL);
-  loop_.RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
   EXPECT_EQ(id, unloaded_id_);
   ASSERT_EQ(0u, loaded_.size());
   EXPECT_EQ(0u, service_->extensions()->size());
@@ -4362,7 +4351,7 @@
 
   base::FilePath no_id_ext = data_dir_.AppendASCII("no_id");
   extensions::UnpackedInstaller::Create(service_)->Load(no_id_ext);
-  loop_.RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
   EXPECT_EQ(0u, GetErrors().size());
   ASSERT_EQ(1u, loaded_.size());
   ASSERT_TRUE(Extension::IdIsValid(loaded_[0]->id()));
@@ -4374,7 +4363,7 @@
 
   // If we reload the same path, we should get the same extension ID.
   extensions::UnpackedInstaller::Create(service_)->Load(no_id_ext);
-  loop_.RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
   ASSERT_EQ(1u, loaded_.size());
   ASSERT_EQ(previous_id, loaded_[0]->id());
 }
@@ -4412,7 +4401,7 @@
   // loaded again.
   loaded_.clear();
   service_->ReloadExtensions();
-  loop_.RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
   ASSERT_EQ(0u, GetErrors().size());
   ASSERT_EQ(1u, loaded_.size());
   ValidatePrefKeyCount(1);
@@ -4441,7 +4430,7 @@
   bool no_uninstall =
       management_policy_->MustRemainEnabled(loaded_[0].get(), NULL);
   service_->UninstallExtension(id, false, NULL);
-  loop_.RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
 
   base::FilePath install_path = extensions_install_dir_.AppendASCII(id);
   if (no_uninstall) {
@@ -4452,7 +4441,7 @@
     ASSERT_FALSE(base::PathExists(install_path));
     loaded_.clear();
     service_->CheckForExternalUpdates();
-    loop_.RunUntilIdle();
+    base::RunLoop().RunUntilIdle();
     ASSERT_EQ(0u, loaded_.size());
     ValidatePrefKeyCount(1);
     ValidateIntegerPref(good_crx, "state",
@@ -4482,7 +4471,7 @@
 
     loaded_.clear();
     service_->OnExternalProviderReady(provider);
-    loop_.RunUntilIdle();
+    base::RunLoop().RunUntilIdle();
     ASSERT_EQ(0u, loaded_.size());
     ValidatePrefKeyCount(0);
 
@@ -4503,7 +4492,7 @@
     // User uninstalls.
     loaded_.clear();
     service_->UninstallExtension(id, false, NULL);
-    loop_.RunUntilIdle();
+    base::RunLoop().RunUntilIdle();
     ASSERT_EQ(0u, loaded_.size());
 
     // Then remove the extension from the extension provider.
@@ -4512,7 +4501,7 @@
     // Should still be at 0.
     loaded_.clear();
     extensions::InstalledLoader(service_).LoadAllExtensions();
-    loop_.RunUntilIdle();
+    base::RunLoop().RunUntilIdle();
     ASSERT_EQ(0u, loaded_.size());
     ValidatePrefKeyCount(1);
 
@@ -4607,7 +4596,7 @@
   // Verify that it's not the disabled extensions flag causing it not to load.
   set_extensions_enabled(true);
   service_->ReloadExtensions();
-  loop_.RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
 
   ASSERT_EQ(0u, GetErrors().size());
   ASSERT_EQ(0u, loaded_.size());
@@ -4630,7 +4619,7 @@
   provider->set_visit_count(0);
   service_->CheckForExternalUpdates();
   service_->CheckForExternalUpdates();
-  loop_.RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
 
   // Two calls should cause two checks for external extensions.
   EXPECT_EQ(2, provider->visit_count());
@@ -4662,7 +4651,7 @@
   provider->set_visit_count(0);
   service_->CheckForExternalUpdates();
   service_->CheckForExternalUpdates();
-  loop_.RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
 
   // Two calls should cause two checks for external extensions.
   // Because the external source no longer includes good_crx,
@@ -4935,9 +4924,7 @@
   ExtensionErrorReporter::Init(false);  // no noisy errors
   ExtensionsReadyRecorder recorder;
   scoped_ptr<TestingProfile> profile(new TestingProfile());
-  base::MessageLoop loop;
-  content::TestBrowserThread ui_thread(BrowserThread::UI, &loop);
-  content::TestBrowserThread file_thread(BrowserThread::FILE, &loop);
+  content::TestBrowserThreadBundle thread_bundle_;
 #if defined OS_CHROMEOS
   chromeos::ScopedTestDeviceSettingsService device_settings_service;
   chromeos::ScopedTestCrosSettings cros_settings;
@@ -4958,7 +4945,7 @@
           false);
   EXPECT_TRUE(service->extensions_enabled());
   service->Init();
-  loop.RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
   EXPECT_TRUE(recorder.ready());
 #if defined OS_CHROMEOS
   user_manager.reset();
@@ -4976,7 +4963,7 @@
           false);
   EXPECT_FALSE(service->extensions_enabled());
   service->Init();
-  loop.RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
   EXPECT_TRUE(recorder.ready());
 
   recorder.set_ready(false);
@@ -4990,7 +4977,7 @@
           false);
   EXPECT_FALSE(service->extensions_enabled());
   service->Init();
-  loop.RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
   EXPECT_TRUE(recorder.ready());
 
   recorder.set_ready(false);
@@ -5005,14 +4992,14 @@
           false);
   EXPECT_FALSE(service->extensions_enabled());
   service->Init();
-  loop.RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
   EXPECT_TRUE(recorder.ready());
 
   // Explicitly delete all the resources used in this test.
   profile.reset();
   service = NULL;
   // Execute any pending deletion tasks.
-  loop.RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
 }
 
 // Test loading extensions that require limited and unlimited storage quotas.
@@ -5037,7 +5024,7 @@
   extensions::UnpackedInstaller::Create(service_)->Load(limited_quota_ext);
   extensions::UnpackedInstaller::Create(service_)->Load(unlimited_quota_ext);
   extensions::UnpackedInstaller::Create(service_)->Load(unlimited_quota_ext2);
-  loop_.RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
 
   ASSERT_EQ(3u, loaded_.size());
   EXPECT_TRUE(profile_.get());
@@ -6203,7 +6190,7 @@
   InstallCRX(path, INSTALL_NEW);
 
   service_->CheckForExternalUpdates();
-  loop_.RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
   EXPECT_FALSE(extensions::HasExternalInstallError(service_));
 
   // A hosted app, installed externally.
@@ -6378,7 +6365,7 @@
       false /* has requirement errors */,
       extensions::Blacklist::BLACKLISTED,
       false /* wait for idle */);
-  loop_.RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
 
   // Extension was installed but not loaded.
   EXPECT_TRUE(notifications.CheckNotifications(
diff --git a/chrome/browser/extensions/extension_service_unittest.h b/chrome/browser/extensions/extension_service_unittest.h
index 884681e..9db4618 100644
--- a/chrome/browser/extensions/extension_service_unittest.h
+++ b/chrome/browser/extensions/extension_service_unittest.h
@@ -13,7 +13,7 @@
 #include "base/message_loop/message_loop.h"
 #include "chrome/browser/extensions/extension_service.h"
 #include "chrome/common/extensions/feature_switch.h"
-#include "content/public/test/test_browser_thread.h"
+#include "content/public/test/test_browser_thread_bundle.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 #if defined(OS_CHROMEOS)
@@ -68,7 +68,7 @@
   void InitializeExtensionServiceHelper(bool autoupdate_enabled,
                                         bool is_first_run);
 
-  base::MessageLoop loop_;
+  content::TestBrowserThreadBundle thread_bundle_;
   base::ShadowingAtExitManager at_exit_manager_;
   base::ScopedTempDir temp_dir_;
   scoped_ptr<TestingProfile> profile_;
@@ -78,11 +78,6 @@
   ExtensionService* service_;
   extensions::ManagementPolicy* management_policy_;
   size_t expected_extensions_count_;
-  content::TestBrowserThread ui_thread_;
-  content::TestBrowserThread db_thread_;
-  content::TestBrowserThread file_thread_;
-  content::TestBrowserThread file_user_blocking_thread_;
-  content::TestBrowserThread io_thread_;
 
 #if defined OS_CHROMEOS
   chromeos::ScopedTestDeviceSettingsService test_device_settings_service_;
diff --git a/chrome/browser/extensions/extension_system.cc b/chrome/browser/extensions/extension_system.cc
index ebbd3c4..0639302 100644
--- a/chrome/browser/extensions/extension_system.cc
+++ b/chrome/browser/extensions/extension_system.cc
@@ -40,7 +40,7 @@
 #include "chrome/common/chrome_switches.h"
 #include "chrome/common/chrome_version_info.h"
 #include "chrome/common/extensions/extension.h"
-#include "chrome/common/extensions/features/feature.h"
+#include "chrome/common/extensions/features/feature_channel.h"
 #include "chrome/common/extensions/manifest.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/url_data_source.h"
@@ -62,8 +62,8 @@
 
 ExtensionSystem::ExtensionSystem() {
   // Only set if it hasn't already been set (e.g. by a test).
-  if (Feature::GetCurrentChannel() == Feature::GetDefaultChannel())
-    Feature::SetCurrentChannel(chrome::VersionInfo::GetChannel());
+  if (GetCurrentChannel() == GetDefaultChannel())
+    SetCurrentChannel(chrome::VersionInfo::GetChannel());
 }
 
 ExtensionSystem::~ExtensionSystem() {
diff --git a/chrome/browser/extensions/extension_tab_util.cc b/chrome/browser/extensions/extension_tab_util.cc
index b5d5ab9..8b427ab 100644
--- a/chrome/browser/extensions/extension_tab_util.cc
+++ b/chrome/browser/extensions/extension_tab_util.cc
@@ -5,8 +5,8 @@
 #include "chrome/browser/extensions/extension_tab_util.h"
 
 #include "apps/shell_window.h"
+#include "apps/shell_window_registry.h"
 #include "chrome/browser/extensions/api/tabs/tabs_constants.h"
-#include "chrome/browser/extensions/shell_window_registry.h"
 #include "chrome/browser/extensions/tab_helper.h"
 #include "chrome/browser/extensions/window_controller.h"
 #include "chrome/browser/extensions/window_controller_list.h"
@@ -44,8 +44,8 @@
 extensions::WindowController* GetShellWindowController(
     const WebContents* contents) {
   Profile* profile = Profile::FromBrowserContext(contents->GetBrowserContext());
-  extensions::ShellWindowRegistry* registry =
-      extensions::ShellWindowRegistry::Get(profile);
+  apps::ShellWindowRegistry* registry =
+      apps::ShellWindowRegistry::Get(profile);
   if (!registry)
     return NULL;
   ShellWindow* shell_window =
diff --git a/chrome/browser/extensions/extension_warning_set.cc b/chrome/browser/extensions/extension_warning_set.cc
index 662e09c..67e90a3 100644
--- a/chrome/browser/extensions/extension_warning_set.cc
+++ b/chrome/browser/extensions/extension_warning_set.cc
@@ -4,6 +4,7 @@
 
 #include "chrome/browser/extensions/extension_warning_set.h"
 
+#include "base/files/file_path.h"
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/browser/chrome_notification_types.h"
 #include "chrome/common/extensions/extension.h"
@@ -157,6 +158,24 @@
       message_parameters);
 }
 
+// static
+ExtensionWarning ExtensionWarning::CreateDownloadFilenameConflictWarning(
+    const std::string& losing_extension_id,
+    const std::string& winning_extension_id,
+    const base::FilePath& losing_filename,
+    const base::FilePath& winning_filename) {
+  std::vector<std::string> message_parameters;
+  message_parameters.push_back(UTF16ToUTF8(losing_filename.LossyDisplayName()));
+  message_parameters.push_back(kTranslate + winning_extension_id);
+  message_parameters.push_back(UTF16ToUTF8(
+      winning_filename.LossyDisplayName()));
+  return ExtensionWarning(
+      kDownloadFilenameConflict,
+      losing_extension_id,
+      IDS_EXTENSION_WARNINGS_DOWNLOAD_FILENAME_CONFLICT,
+      message_parameters);
+}
+
 std::string ExtensionWarning::GetLocalizedMessage(
     const ExtensionSet* extensions) const {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
diff --git a/chrome/browser/extensions/extension_warning_set.h b/chrome/browser/extensions/extension_warning_set.h
index c0510f1..9e00823 100644
--- a/chrome/browser/extensions/extension_warning_set.h
+++ b/chrome/browser/extensions/extension_warning_set.h
@@ -13,6 +13,10 @@
 
 // TODO(battre) Remove the Extension prefix.
 
+namespace base {
+class FilePath;
+}
+
 class ExtensionSet;
 
 namespace extensions {
@@ -37,6 +41,9 @@
     // The extension repeatedly flushed WebKit's in-memory cache, which slows
     // down the overall performance.
     kRepeatedCacheFlushes,
+    // The extension failed to determine the filename of a download because
+    // another extension with higher precedence determined a different filename.
+    kDownloadFilenameConflict,
     kMaxWarningType
   };
 
@@ -69,6 +76,11 @@
       const std::string& winning_extension_id);
   static ExtensionWarning CreateRepeatedCacheFlushesWarning(
       const std::string& extension_id);
+  static ExtensionWarning CreateDownloadFilenameConflictWarning(
+      const std::string& losing_extension_id,
+      const std::string& winning_extension_id,
+      const base::FilePath& losing_filename,
+      const base::FilePath& winning_filename);
 
   // Returns the specific warning type.
   WarningType warning_type() const { return type_; }
diff --git a/chrome/browser/extensions/external_provider_impl_chromeos_unittest.cc b/chrome/browser/extensions/external_provider_impl_chromeos_unittest.cc
index 20bd554..3cfba4c 100644
--- a/chrome/browser/extensions/external_provider_impl_chromeos_unittest.cc
+++ b/chrome/browser/extensions/external_provider_impl_chromeos_unittest.cc
@@ -79,7 +79,7 @@
   InitServiceWithExternalProviders();
 
   service_->CheckForExternalUpdates();
-  loop_.RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
 
   EXPECT_FALSE(service_->GetInstalledExtension(kExternalAppId));
 }
diff --git a/chrome/browser/extensions/platform_app_browsertest.cc b/chrome/browser/extensions/platform_app_browsertest.cc
index 1f124a8..8126988 100644
--- a/chrome/browser/extensions/platform_app_browsertest.cc
+++ b/chrome/browser/extensions/platform_app_browsertest.cc
@@ -5,6 +5,7 @@
 #include "apps/launcher.h"
 #include "apps/native_app_window.h"
 #include "apps/shell_window.h"
+#include "apps/shell_window_registry.h"
 #include "base/bind.h"
 #include "base/command_line.h"
 #include "base/file_util.h"
@@ -28,7 +29,6 @@
 #include "chrome/browser/extensions/extension_system.h"
 #include "chrome/browser/extensions/extension_test_message_listener.h"
 #include "chrome/browser/extensions/platform_app_browsertest_util.h"
-#include "chrome/browser/extensions/shell_window_registry.h"
 #include "chrome/browser/tab_contents/render_view_context_menu.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/extensions/application_launch.h"
@@ -48,6 +48,7 @@
 #include "url/gurl.h"
 
 using apps::ShellWindow;
+using apps::ShellWindowRegistry;
 using content::WebContents;
 using web_modal::WebContentsModalDialogManager;
 
diff --git a/chrome/browser/extensions/platform_app_browsertest_util.cc b/chrome/browser/extensions/platform_app_browsertest_util.cc
index b896892..3348a00 100644
--- a/chrome/browser/extensions/platform_app_browsertest_util.cc
+++ b/chrome/browser/extensions/platform_app_browsertest_util.cc
@@ -6,11 +6,11 @@
 
 #include "apps/app_window_contents.h"
 #include "apps/native_app_window.h"
+#include "apps/shell_window_registry.h"
 #include "base/command_line.h"
 #include "base/strings/stringprintf.h"
 #include "chrome/browser/extensions/api/tabs/tabs_api.h"
 #include "chrome/browser/extensions/extension_function_test_utils.h"
-#include "chrome/browser/extensions/shell_window_registry.h"
 #include "chrome/browser/ui/apps/chrome_shell_window_delegate.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/extensions/application_launch.h"
@@ -20,6 +20,7 @@
 #include "extensions/common/switches.h"
 
 using apps::ShellWindow;
+using apps::ShellWindowRegistry;
 using content::WebContents;
 
 namespace utils = extension_function_test_utils;
diff --git a/chrome/browser/extensions/script_badge_controller_unittest.cc b/chrome/browser/extensions/script_badge_controller_unittest.cc
index 9b0eddc..01bfd60 100644
--- a/chrome/browser/extensions/script_badge_controller_unittest.cc
+++ b/chrome/browser/extensions/script_badge_controller_unittest.cc
@@ -19,7 +19,7 @@
 #include "chrome/common/extensions/extension.h"
 #include "chrome/common/extensions/extension_builder.h"
 #include "chrome/common/extensions/feature_switch.h"
-#include "chrome/common/extensions/features/feature.h"
+#include "chrome/common/extensions/features/feature_channel.h"
 #include "chrome/common/extensions/value_builder.h"
 #include "chrome/test/base/chrome_render_view_host_test_harness.h"
 #include "chrome/test/base/testing_profile.h"
@@ -105,7 +105,7 @@
 
  private:
   FeatureSwitch::ScopedOverride feature_override_;
-  Feature::ScopedCurrentChannel current_channel_;
+  ScopedCurrentChannel current_channel_;
 
 #if defined OS_CHROMEOS
   chromeos::ScopedTestDeviceSettingsService test_device_settings_service_;
diff --git a/chrome/browser/extensions/startup_helper.cc b/chrome/browser/extensions/startup_helper.cc
index 09f45f3..0362c95 100644
--- a/chrome/browser/extensions/startup_helper.cc
+++ b/chrome/browser/extensions/startup_helper.cc
@@ -18,9 +18,8 @@
 #include "chrome/browser/extensions/webstore_startup_installer.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/common/chrome_switches.h"
-#include "chrome/common/extensions/chrome_manifest_handlers.h"
+#include "chrome/common/extensions/chrome_extensions_client.h"
 #include "chrome/common/extensions/extension.h"
-#include "chrome/common/extensions/permissions/chrome_api_permissions.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/web_contents.h"
 #include "ipc/ipc_message.h"
@@ -38,9 +37,7 @@
 namespace extensions {
 
 StartupHelper::StartupHelper() : pack_job_succeeded_(false) {
-  PermissionsInfo::GetInstance()->InitializeWithDelegate(
-      ChromeAPIPermissions());
-  RegisterChromeManifestHandlers();
+  ExtensionsClient::Set(ChromeExtensionsClient::GetInstance());
 }
 
 void StartupHelper::OnPackSuccess(
diff --git a/chrome/browser/extensions/updater/extension_updater_unittest.cc b/chrome/browser/extensions/updater/extension_updater_unittest.cc
index 3c78899..8b8cb2d 100644
--- a/chrome/browser/extensions/updater/extension_updater_unittest.cc
+++ b/chrome/browser/extensions/updater/extension_updater_unittest.cc
@@ -1218,9 +1218,9 @@
     extension_service->set_show_extensions_prompts(false);
 
     scoped_refptr<CrxInstaller> fake_crx1(
-        CrxInstaller::Create(extension_service, NULL));
+        CrxInstaller::CreateSilent(extension_service));
     scoped_refptr<CrxInstaller> fake_crx2(
-        CrxInstaller::Create(extension_service, NULL));
+        CrxInstaller::CreateSilent(extension_service));
 
     if (updates_start_running) {
       // Add fake CrxInstaller to be returned by service.UpdateExtension().
diff --git a/chrome/browser/extensions/web_view_interactive_browsertest.cc b/chrome/browser/extensions/web_view_interactive_browsertest.cc
index 95fcfb8..170fb9b 100644
--- a/chrome/browser/extensions/web_view_interactive_browsertest.cc
+++ b/chrome/browser/extensions/web_view_interactive_browsertest.cc
@@ -3,11 +3,11 @@
 // found in the LICENSE file.
 
 #include "apps/shell_window.h"
+#include "apps/shell_window_registry.h"
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/browser/extensions/extension_test_message_listener.h"
 #include "chrome/browser/extensions/platform_app_browsertest_util.h"
-#include "chrome/browser/extensions/shell_window_registry.h"
 #include "chrome/test/base/interactive_test_utils.h"
 #include "chrome/test/base/test_launcher_utils.h"
 #include "chrome/test/base/ui_test_utils.h"
@@ -59,8 +59,8 @@
   }
 
   gfx::NativeWindow GetPlatformAppWindow() {
-    const extensions::ShellWindowRegistry::ShellWindowList& shell_windows =
-        extensions::ShellWindowRegistry::Get(
+    const apps::ShellWindowRegistry::ShellWindowList& shell_windows =
+        apps::ShellWindowRegistry::Get(
             browser()->profile())->shell_windows();
     return (*shell_windows.begin())->GetNativeWindow();
   }
diff --git a/chrome/browser/extensions/webstore_installer.cc b/chrome/browser/extensions/webstore_installer.cc
index dd23748..f9bced0 100644
--- a/chrome/browser/extensions/webstore_installer.cc
+++ b/chrome/browser/extensions/webstore_installer.cc
@@ -17,6 +17,7 @@
 #include "chrome/browser/chrome_notification_types.h"
 #include "chrome/browser/download/download_crx_util.h"
 #include "chrome/browser/download/download_prefs.h"
+#include "chrome/browser/download/download_stats.h"
 #include "chrome/browser/download/download_util.h"
 #include "chrome/browser/extensions/crx_installer.h"
 #include "chrome/browser/extensions/install_tracker.h"
@@ -421,8 +422,7 @@
   // The download url for the given extension is contained in |download_url_|.
   // We will navigate the current tab to this url to start the download. The
   // download system will then pass the crx to the CrxInstaller.
-  download_util::RecordDownloadSource(
-      download_util::INITIATED_BY_WEBSTORE_INSTALLER);
+  RecordDownloadSource(DOWNLOAD_INITIATED_BY_WEBSTORE_INSTALLER);
   int render_process_host_id =
     controller_->GetWebContents()->GetRenderProcessHost()->GetID();
   int render_view_host_routing_id =
diff --git a/chrome/browser/extensions/window_open_apitest.cc b/chrome/browser/extensions/window_open_apitest.cc
index 4991a97..b16edc1 100644
--- a/chrome/browser/extensions/window_open_apitest.cc
+++ b/chrome/browser/extensions/window_open_apitest.cc
@@ -28,7 +28,7 @@
 #include "testing/gtest/include/gtest/gtest.h"
 
 #if defined(USE_ASH)
-#include "chrome/browser/extensions/shell_window_registry.h"
+#include "apps/shell_window_registry.h"
 #endif
 
 #if defined(USE_ASH) && !defined(OS_WIN)
@@ -53,7 +53,7 @@
 
 int GetPanelCount(Browser* browser) {
 #if defined(USE_ASH_PANELS)
-  return static_cast<int>(extensions::ShellWindowRegistry::Get(
+  return static_cast<int>(apps::ShellWindowRegistry::Get(
       browser->profile())->shell_windows().size());
 #else
   return PanelManager::GetInstance()->num_panels();
diff --git a/chrome/browser/feedback/feedback_data.cc b/chrome/browser/feedback/feedback_data.cc
index 4b4c71f..b0f3770 100644
--- a/chrome/browser/feedback/feedback_data.cc
+++ b/chrome/browser/feedback/feedback_data.cc
@@ -11,6 +11,7 @@
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/chromeos/settings/cros_settings.h"
 #include "chrome/browser/feedback/feedback_util.h"
+#include "chrome/browser/feedback/tracing_manager.h"
 #include "chrome/browser/profiles/profile_manager.h"
 #include "content/public/browser/browser_thread.h"
 
@@ -28,6 +29,8 @@
 const char kMultilineStartString[] = "---------- START ----------\n";
 const char kMultilineEndString[] = "---------- END ----------\n\n";
 
+const char kTraceFilename[] = "tracing.log\n";
+
 std::string LogsToString(chromeos::SystemLogsResponse* sys_info) {
   std::string syslogs_string;
   for (chromeos::SystemLogsResponse::const_iterator it = sys_info->begin();
@@ -67,6 +70,7 @@
                                feedback_page_data_complete_(false) {
 #if defined(OS_CHROMEOS)
   sys_info_.reset(NULL);
+  trace_id_ = 0;
   attached_filedata_.reset(NULL);
   send_sys_info_ = true;
   read_attached_file_complete_ = false;
@@ -94,6 +98,19 @@
 
 void FeedbackData::FeedbackPageDataComplete() {
 #if defined(OS_CHROMEOS)
+  if (trace_id_ != 0) {
+    TracingManager* manager = TracingManager::Get();
+    // When there is a trace id attached to this report, fetch it and attach it
+    // as a file.  In this case, return early and retry this function later.
+    if (manager &&
+        manager->GetTraceData(
+            trace_id_,
+            base::Bind(&FeedbackData::OnGetTraceData, this))) {
+      return;
+    } else {
+      trace_id_ = 0;
+    }
+  }
   if (attached_filename_.size() &&
       base::FilePath::IsSeparator(attached_filename_[0]) &&
       !attached_filedata_.get()) {
@@ -167,7 +184,8 @@
 }
 
 void FeedbackData::StartSyslogsCollection() {
-  chromeos::SystemLogsFetcher* fetcher = new chromeos::SystemLogsFetcher();
+  chromeos::ScrubbedSystemLogsFetcher* fetcher =
+      new chromeos::ScrubbedSystemLogsFetcher();
   fetcher->Fetch(base::Bind(&FeedbackData::CompressSyslogs, this));
 }
 
@@ -178,4 +196,15 @@
       attached_filedata_->clear();
   }
 }
+
+void FeedbackData::OnGetTraceData(
+    scoped_refptr<base::RefCountedString> trace_data) {
+  scoped_ptr<std::string> data(new std::string(trace_data->data()));
+
+  set_attached_filename(kTraceFilename);
+  set_attached_filedata(data.Pass());
+  trace_id_ = 0;
+  FeedbackPageDataComplete();
+}
+
 #endif
diff --git a/chrome/browser/feedback/feedback_data.h b/chrome/browser/feedback/feedback_data.h
index 111721b..449035f 100644
--- a/chrome/browser/feedback/feedback_data.h
+++ b/chrome/browser/feedback/feedback_data.h
@@ -13,10 +13,15 @@
 #include "url/gurl.h"
 
 #if defined(OS_CHROMEOS)
-#include "chrome/browser/chromeos/system_logs/system_logs_fetcher.h"
+#include "chrome/browser/chromeos/system_logs/scrubbed_system_logs_fetcher.h"
 #endif
 
 class Profile;
+#if defined(OS_CHROMEOS)
+namespace base {
+class RefCountedString;
+}
+#endif
 
 class FeedbackData : public base::RefCountedThreadSafe<FeedbackData> {
  public:
@@ -69,6 +74,7 @@
   chromeos::SystemLogsResponse* sys_info() const {
     return send_sys_info_ ? sys_info_.get() : NULL;
   }
+  const int trace_id() const { return trace_id_; }
   const std::string timestamp() const { return timestamp_; }
   std::string* compressed_logs() const { return compressed_logs_.get(); }
 #endif
@@ -96,6 +102,7 @@
   void set_screenshot_url(const GURL& url) { screenshot_url_ = url; }
 #if defined(OS_CHROMEOS)
   void set_sys_info(scoped_ptr<chromeos::SystemLogsResponse> sys_info);
+  void set_trace_id(int trace_id) { trace_id_ = trace_id; }
   void set_send_sys_info(bool send_sys_info) { send_sys_info_ = send_sys_info; }
   void set_timestamp(const std::string& timestamp) {
     timestamp_ = timestamp;
@@ -109,6 +116,7 @@
 
 #if defined(OS_CHROMEOS)
   void ReadAttachedFile(const base::FilePath& from);
+  void OnGetTraceData(scoped_refptr<base::RefCountedString> trace_data);
 #endif
 
   Profile* profile_;
@@ -130,6 +138,7 @@
   // we don't send the logs with the report.
   scoped_ptr<chromeos::SystemLogsResponse> sys_info_;
 
+  int trace_id_;
   std::string timestamp_;
   scoped_ptr<std::string> compressed_logs_;
 
diff --git a/chrome/browser/feedback/tracing_manager.cc b/chrome/browser/feedback/tracing_manager.cc
index 3ea14cf..3a8a4cc 100644
--- a/chrome/browser/feedback/tracing_manager.cc
+++ b/chrome/browser/feedback/tracing_manager.cc
@@ -96,8 +96,8 @@
   std::string output_val;
   FeedbackUtil::ZipString(data_, &output_val);
 
-  scoped_refptr<base::RefCountedString> output;
-  output->TakeString(&output_val);
+  scoped_refptr<base::RefCountedString> output(
+      base::RefCountedString::TakeString(&output_val));
 
   trace_data_[current_trace_id_] = output;
 
diff --git a/chrome/browser/first_run/first_run.cc b/chrome/browser/first_run/first_run.cc
index e7a6fcc..6b9e650 100644
--- a/chrome/browser/first_run/first_run.cc
+++ b/chrome/browser/first_run/first_run.cc
@@ -598,9 +598,10 @@
   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)) {
+  } else if (command_line->HasSwitch(switches::kCancelFirstRun)) {
     internal::first_run_ = internal::FIRST_RUN_CANCEL;
-  } else if (internal::GetFirstRunSentinelFilePath(&first_run_sentinel) &&
+  } else if (!command_line->HasSwitch(switches::kNoFirstRun) &&
+             internal::GetFirstRunSentinelFilePath(&first_run_sentinel) &&
              !base::PathExists(first_run_sentinel)) {
     internal::first_run_ = internal::FIRST_RUN_TRUE;
   }
@@ -608,6 +609,11 @@
   return internal::first_run_ == internal::FIRST_RUN_TRUE;
 }
 
+bool IsFirstRunSuppressed(const CommandLine& command_line) {
+  return command_line.HasSwitch(switches::kCancelFirstRun) ||
+      command_line.HasSwitch(switches::kNoFirstRun);
+}
+
 void CreateSentinelIfNeeded() {
   if (IsChromeFirstRun() ||
       internal::first_run_ == internal::FIRST_RUN_CANCEL) {
diff --git a/chrome/browser/first_run/first_run.h b/chrome/browser/first_run/first_run.h
index 9f86f83..b180e29 100644
--- a/chrome/browser/first_run/first_run.h
+++ b/chrome/browser/first_run/first_run.h
@@ -10,6 +10,7 @@
 
 #include "base/basictypes.h"
 
+class CommandLine;
 class GURL;
 class Profile;
 
@@ -84,6 +85,10 @@
 // Returns true if this is the first time chrome is run for this user.
 bool IsChromeFirstRun();
 
+// Returns true if |command_line|'s switches explicitly specify that first run
+// should be suppressed in the current run.
+bool IsFirstRunSuppressed(const CommandLine& command_line);
+
 // Creates the first run sentinel if needed. This should only be called after
 // the process singleton has been grabbed by the current process
 // (http://crbug.com/264694).
diff --git a/chrome/browser/first_run/first_run_browsertest.cc b/chrome/browser/first_run/first_run_browsertest.cc
index b6fd6fd..62b439b 100644
--- a/chrome/browser/first_run/first_run_browsertest.cc
+++ b/chrome/browser/first_run/first_run_browsertest.cc
@@ -146,7 +146,7 @@
   // Internet Explorer always exists and always has something to import.
   EXPECT_GT(source_profile_count, 0);
 #endif
-  if (source_profile_count == 0)
+  if (source_profile_count == 1)
     return expected_import_state & ~first_run::AUTO_IMPORT_PROFILE_IMPORTED;
 
   return expected_import_state;
diff --git a/chrome/browser/google/google_util_chromeos.cc b/chrome/browser/google/google_util_chromeos.cc
index b39d910..06232e4 100644
--- a/chrome/browser/google/google_util_chromeos.cc
+++ b/chrome/browser/google/google_util_chromeos.cc
@@ -46,16 +46,16 @@
 }  // namespace
 
 void ClearBrandForCurrentSession() {
-  DCHECK(
-      !content::BrowserThread::IsWellKnownThread(content::BrowserThread::UI) ||
-      content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+  DCHECK(!content::BrowserThread::IsThreadInitialized(
+             content::BrowserThread::UI) ||
+         content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
   g_brand_empty = true;
 }
 
 std::string GetBrand() {
-  DCHECK(
-      !content::BrowserThread::IsWellKnownThread(content::BrowserThread::UI) ||
-      content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+  DCHECK(!content::BrowserThread::IsThreadInitialized(
+             content::BrowserThread::UI) ||
+         content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
   if (g_brand_empty)
     return std::string();
   DCHECK(g_browser_process->local_state());
diff --git a/chrome/browser/history/download_database.cc b/chrome/browser/history/download_database.cc
index 12745ca..369c8c2 100644
--- a/chrome/browser/history/download_database.cc
+++ b/chrome/browser/history/download_database.cc
@@ -40,28 +40,31 @@
 
 static const char kSchema[] =
     "CREATE TABLE downloads ("
-    "id INTEGER PRIMARY KEY,"  // Primary key.
+    "id INTEGER PRIMARY KEY,"             // Primary key.
     "current_path LONGVARCHAR NOT NULL,"  // Current disk location
-    "target_path LONGVARCHAR NOT NULL,"  // Final disk location
-    "start_time INTEGER NOT NULL,"  // When the download was started.
-    "received_bytes INTEGER NOT NULL,"  // Total size downloaded.
-    "total_bytes INTEGER NOT NULL,"  // Total size of the download.
-    "state INTEGER NOT NULL,"  // 1=complete, 4=interrupted
-    "danger_type INTEGER NOT NULL, "  // Not dangerous, danger type, validated.
-    "interrupt_reason INTEGER NOT NULL,"
-    "end_time INTEGER NOT NULL,"  // When the download completed.
-    "opened INTEGER NOT NULL,"  // 1 if it has ever been opened else 0
-    "referrer VARCHAR NOT NULL,"  // HTTP Referrer
-    "by_ext_id VARCHAR NOT NULL,"  // ID of extension that started the download
-    "by_ext_name VARCHAR NOT NULL)";  // name of extension
+    "target_path LONGVARCHAR NOT NULL,"   // Final disk location
+    "start_time INTEGER NOT NULL,"        // When the download was started.
+    "received_bytes INTEGER NOT NULL,"    // Total size downloaded.
+    "total_bytes INTEGER NOT NULL,"       // Total size of the download.
+    "state INTEGER NOT NULL,"             // 1=complete, 4=interrupted
+    "danger_type INTEGER NOT NULL, "      // Danger type, validated.
+    "interrupt_reason INTEGER NOT NULL,"  // content::DownloadInterruptReason
+    "end_time INTEGER NOT NULL,"          // When the download completed.
+    "opened INTEGER NOT NULL,"            // 1 if it has ever been opened else 0
+    "referrer VARCHAR NOT NULL,"          // HTTP Referrer
+    "by_ext_id VARCHAR NOT NULL,"         // ID of extension that started the
+                                          // download
+    "by_ext_name VARCHAR NOT NULL,"       // name of extension
+    "etag VARCHAR NOT NULL,"              // ETag
+    "last_modified VARCHAR NOT NULL)";    // Last-Modified header
 
 static const char kUrlChainSchema[] =
     "CREATE TABLE downloads_url_chains ("
-    "id INTEGER NOT NULL,"           // downloads.id.
-    "chain_index INTEGER NOT NULL,"  // Index of url in chain
-                                     // 0 is initial target,
-                                     // MAX is target after redirects.
-    "url LONGVARCHAR NOT NULL, "     // URL.
+    "id INTEGER NOT NULL,"                // downloads.id.
+    "chain_index INTEGER NOT NULL,"       // Index of url in chain
+                                          // 0 is initial target,
+                                          // MAX is target after redirects.
+    "url LONGVARCHAR NOT NULL, "          // URL.
     "PRIMARY KEY (id, chain_index) )";
 
 #if defined(OS_POSIX)
@@ -233,19 +236,19 @@
   // since the Windows Epoch).  Note that this is dependent on the
   // internal representation of base::Time and needs to change if that changes.
   sql::Statement statement_populate(GetDB().GetUniqueStatement(
-    "INSERT INTO downloads "
-    "( id, current_path, target_path, start_time, received_bytes, total_bytes, "
-    "  state, danger_type, interrupt_reason, end_time, opened, referrer, "
-    "  by_ext_id, by_ext_name ) "
-    "SELECT id, full_path, full_path, "
-    "       CASE start_time WHEN 0 THEN 0 ELSE "
-    "            (start_time + 11644473600) * 1000000 END, "
-    "       received_bytes, total_bytes, "
-    "       state, ?, ?, "
-    "       CASE end_time WHEN 0 THEN 0 ELSE "
-    "            (end_time + 11644473600) * 1000000 END, "
-    "       opened, \"\", \"\", \"\" "
-    "FROM downloads_tmp"));
+      "INSERT INTO downloads "
+      "( id, current_path, target_path, start_time, received_bytes, "
+      "  total_bytes, state, danger_type, interrupt_reason, end_time, opened, "
+      "  referrer, by_ext_id, by_ext_name, etag, last_modified ) "
+      "SELECT id, full_path, full_path, "
+      "       CASE start_time WHEN 0 THEN 0 ELSE "
+      "            (start_time + 11644473600) * 1000000 END, "
+      "       received_bytes, total_bytes, "
+      "       state, ?, ?, "
+      "       CASE end_time WHEN 0 THEN 0 ELSE "
+      "            (end_time + 11644473600) * 1000000 END, "
+      "       opened, \"\", \"\", \"\", \"\", \"\" "
+      "FROM downloads_tmp"));
   statement_populate.BindInt(0, content::DOWNLOAD_INTERRUPT_REASON_NONE);
   statement_populate.BindInt(1, kDangerTypeNotDangerous);
   if (!statement_populate.Run())
@@ -276,6 +279,11 @@
          EnsureColumnExists("by_ext_name", "VARCHAR NOT NULL DEFAULT \"\"");
 }
 
+bool DownloadDatabase::MigrateDownloadValidators() {
+  return EnsureColumnExists("etag", "VARCHAR NOT NULL DEFAULT \"\"") &&
+         EnsureColumnExists("last_modified", "VARCHAR NOT NULL DEFAULT \"\"");
+}
+
 bool DownloadDatabase::InitDownloadTable() {
   if (GetDB().DoesTableExist("downloads")) {
     return EnsureColumnExists("end_time", "INTEGER NOT NULL DEFAULT 0") &&
@@ -324,7 +332,7 @@
   sql::Statement statement_main(GetDB().GetCachedStatement(SQL_FROM_HERE,
       "SELECT id, current_path, target_path, start_time, received_bytes, "
       "total_bytes, state, danger_type, interrupt_reason, end_time, opened, "
-      "referrer, by_ext_id, by_ext_name "
+      "referrer, by_ext_id, by_ext_name, etag, last_modified "
       "FROM downloads ORDER BY start_time"));
 
   while (statement_main.Step()) {
@@ -355,6 +363,8 @@
     info->referrer_url = GURL(statement_main.ColumnString(column++));
     info->by_ext_id = statement_main.ColumnString(column++);
     info->by_ext_name = statement_main.ColumnString(column++);
+    info->etag = statement_main.ColumnString(column++);
+    info->last_modified = statement_main.ColumnString(column++);
 
     // If the record is corrupted, note that and drop it.
     // http://crbug.com/251269
@@ -457,8 +467,9 @@
   sql::Statement statement(GetDB().GetCachedStatement(SQL_FROM_HERE,
       "UPDATE downloads "
       "SET current_path=?, target_path=?, received_bytes=?, state=?, "
-          "danger_type=?, interrupt_reason=?, end_time=?, total_bytes=?, "
-          "opened=?, by_ext_id=?, by_ext_name=? WHERE id=?"));
+      "danger_type=?, interrupt_reason=?, end_time=?, total_bytes=?, "
+      "opened=?, by_ext_id=?, by_ext_name=?, etag=?, last_modified=? "
+      "WHERE id=?"));
   int column = 0;
   BindFilePath(statement, data.current_path, column++);
   BindFilePath(statement, data.target_path, column++);
@@ -471,6 +482,8 @@
   statement.BindInt(column++, (data.opened ? 1 : 0));
   statement.BindString(column++, data.by_ext_id);
   statement.BindString(column++, data.by_ext_name);
+  statement.BindString(column++, data.etag);
+  statement.BindString(column++, data.last_modified);
   statement.BindInt(column++, data.id);
 
   return statement.Run();
@@ -511,8 +524,9 @@
         "INSERT INTO downloads "
         "(id, current_path, target_path, start_time, "
         " received_bytes, total_bytes, state, danger_type, interrupt_reason, "
-        " end_time, opened, referrer, by_ext_id, by_ext_name) "
-        "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"));
+        " end_time, opened, referrer, by_ext_id, by_ext_name, etag, "
+        " last_modified) "
+        "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"));
 
     int column = 0;
     statement_insert.BindInt(column++, info.id);
@@ -529,6 +543,8 @@
     statement_insert.BindString(column++, info.referrer_url.spec());
     statement_insert.BindString(column++, info.by_ext_id);
     statement_insert.BindString(column++, info.by_ext_name);
+    statement_insert.BindString(column++, info.etag);
+    statement_insert.BindString(column++, info.last_modified);
     if (!statement_insert.Run()) {
       // GetErrorCode() returns a bitmask where the lower byte is a more general
       // code and the upper byte is a more specific code. In order to save
diff --git a/chrome/browser/history/download_database.h b/chrome/browser/history/download_database.h
index adf4651..36f27f2 100644
--- a/chrome/browser/history/download_database.h
+++ b/chrome/browser/history/download_database.h
@@ -69,6 +69,10 @@
   // columns to the downloads table.
   bool MigrateDownloadedByExtension();
 
+  // Returns true if able to successfully add the etag and last-modified columns
+  // to the downloads table.
+  bool MigrateDownloadValidators();
+
   // Creates the downloads table if needed.
   bool InitDownloadTable();
 
diff --git a/chrome/browser/history/download_row.cc b/chrome/browser/history/download_row.cc
index 864c56b..fe44c13 100644
--- a/chrome/browser/history/download_row.cc
+++ b/chrome/browser/history/download_row.cc
@@ -23,6 +23,8 @@
     const GURL& referrer,
     const base::Time& start,
     const base::Time& end,
+    const std::string& etag,
+    const std::string& last_modified,
     int64 received,
     int64 total,
     content::DownloadItem::DownloadState download_state,
@@ -38,6 +40,8 @@
       referrer_url(referrer),
       start_time(start),
       end_time(end),
+      etag(etag),
+      last_modified(last_modified),
       received_bytes(received),
       total_bytes(total),
       state(download_state),
diff --git a/chrome/browser/history/download_row.h b/chrome/browser/history/download_row.h
index a5336bb..d38eec5 100644
--- a/chrome/browser/history/download_row.h
+++ b/chrome/browser/history/download_row.h
@@ -28,6 +28,8 @@
       const GURL& referrer,
       const base::Time& start,
       const base::Time& end,
+      const std::string& etag,
+      const std::string& last_modified,
       int64 received,
       int64 total,
       content::DownloadItem::DownloadState download_state,
@@ -61,6 +63,12 @@
   // The time when the download completed.
   base::Time end_time;
 
+  // Contents of most recently seen ETag header.
+  std::string etag;
+
+  // Contents of most recently seen Last-Modified header.
+  std::string last_modified;
+
   // The number of bytes received (so far).
   int64 received_bytes;
 
diff --git a/chrome/browser/history/history_database.cc b/chrome/browser/history/history_database.cc
index ee3baae..ca2d4ab 100644
--- a/chrome/browser/history/history_database.cc
+++ b/chrome/browser/history/history_database.cc
@@ -27,13 +27,13 @@
 // Current version number. We write databases at the "current" version number,
 // but any previous version that can read the "compatible" one can make do with
 // or database without *too* many bad effects.
-static const int kCurrentVersionNumber = 27;
-static const int kCompatibleVersionNumber = 16;
-static const char kEarlyExpirationThresholdKey[] = "early_expiration_threshold";
+const int kCurrentVersionNumber = 28;
+const int kCompatibleVersionNumber = 16;
+const char kEarlyExpirationThresholdKey[] = "early_expiration_threshold";
 
 // Key in the meta table used to determine if we need to migrate thumbnails out
 // of history.
-static const char kNeedsThumbnailMigrationKey[] = "needs_thumbnail_migration";
+const char kNeedsThumbnailMigrationKey[] = "needs_thumbnail_migration";
 
 }  // namespace
 
@@ -439,6 +439,15 @@
     meta_table_.SetVersionNumber(cur_version);
   }
 
+  if (cur_version == 27) {
+    if (!MigrateDownloadValidators()) {
+      LOG(WARNING) << "Unable to migrate history to version 28";
+      return sql::INIT_FAILURE;
+    }
+    cur_version++;
+    meta_table_.SetVersionNumber(cur_version);
+  }
+
   // When the version is too old, we just try to continue anyway, there should
   // not be a released product that makes a database too old for us to handle.
   LOG_IF(WARNING, cur_version < GetCurrentVersion()) <<
diff --git a/chrome/browser/history/history_unittest.cc b/chrome/browser/history/history_unittest.cc
index c18d908..28db9ba 100644
--- a/chrome/browser/history/history_unittest.cc
+++ b/chrome/browser/history/history_unittest.cc
@@ -173,6 +173,8 @@
                          GURL("http://referrer.com/"),
                          time,
                          time,
+                         std::string(),
+                         std::string(),
                          0,
                          512,
                          state,
@@ -551,6 +553,71 @@
   }
 }
 
+TEST_F(HistoryBackendDBTest, MigrateDownloadValidators) {
+  Time now(base::Time::Now());
+  ASSERT_NO_FATAL_FAILURE(CreateDBVersion(27));
+  {
+    sql::Connection db;
+    ASSERT_TRUE(db.Open(history_dir_.Append(chrome::kHistoryFilename)));
+    {
+      sql::Statement s(db.GetUniqueStatement(
+          "INSERT INTO downloads (id, current_path, target_path, start_time, "
+          "received_bytes, total_bytes, state, danger_type, interrupt_reason, "
+          "end_time, opened, referrer, by_ext_id, by_ext_name) VALUES "
+          "(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"));
+      s.BindInt64(0, 1);
+      s.BindString(1, "current_path");
+      s.BindString(2, "target_path");
+      s.BindInt64(3, now.ToTimeT());
+      s.BindInt64(4, 100);
+      s.BindInt64(5, 100);
+      s.BindInt(6, 1);
+      s.BindInt(7, 0);
+      s.BindInt(8, 0);
+      s.BindInt64(9, now.ToTimeT());
+      s.BindInt(10, 1);
+      s.BindString(11, "referrer");
+      s.BindString(12, "by extension ID");
+      s.BindString(13, "by extension name");
+      ASSERT_TRUE(s.Run());
+    }
+    {
+      sql::Statement s(db.GetUniqueStatement(
+          "INSERT INTO downloads_url_chains (id, chain_index, url) VALUES "
+          "(?, ?, ?)"));
+      s.BindInt64(0, 4);
+      s.BindInt64(1, 0);
+      s.BindString(2, "url");
+      ASSERT_TRUE(s.Run());
+    }
+  }
+  // Re-open the db using the HistoryDatabase, which should migrate to the
+  // current version, creating the etag and last_modified columns.
+  CreateBackendAndDatabase();
+  DeleteBackend();
+  {
+    // Re-open the db for manual manipulation.
+    sql::Connection db;
+    ASSERT_TRUE(db.Open(history_dir_.Append(chrome::kHistoryFilename)));
+    // The version should have been updated.
+    int cur_version = HistoryDatabase::GetCurrentVersion();
+    ASSERT_LE(28, cur_version);
+    {
+      sql::Statement s(db.GetUniqueStatement(
+          "SELECT value FROM meta WHERE key = 'version'"));
+      EXPECT_TRUE(s.Step());
+      EXPECT_EQ(cur_version, s.ColumnInt(0));
+    }
+    {
+      sql::Statement s(db.GetUniqueStatement(
+          "SELECT etag, last_modified from downloads"));
+      EXPECT_TRUE(s.Step());
+      EXPECT_EQ(std::string(), s.ColumnString(0));
+      EXPECT_EQ(std::string(), s.ColumnString(1));
+    }
+  }
+}
+
 TEST_F(HistoryBackendDBTest, ConfirmDownloadRowCreateAndDelete) {
   // Create the DB.
   CreateBackendAndDatabase();
@@ -609,6 +676,8 @@
                        GURL(std::string()),
                        now,
                        now,
+                       std::string(),
+                       std::string(),
                        0,
                        512,
                        DownloadItem::COMPLETE,
diff --git a/chrome/browser/history/in_memory_url_index.cc b/chrome/browser/history/in_memory_url_index.cc
index 0f6ee80..9eba62e 100644
--- a/chrome/browser/history/in_memory_url_index.cc
+++ b/chrome/browser/history/in_memory_url_index.cc
@@ -45,7 +45,7 @@
   whitelist->insert(std::string(chrome::kFtpScheme));
   whitelist->insert(std::string(chrome::kHttpScheme));
   whitelist->insert(std::string(chrome::kHttpsScheme));
-  whitelist->insert(std::string(chrome::kMailToScheme));
+  whitelist->insert(std::string(content::kMailToScheme));
 }
 
 // Restore/SaveCacheObserver ---------------------------------------------------
diff --git a/chrome/browser/history/scored_history_match.cc b/chrome/browser/history/scored_history_match.cc
index 3563a9d..3fb8e77 100644
--- a/chrome/browser/history/scored_history_match.cc
+++ b/chrome/browser/history/scored_history_match.cc
@@ -256,9 +256,9 @@
   // be on it."  The first part is necessary so unit tests pass.  (Many
   // unit tests don't set up the threading naming system; hence
   // CurrentlyOn(UI thread) will fail.)
-  DCHECK(
-      !content::BrowserThread::IsWellKnownThread(content::BrowserThread::UI) ||
-      content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+  DCHECK(!content::BrowserThread::IsThreadInitialized(
+             content::BrowserThread::UI) ||
+         content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
   if (raw_term_score_to_topicality_score == NULL) {
     raw_term_score_to_topicality_score = new float[kMaxRawTermScore];
     FillInTermScoreToTopicalityScoreArray();
@@ -400,9 +400,9 @@
   // be on it."  The first part is necessary so unit tests pass.  (Many
   // unit tests don't set up the threading naming system; hence
   // CurrentlyOn(UI thread) will fail.)
-  DCHECK(
-      !content::BrowserThread::IsWellKnownThread(content::BrowserThread::UI) ||
-      content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+  DCHECK(!content::BrowserThread::IsThreadInitialized(
+             content::BrowserThread::UI) ||
+         content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
   if (days_ago_to_recency_score == NULL) {
     days_ago_to_recency_score = new float[kDaysToPrecomputeRecencyScoresFor];
     FillInDaysAgoToRecencyScoreArray();
diff --git a/chrome/browser/history/shortcuts_backend.cc b/chrome/browser/history/shortcuts_backend.cc
index dfa7257..6bb8c0c 100644
--- a/chrome/browser/history/shortcuts_backend.cc
+++ b/chrome/browser/history/shortcuts_backend.cc
@@ -266,7 +266,7 @@
 }
 
 void ShortcutsBackend::ShutdownOnUIThread() {
-  DCHECK(!BrowserThread::IsWellKnownThread(BrowserThread::UI) ||
+  DCHECK(!BrowserThread::IsThreadInitialized(BrowserThread::UI) ||
          BrowserThread::CurrentlyOn(BrowserThread::UI));
   notification_registrar_.RemoveAll();
 }
diff --git a/chrome/browser/history/web_history_service_factory.cc b/chrome/browser/history/web_history_service_factory.cc
index 00c1bf5..bd0194b 100644
--- a/chrome/browser/history/web_history_service_factory.cc
+++ b/chrome/browser/history/web_history_service_factory.cc
@@ -7,7 +7,7 @@
 #include "base/command_line.h"
 #include "chrome/browser/content_settings/cookie_settings.h"
 #include "chrome/browser/history/web_history_service.h"
-#include "chrome/browser/signin/token_service_factory.h"
+#include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
 #include "chrome/browser/sync/profile_sync_service.h"
 #include "chrome/browser/sync/profile_sync_service_factory.h"
 #include "chrome/common/chrome_switches.h"
@@ -59,8 +59,8 @@
     : BrowserContextKeyedServiceFactory(
         "WebHistoryServiceFactory",
         BrowserContextDependencyManager::GetInstance()) {
-  DependsOn(TokenServiceFactory::GetInstance());
   DependsOn(CookieSettings::Factory::GetInstance());
+  DependsOn(ProfileOAuth2TokenServiceFactory::GetInstance());
 }
 
 WebHistoryServiceFactory::~WebHistoryServiceFactory() {
diff --git a/chrome/browser/importer/importer_list.cc b/chrome/browser/importer/importer_list.cc
index 1863d4a..598843e 100644
--- a/chrome/browser/importer/importer_list.cc
+++ b/chrome/browser/importer/importer_list.cc
@@ -175,6 +175,12 @@
 #else
   DetectFirefoxProfiles(locale, &profiles);
 #endif
+  importer::SourceProfile* bookmarks_file = new importer::SourceProfile;
+  bookmarks_file->importer_name =
+      l10n_util::GetStringUTF16(IDS_IMPORT_FROM_BOOKMARKS_HTML_FILE);
+  bookmarks_file->importer_type = importer::TYPE_BOOKMARKS_FILE;
+  bookmarks_file->services_supported = importer::FAVORITES;
+  profiles.push_back(bookmarks_file);
 
   // TODO(jhawkins): Remove this condition once DetectSourceProfilesHack is
   // removed.
diff --git a/chrome/browser/importer/in_process_importer_bridge.cc b/chrome/browser/importer/in_process_importer_bridge.cc
index 61d09d2..4fe6785 100644
--- a/chrome/browser/importer/in_process_importer_bridge.cc
+++ b/chrome/browser/importer/in_process_importer_bridge.cc
@@ -118,7 +118,6 @@
 
   typedef std::map<std::string, TemplateURL*> SearchEnginesMap;
   SearchEnginesMap search_engine_for_url;
-  std::string content;
   FirefoxURLParameterFilter param_filter;
   // The first XML file represents the default search engine in Firefox 3, so we
   // need to keep it on top of the list.
diff --git a/chrome/browser/infobars/infobars_browsertest.cc b/chrome/browser/infobars/infobars_browsertest.cc
index 3a5d3ab..aa68737 100644
--- a/chrome/browser/infobars/infobars_browsertest.cc
+++ b/chrome/browser/infobars/infobars_browsertest.cc
@@ -41,10 +41,10 @@
         chrome::NOTIFICATION_EXTENSION_LOADED,
         content::NotificationService::AllSources());
 
-    ExtensionInstallPrompt* client = new ExtensionInstallPrompt(
-        browser()->tab_strip_model()->GetActiveWebContents());
+    scoped_ptr<ExtensionInstallPrompt> client(new ExtensionInstallPrompt(
+        browser()->tab_strip_model()->GetActiveWebContents()));
     scoped_refptr<extensions::CrxInstaller> installer(
-        extensions::CrxInstaller::Create(service, client));
+        extensions::CrxInstaller::Create(service, client.Pass()));
     installer->set_install_cause(extension_misc::INSTALL_CAUSE_AUTOMATION);
     installer->InstallCrx(path);
 
diff --git a/chrome/browser/managed_mode/managed_mode_interstitial.cc b/chrome/browser/managed_mode/managed_mode_interstitial.cc
index e74e665..b3daecc 100644
--- a/chrome/browser/managed_mode/managed_mode_interstitial.cc
+++ b/chrome/browser/managed_mode/managed_mode_interstitial.cc
@@ -41,8 +41,8 @@
       Profile::FromBrowserContext(web_contents->GetBrowserContext());
   languages_ = profile->GetPrefs()->GetString(prefs::kAcceptLanguages);
 
-  interstitial_page_ = content::InterstitialPage::Create(
-      web_contents, true, url_, this);
+  interstitial_page_ =
+      content::InterstitialPage::Create(web_contents, true, url_, this);
   interstitial_page_->Show();
 }
 
@@ -57,10 +57,18 @@
       Profile::FromBrowserContext(web_contents_->GetBrowserContext());
   ManagedUserService* managed_user_service =
       ManagedUserServiceFactory::GetForProfile(profile);
+
+  bool allow_access_requests = managed_user_service->AccessRequestsEnabled();
+  strings.SetBoolean("allowAccessRequests", allow_access_requests);
+
   string16 custodian = UTF8ToUTF16(managed_user_service->GetCustodianName());
   strings.SetString(
       "blockPageMessage",
-      l10n_util::GetStringFUTF16(IDS_BLOCK_INTERSTITIAL_MESSAGE, custodian));
+      allow_access_requests
+          ? l10n_util::GetStringFUTF16(IDS_BLOCK_INTERSTITIAL_MESSAGE,
+                                       custodian)
+          : l10n_util::GetStringUTF16(
+                IDS_BLOCK_INTERSTITIAL_MESSAGE_ACCESS_REQUESTS_DISABLED));
 
   strings.SetString("backButton", l10n_util::GetStringUTF16(IDS_BACK_BUTTON));
   strings.SetString(
@@ -74,9 +82,8 @@
 
   webui::SetFontAndTextDirection(&strings);
 
-  base::StringPiece html(
-      ResourceBundle::GetSharedInstance().GetRawDataResource(
-          IDR_MANAGED_MODE_BLOCK_INTERSTITIAL_HTML));
+  base::StringPiece html(ResourceBundle::GetSharedInstance().GetRawDataResource(
+      IDR_MANAGED_MODE_BLOCK_INTERSTITIAL_HTML));
 
   webui::UseVersion2 version;
   return webui::GetI18nTemplateHtml(html, &strings);
@@ -118,15 +125,13 @@
   NOTREACHED();
 }
 
-void ManagedModeInterstitial::OnProceed() {
-  NOTREACHED();
-}
+void ManagedModeInterstitial::OnProceed() { NOTREACHED(); }
 
 void ManagedModeInterstitial::OnDontProceed() {
   DispatchContinueRequest(false);
 }
 
 void ManagedModeInterstitial::DispatchContinueRequest(bool continue_request) {
-  BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
-                          base::Bind(callback_, continue_request));
+  BrowserThread::PostTask(
+      BrowserThread::IO, FROM_HERE, base::Bind(callback_, continue_request));
 }
diff --git a/chrome/browser/managed_mode/managed_user_service.cc b/chrome/browser/managed_mode/managed_user_service.cc
index 90ad387..f42f768 100644
--- a/chrome/browser/managed_mode/managed_user_service.cc
+++ b/chrome/browser/managed_mode/managed_user_service.cc
@@ -51,6 +51,10 @@
 #include "policy/policy_constants.h"
 #include "ui/base/l10n/l10n_util.h"
 
+#if defined(OS_CHROMEOS)
+#include "chrome/browser/chromeos/login/user_manager.h"
+#endif
+
 using base::DictionaryValue;
 using base::Value;
 using content::BrowserThread;
@@ -238,13 +242,25 @@
 }
 
 std::string ManagedUserService::GetCustodianEmailAddress() const {
+#if defined(OS_CHROMEOS)
+  return chromeos::UserManager::Get()->
+      GetManagerDisplayEmailForManagedUser(
+          chromeos::UserManager::Get()->GetActiveUser()->email());
+#else
   return profile_->GetPrefs()->GetString(prefs::kManagedUserCustodianEmail);
+#endif
 }
 
 std::string ManagedUserService::GetCustodianName() const {
+#if defined(OS_CHROMEOS)
+  return UTF16ToUTF8(chromeos::UserManager::Get()->
+      GetManagerDisplayNameForManagedUser(
+          chromeos::UserManager::Get()->GetActiveUser()->email()));
+#else
   std::string name = profile_->GetPrefs()->GetString(
       prefs::kManagedUserCustodianName);
   return name.empty() ? GetCustodianEmailAddress() : name;
+#endif
 }
 
 void ManagedUserService::AddNavigationBlockedCallback(
@@ -261,6 +277,11 @@
   }
 }
 
+void ManagedUserService::AddInitCallback(
+    const base::Closure& callback) {
+  init_callbacks_.push_back(callback);
+}
+
 std::string ManagedUserService::GetDebugPolicyProviderName() const {
   // Save the string space in official builds.
 #ifdef NDEBUG
@@ -432,6 +453,16 @@
   url_filter_context_.LoadWhitelists(GetActiveSiteLists());
 }
 
+bool ManagedUserService::AccessRequestsEnabled() {
+  ProfileSyncService* service =
+      ProfileSyncServiceFactory::GetForProfile(profile_);
+  GoogleServiceAuthError::State state = service->GetAuthError().state();
+  // We allow requesting access if Sync is working or has a transient error.
+  return (state == GoogleServiceAuthError::NONE ||
+          state == GoogleServiceAuthError::CONNECTION_FAILED ||
+          state == GoogleServiceAuthError::SERVICE_UNAVAILABLE);
+}
+
 void ManagedUserService::AddAccessRequest(const GURL& url) {
   // Normalize the URL.
   GURL normalized_url = ManagedModeURLFilter::Normalize(url);
@@ -570,6 +601,14 @@
   UpdateSiteLists();
   UpdateManualHosts();
   UpdateManualURLs();
+
+  // Call the callbacks to notify that the ManagedUserService has been
+  // initialized.
+  for (std::vector<base::Closure>::iterator it = init_callbacks_.begin();
+       it != init_callbacks_.end();
+       ++it) {
+    it->Run();
+  }
 }
 
 void ManagedUserService::RegisterAndInitSync(
diff --git a/chrome/browser/managed_mode/managed_user_service.h b/chrome/browser/managed_mode/managed_user_service.h
index 0d01b6c..6dc4b56 100644
--- a/chrome/browser/managed_mode/managed_user_service.h
+++ b/chrome/browser/managed_mode/managed_user_service.h
@@ -83,6 +83,9 @@
   // be fast.
   void GetCategoryNames(CategoryList* list);
 
+  // Whether the user can request access to blocked URLs.
+  bool AccessRequestsEnabled();
+
   // Adds an access request for the given URL. The requests are stored using
   // a prefix followed by a URIEncoded version of the URL. Each entry contains
   // a dictionary which currently has the timestamp of the request in it.
@@ -141,6 +144,8 @@
   void AddNavigationBlockedCallback(const NavigationBlockedCallback& callback);
   void DidBlockNavigation(content::WebContents* web_contents);
 
+  void AddInitCallback(const base::Closure& callback);
+
   // extensions::ManagementPolicy::Provider implementation:
   virtual std::string GetDebugPolicyProviderName() const OVERRIDE;
   virtual bool UserMayLoad(const extensions::Extension* extension,
@@ -254,6 +259,8 @@
   bool waiting_for_sync_initialization_;
   bool is_profile_active_;
 
+  std::vector<base::Closure> init_callbacks_;
+
   std::vector<NavigationBlockedCallback> navigation_blocked_callbacks_;
 
   // Sets a profile in elevated state for testing if set to true.
diff --git a/chrome/browser/media/chrome_webrtc_audio_quality_browsertest.cc b/chrome/browser/media/chrome_webrtc_audio_quality_browsertest.cc
new file mode 100644
index 0000000..1ca2cf2
--- /dev/null
+++ b/chrome/browser/media/chrome_webrtc_audio_quality_browsertest.cc
@@ -0,0 +1,450 @@
+// 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/command_line.h"
+#include "base/file_util.h"
+#include "base/path_service.h"
+#include "base/process/launch.h"
+#include "base/strings/stringprintf.h"
+#include "chrome/browser/media/webrtc_browsertest_base.h"
+#include "chrome/browser/media/webrtc_browsertest_common.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/browser_tabstrip.h"
+#include "chrome/browser/ui/tabs/tab_strip_model.h"
+#include "chrome/common/chrome_paths.h"
+#include "chrome/common/chrome_switches.h"
+#include "chrome/test/base/ui_test_utils.h"
+#include "chrome/test/perf/perf_test.h"
+#include "chrome/test/ui/ui_test.h"
+#include "content/public/test/browser_test_utils.h"
+#include "net/test/embedded_test_server/embedded_test_server.h"
+
+static const base::FilePath::CharType kPeerConnectionServer[] =
+#if defined(OS_WIN)
+    FILE_PATH_LITERAL("peerconnection_server.exe");
+#else
+    FILE_PATH_LITERAL("peerconnection_server");
+#endif
+
+static const base::FilePath::CharType kMediaPath[] =
+    FILE_PATH_LITERAL("pyauto_private/webrtc/");
+static const base::FilePath::CharType kToolsPath[] =
+    FILE_PATH_LITERAL("pyauto_private/media/tools");
+static const base::FilePath::CharType kReferenceFile[] =
+#if defined (OS_WIN)
+    FILE_PATH_LITERAL("human-voice-win.wav");
+#else
+    FILE_PATH_LITERAL("human-voice-linux.wav");
+#endif
+
+static const char kMainWebrtcTestHtmlPage[] =
+    "files/webrtc/webrtc_audio_quality_test.html";
+
+base::FilePath GetTestDataDir() {
+  base::FilePath source_dir;
+  PathService::Get(chrome::DIR_TEST_DATA, &source_dir);
+  return source_dir;
+}
+
+// Test we can set up a WebRTC call and play audio through it.
+//
+// This test will only work on machines that have been configured to record
+// their own input.
+//
+// On Linux:
+// 1. # sudo apt-get install pavucontrol
+// 2. For the user who will run the test: # pavucontrol
+// 3. In a separate terminal, # arecord dummy
+// 4. In pavucontrol, go to the recording tab.
+// 5. For the ALSA plug-in [aplay]: ALSA Capture from, change from <x> to
+//    <Monitor of x>, where x is whatever your primary sound device is called.
+//    This test expects the device id to be render.monitor - if it's something
+//    else, the microphone level will not get forced to 100% appropriately.
+//    See ForceMicrophoneVolumeTo100% for more details. You can list the
+//    available monitor devices on your system by running the command
+//    pacmd list-sources | grep name | grep monitor.
+// 6. Try launching chrome as the target user on the target machine, try
+//    playing, say, a YouTube video, and record with # arecord -f dat tmp.dat.
+//    Verify the recording with aplay (should have recorded what you played
+//    from chrome).
+//
+// On Windows 7:
+// 1. Control panel > Sound > Manage audio devices.
+// 2. In the recording tab, right-click in an empty space in the pane with the
+//    devices. Tick 'show disabled devices'.
+// 3. You should see a 'stero mix' device - this is what your speakers output.
+//    Right click > Properties.
+// 4. In the Listen tab for the mix device, check the 'listen to this device'
+//    checkbox. Ensure the mix device is the default recording device.
+// 5. Launch chrome and try playing a video with sound. You should see
+//    in the volume meter for the mix device. Configure the mix device to have
+//    50 / 100 in level. Also go into the playback tab, right-click Speakers,
+//    and set that level to 50 / 100. Otherwise you will get distortion in
+//    the recording.
+class WebrtcAudioQualityBrowserTest : public WebRtcTestBase {
+ public:
+  WebrtcAudioQualityBrowserTest()
+      : peerconnection_server_(base::kNullProcessHandle) {}
+
+  virtual void SetUp() OVERRIDE {
+    RunPeerConnectionServer();
+    InProcessBrowserTest::SetUp();
+  }
+
+  virtual void TearDown() OVERRIDE {
+    ShutdownPeerConnectionServer();
+    InProcessBrowserTest::TearDown();
+  }
+
+  virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
+    // TODO(phoglund): check that user actually has the requisite devices and
+    // print a nice message if not; otherwise the test just times out which can
+    // be confusing.
+    // This test expects real device handling and requires a real webcam / audio
+    // device; it will not work with fake devices.
+    EXPECT_FALSE(command_line->HasSwitch(
+        switches::kUseFakeDeviceForMediaStream));
+    EXPECT_FALSE(command_line->HasSwitch(
+        switches::kUseFakeUIForMediaStream));
+
+    // Ensure we have the stuff we need.
+    base::FilePath reference_file =
+        GetTestDataDir().Append(kMediaPath).Append(kReferenceFile);
+    EXPECT_TRUE(base::PathExists(reference_file))
+        << "Cannot find the reference file to be used for audio quality "
+        << "comparison: " << reference_file.value();
+  }
+
+  void AddAudioFile(const base::FilePath& input_file_relative,
+                    content::WebContents* tab_contents) {
+    EXPECT_EQ("ok-added", ExecuteJavascript(
+        base::StringPrintf("addAudioFile('%s')",
+                           input_file_relative.value().c_str()), tab_contents));
+  }
+
+  void PlayAudioFile(content::WebContents* tab_contents) {
+    EXPECT_EQ("ok-playing", ExecuteJavascript("playAudioFile()", tab_contents));
+  }
+
+  // Convenience method which executes the provided javascript in the context
+  // of the provided web contents and returns what it evaluated to.
+  std::string ExecuteJavascript(const std::string& javascript,
+                                content::WebContents* tab_contents) {
+    std::string result;
+    EXPECT_TRUE(content::ExecuteScriptAndExtractString(
+        tab_contents, javascript, &result));
+    return result;
+  }
+
+  // Ensures we didn't get any errors asynchronously (e.g. while no javascript
+  // call from this test was outstanding).
+  // TODO(phoglund): this becomes obsolete when we switch to communicating with
+  // the DOM message queue.
+  void AssertNoAsynchronousErrors(content::WebContents* tab_contents) {
+    EXPECT_EQ("ok-no-errors",
+              ExecuteJavascript("getAnyTestFailures()", tab_contents));
+  }
+
+  // The peer connection server lets our two tabs find each other and talk to
+  // each other (e.g. it is the application-specific "signaling solution").
+  void ConnectToPeerConnectionServer(const std::string peer_name,
+                                     content::WebContents* tab_contents) {
+    std::string javascript = base::StringPrintf(
+        "connect('http://localhost:8888', '%s');", peer_name.c_str());
+    EXPECT_EQ("ok-connected", ExecuteJavascript(javascript, tab_contents));
+  }
+
+  void EstablishCall(content::WebContents* from_tab,
+                     content::WebContents* to_tab) {
+    EXPECT_EQ("ok-negotiating",
+              ExecuteJavascript("negotiateCall()", from_tab));
+
+    // Ensure the call gets up on both sides.
+    EXPECT_TRUE(PollingWaitUntil("getPeerConnectionReadyState()",
+                                 "active", from_tab));
+    EXPECT_TRUE(PollingWaitUntil("getPeerConnectionReadyState()",
+                                 "active", to_tab));
+  }
+
+  void HangUp(content::WebContents* from_tab) {
+    EXPECT_EQ("ok-call-hung-up", ExecuteJavascript("hangUp()", from_tab));
+  }
+
+  void WaitUntilHangupVerified(content::WebContents* tab_contents) {
+    EXPECT_TRUE(PollingWaitUntil("getPeerConnectionReadyState()",
+                                 "no-peer-connection", tab_contents));
+  }
+
+  base::FilePath CreateTemporaryWaveFile() {
+    base::FilePath filename;
+    EXPECT_TRUE(file_util::CreateTemporaryFile(&filename));
+    base::FilePath wav_filename =
+        filename.AddExtension(FILE_PATH_LITERAL(".wav"));
+    EXPECT_TRUE(base::Move(filename, wav_filename));
+    return wav_filename;
+  }
+
+ private:
+  void RunPeerConnectionServer() {
+    base::FilePath peerconnection_server;
+    EXPECT_TRUE(PathService::Get(base::DIR_MODULE, &peerconnection_server));
+    peerconnection_server = peerconnection_server.Append(kPeerConnectionServer);
+
+    EXPECT_TRUE(base::PathExists(peerconnection_server)) <<
+        "Missing peerconnection_server. You must build "
+        "it so it ends up next to the browser test binary.";
+    EXPECT_TRUE(base::LaunchProcess(
+        CommandLine(peerconnection_server),
+        base::LaunchOptions(),
+        &peerconnection_server_)) << "Failed to launch peerconnection_server.";
+  }
+
+  void ShutdownPeerConnectionServer() {
+    EXPECT_TRUE(base::KillProcess(peerconnection_server_, 0, false)) <<
+        "Failed to shut down peerconnection_server!";
+  }
+
+  base::ProcessHandle peerconnection_server_;
+};
+
+class AudioRecorder {
+ public:
+  AudioRecorder(): recording_application_(base::kNullProcessHandle) {}
+  ~AudioRecorder() {}
+
+  void StartRecording(int duration_sec, const base::FilePath& output_file,
+                      bool mono) {
+    EXPECT_EQ(base::kNullProcessHandle, recording_application_)
+        << "Tried to record, but is already recording.";
+
+    CommandLine command_line(CommandLine::NO_PROGRAM);
+#if defined(OS_WIN)
+    NOTREACHED();  // TODO(phoglund): implement.
+#else
+    int num_channels = mono ? 1 : 2;
+    command_line.SetProgram(base::FilePath("arecord"));
+    command_line.AppendArg("-d");
+    command_line.AppendArg(base::StringPrintf("%d", duration_sec));
+    command_line.AppendArg("-f");
+    command_line.AppendArg("dat");
+    command_line.AppendArg("-c");
+    command_line.AppendArg(base::StringPrintf("%d", num_channels));
+    command_line.AppendArgPath(output_file);
+#endif
+
+    LOG(INFO) << "Running " << command_line.GetCommandLineString();
+    EXPECT_TRUE(base::LaunchProcess(
+        command_line,
+        base::LaunchOptions(),
+        &recording_application_)) << "Failed to launch recording application.";
+  }
+
+  void WaitForRecordingToEnd() {
+    int exit_code;
+    EXPECT_TRUE(base::WaitForExitCode(recording_application_, &exit_code)) <<
+        "Failed to wait for recording to end.";
+    EXPECT_EQ(0, exit_code);
+  }
+ private:
+  base::ProcessHandle recording_application_;
+};
+
+void ForceMicrophoneVolumeTo100Percent() {
+#if defined(OS_WIN)
+  NOTREACHED();  // TODO(phoglund): implement.
+#else
+  const std::string kRecordingDeviceId = "render.monitor";
+  const std::string kHundredPercentVolume = "65536";
+
+  CommandLine command_line(base::FilePath(FILE_PATH_LITERAL("pacmd")));
+  command_line.AppendArg("set-source-volume");
+  command_line.AppendArg(kRecordingDeviceId);
+  command_line.AppendArg(kHundredPercentVolume);
+  LOG(INFO) << "Running " << command_line.GetCommandLineString();
+  std::string result;
+  if (!base::GetAppOutput(command_line, &result)) {
+    // It's hard to figure out for instance the default PA recording device name
+    // for different systems, so just warn here. Users will most often have a
+    // reasonable mic level on their systems.
+    LOG(WARNING) << "Failed to set mic volume to 100% on your system. " <<
+        "The test may fail or have results distorted; please ensure that " <<
+        "your mic level is 100% manually.";
+  }
+#endif
+}
+
+// Removes silence from beginning and end of the |input_audio_file| and writes
+// the result to the |output_audio_file|.
+void RemoveSilence(const base::FilePath& input_file,
+                   const base::FilePath& output_file) {
+  // SOX documentation for silence command: http://sox.sourceforge.net/sox.html
+  // To remove the silence from both beginning and end of the audio file, we
+  // call sox silence command twice: once on normal file and again on its
+  // reverse, then we reverse the final output.
+  // Silence parameters are (in sequence):
+  // ABOVE_PERIODS: The period for which silence occurs. Value 1 is used for
+  //                 silence at beginning of audio.
+  // DURATION: the amount of time in seconds that non-silence must be detected
+  //           before sox stops trimming audio.
+  // THRESHOLD: value used to indicate what sample value is treates as silence.
+  const char* kAbovePeriods = "1";
+  const char* kDuration = "2";
+  const char* kTreshold = "5%";
+
+  CommandLine command_line(base::FilePath(FILE_PATH_LITERAL("sox")));
+  command_line.AppendArgPath(input_file);
+  command_line.AppendArgPath(output_file);
+  command_line.AppendArg("silence");
+  command_line.AppendArg(kAbovePeriods);
+  command_line.AppendArg(kDuration);
+  command_line.AppendArg(kTreshold);
+  command_line.AppendArg("reverse");
+  command_line.AppendArg("silence");
+  command_line.AppendArg(kAbovePeriods);
+  command_line.AppendArg(kDuration);
+  command_line.AppendArg(kTreshold);
+  command_line.AppendArg("reverse");
+
+  LOG(INFO) << "Running " << command_line.GetCommandLineString();
+  std::string result;
+  EXPECT_TRUE(base::GetAppOutput(command_line, &result))
+      << "Failed to launch sox.";
+  LOG(INFO) << "Output was:\n\n" << result;
+}
+
+bool CanParseAsFloat(const std::string& value) {
+  return atof(value.c_str()) != 0 || value == "0";
+}
+
+// Runs PESQ to compare |reference_file| to a |actual_file|. The |sample_rate|
+// can be either 16000 or 8000.
+//
+// PESQ is only mono-aware, so the files should preferably be recorded in mono.
+// Furthermore it expects the file to be 16 rather than 32 bits, even though
+// 32 bits might work. The audio bandwidth of the two files should be the same
+// e.g. don't compare a 32 kHz file to a 8 kHz file.
+//
+// The raw score in MOS is written to |raw_mos|, whereas the MOS-LQO score is
+// written to mos_lqo. The scores are returned as floats in string form (e.g.
+// "3.145", etc).
+void RunPesq(const base::FilePath& reference_file,
+             const base::FilePath& actual_file,
+             int sample_rate, std::string* raw_mos, std::string* mos_lqo) {
+  // PESQ will break if the paths are too long (!).
+  EXPECT_LT(reference_file.value().length(), 128u);
+  EXPECT_LT(actual_file.value().length(), 128u);
+
+  base::FilePath pesq_path =
+      GetTestDataDir().Append(kToolsPath).Append(FILE_PATH_LITERAL("pesq"));
+  CommandLine command_line(pesq_path);
+  command_line.AppendArg(base::StringPrintf("+%d", sample_rate));
+  command_line.AppendArgPath(reference_file);
+  command_line.AppendArgPath(actual_file);
+
+  LOG(INFO) << "Running " << command_line.GetCommandLineString();
+  std::string result;
+  EXPECT_TRUE(base::GetAppOutput(command_line, &result))
+      << "Failed to launch pesq.";
+  LOG(INFO) << "Output was:\n\n" << result;
+
+  const std::string result_anchor = "Prediction (Raw MOS, MOS-LQO):  = ";
+  std::size_t anchor_pos = result.find(result_anchor);
+  EXPECT_NE(std::string::npos, anchor_pos);
+
+  // There are two tab-separated numbers on the format x.xxx, e.g. 5 chars each.
+  std::size_t first_number_pos = anchor_pos + result_anchor.length();
+  *raw_mos = result.substr(first_number_pos, 5);
+  EXPECT_TRUE(CanParseAsFloat(*raw_mos)) << "Failed to parse raw MOS number.";
+  *mos_lqo = result.substr(first_number_pos + 5 + 1, 5);
+  EXPECT_TRUE(CanParseAsFloat(*mos_lqo)) << "Failed to parse MOS LQO number.";
+}
+
+#if defined(OS_LINUX)
+// Only implemented on Linux for now.
+#define MAYBE_MANUAL_TestAudioQuality MANUAL_TestAudioQuality
+#else
+#define MAYBE_MANUAL_TestAudioQuality DISABLED_MANUAL_TestAudioQuality
+#endif
+
+IN_PROC_BROWSER_TEST_F(WebrtcAudioQualityBrowserTest,
+                       MAYBE_MANUAL_TestAudioQuality) {
+  EXPECT_TRUE(test_server()->Start());
+
+  ForceMicrophoneVolumeTo100Percent();
+
+  ui_test_utils::NavigateToURL(
+      browser(), test_server()->GetURL(kMainWebrtcTestHtmlPage));
+  content::WebContents* left_tab =
+      browser()->tab_strip_model()->GetActiveWebContents();
+
+  chrome::AddBlankTabAt(browser(), -1, true);
+  content::WebContents* right_tab =
+      browser()->tab_strip_model()->GetActiveWebContents();
+  ui_test_utils::NavigateToURL(
+        browser(), test_server()->GetURL(kMainWebrtcTestHtmlPage));
+
+  ConnectToPeerConnectionServer("peer 1", left_tab);
+  ConnectToPeerConnectionServer("peer 2", right_tab);
+
+  EXPECT_EQ("ok-peerconnection-created",
+            ExecuteJavascript("preparePeerConnection()", left_tab));
+
+  base::FilePath reference_file =
+      base::FilePath(kMediaPath).Append(kReferenceFile);
+
+  // The javascript will load the reference file relative to its location,
+  // which is in /webrtc on the web server. Therefore, prepend a '..' traversal.
+  AddAudioFile(base::FilePath(FILE_PATH_LITERAL("..")).Append(reference_file),
+               left_tab);
+
+  EstablishCall(left_tab, right_tab);
+
+  // Note: the media flow isn't necessarily established on the connection just
+  // because the ready state is ok on both sides. We sleep a bit between call
+  // establishment and playing to avoid cutting of the beginning of the audio
+  // file.
+  SleepInJavascript(left_tab, 2000);
+
+  base::FilePath recording = CreateTemporaryWaveFile();
+
+  // Note: the sound clip is about 10 seconds: record for 15 seconds to get some
+  // safety margins on each side.
+  AudioRecorder recorder;
+  static int kRecordingTimeSeconds = 15;
+  recorder.StartRecording(kRecordingTimeSeconds, recording, true);
+
+  PlayAudioFile(left_tab);
+
+  recorder.WaitForRecordingToEnd();
+  LOG(INFO) << "Done recording to " << recording.value() << std::endl;
+
+  AssertNoAsynchronousErrors(left_tab);
+  AssertNoAsynchronousErrors(right_tab);
+
+  HangUp(left_tab);
+  WaitUntilHangupVerified(left_tab);
+  WaitUntilHangupVerified(right_tab);
+
+  AssertNoAsynchronousErrors(left_tab);
+  AssertNoAsynchronousErrors(right_tab);
+
+  base::FilePath trimmed_recording = CreateTemporaryWaveFile();
+
+  RemoveSilence(recording, trimmed_recording);
+  LOG(INFO) << "Trimmed silence: " << trimmed_recording.value() << std::endl;
+
+  std::string raw_mos;
+  std::string mos_lqo;
+  base::FilePath reference_file_in_test_dir =
+      GetTestDataDir().Append(reference_file);
+  RunPesq(reference_file_in_test_dir, trimmed_recording, 16000, &raw_mos,
+          &mos_lqo);
+
+  perf_test::PrintResult("audio_pesq", "", "raw_mos", raw_mos, "score", true);
+  perf_test::PrintResult("audio_pesq", "", "mos_lqo", mos_lqo, "score", true);
+
+  EXPECT_TRUE(base::DeleteFile(recording, false));
+  EXPECT_TRUE(base::DeleteFile(trimmed_recording, false));
+}
diff --git a/chrome/browser/media/desktop_media_picker.h b/chrome/browser/media/desktop_media_picker.h
index 8720698..18f8ab3 100644
--- a/chrome/browser/media/desktop_media_picker.h
+++ b/chrome/browser/media/desktop_media_picker.h
@@ -8,15 +8,17 @@
 #include "base/basictypes.h"
 #include "base/callback_forward.h"
 #include "base/memory/scoped_ptr.h"
-#include "chrome/browser/media/desktop_media_picker_model.h"
+#include "base/strings/string16.h"
+#include "content/public/common/desktop_media_id.h"
 #include "ui/gfx/native_widget_types.h"
 
+class DesktopMediaPickerModel;
 
 // Abstract interface for desktop media picker UI. It's used by Desktop Media
 // API to let user choose a desktop media source.
 class DesktopMediaPicker {
  public:
-  typedef base::Callback<void(DesktopMediaPickerModel::SourceId)> DoneCallback;
+  typedef base::Callback<void(content::DesktopMediaID)> DoneCallback;
 
   // Creates default implementation of DesktopMediaPicker for the current
   // platform.
diff --git a/chrome/browser/media/desktop_media_picker_model.cc b/chrome/browser/media/desktop_media_picker_model.cc
index 37f4959..878d04f 100644
--- a/chrome/browser/media/desktop_media_picker_model.cc
+++ b/chrome/browser/media/desktop_media_picker_model.cc
@@ -22,6 +22,7 @@
 #include "ui/gfx/skia_util.h"
 
 using content::BrowserThread;
+using content::DesktopMediaID;
 
 namespace {
 
@@ -74,34 +75,13 @@
 
 }  // namespace
 
-DesktopMediaPickerModel::SourceId::SourceId()
-    : type(content::MEDIA_NO_SERVICE),
-      id(0) {
-}
-
-DesktopMediaPickerModel::SourceId::SourceId(content::MediaStreamType type,
-                                            intptr_t id)
-    : type(type),
-      id(id) {
-}
-
-DesktopMediaPickerModel::Source::Source(SourceId id, const string16 name)
+DesktopMediaPickerModel::Source::Source(DesktopMediaID id, const string16& name)
     : id(id),
       name(name) {
 }
 
-bool DesktopMediaPickerModel::SourceId::operator<(
-    const DesktopMediaPickerModel::SourceId& other) const {
-  return type < other.type || (type == other.type && id < other.id);
-}
-
-bool DesktopMediaPickerModel::SourceId::operator==(
-    const DesktopMediaPickerModel::SourceId& other) const {
-  return type == other.type && id == other.id;
-}
-
 DesktopMediaPickerModel::SourceDescription::SourceDescription(
-    DesktopMediaPickerModel::SourceId id,
+    DesktopMediaID id,
     const string16& name)
     : id(id),
       name(name) {
@@ -118,7 +98,7 @@
   void Refresh(const gfx::Size& thumbnail_size);
 
  private:
-  typedef std::map<SourceId, uint32> ImageHashesMap;
+  typedef std::map<DesktopMediaID, uint32> ImageHashesMap;
 
   // webrtc::DesktopCapturer::Callback interface.
   virtual webrtc::SharedMemory* CreateSharedMemory(size_t size) OVERRIDE;
@@ -156,8 +136,8 @@
 
   if (screen_capturer_) {
     // TODO(sergeyu): Enumerate each screen when ScreenCapturer supports it.
-    sources.push_back(SourceDescription(SourceId(
-        content::MEDIA_SCREEN_VIDEO_CAPTURE, 0),
+    sources.push_back(SourceDescription(DesktopMediaID(
+        DesktopMediaID::TYPE_SCREEN, 0),
         l10n_util::GetStringUTF16(IDS_DESKTOP_MEDIA_PICKER_SCREEN_NAME)));
   }
 
@@ -167,8 +147,7 @@
       for (webrtc::WindowCapturer::WindowList::iterator it = windows.begin();
            it != windows.end(); ++it) {
         sources.push_back(SourceDescription(
-            DesktopMediaPickerModel::SourceId(
-                content::MEDIA_WINDOW_VIDEO_CAPTURE, it->id),
+            DesktopMediaID(DesktopMediaID::TYPE_WINDOW, it->id),
             base::UTF8ToUTF16(it->title)));
       }
     }
@@ -188,12 +167,12 @@
   for (size_t i = 0; i < sources.size(); ++i) {
     SourceDescription& source = sources[i];
     switch (source.id.type) {
-      case content::MEDIA_SCREEN_VIDEO_CAPTURE:
+      case DesktopMediaID::TYPE_SCREEN:
         screen_capturer_->Capture(webrtc::DesktopRegion());
         DCHECK(current_frame_);
         break;
 
-      case content::MEDIA_WINDOW_VIDEO_CAPTURE:
+      case DesktopMediaID::TYPE_WINDOW:
         if (!window_capturer_->SelectWindow(source.id.id))
           continue;
         window_capturer_->Capture(webrtc::DesktopRegion());
diff --git a/chrome/browser/media/desktop_media_picker_model.h b/chrome/browser/media/desktop_media_picker_model.h
index 8dfe9b7..494a325 100644
--- a/chrome/browser/media/desktop_media_picker_model.h
+++ b/chrome/browser/media/desktop_media_picker_model.h
@@ -9,7 +9,7 @@
 #include "base/memory/scoped_ptr.h"
 #include "base/memory/weak_ptr.h"
 #include "base/sequenced_task_runner.h"
-#include "content/public/common/media_stream_request.h"
+#include "content/public/common/desktop_media_id.h"
 #include "ui/gfx/image/image_skia.h"
 
 namespace webrtc {
@@ -35,23 +35,12 @@
     virtual void OnSourceThumbnailChanged(int index) = 0;
   };
 
-  // Type used to identify desktop media sources.
-  struct SourceId {
-    SourceId();
-    SourceId(content::MediaStreamType type, intptr_t id);
-    bool operator<(const SourceId& other) const;
-    bool operator==(const SourceId& other) const;
-
-    content::MediaStreamType type;
-    intptr_t id;
-  };
-
   // Struct used to represent each entry in the model.
   struct Source {
-    Source(SourceId id, const string16 name);
+    Source(content::DesktopMediaID id, const string16& name);
 
     // Id of the source.
-    SourceId id;
+    content::DesktopMediaID id;
 
     // Name of the source that should be shown to the user.
     string16 name;
@@ -97,9 +86,9 @@
 
   // Struct used to represent sources list the model gets from the Worker.
   struct SourceDescription {
-    SourceDescription(SourceId id, const string16& name);
+    SourceDescription(content::DesktopMediaID id, const string16& name);
 
-    SourceId id;
+    content::DesktopMediaID id;
     string16 name;
   };
 
diff --git a/chrome/browser/media/desktop_media_picker_model_unittest.cc b/chrome/browser/media/desktop_media_picker_model_unittest.cc
index 6cd5fa1..3d2112c 100644
--- a/chrome/browser/media/desktop_media_picker_model_unittest.cc
+++ b/chrome/browser/media/desktop_media_picker_model_unittest.cc
@@ -186,9 +186,9 @@
 
   message_loop_.Run();
 
-  EXPECT_EQ(model_.source(0).id.type, content::MEDIA_SCREEN_VIDEO_CAPTURE);
+  EXPECT_EQ(model_.source(0).id.type, content::DesktopMediaID::TYPE_SCREEN);
   EXPECT_EQ(model_.source(0).id.id, 0);
-  EXPECT_EQ(model_.source(1).id.type, content::MEDIA_WINDOW_VIDEO_CAPTURE);
+  EXPECT_EQ(model_.source(1).id.type, content::DesktopMediaID::TYPE_WINDOW);
   EXPECT_EQ(model_.source(1).id.id, 0);
   EXPECT_EQ(model_.source(1).name, UTF8ToUTF16(window.title));
 }
@@ -217,7 +217,7 @@
 
   message_loop_.Run();
 
-  EXPECT_EQ(model_.source(0).id.type, content::MEDIA_WINDOW_VIDEO_CAPTURE);
+  EXPECT_EQ(model_.source(0).id.type, content::DesktopMediaID::TYPE_WINDOW);
 }
 
 TEST_F(DesktopMediaPickerModelTest, ScreenOnly) {
@@ -236,7 +236,7 @@
 
   message_loop_.Run();
 
-  EXPECT_EQ(model_.source(0).id.type, content::MEDIA_SCREEN_VIDEO_CAPTURE);
+  EXPECT_EQ(model_.source(0).id.type, content::DesktopMediaID::TYPE_SCREEN);
 }
 
 TEST_F(DesktopMediaPickerModelTest, AddWindow) {
@@ -276,7 +276,7 @@
 
   message_loop_.Run();
 
-  EXPECT_EQ(model_.source(1).id.type, content::MEDIA_WINDOW_VIDEO_CAPTURE);
+  EXPECT_EQ(model_.source(1).id.type, content::DesktopMediaID::TYPE_WINDOW);
   EXPECT_EQ(model_.source(1).id.id, 0);
 }
 
diff --git a/chrome/browser/media/media_capture_devices_dispatcher.cc b/chrome/browser/media/media_capture_devices_dispatcher.cc
index 03ca4c5..936257e 100644
--- a/chrome/browser/media/media_capture_devices_dispatcher.cc
+++ b/chrome/browser/media/media_capture_devices_dispatcher.cc
@@ -30,6 +30,7 @@
 #include "content/public/browser/notification_source.h"
 #include "content/public/browser/notification_types.h"
 #include "content/public/browser/web_contents.h"
+#include "content/public/common/desktop_media_id.h"
 #include "content/public/common/media_stream_request.h"
 #include "extensions/common/constants.h"
 #include "grit/generated_resources.h"
@@ -179,7 +180,7 @@
     const extensions::Extension* extension) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
 
-  if (request.video_type == content::MEDIA_SCREEN_VIDEO_CAPTURE ||
+  if (request.video_type == content::MEDIA_DESKTOP_VIDEO_CAPTURE ||
       request.audio_type == content::MEDIA_SYSTEM_AUDIO_CAPTURE) {
     ProcessScreenCaptureAccessRequest(
         web_contents, request, callback, extension);
@@ -197,10 +198,41 @@
     const content::MediaStreamRequest& request,
     const content::MediaResponseCallback& callback,
     const extensions::Extension* extension) {
-  const bool component_extension =
-    extension && extension->location() == extensions::Manifest::COMPONENT;
-
   content::MediaStreamDevices devices;
+  scoped_ptr<content::MediaStreamUI> ui;
+
+  if (request.video_type != content::MEDIA_DESKTOP_VIDEO_CAPTURE) {
+    callback.Run(devices, ui.Pass());
+    return;
+  }
+
+  content::DesktopMediaID media_id =
+      content::DesktopMediaID::Parse(request.requested_video_device_id);
+  if (media_id.is_null()) {
+    LOG(ERROR) << "Invalid desktop media ID: "
+               << request.requested_video_device_id;
+    callback.Run(devices, ui.Pass());
+    return;
+  }
+
+  const bool system_audio_capture_requested =
+      request.audio_type == content::MEDIA_SYSTEM_AUDIO_CAPTURE;
+
+#if defined(USE_CRAS)
+  const bool system_audio_capture_supported = true;
+#else
+  const bool system_audio_capture_supported = false;
+#endif
+
+  // Reject request when audio capture was requested but is not supported on
+  // this system.
+  if (system_audio_capture_requested && !system_audio_capture_supported) {
+    callback.Run(devices, ui.Pass());
+    return;
+  }
+
+  const bool component_extension =
+      extension && extension->location() == extensions::Manifest::COMPONENT;
 
   const bool screen_capture_enabled =
       CommandLine::ForCurrentProcess()->HasSwitch(
@@ -213,27 +245,11 @@
       CommandLine::ForCurrentProcess()->HasSwitch(
           switches::kAllowHttpScreenCapture);
 
-  const bool screen_video_capture_requested =
-      request.video_type == content::MEDIA_SCREEN_VIDEO_CAPTURE;
-
-  const bool system_audio_capture_requested =
-      request.audio_type == content::MEDIA_SYSTEM_AUDIO_CAPTURE;
-
-#if defined(USE_CRAS)
-  const bool system_audio_capture_supported = true;
-#else
-  const bool system_audio_capture_supported = false;
-#endif
-
   // Approve request only when the following conditions are met:
   //  1. Screen capturing is enabled via command line switch or white-listed for
   //     the given origin.
   //  2. Request comes from a page with a secure origin or from an extension.
-  //  3. Video capture is requested for screen video.
-  //  4. Audio capture is either not requested, or requested for system audio.
-  if (screen_capture_enabled && origin_is_secure &&
-      screen_video_capture_requested &&
-      (!system_audio_capture_requested || system_audio_capture_supported)) {
+  if (screen_capture_enabled && origin_is_secure) {
     // For component extensions, bypass message box.
     bool user_approved = false;
     if (!component_extension) {
@@ -254,7 +270,7 @@
 
     if (user_approved || component_extension) {
       devices.push_back(content::MediaStreamDevice(
-          content::MEDIA_SCREEN_VIDEO_CAPTURE, std::string(), "Screen"));
+          content::MEDIA_DESKTOP_VIDEO_CAPTURE, media_id.ToString(), "Screen"));
       if (system_audio_capture_requested) {
 #if defined(USE_CRAS)
         // Use the special loopback device ID for system audio capture.
@@ -267,7 +283,6 @@
     }
   }
 
-  scoped_ptr<content::MediaStreamUI> ui;
   // Unless we're being invoked from a component extension, register to display
   // the notification for stream capture.
   if (!devices.empty() && !component_extension) {
@@ -282,6 +297,7 @@
     ui = ScreenCaptureNotificationUI::Create(l10n_util::GetStringFUTF16(
         IDS_MEDIA_SCREEN_CAPTURE_NOTIFICATION_TEXT, UTF8ToUTF16(title)));
   }
+
   callback.Run(devices, ui.Pass());
 }
 
diff --git a/chrome/browser/media/webrtc_browsertest_common.h b/chrome/browser/media/webrtc_browsertest_common.h
index 34b9c6a..23ec4e7 100644
--- a/chrome/browser/media/webrtc_browsertest_common.h
+++ b/chrome/browser/media/webrtc_browsertest_common.h
@@ -13,6 +13,10 @@
 class WebContents;
 }
 
+// Executes javascript code which will sleep for |timeout_msec| milliseconds.
+// Returns true on success.
+bool SleepInJavascript(content::WebContents* tab_contents, int timeout_msec);
+
 // This function will execute the provided |javascript| until it causes a call
 // to window.domAutomationController.send() with |evaluates_to| as the message.
 // That is, we are NOT checking what the javascript evaluates to. Returns false
diff --git a/chrome/browser/media_galleries/fileapi/media_file_validator_unittest.cc b/chrome/browser/media_galleries/fileapi/media_file_validator_browsertest.cc
similarity index 78%
rename from chrome/browser/media_galleries/fileapi/media_file_validator_unittest.cc
rename to chrome/browser/media_galleries/fileapi/media_file_validator_browsertest.cc
index 5fde5e4..91901bf 100644
--- a/chrome/browser/media_galleries/fileapi/media_file_validator_unittest.cc
+++ b/chrome/browser/media_galleries/fileapi/media_file_validator_browsertest.cc
@@ -9,6 +9,7 @@
 #include "base/files/scoped_temp_dir.h"
 #include "base/message_loop/message_loop.h"
 #include "base/message_loop/message_loop_proxy.h"
+#include "base/path_service.h"
 #include "chrome/browser/media_galleries/fileapi/media_file_system_backend.h"
 #include "chrome/test/base/in_process_browser_test.h"
 #include "content/public/test/browser_test.h"
@@ -32,7 +33,7 @@
                            "\x01\0\x01\0\x2F\x9D\xCE\xE7s\xA8((((\x01\x9CK(\0"
                            "\x05\xCE\xB3l\0\0\xFE\xD8\x80\0\0";
 
-const char kInvalidImage[] = "Not an image";
+const char kInvalidMediaFile[] = "Not a media file";
 
 const int64 kNoFileSize = -1;
 
@@ -55,6 +56,13 @@
   callback.Run(false);
 }
 
+base::FilePath GetMediaTestDir() {
+  base::FilePath test_file;
+  if (!PathService::Get(base::DIR_SOURCE_ROOT, &test_file))
+    return base::FilePath();
+  return test_file.AppendASCII("media").AppendASCII("test").AppendASCII("data");
+}
+
 }  // namespace
 
 namespace chrome {
@@ -78,6 +86,19 @@
     loop_runner_->Run();
   }
 
+  // Write |source| into |filename| in a test file system and try to move it
+  // into a media file system.  The result is compared to |expected_result|.
+  void MoveTestFromFile(const std::string& filename,
+                        const base::FilePath& source, bool expected_result) {
+    content::BrowserThread::PostTask(
+        content::BrowserThread::FILE,
+        FROM_HERE,
+        base::Bind(&MediaFileValidatorTest::SetupFromFileOnFileThread,
+                   base::Unretained(this), filename, source, expected_result));
+    loop_runner_ = new content::MessageLoopRunner;
+    loop_runner_->Run();
+  }
+
  private:
   // Create the test files, filesystem objects, etc.
   void SetupOnFileThread(const std::string& filename,
@@ -129,6 +150,14 @@
                               base::Unretained(this), expected_result)));
   }
 
+  void SetupFromFileOnFileThread(const std::string& filename,
+                                 const base::FilePath& source,
+                                 bool expected_result) {
+    std::string content;
+    ASSERT_TRUE(file_util::ReadFileToString(source, &content));
+    SetupOnFileThread(filename, content, expected_result);
+  }
+
   // Check that exactly one of |move_src_| and |move_dest_| exists.
   // |src_expected| indicates which one should exist.  When complete,
   // |callback| is called with success/failure.
@@ -212,17 +241,43 @@
   DISALLOW_COPY_AND_ASSIGN(MediaFileValidatorTest);
 };
 
+IN_PROC_BROWSER_TEST_F(MediaFileValidatorTest, UnsupportedExtension) {
+  MoveTest("a.txt", std::string(kValidImage, arraysize(kValidImage)), false);
+}
+
 IN_PROC_BROWSER_TEST_F(MediaFileValidatorTest, ValidImage) {
   MoveTest("a.webp", std::string(kValidImage, arraysize(kValidImage)), true);
 }
 
 IN_PROC_BROWSER_TEST_F(MediaFileValidatorTest, InvalidImage) {
-  MoveTest("a.webp", std::string(kInvalidImage, arraysize(kInvalidImage)),
-           false);
+  MoveTest("a.webp", std::string(kInvalidMediaFile,
+           arraysize(kInvalidMediaFile)), false);
 }
 
-IN_PROC_BROWSER_TEST_F(MediaFileValidatorTest, UnsupportedExtension) {
-  MoveTest("a.txt", std::string(kValidImage, arraysize(kValidImage)), false);
+IN_PROC_BROWSER_TEST_F(MediaFileValidatorTest, InvalidAudio) {
+  MoveTest("a.ogg", std::string(kInvalidMediaFile,
+           arraysize(kInvalidMediaFile)), false);
+}
+
+IN_PROC_BROWSER_TEST_F(MediaFileValidatorTest, ValidAudio) {
+  base::FilePath test_file = GetMediaTestDir();
+  ASSERT_FALSE(test_file.empty());
+  test_file = test_file.AppendASCII("sfx.ogg");
+  MoveTestFromFile("sfx.ogg", test_file, true);
+}
+
+IN_PROC_BROWSER_TEST_F(MediaFileValidatorTest, InvalidVideo) {
+  base::FilePath test_file = GetMediaTestDir();
+  ASSERT_FALSE(test_file.empty());
+  test_file = test_file.AppendASCII("no_streams.webm");
+  MoveTestFromFile("no_streams.webm", test_file, false);
+}
+
+IN_PROC_BROWSER_TEST_F(MediaFileValidatorTest, ValidVideo) {
+  base::FilePath test_file = GetMediaTestDir();
+  ASSERT_FALSE(test_file.empty());
+  test_file = test_file.AppendASCII("bear-320x240-multitrack.webm");
+  MoveTestFromFile("multitrack.webm", test_file, true);
 }
 
 }  // namespace chrome
diff --git a/chrome/browser/media_galleries/fileapi/media_file_validator_factory.cc b/chrome/browser/media_galleries/fileapi/media_file_validator_factory.cc
index e180460..ead22c1 100644
--- a/chrome/browser/media_galleries/fileapi/media_file_validator_factory.cc
+++ b/chrome/browser/media_galleries/fileapi/media_file_validator_factory.cc
@@ -6,6 +6,7 @@
 
 #include "base/files/file_path.h"
 #include "base/platform_file.h"
+#include "chrome/browser/media_galleries/fileapi/supported_audio_video_checker.h"
 #include "chrome/browser/media_galleries/fileapi/supported_image_type_validator.h"
 #include "webkit/browser/fileapi/copy_or_move_file_validator.h"
 #include "webkit/browser/fileapi/file_system_url.h"
@@ -50,7 +51,8 @@
   base::FilePath src_path = src.virtual_path();
   if (SupportedImageTypeValidator::SupportsFileType(src_path))
     return new SupportedImageTypeValidator(platform_path);
-  // TODO(vandebo): Support other file types.
+  if (SupportedAudioVideoChecker::SupportsFileType(src_path))
+    return new SupportedAudioVideoChecker(platform_path);
 
   return new InvalidFileValidator();
 }
diff --git a/chrome/browser/media_galleries/fileapi/safe_audio_video_checker.cc b/chrome/browser/media_galleries/fileapi/safe_audio_video_checker.cc
new file mode 100644
index 0000000..dbc55b0
--- /dev/null
+++ b/chrome/browser/media_galleries/fileapi/safe_audio_video_checker.cc
@@ -0,0 +1,91 @@
+// 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_galleries/fileapi/safe_audio_video_checker.h"
+
+#include "base/bind.h"
+#include "base/callback.h"
+#include "base/location.h"
+#include "base/logging.h"
+#include "base/process/process_handle.h"
+#include "chrome/common/chrome_utility_messages.h"
+#include "content/public/browser/child_process_data.h"
+#include "content/public/browser/utility_process_host.h"
+#include "content/public/browser/browser_thread.h"
+#include "ipc/ipc_message_macros.h"
+#include "ipc/ipc_platform_file.h"
+
+SafeAudioVideoChecker::SafeAudioVideoChecker(
+    const base::PlatformFile& file,
+    const fileapi::CopyOrMoveFileValidator::ResultCallback& callback)
+    : state_(INITIAL_STATE),
+      file_(file),
+      file_closer_(&file_),
+      callback_(callback) {
+  DCHECK(!callback.is_null());
+}
+
+void SafeAudioVideoChecker::Start() {
+  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
+  if (state_ != INITIAL_STATE)
+    return;
+  state_ = PINGED_STATE;
+
+  DCHECK(file_closer_);
+  if (*file_closer_.get() == base::kInvalidPlatformFileValue) {
+    callback_.Run(base::PLATFORM_FILE_ERROR_SECURITY);
+    state_ = FINISHED_STATE;
+    return;
+  }
+
+  utility_process_host_ = content::UtilityProcessHost::Create(
+      this, base::MessageLoopProxy::current())->AsWeakPtr();
+  utility_process_host_->EnableZygote();
+  utility_process_host_->Send(new ChromeUtilityMsg_StartupPing);
+}
+
+SafeAudioVideoChecker::~SafeAudioVideoChecker() {}
+
+void SafeAudioVideoChecker::OnProcessStarted() {
+  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
+  if (state_ != PINGED_STATE)
+    return;
+  state_ = STARTED_STATE;
+
+  if (utility_process_host_->GetData().handle == base::kNullProcessHandle)
+    DLOG(ERROR) << "Child process handle is null";
+  IPC::PlatformFileForTransit file_for_transit =
+      IPC::GetFileHandleForProcess(*file_closer_.release(),
+                                   utility_process_host_->GetData().handle,
+                                   true /* close_source_handle */);
+  const int64 kFileDecodeTimeInMS = 250;
+  utility_process_host_->Send(new ChromeUtilityMsg_CheckMediaFile(
+      kFileDecodeTimeInMS, file_for_transit));
+}
+
+void SafeAudioVideoChecker::OnCheckingFinished(bool valid) {
+  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
+  if (state_ != STARTED_STATE)
+    return;
+  state_ = FINISHED_STATE;
+
+  callback_.Run(valid ? base::PLATFORM_FILE_OK
+                      : base::PLATFORM_FILE_ERROR_SECURITY);
+}
+
+void SafeAudioVideoChecker::OnProcessCrashed(int exit_code) {
+  OnCheckingFinished(false);
+}
+
+bool SafeAudioVideoChecker::OnMessageReceived(const IPC::Message& message) {
+  bool handled = true;
+  IPC_BEGIN_MESSAGE_MAP(SafeAudioVideoChecker, message)
+    IPC_MESSAGE_HANDLER(ChromeUtilityHostMsg_ProcessStarted,
+        OnProcessStarted)
+    IPC_MESSAGE_HANDLER(ChromeUtilityHostMsg_CheckMediaFile_Finished,
+        OnCheckingFinished)
+    IPC_MESSAGE_UNHANDLED(handled = false)
+  IPC_END_MESSAGE_MAP()
+  return handled;
+}
diff --git a/chrome/browser/media_galleries/fileapi/safe_audio_video_checker.h b/chrome/browser/media_galleries/fileapi/safe_audio_video_checker.h
new file mode 100644
index 0000000..5ce8dfb
--- /dev/null
+++ b/chrome/browser/media_galleries/fileapi/safe_audio_video_checker.h
@@ -0,0 +1,72 @@
+// 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_GALLERIES_FILEAPI_SAFE_AUDIO_VIDEO_CHECKER_H_
+#define CHROME_BROWSER_MEDIA_GALLERIES_FILEAPI_SAFE_AUDIO_VIDEO_CHECKER_H_
+
+#include "base/basictypes.h"
+#include "base/callback_forward.h"
+#include "base/files/scoped_platform_file_closer.h"
+#include "base/memory/weak_ptr.h"
+#include "base/platform_file.h"
+#include "content/public/browser/utility_process_host_client.h"
+#include "webkit/browser/fileapi/copy_or_move_file_validator.h"
+
+namespace content {
+class UtilityProcessHost;
+}
+
+// Uses a utility process to validate a media file.  If the callback returns
+// PLATFORM_FILE_OK, then the file appears to be a valid media file. This does
+// not attempt to decode the entire file, which may take a considerable amount
+// of time.  This class may be constructed on any thread, but should run on the
+// IO thread.
+class SafeAudioVideoChecker : public content::UtilityProcessHostClient {
+ public:
+  // Takes responsibility for closing |file|.
+  SafeAudioVideoChecker(
+      const base::PlatformFile& file,
+      const fileapi::CopyOrMoveFileValidator::ResultCallback& callback);
+
+  // Must be called on the IO thread.
+  void Start();
+
+ private:
+  enum State {
+    INITIAL_STATE,
+    PINGED_STATE,
+    STARTED_STATE,
+    FINISHED_STATE
+  };
+
+  virtual ~SafeAudioVideoChecker();
+
+  // Starts validation once the utility process has been started.
+  virtual void OnProcessStarted();
+
+  // Notification of the result from the utility process.
+  void OnCheckingFinished(bool valid);
+
+  // UtilityProcessHostClient implementation.
+  virtual void OnProcessCrashed(int exit_code) OVERRIDE;
+  virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
+
+  State state_;
+
+  // This should be accessed through |file_closer_| to ensure it hasn't already
+  // been closed.
+  base::PlatformFile file_;
+
+  // Ensures that |file_| is closed if the utility process is not started for
+  // some reason.
+  base::ScopedPlatformFileCloser file_closer_;
+
+  const fileapi::CopyOrMoveFileValidator::ResultCallback callback_;
+
+  base::WeakPtr<content::UtilityProcessHost> utility_process_host_;
+
+  DISALLOW_COPY_AND_ASSIGN(SafeAudioVideoChecker);
+};
+
+#endif  // CHROME_BROWSER_MEDIA_GALLERIES_FILEAPI_SAFE_AUDIO_VIDEO_CHECKER_H_
diff --git a/chrome/browser/media_galleries/fileapi/supported_audio_video_checker.cc b/chrome/browser/media_galleries/fileapi/supported_audio_video_checker.cc
new file mode 100644
index 0000000..bed3c23
--- /dev/null
+++ b/chrome/browser/media_galleries/fileapi/supported_audio_video_checker.cc
@@ -0,0 +1,96 @@
+// 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_galleries/fileapi/supported_audio_video_checker.h"
+
+#include <set>
+#include <vector>
+
+#include "base/bind.h"
+#include "base/callback.h"
+#include "base/lazy_instance.h"
+#include "base/location.h"
+#include "base/logging.h"
+#include "base/stl_util.h"
+#include "chrome/browser/media_galleries/fileapi/safe_audio_video_checker.h"
+#include "content/public/browser/browser_thread.h"
+#include "net/base/mime_util.h"
+
+namespace {
+
+class SupportedAudioVideoExtensions {
+ public:
+  SupportedAudioVideoExtensions() {
+    std::vector<base::FilePath::StringType> extensions;
+    net::GetExtensionsForMimeType("audio/*", &extensions);
+    net::GetExtensionsForMimeType("video/*", &extensions);
+    for (size_t i = 0; i < extensions.size(); ++i) {
+      std::string mime_type;
+      if (net::GetWellKnownMimeTypeFromExtension(extensions[i], &mime_type) &&
+          net::IsSupportedMimeType(mime_type)) {
+        audio_video_extensions_.insert(
+            base::FilePath::kExtensionSeparator + extensions[i]);
+      }
+    }
+  };
+
+  bool HasSupportedAudioVideoExtension(const base::FilePath& file) {
+    return ContainsKey(audio_video_extensions_, file.Extension());
+  }
+
+ private:
+  std::set<base::FilePath::StringType> audio_video_extensions_;
+
+  DISALLOW_COPY_AND_ASSIGN(SupportedAudioVideoExtensions);
+};
+
+base::LazyInstance<SupportedAudioVideoExtensions> g_audio_video_extensions =
+    LAZY_INSTANCE_INITIALIZER;
+
+base::PlatformFile OpenOnFileThread(const base::FilePath& path) {
+  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::FILE));
+  return base::CreatePlatformFile(
+      path, base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_READ,
+      NULL /*created*/, NULL /*error_code*/);
+}
+
+}  // namespace
+
+SupportedAudioVideoChecker::~SupportedAudioVideoChecker() {}
+
+// static
+bool SupportedAudioVideoChecker::SupportsFileType(const base::FilePath& path) {
+  return g_audio_video_extensions.Get().HasSupportedAudioVideoExtension(path);
+}
+
+void SupportedAudioVideoChecker::StartPreWriteValidation(
+    const fileapi::CopyOrMoveFileValidator::ResultCallback& result_callback) {
+  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
+  DCHECK(callback_.is_null());
+  callback_ = result_callback;
+
+  content::BrowserThread::PostTaskAndReplyWithResult(
+      content::BrowserThread::FILE,
+      FROM_HERE,
+      base::Bind(&OpenOnFileThread, path_),
+      base::Bind(&SupportedAudioVideoChecker::OnFileOpen,
+                 weak_factory_.GetWeakPtr()));
+}
+
+SupportedAudioVideoChecker::SupportedAudioVideoChecker(
+    const base::FilePath& path)
+    : path_(path),
+      weak_factory_(this) {
+}
+
+void SupportedAudioVideoChecker::OnFileOpen(const base::PlatformFile& file) {
+  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
+  if (file == base::kInvalidPlatformFileValue) {
+    callback_.Run(base::PLATFORM_FILE_ERROR_SECURITY);
+    return;
+  }
+
+  safe_checker_ = new SafeAudioVideoChecker(file, callback_);
+  safe_checker_->Start();
+}
diff --git a/chrome/browser/media_galleries/fileapi/supported_audio_video_checker.h b/chrome/browser/media_galleries/fileapi/supported_audio_video_checker.h
new file mode 100644
index 0000000..d2dad4f
--- /dev/null
+++ b/chrome/browser/media_galleries/fileapi/supported_audio_video_checker.h
@@ -0,0 +1,49 @@
+// 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_GALLERIES_FILEAPI_SUPPORTED_AUDIO_VIDEO_CHECKER_H_
+#define CHROME_BROWSER_MEDIA_GALLERIES_FILEAPI_SUPPORTED_AUDIO_VIDEO_CHECKER_H_
+
+#include "base/basictypes.h"
+#include "base/files/file_path.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/weak_ptr.h"
+#include "base/platform_file.h"
+#include "chrome/browser/media_galleries/fileapi/av_scanning_file_validator.h"
+
+class SafeAudioVideoChecker;
+
+namespace chrome {
+class MediaFileValidatorFactory;
+}
+
+// Uses SafeAudioVideoChecker to validate supported audio and video files in
+// the utility process and then uses AVScanningFileValidator to ask the OS to
+// virus scan them. The entire file is not decoded so a positive result from
+// this class does not make the file safe to use in the browser process.
+class SupportedAudioVideoChecker : public chrome::AVScanningFileValidator {
+ public:
+  virtual ~SupportedAudioVideoChecker();
+
+  static bool SupportsFileType(const base::FilePath& path);
+
+  virtual void StartPreWriteValidation(
+      const ResultCallback& result_callback) OVERRIDE;
+
+ private:
+  friend class chrome::MediaFileValidatorFactory;
+
+  explicit SupportedAudioVideoChecker(const base::FilePath& file);
+
+  void OnFileOpen(const base::PlatformFile& file);
+
+  base::FilePath path_;
+  fileapi::CopyOrMoveFileValidator::ResultCallback callback_;
+  scoped_refptr<SafeAudioVideoChecker> safe_checker_;
+  base::WeakPtrFactory<SupportedAudioVideoChecker> weak_factory_;
+
+  DISALLOW_COPY_AND_ASSIGN(SupportedAudioVideoChecker);
+};
+
+#endif  // CHROME_BROWSER_MEDIA_GALLERIES_FILEAPI_SUPPORTED_AUDIO_VIDEO_CHECKER_H_
diff --git a/chrome/browser/media_galleries/media_galleries_preferences_unittest.cc b/chrome/browser/media_galleries/media_galleries_preferences_unittest.cc
index 5215905..e36df44 100644
--- a/chrome/browser/media_galleries/media_galleries_preferences_unittest.cc
+++ b/chrome/browser/media_galleries/media_galleries_preferences_unittest.cc
@@ -9,7 +9,6 @@
 #include "base/command_line.h"
 #include "base/memory/ref_counted.h"
 #include "base/memory/scoped_ptr.h"
-#include "base/message_loop/message_loop.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/values.h"
 #include "chrome/browser/extensions/extension_system.h"
@@ -22,7 +21,7 @@
 #include "chrome/common/extensions/background_info.h"
 #include "chrome/common/extensions/extension.h"
 #include "chrome/test/base/testing_profile.h"
-#include "content/public/test/test_browser_thread.h"
+#include "content/public/test/test_browser_thread_bundle.h"
 #include "grit/generated_resources.h"
 #include "sync/api/string_ordinal.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -72,17 +71,11 @@
       DeviceIdPrefIdsMap;
 
   MediaGalleriesPreferencesTest()
-      : ui_thread_(content::BrowserThread::UI, &loop_),
-        file_thread_(content::BrowserThread::FILE, &loop_),
-        profile_(new TestingProfile()),
+      : profile_(new TestingProfile()),
         default_galleries_count_(0) {
   }
 
   virtual ~MediaGalleriesPreferencesTest() {
-    // TestExtensionSystem uses DeleteSoon, so we need to delete the profile
-    // and then run the message queue to clean up.
-    profile_.reset();
-    base::MessageLoop::current()->RunUntilIdle();
   }
 
   virtual void SetUp() OVERRIDE {
@@ -240,9 +233,7 @@
 
  private:
   // Needed for extension service & friends to work.
-  base::MessageLoop loop_;
-  content::TestBrowserThread ui_thread_;
-  content::TestBrowserThread file_thread_;
+  content::TestBrowserThreadBundle thread_bundle_;
 
 #if defined OS_CHROMEOS
   chromeos::ScopedTestDeviceSettingsService test_device_settings_service_;
diff --git a/chrome/browser/metrics/metrics_log.cc b/chrome/browser/metrics/metrics_log.cc
index bb9d550..bebdad2 100644
--- a/chrome/browser/metrics/metrics_log.cc
+++ b/chrome/browser/metrics/metrics_log.cc
@@ -163,6 +163,9 @@
     case AutocompleteInput::INSTANT_NEW_TAB_PAGE_WITH_FAKEBOX_AS_STARTING_FOCUS:
       return OmniboxEventProto::
           INSTANT_NEW_TAB_PAGE_WITH_FAKEBOX_AS_STARTING_FOCUS;
+    case AutocompleteInput::SEARCH_RESULT_PAGE_NO_SEARCH_TERM_REPLACEMENT:
+      return OmniboxEventProto::
+          SEARCH_RESULT_PAGE_NO_SEARCH_TERM_REPLACEMENT;
   }
   return OmniboxEventProto::INVALID_SPEC;
 }
@@ -859,11 +862,11 @@
   omnibox_event->set_input_type(AsOmniboxEventInputType(log.input_type));
 
   // The view code to hide the top result is currently only implemented on the
-  // Mac.
-#if defined(OS_MACOSX)
+  // Mac and for views.
+#if defined(OS_MACOSX) || defined(TOOLKIT_VIEWS)
   omnibox_event->set_is_top_result_hidden_in_dropdown(
       log.result.ShouldHideTopMatch());
-#endif  // defined(OS_MACOSX)
+#endif  // defined(OS_MACOSX) || defined(TOOLKIT_VIEWS)
 
   for (AutocompleteResult::const_iterator i(log.result.begin());
        i != log.result.end(); ++i) {
diff --git a/chrome/browser/metrics/metrics_service.cc b/chrome/browser/metrics/metrics_service.cc
index 3e8d17a..5c6a8e2 100644
--- a/chrome/browser/metrics/metrics_service.cc
+++ b/chrome/browser/metrics/metrics_service.cc
@@ -1514,16 +1514,6 @@
   IncrementLongPrefsValue(prefs::kUninstallMetricsPageLoadCount);
   // We need to save the prefs, as page load count is a critical stat, and it
   // might be lost due to a crash :-(.
-
-  // Track whether the page loaded is a search results page.
-  if (web_contents) {
-    SearchTabHelper* search_tab_helper =
-        SearchTabHelper::FromWebContents(web_contents);
-    if (search_tab_helper) {
-      if (search_tab_helper->model()->mode().is_search_results())
-        content::RecordAction(content::UserMetricsAction("PageLoadSRP"));
-    }
-  }
 }
 
 void MetricsService::LogRendererCrash(content::RenderProcessHost* host,
diff --git a/chrome/browser/metrics/proto/study.proto b/chrome/browser/metrics/proto/study.proto
index 6a3d2b1..fdaa41f 100644
--- a/chrome/browser/metrics/proto/study.proto
+++ b/chrome/browser/metrics/proto/study.proto
@@ -93,6 +93,9 @@
   // Possible Chrome release channels.
   // See: http://dev.chromium.org/getting-involved/dev-channel
   enum Channel {
+    // UNKNOWN value is defined here for the benefit of code using this enum
+    // type, but is not actually meant to be encoded in the protobuf.
+    UNKNOWN = -1;
     CANARY = 0;
     DEV = 1;
     BETA = 2;
diff --git a/chrome/browser/metrics/variations/variations_seed_processor.cc b/chrome/browser/metrics/variations/variations_seed_processor.cc
index dfc351f..3600a7e 100644
--- a/chrome/browser/metrics/variations/variations_seed_processor.cc
+++ b/chrome/browser/metrics/variations/variations_seed_processor.cc
@@ -12,7 +12,6 @@
 #include "base/metrics/field_trial.h"
 #include "base/stl_util.h"
 #include "base/version.h"
-#include "chrome/browser/browser_process.h"
 #include "chrome/browser/metrics/proto/trials_seed.pb.h"
 #include "chrome/common/metrics/variations/variations_associated_data.h"
 
@@ -20,25 +19,6 @@
 
 namespace {
 
-// Maps Study_Channel enum values to corresponding chrome::VersionInfo::Channel
-// enum values.
-chrome::VersionInfo::Channel ConvertStudyChannelToVersionChannel(
-    Study_Channel study_channel) {
-  switch (study_channel) {
-    case Study_Channel_CANARY:
-      return chrome::VersionInfo::CHANNEL_CANARY;
-    case Study_Channel_DEV:
-      return chrome::VersionInfo::CHANNEL_DEV;
-    case Study_Channel_BETA:
-      return chrome::VersionInfo::CHANNEL_BETA;
-    case Study_Channel_STABLE:
-      return chrome::VersionInfo::CHANNEL_STABLE;
-  }
-  // All enum values of |study_channel| were handled above.
-  NOTREACHED();
-  return chrome::VersionInfo::CHANNEL_UNKNOWN;
-}
-
 Study_Platform GetCurrentPlatform() {
 #if defined(OS_WIN)
   return Study_Platform_PLATFORM_WINDOWS;
@@ -76,8 +56,10 @@
     const TrialsSeed& seed,
     const std::string& locale,
     const base::Time& reference_date,
-    const chrome::VersionInfo& version_info,
-    chrome::VersionInfo::Channel channel) {
+    const base::Version& version,
+    Study_Channel channel) {
+  DCHECK(version.IsValid());
+
   // Add expired studies (in a disabled state) only after all the non-expired
   // studies have been added (and do not add an expired study if a corresponding
   // non-expired study got added). This way, if there's both an expired and a
@@ -87,7 +69,7 @@
 
   for (int i = 0; i < seed.study_size(); ++i) {
     const Study& study = seed.study(i);
-    if (!ShouldAddStudy(study, locale, reference_date, version_info, channel))
+    if (!ShouldAddStudy(study, locale, reference_date, version, channel))
       continue;
 
     if (IsStudyExpired(study, reference_date)) {
@@ -104,15 +86,14 @@
   }
 }
 
-bool VariationsSeedProcessor::CheckStudyChannel(
-    const Study_Filter& filter,
-    chrome::VersionInfo::Channel channel) {
+bool VariationsSeedProcessor::CheckStudyChannel(const Study_Filter& filter,
+                                                Study_Channel channel) {
   // An empty channel list matches all channels.
   if (filter.channel_size() == 0)
     return true;
 
   for (int i = 0; i < filter.channel_size(); ++i) {
-    if (ConvertStudyChannelToVersionChannel(filter.channel(i)) == channel)
+    if (filter.channel(i) == channel)
       return true;
   }
   return false;
@@ -160,13 +141,7 @@
 
 bool VariationsSeedProcessor::CheckStudyVersion(
     const Study_Filter& filter,
-    const std::string& version_string) {
-  const Version version(version_string);
-  if (!version.IsValid()) {
-    NOTREACHED();
-    return false;
-  }
-
+    const base::Version& version) {
   if (filter.has_min_version()) {
     if (version.CompareToWildcardString(filter.min_version()) < 0)
       return false;
@@ -276,8 +251,8 @@
     const Study& study,
     const std::string& locale,
     const base::Time& reference_date,
-    const chrome::VersionInfo& version_info,
-    chrome::VersionInfo::Channel channel) {
+    const base::Version& version,
+    Study_Channel channel) {
   if (study.has_filter()) {
     if (!CheckStudyChannel(study.filter(), channel)) {
       DVLOG(1) << "Filtered out study " << study.name() << " due to channel.";
@@ -294,7 +269,7 @@
       return false;
     }
 
-    if (!CheckStudyVersion(study.filter(), version_info.Version())) {
+    if (!CheckStudyVersion(study.filter(), version)) {
       DVLOG(1) << "Filtered out study " << study.name() << " due to version.";
       return false;
     }
diff --git a/chrome/browser/metrics/variations/variations_seed_processor.h b/chrome/browser/metrics/variations/variations_seed_processor.h
index fff3915..074d1af 100644
--- a/chrome/browser/metrics/variations/variations_seed_processor.h
+++ b/chrome/browser/metrics/variations/variations_seed_processor.h
@@ -11,9 +11,9 @@
 #include "base/gtest_prod_util.h"
 #include "base/metrics/field_trial.h"
 #include "base/time/time.h"
+#include "base/version.h"
 #include "chrome/browser/metrics/proto/study.pb.h"
 #include "chrome/browser/metrics/proto/trials_seed.pb.h"
-#include "chrome/common/chrome_version_info.h"
 
 namespace chrome_variations {
 
@@ -28,8 +28,8 @@
   void CreateTrialsFromSeed(const TrialsSeed& seed,
                             const std::string& locale,
                             const base::Time& reference_date,
-                            const chrome::VersionInfo& version_info,
-                            chrome::VersionInfo::Channel channel);
+                            const base::Version& version,
+                            Study_Channel channel);
 
  private:
   FRIEND_TEST_ALL_PREFIXES(VariationsSeedProcessorTest, CheckStudyChannel);
@@ -50,8 +50,7 @@
   FRIEND_TEST_ALL_PREFIXES(VariationsSeedProcessorTest, VariationParams);
 
   // Checks whether a study is applicable for the given |channel| per |filter|.
-  bool CheckStudyChannel(const Study_Filter& filter,
-                         chrome::VersionInfo::Channel channel);
+  bool CheckStudyChannel(const Study_Filter& filter, Study_Channel channel);
 
   // Checks whether a study is applicable for the given |locale| per |filter|.
   bool CheckStudyLocale(const Study_Filter& filter, const std::string& locale);
@@ -65,7 +64,7 @@
 
   // Checks whether a study is applicable for the given version per |filter|.
   bool CheckStudyVersion(const Study_Filter& filter,
-                         const std::string& version_string);
+                         const base::Version& version);
 
   // Creates and registers a field trial from the |study| data. Disables the
   // trial if |is_expired| is true.
@@ -81,8 +80,8 @@
   bool ShouldAddStudy(const Study& study,
                       const std::string& locale,
                       const base::Time& reference_date,
-                      const chrome::VersionInfo& version_info,
-                      chrome::VersionInfo::Channel channel);
+                      const base::Version& version,
+                      Study_Channel channel);
 
   // Validates the sanity of |study| and computes the total probability.
   bool ValidateStudyAndComputeTotalProbability(
diff --git a/chrome/browser/metrics/variations/variations_seed_processor_unittest.cc b/chrome/browser/metrics/variations/variations_seed_processor_unittest.cc
index ce2da44..1ab7c62 100644
--- a/chrome/browser/metrics/variations/variations_seed_processor_unittest.cc
+++ b/chrome/browser/metrics/variations/variations_seed_processor_unittest.cc
@@ -8,8 +8,7 @@
 
 #include "base/command_line.h"
 #include "base/strings/string_split.h"
-#include "chrome/common/chrome_version_info.h"
-#include "chrome/common/metrics/variations/variations_util.h"
+#include "chrome/common/metrics/variations/variations_associated_data.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace chrome_variations {
@@ -66,34 +65,27 @@
 TEST(VariationsSeedProcessorTest, CheckStudyChannel) {
   VariationsSeedProcessor seed_processor;
 
-  const chrome::VersionInfo::Channel channels[] = {
-    chrome::VersionInfo::CHANNEL_CANARY,
-    chrome::VersionInfo::CHANNEL_DEV,
-    chrome::VersionInfo::CHANNEL_BETA,
-    chrome::VersionInfo::CHANNEL_STABLE,
-  };
-  const Study_Channel study_channels[] = {
+  const Study_Channel channels[] = {
     Study_Channel_CANARY,
     Study_Channel_DEV,
     Study_Channel_BETA,
     Study_Channel_STABLE,
   };
-  ASSERT_EQ(arraysize(channels), arraysize(study_channels));
   bool channel_added[arraysize(channels)] = { 0 };
 
   Study_Filter filter;
 
-  // Check in the forwarded order. The loop cond is <= arraysize(study_channels)
+  // Check in the forwarded order. The loop cond is <= arraysize(channels)
   // instead of < so that the result of adding the last channel gets checked.
-  for (size_t i = 0; i <= arraysize(study_channels); ++i) {
+  for (size_t i = 0; i <= arraysize(channels); ++i) {
     for (size_t j = 0; j < arraysize(channels); ++j) {
       const bool expected = channel_added[j] || filter.channel_size() == 0;
       const bool result = seed_processor.CheckStudyChannel(filter, channels[j]);
       EXPECT_EQ(expected, result) << "Case " << i << "," << j << " failed!";
     }
 
-    if (i < arraysize(study_channels)) {
-      filter.add_channel(study_channels[i]);
+    if (i < arraysize(channels)) {
+      filter.add_channel(channels[i]);
       channel_added[i] = true;
     }
   }
@@ -101,16 +93,16 @@
   // Do the same check in the reverse order.
   filter.clear_channel();
   memset(&channel_added, 0, sizeof(channel_added));
-  for (size_t i = 0; i <= arraysize(study_channels); ++i) {
+  for (size_t i = 0; i <= arraysize(channels); ++i) {
     for (size_t j = 0; j < arraysize(channels); ++j) {
       const bool expected = channel_added[j] || filter.channel_size() == 0;
       const bool result = seed_processor.CheckStudyChannel(filter, channels[j]);
       EXPECT_EQ(expected, result) << "Case " << i << "," << j << " failed!";
     }
 
-    if (i < arraysize(study_channels)) {
-      const int index = arraysize(study_channels) - i - 1;
-      filter.add_channel(study_channels[index]);
+    if (i < arraysize(channels)) {
+      const int index = arraysize(channels) - i - 1;
+      filter.add_channel(channels[index]);
       channel_added[index] = true;
     }
   }
@@ -275,12 +267,13 @@
   Study_Filter filter;
 
   // Min/max version not set should result in true.
-  EXPECT_TRUE(seed_processor.CheckStudyVersion(filter, "1.2.3"));
+  EXPECT_TRUE(seed_processor.CheckStudyVersion(filter, base::Version("1.2.3")));
 
   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(min_test_cases); ++i) {
     filter.set_min_version(min_test_cases[i].min_version);
     const bool result =
-        seed_processor.CheckStudyVersion(filter, min_test_cases[i].version);
+        seed_processor.CheckStudyVersion(filter,
+                                         Version(min_test_cases[i].version));
     EXPECT_EQ(min_test_cases[i].expected_result, result) <<
         "Min. version case " << i << " failed!";
   }
@@ -289,7 +282,8 @@
   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(max_test_cases); ++i) {
     filter.set_max_version(max_test_cases[i].max_version);
     const bool result =
-        seed_processor.CheckStudyVersion(filter, max_test_cases[i].version);
+        seed_processor.CheckStudyVersion(filter,
+                                         Version(max_test_cases[i].version));
     EXPECT_EQ(max_test_cases[i].expected_result, result) <<
         "Max version case " << i << " failed!";
   }
@@ -302,13 +296,15 @@
 
       if (!min_test_cases[i].expected_result) {
         const bool result =
-            seed_processor.CheckStudyVersion(filter, min_test_cases[i].version);
+            seed_processor.CheckStudyVersion(
+                filter, Version(min_test_cases[i].version));
         EXPECT_FALSE(result) << "Case " << i << "," << j << " failed!";
       }
 
       if (!max_test_cases[j].expected_result) {
         const bool result =
-            seed_processor.CheckStudyVersion(filter, max_test_cases[j].version);
+            seed_processor.CheckStudyVersion(
+                filter, Version(max_test_cases[j].version));
         EXPECT_FALSE(result) << "Case " << i << "," << j << " failed!";
       }
     }
@@ -413,14 +409,15 @@
   const base::Time year_ago =
       base::Time::Now() - base::TimeDelta::FromDays(365);
 
+  const base::Version version("20.0.0.0");
+
   // Check that adding [expired, non-expired] activates the non-expired one.
   ASSERT_EQ(std::string(), base::FieldTrialList::FindFullName(kTrialName));
   {
     base::FieldTrialList field_trial_list(NULL);
     study1->set_expiry_date(TimeToProtoTime(year_ago));
     seed_processor.CreateTrialsFromSeed(seed, "en-CA", base::Time::Now(),
-                                        chrome::VersionInfo(),
-                                        chrome::VersionInfo::GetChannel());
+                                        version, Study_Channel_STABLE);
     EXPECT_EQ(kGroup1Name, base::FieldTrialList::FindFullName(kTrialName));
   }
 
@@ -431,8 +428,7 @@
     study1->clear_expiry_date();
     study2->set_expiry_date(TimeToProtoTime(year_ago));
     seed_processor.CreateTrialsFromSeed(seed, "en-CA", base::Time::Now(),
-                                        chrome::VersionInfo(),
-                                        chrome::VersionInfo::GetChannel());
+                                        version, Study_Channel_STABLE);
     EXPECT_EQ(kGroup1Name, base::FieldTrialList::FindFullName(kTrialName));
   }
 }
diff --git a/chrome/browser/metrics/variations/variations_service.cc b/chrome/browser/metrics/variations/variations_service.cc
index d4a23a3..973d009 100644
--- a/chrome/browser/metrics/variations/variations_service.cc
+++ b/chrome/browser/metrics/variations/variations_service.cc
@@ -59,24 +59,32 @@
 // that channel value. Otherwise, if the fake channel flag is provided, this
 // will return the fake channel. Failing that, this will return the UNKNOWN
 // channel.
-chrome::VersionInfo::Channel GetChannelForVariations() {
-  chrome::VersionInfo::Channel channel = chrome::VersionInfo::GetChannel();
-  if (channel != chrome::VersionInfo::CHANNEL_UNKNOWN)
-    return channel;
-  std::string forced_channel =
+Study_Channel GetChannelForVariations() {
+  switch (chrome::VersionInfo::GetChannel()) {
+    case chrome::VersionInfo::CHANNEL_CANARY:
+      return Study_Channel_CANARY;
+    case chrome::VersionInfo::CHANNEL_DEV:
+      return Study_Channel_DEV;
+    case chrome::VersionInfo::CHANNEL_BETA:
+      return Study_Channel_BETA;
+    case chrome::VersionInfo::CHANNEL_STABLE:
+      return Study_Channel_STABLE;
+    case chrome::VersionInfo::CHANNEL_UNKNOWN:
+      break;
+  }
+  const std::string forced_channel =
       CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
           switches::kFakeVariationsChannel);
   if (forced_channel == "stable")
-    channel = chrome::VersionInfo::CHANNEL_STABLE;
-  else if (forced_channel == "beta")
-    channel = chrome::VersionInfo::CHANNEL_BETA;
-  else if (forced_channel == "dev")
-    channel = chrome::VersionInfo::CHANNEL_DEV;
-  else if (forced_channel == "canary")
-    channel = chrome::VersionInfo::CHANNEL_CANARY;
-  else
-    DVLOG(1) << "Invalid channel provided: " << forced_channel;
-  return channel;
+    return Study_Channel_STABLE;
+  if (forced_channel == "beta")
+    return Study_Channel_BETA;
+  if (forced_channel == "dev")
+    return Study_Channel_DEV;
+  if (forced_channel == "canary")
+    return Study_Channel_CANARY;
+  DVLOG(1) << "Invalid channel provided: " << forced_channel;
+  return Study_Channel_UNKNOWN;
 }
 
 // Returns a string that will be used for the value of the 'osname' URL param
@@ -196,9 +204,13 @@
   if (!current_version_info.is_valid())
     return false;
 
+  const base::Version current_version(current_version_info.Version());
+  if (!current_version.IsValid())
+    return false;
+
   VariationsSeedProcessor().CreateTrialsFromSeed(
       seed, g_browser_process->GetApplicationLocale(), reference_date,
-      current_version_info, GetChannelForVariations());
+      current_version, GetChannelForVariations());
 
   // Log the "freshness" of the seed that was just used. The freshness is the
   // time between the last successful seed download and now.
diff --git a/chrome/browser/nacl_host/nacl_host_message_filter.cc b/chrome/browser/nacl_host/nacl_host_message_filter.cc
index c7c7935..784f9f9 100644
--- a/chrome/browser/nacl_host/nacl_host_message_filter.cc
+++ b/chrome/browser/nacl_host/nacl_host_message_filter.cc
@@ -11,6 +11,7 @@
 #include "chrome/browser/nacl_host/pnacl_host.h"
 #include "components/nacl/common/nacl_host_messages.h"
 #include "extensions/common/constants.h"
+#include "ipc/ipc_platform_file.h"
 #include "net/url_request/url_request_context.h"
 #include "net/url_request/url_request_context_getter.h"
 
@@ -134,12 +135,13 @@
 // NaClHostMsg_NaClCreateTemporaryFile sync message.
 void NaClHostMessageFilter::SyncReturnTemporaryFile(
     IPC::Message* reply_msg,
-    IPC::PlatformFileForTransit fd) {
-  if (fd == IPC::InvalidPlatformFileForTransit()) {
+    base::PlatformFile fd) {
+  if (fd == base::kInvalidPlatformFileValue) {
     reply_msg->set_reply_error();
   } else {
     NaClHostMsg_NaClCreateTemporaryFile::WriteReplyParams(
-        reply_msg, fd);
+        reply_msg,
+        IPC::GetFileHandleForProcess(fd, PeerHandle(), true));
   }
   Send(reply_msg);
 }
@@ -147,22 +149,21 @@
 void NaClHostMessageFilter::OnNaClCreateTemporaryFile(
     IPC::Message* reply_msg) {
   PnaclHost::GetInstance()->CreateTemporaryFile(
-      PeerHandle(),
       base::Bind(&NaClHostMessageFilter::SyncReturnTemporaryFile,
                  this,
                  reply_msg));
 }
 
-// For now, GetNexeFd cache requests always set is_hit to false and returns
-// a new temporary file via a NaClViewMsg_NexeTempFileReply message.
-// A future CL will implement the cache lookup logic (and use the currently-
-// unused parameters)
-// See also https://code.google.com/p/nativeclient/issues/detail?id=3372
 void NaClHostMessageFilter::AsyncReturnTemporaryFile(
     int pp_instance,
-    IPC::PlatformFileForTransit fd,
+    base::PlatformFile fd,
     bool is_hit) {
-  Send(new NaClViewMsg_NexeTempFileReply(pp_instance, is_hit, fd));
+  Send(new NaClViewMsg_NexeTempFileReply(
+      pp_instance,
+      is_hit,
+      // Don't close our copy of the handle, because PnaclHost will use it
+      // when the translation finishes.
+      IPC::GetFileHandleForProcess(fd, PeerHandle(), false)));
 }
 
 void NaClHostMessageFilter::OnGetNexeFd(
@@ -175,11 +176,12 @@
     BadMessageReceived();
     return;
   }
+
   PnaclHost::GetInstance()->GetNexeFd(
       render_process_id_,
-      PeerHandle(),
       render_view_id,
       pp_instance,
+      off_the_record_,
       cache_info,
       base::Bind(&NaClHostMessageFilter::AsyncReturnTemporaryFile,
                  this,
diff --git a/chrome/browser/nacl_host/nacl_host_message_filter.h b/chrome/browser/nacl_host/nacl_host_message_filter.h
index 7d31a90..4c05f22 100644
--- a/chrome/browser/nacl_host/nacl_host_message_filter.h
+++ b/chrome/browser/nacl_host/nacl_host_message_filter.h
@@ -7,8 +7,8 @@
 
 #include "base/files/file_path.h"
 #include "base/memory/weak_ptr.h"
+#include "base/platform_file.h"
 #include "content/public/browser/browser_message_filter.h"
-#include "ipc/ipc_platform_file.h"
 
 class ExtensionInfoMap;
 class GURL;
@@ -70,9 +70,9 @@
       int instance,
       const nacl::PnaclInstallProgress& progress);
   void SyncReturnTemporaryFile(IPC::Message* reply_msg,
-                               IPC::PlatformFileForTransit fd);
+                               base::PlatformFile fd);
   void AsyncReturnTemporaryFile(int pp_instance,
-                                IPC::PlatformFileForTransit fd,
+                                base::PlatformFile fd,
                                 bool is_hit);
 #endif
   int render_process_id_;
diff --git a/chrome/browser/nacl_host/pnacl_host.cc b/chrome/browser/nacl_host/pnacl_host.cc
index 9bb5b72..2468f9d 100644
--- a/chrome/browser/nacl_host/pnacl_host.cc
+++ b/chrome/browser/nacl_host/pnacl_host.cc
@@ -5,6 +5,7 @@
 #include "chrome/browser/nacl_host/pnacl_host.h"
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/file_util.h"
 #include "base/files/file_path.h"
 #include "base/logging.h"
@@ -13,6 +14,7 @@
 #include "chrome/browser/nacl_host/nacl_browser.h"
 #include "chrome/browser/nacl_host/pnacl_translation_cache.h"
 #include "content/public/browser/browser_thread.h"
+#include "net/base/io_buffer.h"
 #include "net/base/net_errors.h"
 
 using content::BrowserThread;
@@ -20,6 +22,8 @@
 namespace {
 static const base::FilePath::CharType kTranslationCacheDirectoryName[] =
     FILE_PATH_LITERAL("PnaclTranslationCache");
+// Delay to wait for initialization of the cache backend
+static const int kTranslationCacheInitializationDelayMs = 20;
 }
 
 PnaclHost::PnaclHost()
@@ -29,7 +33,16 @@
 
 PnaclHost* PnaclHost::GetInstance() { return Singleton<PnaclHost>::get(); }
 
-PnaclHost::PendingTranslation::PendingTranslation() {}
+PnaclHost::PendingTranslation::PendingTranslation()
+    : process_handle(base::kNullProcessHandle),
+      render_view_id(0),
+      nexe_fd(base::kInvalidPlatformFileValue),
+      got_nexe_fd(false),
+      got_cache_reply(false),
+      got_cache_hit(false),
+      is_incognito(false),
+      callback(NexeFdCallback()),
+      cache_info(nacl::PnaclCacheInfo()) {}
 PnaclHost::PendingTranslation::~PendingTranslation() {}
 
 /////////////////////////////////////// Initialization
@@ -53,19 +66,24 @@
   return cache_file_path.Append(kTranslationCacheDirectoryName);
 }
 
-void PnaclHost::OnCacheInitialized(int error) {
+void PnaclHost::OnCacheInitialized(int net_error) {
+  DCHECK(thread_checker_.CalledOnValidThread());
   // If the cache was cleared before the load completed, ignore.
   if (cache_state_ == CacheReady)
     return;
-  if (error != net::OK) {
-    LOG(ERROR) << "PNaCl translation cache initalization failure: " << error
-               << "\n";
+  if (net_error != net::OK) {
+    // This will cause the cache to attempt to re-init on the next call to
+    // GetNexeFd.
+    cache_state_ = CacheUninitialized;
   } else {
     cache_state_ = CacheReady;
   }
 }
 
 void PnaclHost::Init() {
+  // Extra check that we're on the real IO thread since this version of
+  // Init isn't used in unit tests.
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
   DCHECK(thread_checker_.CalledOnValidThread());
   base::FilePath cache_path(GetCachePath());
   if (cache_path.empty() || cache_state_ != CacheUninitialized)
@@ -74,7 +92,7 @@
   cache_state_ = CacheInitializing;
   disk_cache_->InitCache(
       cache_path,
-      true,
+      false,
       base::Bind(&PnaclHost::OnCacheInitialized, weak_factory_.GetWeakPtr()));
 }
 
@@ -94,9 +112,8 @@
 ///////////////////////////////////////// Temp files
 
 // Create a temporary file on the blocking pool
-IPC::PlatformFileForTransit PnaclHost::DoCreateTemporaryFile(
-    base::ProcessHandle process_handle,
-    base::FilePath temp_dir) {
+// static
+base::PlatformFile PnaclHost::DoCreateTemporaryFile(base::FilePath temp_dir) {
   DCHECK(BrowserThread::GetBlockingPool()->RunsTasksOnCurrentThread());
 
   base::FilePath file_path;
@@ -104,9 +121,10 @@
                 ? file_util::CreateTemporaryFile(&file_path)
                 : file_util::CreateTemporaryFileInDir(temp_dir, &file_path);
 
-  if (!rv)
-    return IPC::InvalidPlatformFileForTransit();
-
+  if (!rv) {
+    LOG(ERROR) << "PnaclHost:: Temp file creation failed.";
+    return base::kInvalidPlatformFileValue;
+  }
   base::PlatformFileError error;
   base::PlatformFile file_handle(base::CreatePlatformFile(
       file_path,
@@ -116,96 +134,442 @@
       NULL,
       &error));
 
-  if (error != base::PLATFORM_FILE_OK)
-    return IPC::InvalidPlatformFileForTransit();
+  if (error != base::PLATFORM_FILE_OK) {
+    LOG(ERROR) << "PnaclHost: Temp file open failed: " << error;
+    return base::kInvalidPlatformFileValue;
+  }
 
-  // Do any DuplicateHandle magic that is necessary first.
-  return IPC::GetFileHandleForProcess(file_handle, process_handle, true);
+  return file_handle;
 }
 
-void PnaclHost::CreateTemporaryFile(base::ProcessHandle process_handle,
-                                    TempFileCallback cb) {
+void PnaclHost::CreateTemporaryFile(TempFileCallback cb) {
   if (!base::PostTaskAndReplyWithResult(
           BrowserThread::GetBlockingPool(),
           FROM_HERE,
-          base::Bind(
-              &PnaclHost::DoCreateTemporaryFile, process_handle, temp_dir_),
+          base::Bind(&PnaclHost::DoCreateTemporaryFile, temp_dir_),
           cb)) {
     DCHECK(thread_checker_.CalledOnValidThread());
-    cb.Run(IPC::InvalidPlatformFileForTransit());
+    cb.Run(base::kInvalidPlatformFileValue);
   }
 }
 
 ///////////////////////////////////////// GetNexeFd implementation
-
-void PnaclHost::ReturnMiss(TranslationID id, IPC::PlatformFileForTransit fd) {
-  DCHECK(thread_checker_.CalledOnValidThread());
-  PendingTranslationMap::iterator entry(pending_translations_.find(id));
-  if (entry == pending_translations_.end()) {
-    LOG(ERROR) << "PnaclHost::ReturnMiss: Failed to find TranslationID "
-               << id.first << "," << id.second;
-    return;
-  }
-  NexeFdCallback cb(entry->second.callback);
-  if (fd == IPC::InvalidPlatformFileForTransit()) {
-    pending_translations_.erase(entry);
-  } else {
-    entry->second.nexe_fd = fd;
-  }
-  cb.Run(fd, false);
-}
+////////////////////// Common steps
 
 void PnaclHost::GetNexeFd(int render_process_id,
-                          base::ProcessHandle process_handle,
                           int render_view_id,
                           int pp_instance,
+                          bool is_incognito,
                           const nacl::PnaclCacheInfo& cache_info,
                           const NexeFdCallback& cb) {
   DCHECK(thread_checker_.CalledOnValidThread());
-  if (cache_state_ != CacheReady)
+  if (cache_state_ == CacheUninitialized) {
+    Init();
+  }
+  if (cache_state_ != CacheReady) {
+    // If the backend hasn't yet initialized, try the request again later.
+    BrowserThread::PostDelayedTask(BrowserThread::IO,
+                                   FROM_HERE,
+                                   base::Bind(&PnaclHost::GetNexeFd,
+                                              weak_factory_.GetWeakPtr(),
+                                              render_process_id,
+                                              render_view_id,
+                                              pp_instance,
+                                              is_incognito,
+                                              cache_info,
+                                              cb),
+                                   base::TimeDelta::FromMilliseconds(
+                                       kTranslationCacheInitializationDelayMs));
     return;
+  }
+
+  TranslationID id(render_process_id, pp_instance);
+  PendingTranslationMap::iterator entry = pending_translations_.find(id);
+  if (entry != pending_translations_.end()) {
+    // Existing translation must have been abandonded. Clean it up.
+    LOG(ERROR) << "PnaclHost::GetNexeFd for already-pending translation";
+    pending_translations_.erase(entry);
+  }
+
+  std::string cache_key(disk_cache_->GetKey(cache_info));
+  if (cache_key.empty()) {
+    LOG(ERROR) << "PnaclHost::GetNexeFd: Invalid cache info";
+    cb.Run(base::kInvalidPlatformFileValue, false);
+    return;
+  }
+
   PendingTranslation pt;
   pt.render_view_id = render_view_id;
   pt.callback = cb;
   pt.cache_info = cache_info;
-
-  pending_translations_[TranslationID(render_process_id, pp_instance)] = pt;
-
-  CreateTemporaryFile(
-      process_handle,
-      base::Bind(&PnaclHost::ReturnMiss,
-                 weak_factory_.GetWeakPtr(),
-                 TranslationID(render_process_id, pp_instance)));
+  pt.cache_key = cache_key;
+  pt.is_incognito = is_incognito;
+  pending_translations_[id] = pt;
+  SendCacheQueryAndTempFileRequest(cache_key, id);
 }
 
-/////////////////// Cleanup
+// Dispatch the cache read request and the temp file creation request
+// simultaneously; currently we need a temp file regardless of whether the
+// request hits.
+void PnaclHost::SendCacheQueryAndTempFileRequest(const std::string& cache_key,
+                                                 const TranslationID& id) {
+  disk_cache_->GetNexe(
+      cache_key,
+      base::Bind(
+          &PnaclHost::OnCacheQueryReturn, weak_factory_.GetWeakPtr(), id));
 
+  CreateTemporaryFile(
+      base::Bind(&PnaclHost::OnTempFileReturn, weak_factory_.GetWeakPtr(), id));
+}
+
+// Callback from the translation cache query. |id| is bound from
+// SendCacheQueryAndTempFileRequest, |net_error| is a net::Error code (which for
+// our purposes means a hit if it's net::OK (i.e. 0). |buffer| is allocated
+// by PnaclTranslationCache and now belongs to PnaclHost.
+// (Bound callbacks must re-lookup the TranslationID because the translation
+// could be cancelled before they get called).
+void PnaclHost::OnCacheQueryReturn(
+    const TranslationID& id,
+    int net_error,
+    scoped_refptr<net::DrainableIOBuffer> buffer) {
+  DCHECK(thread_checker_.CalledOnValidThread());
+  PendingTranslationMap::iterator entry(pending_translations_.find(id));
+  if (entry == pending_translations_.end()) {
+    LOG(ERROR) << "PnaclHost::OnCacheQueryReturn: id not found";
+    return;
+  }
+  PendingTranslation* pt = &entry->second;
+  pt->got_cache_reply = true;
+  pt->got_cache_hit = (net_error == net::OK);
+  if (pt->got_cache_hit)
+    pt->nexe_read_buffer = buffer;
+  CheckCacheQueryReady(entry);
+}
+
+// Callback from temp file creation. |id| is bound from
+// SendCacheQueryAndTempFileRequest, and fd is the created file descriptor.
+// If there was an error, fd is kInvalidPlatformFileValue.
+// (Bound callbacks must re-lookup the TranslationID because the translation
+// could be cancelled before they get called).
+void PnaclHost::OnTempFileReturn(const TranslationID& id,
+                                 base::PlatformFile fd) {
+  DCHECK(thread_checker_.CalledOnValidThread());
+  PendingTranslationMap::iterator entry(pending_translations_.find(id));
+  if (entry == pending_translations_.end()) {
+    // The renderer may have signaled an error or closed while the temp
+    // file was being created.
+    LOG(ERROR) << "PnaclHost::OnTempFileReturn: id not found";
+    BrowserThread::PostBlockingPoolTask(
+        FROM_HERE, base::Bind(base::IgnoreResult(base::ClosePlatformFile), fd));
+    return;
+  }
+  if (fd == base::kInvalidPlatformFileValue) {
+    // This translation will fail, but we need to retry any translation
+    // waiting for its result.
+    LOG(ERROR) << "PnaclHost::OnTempFileReturn: temp file creation failed";
+    std::string key(entry->second.cache_key);
+    bool is_incognito = entry->second.is_incognito;
+    entry->second.callback.Run(fd, false);
+    pending_translations_.erase(entry);
+    // No translations will be waiting for an incongnito translation
+    if (!is_incognito)
+      RequeryMatchingTranslations(key);
+    return;
+  }
+  PendingTranslation* pt = &entry->second;
+  pt->got_nexe_fd = true;
+  pt->nexe_fd = fd;
+  CheckCacheQueryReady(entry);
+}
+
+// Check whether both the cache query and the temp file have returned, and check
+// whether we actually got a hit or not.
+void PnaclHost::CheckCacheQueryReady(
+    const PendingTranslationMap::iterator& entry) {
+  PendingTranslation* pt = &entry->second;
+  if (!(pt->got_cache_reply && pt->got_nexe_fd))
+    return;
+  if (!pt->got_cache_hit) {
+    // Check if there is already a pending translation for this file. If there
+    // is, we will wait for it to come back, to avoid redundant translations.
+    for (PendingTranslationMap::iterator it = pending_translations_.begin();
+         it != pending_translations_.end();
+         ++it) {
+      // Another translation matches if it's a request for the same file,
+      if (it->second.cache_key == entry->second.cache_key &&
+          // and it's not this translation,
+          it->first != entry->first &&
+          // and it's not incognito,
+          !it->second.is_incognito &&
+          // and if it's already gotten past this check and returned the miss.
+          it->second.got_cache_reply &&
+          it->second.got_nexe_fd) {
+        return;
+      }
+    }
+    ReturnMiss(entry);
+    return;
+  }
+
+  if (!base::PostTaskAndReplyWithResult(
+          BrowserThread::GetBlockingPool(),
+          FROM_HERE,
+          base::Bind(
+              &PnaclHost::CopyBufferToFile, pt->nexe_fd, pt->nexe_read_buffer),
+          base::Bind(&PnaclHost::OnBufferCopiedToTempFile,
+                     weak_factory_.GetWeakPtr(),
+                     entry->first))) {
+    pt->callback.Run(base::kInvalidPlatformFileValue, false);
+  }
+}
+
+//////////////////// GetNexeFd miss path
+// Return the temp fd to the renderer, reporting a miss.
+void PnaclHost::ReturnMiss(const PendingTranslationMap::iterator& entry) {
+  // Return the fd
+  PendingTranslation* pt = &entry->second;
+  NexeFdCallback cb(pt->callback);
+  if (pt->nexe_fd == base::kInvalidPlatformFileValue) {
+    // Bad FD is unrecoverable, so clear out the entry
+    pending_translations_.erase(entry);
+  }
+  cb.Run(pt->nexe_fd, false);
+}
+
+// On error, just return a null refptr.
+// static
+scoped_refptr<net::DrainableIOBuffer> PnaclHost::CopyFileToBuffer(
+    base::PlatformFile fd) {
+  base::PlatformFileInfo info;
+  scoped_refptr<net::DrainableIOBuffer> buffer;
+  bool error = false;
+  if (!base::GetPlatformFileInfo(fd, &info) ||
+      info.size >= std::numeric_limits<int>::max()) {
+    LOG(ERROR) << "PnaclHost: GetPlatformFileInfo failed";
+    error = true;
+  } else {
+    buffer = new net::DrainableIOBuffer(
+        new net::IOBuffer(static_cast<int>(info.size)), info.size);
+    if (base::ReadPlatformFile(fd, 0, buffer->data(), buffer->size()) !=
+        info.size) {
+      LOG(ERROR) << "PnaclHost: CopyFileToBuffer write failed";
+      error = true;
+    }
+  }
+  if (error) {
+    buffer = NULL;
+  }
+  base::ClosePlatformFile(fd);
+  return buffer;
+}
+
+// Called by the renderer in the miss path to report a finished translation
 void PnaclHost::TranslationFinished(int render_process_id,
                                     int pp_instance,
                                     bool success) {
   DCHECK(thread_checker_.CalledOnValidThread());
   if (cache_state_ != CacheReady)
     return;
-  PendingTranslationMap::iterator it(pending_translations_.find(
-      TranslationID(render_process_id, pp_instance)));
-  if (it == pending_translations_.end()) {
+  TranslationID id(render_process_id, pp_instance);
+  PendingTranslationMap::iterator entry(pending_translations_.find(id));
+  if (entry == pending_translations_.end()) {
     LOG(ERROR) << "TranslationFinished: TranslationID " << render_process_id
                << "," << pp_instance << " not found.";
-  } else {
-    pending_translations_.erase(it);
+    return;
+  }
+  bool store_nexe = true;
+  // If this is a premature response (i.e. we haven't returned a temp file
+  // yet) or if it's an unsuccessful translation, or if we are incognito,
+  // don't store in the cache.
+  // TODO(dschuff): use a separate in-memory cache for incognito
+  // translations.
+  if (!entry->second.got_nexe_fd || !entry->second.got_cache_reply ||
+      !success || entry->second.is_incognito) {
+    store_nexe = false;
+  } else if (!base::PostTaskAndReplyWithResult(
+                 BrowserThread::GetBlockingPool(),
+                 FROM_HERE,
+                 base::Bind(&PnaclHost::CopyFileToBuffer,
+                            entry->second.nexe_fd),
+                 base::Bind(&PnaclHost::StoreTranslatedNexe,
+                            weak_factory_.GetWeakPtr(),
+                            id))) {
+    store_nexe = false;
+  }
+
+  if (!store_nexe) {
+    // If store_nexe is true, the fd will be closed by CopyFileToBuffer.
+    if (entry->second.got_nexe_fd) {
+      BrowserThread::PostBlockingPoolTask(
+          FROM_HERE,
+          base::Bind(base::IgnoreResult(base::ClosePlatformFile),
+                     entry->second.nexe_fd));
+    }
+    pending_translations_.erase(entry);
   }
 }
 
-void PnaclHost::RendererClosing(int render_process_id) {
+// Store the translated nexe in the translation cache. Called back with the
+// TranslationID from the host and the result of CopyFileToBuffer.
+// (Bound callbacks must re-lookup the TranslationID because the translation
+// could be cancelled before they get called).
+void PnaclHost::StoreTranslatedNexe(
+    TranslationID id,
+    scoped_refptr<net::DrainableIOBuffer> buffer) {
+  DCHECK(thread_checker_.CalledOnValidThread());
   if (cache_state_ != CacheReady)
     return;
+  PendingTranslationMap::iterator it(pending_translations_.find(id));
+  if (it == pending_translations_.end()) {
+    LOG(ERROR) << "StoreTranslatedNexe: TranslationID " << id.first << ","
+               << id.second << " not found.";
+    return;
+  }
+
+  if (buffer.get() == NULL) {
+    LOG(ERROR) << "Error reading translated nexe";
+    return;
+  }
+
+  disk_cache_->StoreNexe(it->second.cache_key,
+                         buffer,
+                         base::Bind(&PnaclHost::OnTranslatedNexeStored,
+                                    weak_factory_.GetWeakPtr(),
+                                    it->first));
+}
+
+// After we know the nexe has been stored, we can clean up, and unblock any
+// outstanding requests for the same file.
+// (Bound callbacks must re-lookup the TranslationID because the translation
+// could be cancelled before they get called).
+void PnaclHost::OnTranslatedNexeStored(const TranslationID& id, int net_error) {
+  PendingTranslationMap::iterator entry(pending_translations_.find(id));
+  if (entry == pending_translations_.end()) {
+    return;
+  }
+  std::string key(entry->second.cache_key);
+  pending_translations_.erase(entry);
+  RequeryMatchingTranslations(key);
+}
+
+// Check if any pending translations match |key|. If so, re-issue the cache
+// query. In the overlapped miss case, we expect a hit this time, but a miss
+// is also possible in case of an error.
+void PnaclHost::RequeryMatchingTranslations(const std::string& key) {
+  // Check for outstanding misses to this same file
+  for (PendingTranslationMap::iterator it = pending_translations_.begin();
+       it != pending_translations_.end();
+       ++it) {
+    if (it->second.cache_key == key) {
+      // Re-send the cache read request. This time we expect a hit, but if
+      // something goes wrong, it will just handle it like a miss.
+      it->second.got_cache_reply = false;
+      disk_cache_->GetNexe(key,
+                           base::Bind(&PnaclHost::OnCacheQueryReturn,
+                                      weak_factory_.GetWeakPtr(),
+                                      it->first));
+    }
+  }
+}
+
+//////////////////// GetNexeFd hit path
+
+// static
+int PnaclHost::CopyBufferToFile(base::PlatformFile fd,
+                                scoped_refptr<net::DrainableIOBuffer> buffer) {
+  return base::WritePlatformFile(fd, 0, buffer->data(), buffer->size());
+}
+
+void PnaclHost::OnBufferCopiedToTempFile(const TranslationID& id,
+                                         int file_error) {
   DCHECK(thread_checker_.CalledOnValidThread());
+  PendingTranslationMap::iterator entry(pending_translations_.find(id));
+  if (entry == pending_translations_.end()) {
+    return;
+  }
+  if (file_error == -1) {
+    // Write error on the temp file. Request a new file and start over.
+    LOG(ERROR) << "PnaclHost::OnBufferCopiedToTempFile write error";
+    BrowserThread::PostBlockingPoolTask(
+        FROM_HERE,
+        base::Bind(base::IgnoreResult(base::ClosePlatformFile),
+                   entry->second.nexe_fd));
+    entry->second.got_nexe_fd = false;
+    CreateTemporaryFile(base::Bind(&PnaclHost::OnTempFileReturn,
+                                   weak_factory_.GetWeakPtr(),
+                                   entry->first));
+    return;
+  }
+  base::PlatformFile fd = entry->second.nexe_fd;
+  entry->second.callback.Run(fd, true);
+  BrowserThread::PostBlockingPoolTask(
+      FROM_HERE, base::Bind(base::IgnoreResult(base::ClosePlatformFile), fd));
+  pending_translations_.erase(entry);
+}
+
+///////////////////
+
+void PnaclHost::RendererClosing(int render_process_id) {
+  DCHECK(thread_checker_.CalledOnValidThread());
+  if (cache_state_ != CacheReady)
+    return;
   for (PendingTranslationMap::iterator it = pending_translations_.begin();
        it != pending_translations_.end();) {
     PendingTranslationMap::iterator to_erase(it++);
     if (to_erase->first.first == render_process_id) {
-      // clean up the open files
+      // Clean up the open files.
+      BrowserThread::PostBlockingPoolTask(
+          FROM_HERE,
+          base::Bind(base::IgnoreResult(base::ClosePlatformFile),
+                     to_erase->second.nexe_fd));
+      std::string key(to_erase->second.cache_key);
+      bool is_incognito = to_erase->second.is_incognito;
       pending_translations_.erase(to_erase);
+      // No translations will be blocked waiting for an incongnito translation
+      if (!is_incognito)
+        RequeryMatchingTranslations(key);
     }
   }
+  if (pending_translations_.empty()) {
+    cache_state_ = CacheUninitialized;
+    // Freeing the backend causes it to flush to disk, so do it when the
+    // last renderer closes rather than on destruction.
+    disk_cache_.reset();
+  }
+}
+
+////////////////// Cache data removal
+void PnaclHost::ClearTranslationCacheEntriesBetween(
+    base::Time initial_time,
+    base::Time end_time,
+    const base::Closure& callback) {
+  DCHECK(thread_checker_.CalledOnValidThread());
+  if (cache_state_ == CacheUninitialized) {
+    Init();
+  }
+  if (cache_state_ == CacheInitializing) {
+    // If the backend hasn't yet initialized, try the request again later.
+    BrowserThread::PostDelayedTask(
+        BrowserThread::IO,
+        FROM_HERE,
+        base::Bind(&PnaclHost::ClearTranslationCacheEntriesBetween,
+                   weak_factory_.GetWeakPtr(),
+                   initial_time,
+                   end_time,
+                   callback),
+        base::TimeDelta::FromMilliseconds(
+            kTranslationCacheInitializationDelayMs));
+    return;
+  }
+  int rv = disk_cache_->DoomEntriesBetween(
+      initial_time,
+      end_time,
+      base::Bind(&PnaclHost::OnEntriesDoomed, callback));
+  if (rv != net::ERR_IO_PENDING)
+    OnEntriesDoomed(callback, rv);
+}
+
+// static
+void PnaclHost::OnEntriesDoomed(const base::Closure& callback, int net_error) {
+  BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, callback);
 }
diff --git a/chrome/browser/nacl_host/pnacl_host.h b/chrome/browser/nacl_host/pnacl_host.h
index 2093b44..3c0d2e8 100644
--- a/chrome/browser/nacl_host/pnacl_host.h
+++ b/chrome/browser/nacl_host/pnacl_host.h
@@ -15,6 +15,10 @@
 #include "components/nacl/common/pnacl_types.h"
 #include "ipc/ipc_platform_file.h"
 
+namespace net {
+class DrainableIOBuffer;
+}
+
 namespace pnacl {
 class PnaclHostTest;
 class PnaclTranslationCache;
@@ -25,28 +29,28 @@
 // called on the IO thread.
 class PnaclHost {
  public:
-  typedef base::Callback<void(IPC::PlatformFileForTransit)> TempFileCallback;
-  typedef base::Callback<void(IPC::PlatformFileForTransit, bool is_hit)>
-      NexeFdCallback;
+  typedef base::Callback<void(base::PlatformFile)> TempFileCallback;
+  typedef base::Callback<void(base::PlatformFile, bool is_hit)> NexeFdCallback;
 
   static PnaclHost* GetInstance();
 
   PnaclHost();
   ~PnaclHost();
+
+  // Initialize cache backend. GetNexeFd will also initialize the backend if
+  // necessary, but calling Init ahead of time will minimize the latency.
   void Init();
 
   // Creates a temporary file that will be deleted when the last handle
-  // is closed, or earlier. Returns a PlatformFileForTransit usable by the
-  // process identified by |process_handle|.
-  void CreateTemporaryFile(base::ProcessHandle process_handle,
-                           TempFileCallback cb);
+  // is closed, or earlier. Returns a PlatformFile handle.
+  void CreateTemporaryFile(TempFileCallback cb);
 
   // Create a temporary file, which will be deleted by the time the last
   // handle is closed (or earlier on POSIX systems), to use for the nexe
   // with the cache information given in |cache_info|. The specific instance
   // is identified by the combination of |render_process_id| and |pp_instance|.
-  // Returns by calling |cb| with a PlatformFileForTransit usable by the process
-  // identified by |process_handle|. If the nexe is already present
+  // Returns by calling |cb| with a PlatformFile handle.
+  // If the nexe is already present
   // in the cache, |is_hit| is set to true and the contents of the nexe
   // have been copied into the temporary file. Otherwise |is_hit| is set to
   // false and the temporary file will be writeable.
@@ -55,10 +59,16 @@
   // If the cache request was a miss, the caller is expected to call
   // TranslationFinished after it finishes translation to allow the nexe to be
   // stored in the cache.
+  // The returned temp fd may be closed at any time by PnaclHost, so it should
+  // be duplicated (e.g. with IPC::GetFileHandleForProcess) before the callback
+  // returns.
+  // If |is_incognito| is true, the nexe will not be stored
+  // in the cache, but the renderer is still expected to call
+  // TranslationFinished.
   void GetNexeFd(int render_process_id,
-                 base::ProcessHandle process_handle,
                  int render_view_id,
                  int pp_instance,
+                 bool is_incognito,
                  const nacl::PnaclCacheInfo& cache_info,
                  const NexeFdCallback& cb);
 
@@ -70,9 +80,21 @@
                            bool success);
 
   // Called when the renderer identified by |render_process_id| is closing.
-  // Clean up any outstanding translations for that renderer.
+  // Clean up any outstanding translations for that renderer. If there are no
+  // more pending translations, the backend is freed, allowing it to flush.
   void RendererClosing(int render_process_id);
 
+  // Doom all entries between |initial_time| and |end_time|. Like disk_cache_,
+  // PnaclHost supports supports unbounded deletes in either direction by using
+  // null Time values for either argument. |callback| will be called on the UI
+  // thread when finished.
+  void ClearTranslationCacheEntriesBetween(base::Time initial_time,
+                                           base::Time end_time,
+                                           const base::Closure& callback);
+
+  // Return the number of tracked translations or FD requests currently pending.
+  size_t pending_translations() { return pending_translations_.size(); }
+
  private:
   // PnaclHost is a singleton because there is only one translation cache, and
   // so that the BrowsingDataRemover can clear it even if no translation has
@@ -84,13 +106,20 @@
     CacheInitializing,
     CacheReady
   };
-  struct PendingTranslation {
+  class PendingTranslation {
    public:
     PendingTranslation();
     ~PendingTranslation();
+    base::ProcessHandle process_handle;
     int render_view_id;
-    IPC::PlatformFileForTransit nexe_fd;
+    base::PlatformFile nexe_fd;
+    bool got_nexe_fd;
+    bool got_cache_reply;
+    bool got_cache_hit;
+    bool is_incognito;
+    scoped_refptr<net::DrainableIOBuffer> nexe_read_buffer;
     NexeFdCallback callback;
+    std::string cache_key;
     nacl::PnaclCacheInfo cache_info;
   };
 
@@ -98,11 +127,34 @@
   typedef std::map<TranslationID, PendingTranslation> PendingTranslationMap;
 
   void InitForTest(base::FilePath temp_dir);
-  void OnCacheInitialized(int error);
-  static IPC::PlatformFileForTransit DoCreateTemporaryFile(
-      base::ProcessHandle process_handle,
-      base::FilePath temp_dir_);
-  void ReturnMiss(TranslationID id, IPC::PlatformFileForTransit fd);
+  void OnCacheInitialized(int net_error);
+
+  static base::PlatformFile DoCreateTemporaryFile(base::FilePath temp_dir_);
+
+  // GetNexeFd common steps
+  void SendCacheQueryAndTempFileRequest(const std::string& key,
+                                        const TranslationID& id);
+  void OnCacheQueryReturn(const TranslationID& id,
+                          int net_error,
+                          scoped_refptr<net::DrainableIOBuffer> buffer);
+  void OnTempFileReturn(const TranslationID& id, base::PlatformFile fd);
+  void CheckCacheQueryReady(const PendingTranslationMap::iterator& entry);
+
+  // GetNexeFd miss path
+  void ReturnMiss(const PendingTranslationMap::iterator& entry);
+  static scoped_refptr<net::DrainableIOBuffer> CopyFileToBuffer(
+      base::PlatformFile fd);
+  void StoreTranslatedNexe(TranslationID id,
+                           scoped_refptr<net::DrainableIOBuffer>);
+  void OnTranslatedNexeStored(const TranslationID& id, int net_error);
+  void RequeryMatchingTranslations(const std::string& key);
+
+  // GetNexeFd hit path
+  static int CopyBufferToFile(base::PlatformFile fd,
+                              scoped_refptr<net::DrainableIOBuffer> buffer);
+  void OnBufferCopiedToTempFile(const TranslationID& id, int file_error);
+
+  static void OnEntriesDoomed(const base::Closure& callback, int net_error);
 
   CacheState cache_state_;
   base::FilePath temp_dir_;
diff --git a/chrome/browser/nacl_host/pnacl_host_unittest.cc b/chrome/browser/nacl_host/pnacl_host_unittest.cc
index cb5e8ef..0ad9cd5 100644
--- a/chrome/browser/nacl_host/pnacl_host_unittest.cc
+++ b/chrome/browser/nacl_host/pnacl_host_unittest.cc
@@ -4,20 +4,29 @@
 
 #include "chrome/browser/nacl_host/pnacl_host.h"
 
+#include <stdio.h>
 #include "base/bind.h"
 #include "base/files/scoped_temp_dir.h"
 #include "base/run_loop.h"
 #include "base/threading/sequenced_worker_pool.h"
+#include "chrome/browser/nacl_host/pnacl_translation_cache.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/test/test_browser_thread_bundle.h"
+#include "net/base/test_completion_callback.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
+#if defined(OS_WIN)
+#define snprintf _snprintf
+#endif
+
 namespace pnacl {
 
 class PnaclHostTest : public testing::Test {
  protected:
   PnaclHostTest()
-      : temp_callback_count_(0),
+      : host_(NULL),
+        temp_callback_count_(0),
+        write_callback_count_(0),
         thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP) {}
   virtual void SetUp() {
     host_ = new PnaclHost();
@@ -26,78 +35,339 @@
     EXPECT_EQ(host_->cache_state_, PnaclHost::CacheReady);
   }
   virtual void TearDown() {
-    ExpectPendingTranslations(0);
+    EXPECT_EQ(0U, host_->pending_translations());
     delete host_;
   }
-  // Utilities for inspecting internal state of the pnacl host
-  void ExpectPendingTranslations(size_t count) {
-    EXPECT_EQ(count, host_->pending_translations_.size());
+  // Flush the blocking pool first, then any tasks it posted to the IO thread.
+  // Do 2 rounds of flushing, because some operations require 2 trips back and
+  // forth between the threads.
+  void FlushQueues() {
+    content::BrowserThread::GetBlockingPool()->FlushForTesting();
+    base::RunLoop().RunUntilIdle();
+    content::BrowserThread::GetBlockingPool()->FlushForTesting();
+    base::RunLoop().RunUntilIdle();
   }
-  void ExpectCallbackCount(int count) {
-    EXPECT_EQ(count, temp_callback_count_);
+  int GetCacheSize() {
+    return host_->disk_cache_->Size();
   }
 
  public:  // Required for derived classes to bind this method
-  void CallbackExpectMiss(IPC::PlatformFileForTransit fd, bool is_hit) {
-    temp_callback_count_++;
+  // Callbacks used by tests which call GetNexeFd.
+  // CallbackExpectMiss checks that the fd is valid and a miss is reported,
+  // and also writes some data into the file, which is read back by
+  // CallbackExpectHit
+  void CallbackExpectMiss(base::PlatformFile fd, bool is_hit) {
     EXPECT_FALSE(is_hit);
-    EXPECT_FALSE(fd == IPC::InvalidPlatformFileForTransit());
+    ASSERT_FALSE(fd == base::kInvalidPlatformFileValue);
+    base::PlatformFileInfo info;
+    EXPECT_TRUE(base::GetPlatformFileInfo(fd, &info));
+    EXPECT_FALSE(info.is_directory);
+    EXPECT_EQ(0LL, info.size);
+    char str[16];
+    memset(str, 0x0, 16);
+    snprintf(str, 16, "testdata%d", ++write_callback_count_);
+    EXPECT_EQ(16, base::WritePlatformFile(fd, 0, str, 16));
+    temp_callback_count_++;
+  }
+  void CallbackExpectHit(base::PlatformFile fd, bool is_hit) {
+    EXPECT_TRUE(is_hit);
+    ASSERT_FALSE(fd == base::kInvalidPlatformFileValue);
+    base::PlatformFileInfo info;
+    EXPECT_TRUE(base::GetPlatformFileInfo(fd, &info));
+    EXPECT_FALSE(info.is_directory);
+    EXPECT_EQ(16LL, info.size);
+    char data[16];
+    memset(data, 0x0, 16);
+    char str[16];
+    memset(str, 0x0, 16);
+    snprintf(str, 16, "testdata%d", write_callback_count_);
+    EXPECT_EQ(16, base::ReadPlatformFile(fd, 0, data, 16));
+    EXPECT_STREQ(str, data);
+    temp_callback_count_++;
   }
 
  protected:
   PnaclHost* host_;
   int temp_callback_count_;
+  int write_callback_count_;
   content::TestBrowserThreadBundle thread_bundle_;
   base::ScopedTempDir temp_dir_;
 };
 
-#define EXPECT_PENDING_TRANSLATIONS(n) \
-  do {                                 \
-    SCOPED_TRACE("");                  \
-    ExpectPendingTranslations(n);      \
+static nacl::PnaclCacheInfo GetTestCacheInfo() {
+  nacl::PnaclCacheInfo info;
+  info.pexe_url = GURL("http://www.google.com");
+  info.abi_version = 0;
+  info.opt_level = 0;
+  return info;
+}
+
+#define GET_NEXE_FD(renderer, instance, incognito, info, expect_hit)\
+  do {                                                              \
+    SCOPED_TRACE("");                                               \
+    host_->GetNexeFd(                                               \
+        renderer,                                                   \
+        0, /* ignore render_view_id for now */                      \
+        instance,                                                   \
+        incognito,                                                  \
+        info,                                                       \
+        base::Bind(expect_hit ? &PnaclHostTest::CallbackExpectHit   \
+                              : &PnaclHostTest::CallbackExpectMiss, \
+                   base::Unretained(this)));                        \
   } while (0)
 
-// We don't do actual caching yet, but just return a new temp file with a miss
 TEST_F(PnaclHostTest, BasicMiss) {
-  nacl::PnaclCacheInfo info;
-  host_->GetNexeFd(
-      0,
-      base::ProcessHandle(),
-      0,
-      0,
-      info,
-      base::Bind(&PnaclHostTest::CallbackExpectMiss, base::Unretained(this)));
-
-  EXPECT_PENDING_TRANSLATIONS(1);
-  content::BrowserThread::GetBlockingPool()->FlushForTesting();
-  base::RunLoop().RunUntilIdle();
-  EXPECT_PENDING_TRANSLATIONS(1);
-  ExpectCallbackCount(1);
+  nacl::PnaclCacheInfo info = GetTestCacheInfo();
+  // Test cold miss.
+  GET_NEXE_FD(0, 0, false, info, false);
+  EXPECT_EQ(1U, host_->pending_translations());
+  FlushQueues();
+  EXPECT_EQ(1U, host_->pending_translations());
+  EXPECT_EQ(1, temp_callback_count_);
   host_->TranslationFinished(0, 0, true);
-  EXPECT_PENDING_TRANSLATIONS(0);
+  FlushQueues();
+  EXPECT_EQ(0U, host_->pending_translations());
+  // Test that a different cache info field also misses.
+  info.etag = std::string("something else");
+  GET_NEXE_FD(0, 0, false, info, false);
+  FlushQueues();
+  EXPECT_EQ(2, temp_callback_count_);
+  EXPECT_EQ(1U, host_->pending_translations());
   host_->RendererClosing(0);
 }
 
 TEST_F(PnaclHostTest, BadArguments) {
-  nacl::PnaclCacheInfo info;
-  host_->GetNexeFd(
-      0,
-      base::ProcessHandle(),
-      0,
-      0,
-      info,
-      base::Bind(&PnaclHostTest::CallbackExpectMiss, base::Unretained(this)));
-
-  EXPECT_PENDING_TRANSLATIONS(1);
+  nacl::PnaclCacheInfo info = GetTestCacheInfo();
+  GET_NEXE_FD(0, 0, false, info, false);
+  EXPECT_EQ(1U, host_->pending_translations());
   host_->TranslationFinished(0, 1, true);  // nonexistent translation
-  EXPECT_PENDING_TRANSLATIONS(1);
+  EXPECT_EQ(1U, host_->pending_translations());
   host_->RendererClosing(1);  // nonexistent renderer
-  EXPECT_PENDING_TRANSLATIONS(1);
-  content::BrowserThread::GetBlockingPool()->FlushForTesting();
-  base::RunLoop().RunUntilIdle();
-  ExpectCallbackCount(1);
+  EXPECT_EQ(1U, host_->pending_translations());
+  FlushQueues();
+  EXPECT_EQ(1, temp_callback_count_);
   host_->RendererClosing(0);  // close without finishing
-  EXPECT_PENDING_TRANSLATIONS(0);
+}
+
+TEST_F(PnaclHostTest, BasicHit) {
+  nacl::PnaclCacheInfo info = GetTestCacheInfo();
+  GET_NEXE_FD(0, 0, false, info, false);
+  FlushQueues();
+  EXPECT_EQ(1, temp_callback_count_);
+  host_->TranslationFinished(0, 0, true);
+  FlushQueues();
+  GET_NEXE_FD(0, 1, false, info, true);
+  FlushQueues();
+  EXPECT_EQ(2, temp_callback_count_);
+  EXPECT_EQ(0U, host_->pending_translations());
+}
+
+TEST_F(PnaclHostTest, TranslationErrors) {
+  nacl::PnaclCacheInfo info = GetTestCacheInfo();
+  info.pexe_url = GURL("http://www.google.com");
+  GET_NEXE_FD(0, 0, false, info, false);
+  // Early abort, before temp file request returns
+  host_->TranslationFinished(0, 0, false);
+  FlushQueues();
+  EXPECT_EQ(0U, host_->pending_translations());
+  EXPECT_EQ(0, temp_callback_count_);
+  // Check that another request for the same info misses successfully.
+  GET_NEXE_FD(0, 0, false, info, false);
+  FlushQueues();
+  host_->TranslationFinished(0, 0, true);
+  FlushQueues();
+  EXPECT_EQ(1, temp_callback_count_);
+  EXPECT_EQ(0U, host_->pending_translations());
+
+  // Now try sending the error after the temp file request returns
+  info.abi_version = 222;
+  GET_NEXE_FD(0, 0, false, info, false);
+  FlushQueues();
+  EXPECT_EQ(2, temp_callback_count_);
+  host_->TranslationFinished(0, 0, false);
+  FlushQueues();
+  EXPECT_EQ(0U, host_->pending_translations());
+  // Check another successful miss
+  GET_NEXE_FD(0, 0, false, info, false);
+  FlushQueues();
+  EXPECT_EQ(3, temp_callback_count_);
+  host_->TranslationFinished(0, 0, false);
+  EXPECT_EQ(0U, host_->pending_translations());
+}
+
+TEST_F(PnaclHostTest, OverlappedMissesAfterTempReturn) {
+  nacl::PnaclCacheInfo info = GetTestCacheInfo();
+  GET_NEXE_FD(0, 0, false, info, false);
+  FlushQueues();
+  EXPECT_EQ(1, temp_callback_count_);
+  EXPECT_EQ(1U, host_->pending_translations());
+  // Test that a second request for the same nexe while the first one is still
+  // outstanding eventually hits.
+  GET_NEXE_FD(0, 1, false, info, true);
+  FlushQueues();
+  EXPECT_EQ(2U, host_->pending_translations());
+  // The temp file should not be returned to the second request until after the
+  // first is finished translating.
+  EXPECT_EQ(1, temp_callback_count_);
+  host_->TranslationFinished(0, 0, true);
+  FlushQueues();
+  EXPECT_EQ(2, temp_callback_count_);
+  EXPECT_EQ(0U, host_->pending_translations());
+}
+
+TEST_F(PnaclHostTest, OverlappedMissesBeforeTempReturn) {
+  nacl::PnaclCacheInfo info = GetTestCacheInfo();
+  GET_NEXE_FD(0, 0, false, info, false);
+  // Send the 2nd fd request before the first one returns a temp file.
+  GET_NEXE_FD(0, 1, false, info, true);
+  FlushQueues();
+  EXPECT_EQ(1, temp_callback_count_);
+  EXPECT_EQ(2U, host_->pending_translations());
+  FlushQueues();
+  EXPECT_EQ(2U, host_->pending_translations());
+  EXPECT_EQ(1, temp_callback_count_);
+  host_->TranslationFinished(0, 0, true);
+  FlushQueues();
+  EXPECT_EQ(2, temp_callback_count_);
+  EXPECT_EQ(0U, host_->pending_translations());
+}
+
+TEST_F(PnaclHostTest, OverlappedHitsBeforeTempReturn) {
+  nacl::PnaclCacheInfo info = GetTestCacheInfo();
+  // Store one in the cache and complete it.
+  GET_NEXE_FD(0, 0, false, info, false);
+  FlushQueues();
+  EXPECT_EQ(1, temp_callback_count_);
+  host_->TranslationFinished(0, 0, true);
+  FlushQueues();
+  EXPECT_EQ(0U, host_->pending_translations());
+  GET_NEXE_FD(0, 0, false, info, true);
+  // Request the second before the first temp file returns.
+  GET_NEXE_FD(0, 1, false, info, true);
+  FlushQueues();
+  EXPECT_EQ(3, temp_callback_count_);
+  EXPECT_EQ(0U, host_->pending_translations());
+}
+
+TEST_F(PnaclHostTest, OverlappedHitsAfterTempReturn) {
+  nacl::PnaclCacheInfo info = GetTestCacheInfo();
+  // Store one in the cache and complete it.
+  GET_NEXE_FD(0, 0, false, info, false);
+  FlushQueues();
+  EXPECT_EQ(1, temp_callback_count_);
+  host_->TranslationFinished(0, 0, true);
+  FlushQueues();
+  EXPECT_EQ(0U, host_->pending_translations());
+  GET_NEXE_FD(0, 0, false, info, true);
+  FlushQueues();
+  GET_NEXE_FD(0, 1, false, info, true);
+  FlushQueues();
+  EXPECT_EQ(3, temp_callback_count_);
+  EXPECT_EQ(0U, host_->pending_translations());
+}
+
+TEST_F(PnaclHostTest, OverlappedMissesRendererClosing) {
+  nacl::PnaclCacheInfo info = GetTestCacheInfo();
+  GET_NEXE_FD(0, 0, false, info, false);
+  // Send the 2nd fd request from a different renderer.
+  // Test that it eventually gets an fd after the first renderer closes.
+  GET_NEXE_FD(1, 1, false, info, false);
+  FlushQueues();
+  EXPECT_EQ(1, temp_callback_count_);
+  EXPECT_EQ(2U, host_->pending_translations());
+  FlushQueues();
+  EXPECT_EQ(2U, host_->pending_translations());
+  EXPECT_EQ(1, temp_callback_count_);
+  host_->RendererClosing(0);
+  FlushQueues();
+  EXPECT_EQ(2, temp_callback_count_);
+  EXPECT_EQ(1U, host_->pending_translations());
+  host_->RendererClosing(1);
+}
+
+TEST_F(PnaclHostTest, Incognito) {
+  nacl::PnaclCacheInfo info = GetTestCacheInfo();
+  GET_NEXE_FD(0, 0, true, info, false);
+  FlushQueues();
+  EXPECT_EQ(1, temp_callback_count_);
+  host_->TranslationFinished(0, 0, true);
+  FlushQueues();
+  // Check that an incognito translation is not stored in the cache
+  GET_NEXE_FD(0, 0, false, info, false);
+  FlushQueues();
+  EXPECT_EQ(2, temp_callback_count_);
+  host_->TranslationFinished(0, 0, true);
+  FlushQueues();
+  // Check that an incognito translation can hit from a normal one.
+  GET_NEXE_FD(0, 0, true, info, true);
+  FlushQueues();
+  EXPECT_EQ(3, temp_callback_count_);
+}
+
+TEST_F(PnaclHostTest, IncognitoOverlappedMiss) {
+  nacl::PnaclCacheInfo info = GetTestCacheInfo();
+  GET_NEXE_FD(0, 0, true, info, false);
+  GET_NEXE_FD(0, 1, false, info, false);
+  FlushQueues();
+  // Check that both translations have returned misses, (i.e. that the
+  // second one has not blocked on the incognito one)
+  EXPECT_EQ(2, temp_callback_count_);
+  host_->TranslationFinished(0, 0, true);
+  host_->TranslationFinished(0, 1, true);
+  FlushQueues();
+  EXPECT_EQ(0U, host_->pending_translations());
+
+  // Same test, but issue the 2nd request after the first has returned a miss.
+  info.abi_version = 222;
+  GET_NEXE_FD(0, 0, true, info, false);
+  FlushQueues();
+  EXPECT_EQ(3, temp_callback_count_);
+  GET_NEXE_FD(0, 1, false, info, false);
+  FlushQueues();
+  EXPECT_EQ(4, temp_callback_count_);
+  host_->RendererClosing(0);
+}
+
+TEST_F(PnaclHostTest, IncognitoSecondOverlappedMiss) {
+  // If the non-incognito request comes first, it should
+  // behave exactly like OverlappedMissBeforeTempReturn
+  nacl::PnaclCacheInfo info = GetTestCacheInfo();
+  GET_NEXE_FD(0, 0, false, info, false);
+  // Send the 2nd fd request before the first one returns a temp file.
+  GET_NEXE_FD(0, 1, true, info, true);
+  FlushQueues();
+  EXPECT_EQ(1, temp_callback_count_);
+  EXPECT_EQ(2U, host_->pending_translations());
+  FlushQueues();
+  EXPECT_EQ(2U, host_->pending_translations());
+  EXPECT_EQ(1, temp_callback_count_);
+  host_->TranslationFinished(0, 0, true);
+  FlushQueues();
+  EXPECT_EQ(2, temp_callback_count_);
+  EXPECT_EQ(0U, host_->pending_translations());
+}
+
+TEST_F(PnaclHostTest, ClearTranslationCache) {
+  nacl::PnaclCacheInfo info = GetTestCacheInfo();
+  // Add 2 entries in the cache
+  GET_NEXE_FD(0, 0, false, info, false);
+  info.abi_version = 222;
+  GET_NEXE_FD(0, 1, false, info, false);
+  FlushQueues();
+  EXPECT_EQ(2, temp_callback_count_);
+  host_->TranslationFinished(0, 0, true);
+  host_->TranslationFinished(0, 1, true);
+  FlushQueues();
+  EXPECT_EQ(0U, host_->pending_translations());
+  EXPECT_EQ(2, GetCacheSize());
+  net::TestCompletionCallback cb;
+  // Since we are using a memory backend, the clear should happen immediately.
+  host_->ClearTranslationCacheEntriesBetween(base::Time(), base::Time(),
+                                             base::Bind(cb.callback(), 0));
+  EXPECT_EQ(0, cb.GetResult(net::ERR_IO_PENDING));
+  // Check that the translation cache has been cleared
+  EXPECT_EQ(0, GetCacheSize());
+  host_->RendererClosing(0);
 }
 
 }  // namespace pnacl
diff --git a/chrome/browser/nacl_host/pnacl_translation_cache.cc b/chrome/browser/nacl_host/pnacl_translation_cache.cc
index fa548f1..508c665 100644
--- a/chrome/browser/nacl_host/pnacl_translation_cache.cc
+++ b/chrome/browser/nacl_host/pnacl_translation_cache.cc
@@ -26,9 +26,8 @@
 }  // namespace
 
 namespace pnacl {
-// These are in pnacl namespace instead of static so they can be used
+// This is in pnacl namespace instead of static so they can be used
 // by the unit test.
-const int kMaxDiskCacheSize = 1000 * 1024 * 1024;
 const int kMaxMemCacheSize = 100 * 1024 * 1024;
 
 //////////////////////////////////////////////////////////////////////
@@ -156,10 +155,10 @@
 // OpenEntry, CreateEntry, WriteEntry, ReadEntry and CloseEntry are only called
 // from DispatchNext, so they know that cache_ is still valid.
 void PnaclTranslationCacheEntry::OpenEntry() {
-  int rv = cache_->backend()
-      ->OpenEntry(key_,
-                  &entry_,
-                  base::Bind(&PnaclTranslationCacheEntry::DispatchNext, this));
+  int rv = cache_->backend()->OpenEntry(
+      key_,
+      &entry_,
+      base::Bind(&PnaclTranslationCacheEntry::DispatchNext, this));
   if (rv != net::ERR_IO_PENDING)
     DispatchNext(rv);
 }
@@ -199,8 +198,11 @@
 
 void PnaclTranslationCacheEntry::CloseEntry(int rv) {
   DCHECK(entry_);
-  if (rv < 0)
+  if (rv < 0) {
+    LOG(ERROR) << "PnaclTranslationCache: failed to close entry: "
+               << net::ErrorToString(rv);
     entry_->Doom();
+  }
   BrowserThread::PostTask(
       BrowserThread::IO, FROM_HERE, base::Bind(&CloseDiskCacheEntry, entry_));
   Finish(rv);
@@ -228,7 +230,7 @@
 
   switch (step_) {
     case UNINITIALIZED:
-      LOG(ERROR) << "Unexpected step in DispatchNext";
+      LOG(ERROR) << "PnaclTranslationCache: DispatchNext called uninitialized";
       break;
 
     case OPEN_ENTRY:
@@ -243,6 +245,11 @@
           WriteEntry(0, io_buf_->size());
         }
       } else {
+        if (rv != net::ERR_FAILED) {
+          // ERROR_FAILED is what we expect if the entry doesn't exist.
+          LOG(ERROR) << "PnaclTranslationCache: OpenEntry failed: "
+                     << net::ErrorToString(rv);
+        }
         if (is_read_) {
           // Just a cache miss, not necessarily an error.
           entry_ = NULL;
@@ -259,7 +266,8 @@
         step_ = TRANSFER_ENTRY;
         WriteEntry(io_buf_->BytesConsumed(), io_buf_->BytesRemaining());
       } else {
-        LOG(ERROR) << "Failed to Create a PNaCl Translation Cache Entry";
+        LOG(ERROR) << "PnaclTranslationCache: Failed to Create Entry: "
+                   << net::ErrorToString(rv);
         Finish(rv);
       }
       break;
@@ -269,8 +277,8 @@
         // We do not call DispatchNext directly if WriteEntry/ReadEntry returns
         // ERR_IO_PENDING, and the callback should not return that value either.
         LOG(ERROR)
-            << "Failed to complete write to PNaCl Translation Cache Entry: "
-            << rv;
+            << "PnaclTranslationCache: Failed to complete write to entry: "
+            << net::ErrorToString(rv);
         step_ = CLOSE_ENTRY;
         CloseEntry(rv);
         break;
@@ -343,6 +351,10 @@
 }
 
 void PnaclTranslationCache::OnCreateBackendComplete(int rv) {
+  if (rv < 0) {
+    LOG(ERROR) << "PnaclTranslationCache: backend init failed:"
+               << net::ErrorToString(rv);
+  }
   // Invoke our client's callback function.
   if (!init_callback_.is_null()) {
     init_callback_.Run(rv);
@@ -383,7 +395,7 @@
   if (in_memory_) {
     rv = InitWithMemBackend(kMaxMemCacheSize, callback);
   } else {
-    rv = InitWithDiskBackend(cache_directory, kMaxDiskCacheSize, callback);
+    rv = InitWithDiskBackend(cache_directory, 0, callback);
   }
 
   return rv;
@@ -400,9 +412,8 @@
   if (!info.pexe_url.is_valid() || info.abi_version < 0 || info.opt_level < 0)
     return std::string();
   std::string retval("ABI:");
-  retval += IntToString(info.abi_version) + ";" +
-      "opt:" + IntToString(info.opt_level) + ";" +
-      "URL:";
+  retval += IntToString(info.abi_version) + ";" + "opt:" +
+            IntToString(info.opt_level) + ";" + "URL:";
   // Filter the username, password, and ref components from the URL
   GURL::Replacements replacements;
   replacements.ClearUsername();
@@ -419,12 +430,20 @@
     memset(&exploded, 0, sizeof(exploded));
   }
   retval += "modified:" + IntToString(exploded.year) + ":" +
-      IntToString(exploded.month) + ":" +
-      IntToString(exploded.day_of_month) + ":" +
-      IntToString(exploded.hour) + ":" + IntToString(exploded.minute) + ":" +
-      IntToString(exploded.second) + ":" +
-      IntToString(exploded.millisecond) + ":UTC;";
+            IntToString(exploded.month) + ":" +
+            IntToString(exploded.day_of_month) + ":" +
+            IntToString(exploded.hour) + ":" + IntToString(exploded.minute) +
+            ":" + IntToString(exploded.second) + ":" +
+            IntToString(exploded.millisecond) + ":UTC;";
   retval += "etag:" + info.etag;
   return retval;
 }
+
+int PnaclTranslationCache::DoomEntriesBetween(
+    base::Time initial,
+    base::Time end,
+    const CompletionCallback& callback) {
+  return disk_cache_->DoomEntriesBetween(initial, end, callback);
+}
+
 }  // namespace pnacl
diff --git a/chrome/browser/nacl_host/pnacl_translation_cache.h b/chrome/browser/nacl_host/pnacl_translation_cache.h
index 8f2d9ac..8b9ffe9 100644
--- a/chrome/browser/nacl_host/pnacl_translation_cache.h
+++ b/chrome/browser/nacl_host/pnacl_translation_cache.h
@@ -10,6 +10,7 @@
 #include "base/callback.h"
 #include "base/files/file_path.h"
 #include "base/memory/weak_ptr.h"
+#include "base/time/time.h"
 #include "net/base/cache_type.h"
 
 namespace base {
@@ -71,6 +72,12 @@
   // Return the cache key for |info|
   static std::string GetKey(const nacl::PnaclCacheInfo& info);
 
+  // Doom all entries between |initial| and |end|. If the return value is
+  // net::ERR_IO_PENDING, |callback| will be invoked when the operation
+  // completes.
+  int DoomEntriesBetween(base::Time initial, base::Time end,
+                         const CompletionCallback& callback);
+
  private:
   friend class PnaclTranslationCacheEntry;
   friend class PnaclTranslationCacheTest;
diff --git a/chrome/browser/notifications/message_center_notification_manager.cc b/chrome/browser/notifications/message_center_notification_manager.cc
index 5661734..2054a7f 100644
--- a/chrome/browser/notifications/message_center_notification_manager.cc
+++ b/chrome/browser/notifications/message_center_notification_manager.cc
@@ -307,7 +307,7 @@
   NotificationMap::const_iterator iter =
       profile_notifications_.find(notification_id);
   if (iter != profile_notifications_.end())
-    RemoveProfileNotification(iter->second, by_user);
+    RemoveProfileNotification(iter->second);
 
 #if defined(OS_WIN)
   CheckFirstRunTimer();
@@ -549,9 +549,7 @@
 }
 
 void MessageCenterNotificationManager::RemoveProfileNotification(
-    ProfileNotification* profile_notification,
-    bool by_user) {
-  profile_notification->notification().Close(by_user);
+    ProfileNotification* profile_notification) {
   std::string id = profile_notification->notification().notification_id();
   profile_notifications_.erase(id);
   delete profile_notification;
diff --git a/chrome/browser/notifications/message_center_notification_manager.h b/chrome/browser/notifications/message_center_notification_manager.h
index be2621e..4589645 100644
--- a/chrome/browser/notifications/message_center_notification_manager.h
+++ b/chrome/browser/notifications/message_center_notification_manager.h
@@ -192,8 +192,7 @@
   // Helpers that add/remove the notification from local map and MessageCenter.
   // They take ownership of profile_notification object.
   void AddProfileNotification(ProfileNotification* profile_notification);
-  void RemoveProfileNotification(ProfileNotification* profile_notification,
-                                 bool by_user);
+  void RemoveProfileNotification(ProfileNotification* profile_notification);
 
   // Returns the ProfileNotification for the |id|, or NULL if no such
   // notification is found.
diff --git a/chrome/browser/notifications/message_center_settings_controller.cc b/chrome/browser/notifications/message_center_settings_controller.cc
index ef91c33..66175a7 100644
--- a/chrome/browser/notifications/message_center_settings_controller.cc
+++ b/chrome/browser/notifications/message_center_settings_controller.cc
@@ -132,6 +132,11 @@
   return *(notifier_groups_[index]);
 }
 
+bool MessageCenterSettingsController::IsNotifierGroupActiveAt(
+    size_t index) const {
+  return current_notifier_group_ == index;
+}
+
 const message_center::NotifierGroup&
 MessageCenterSettingsController::GetActiveNotifierGroup() const {
   DCHECK_LT(current_notifier_group_, notifier_groups_.size());
diff --git a/chrome/browser/notifications/message_center_settings_controller.h b/chrome/browser/notifications/message_center_settings_controller.h
index 4adc136..03f7552 100644
--- a/chrome/browser/notifications/message_center_settings_controller.h
+++ b/chrome/browser/notifications/message_center_settings_controller.h
@@ -50,6 +50,7 @@
   virtual size_t GetNotifierGroupCount() const OVERRIDE;
   virtual const message_center::NotifierGroup& GetNotifierGroupAt(
       size_t index) const OVERRIDE;
+  virtual bool IsNotifierGroupActiveAt(size_t index) const OVERRIDE;
   virtual void SwitchToNotifierGroup(size_t index) OVERRIDE;
   virtual const message_center::NotifierGroup& GetActiveNotifierGroup() const
       OVERRIDE;
diff --git a/chrome/browser/notifications/sync_notifier/chrome_notifier_delegate.cc b/chrome/browser/notifications/sync_notifier/chrome_notifier_delegate.cc
index 794cb5f..49f594b 100644
--- a/chrome/browser/notifications/sync_notifier/chrome_notifier_delegate.cc
+++ b/chrome/browser/notifications/sync_notifier/chrome_notifier_delegate.cc
@@ -65,7 +65,7 @@
 
 void ChromeNotifierDelegate::Close(bool by_user) {
   if (by_user)
-    chrome_notifier_->MarkNotificationAsDismissed(notification_id_);
+    chrome_notifier_->MarkNotificationAsRead(notification_id_);
 }
 
 }  // namespace notifier
diff --git a/chrome/browser/notifications/sync_notifier/chrome_notifier_delegate_browsertest.cc b/chrome/browser/notifications/sync_notifier/chrome_notifier_delegate_browsertest.cc
index d35e532..7532501 100644
--- a/chrome/browser/notifications/sync_notifier/chrome_notifier_delegate_browsertest.cc
+++ b/chrome/browser/notifications/sync_notifier/chrome_notifier_delegate_browsertest.cc
@@ -34,8 +34,8 @@
 
   virtual ~StubChromeNotifierService() {}
 
-  virtual void MarkNotificationAsDismissed(const std::string& id) OVERRIDE {
-    dismissed_id_ = id;
+  virtual void MarkNotificationAsRead(const std::string& id) OVERRIDE {
+    read_id_ = id;
   }
 
   notifier::SyncedNotification* CreateNotification(
@@ -62,10 +62,10 @@
         kTitle1, kText1, kIconUrl1, kImageUrl1, kAppId1, kKey1, kUnread);
   }
 
-  const std::string& dismissed_id() { return dismissed_id_; }
+  const std::string& read_id() { return read_id_; }
 
  private:
-  std::string dismissed_id_;
+  std::string read_id_;
 };
 
 class ChromeNotifierDelegateBrowserTest : public InProcessBrowserTest {};
@@ -153,8 +153,8 @@
       new notifier::ChromeNotifierDelegate(id, &notifier);
 
   delegate->Close(false);
-  ASSERT_EQ("", notifier.dismissed_id());
+  ASSERT_EQ("", notifier.read_id());
 
   delegate->Close(true);
-  ASSERT_EQ(kTestNotificationId, notifier.dismissed_id());
+  ASSERT_EQ(kTestNotificationId, notifier.read_id());
 }
diff --git a/chrome/browser/notifications/sync_notifier/chrome_notifier_service.cc b/chrome/browser/notifications/sync_notifier/chrome_notifier_service.cc
index cc07213..6341a3f 100644
--- a/chrome/browser/notifications/sync_notifier/chrome_notifier_service.cc
+++ b/chrome/browser/notifications/sync_notifier/chrome_notifier_service.cc
@@ -102,7 +102,12 @@
           if (incoming->GetReadState() == SyncedNotification::kDismissed) {
             // If it is marked as read on the server, but not the client.
             found->NotificationHasBeenDismissed();
-            // Tell the Notification UI Manager to mark it read.
+            // Tell the Notification UI Manager to remove it.
+            notification_manager_->CancelById(found->GetKey());
+          } else if (incoming->GetReadState() == SyncedNotification::kRead) {
+            // If it is marked as read on the server, but not the client.
+            found->NotificationHasBeenRead();
+            // Tell the Notification UI Manager to remove it.
             notification_manager_->CancelById(found->GetKey());
           } else {
             // If it is marked as read on the client, but not the server.
@@ -122,7 +127,7 @@
         found->Update(sync_data);
 
         // Tell the notification manager to update the notification.
-        Display(found);
+        UpdateInMessageCenter(found);
       }
     }
   }
@@ -147,10 +152,9 @@
   syncer::SyncDataList sync_data;
 
   // Copy our native format data into a SyncDataList format.
-  for (std::vector<SyncedNotification*>::const_iterator it =
-          notification_data_.begin();
-      it != notification_data_.end();
-      ++it) {
+  ScopedVector<SyncedNotification>::const_iterator it =
+      notification_data_.begin();
+  for (; it != notification_data_.end(); ++it) {
     sync_data.push_back(CreateSyncDataFromNotification(**it));
   }
 
@@ -177,15 +181,38 @@
       continue;
     }
 
+    const std::string& key = new_notification->GetKey();
+    DCHECK_GT(key.length(), 0U);
+    SyncedNotification* found = FindNotificationById(key);
+
     switch (change_type) {
       case syncer::SyncChange::ACTION_ADD:
-        // TODO(petewil): Update the notification if it already exists
-        // as opposed to adding it.
-        Add(new_notification.Pass());
+        // Intentional fall through, cases are identical.
+      case syncer::SyncChange::ACTION_UPDATE:
+        if (found == NULL) {
+          Add(new_notification.Pass());
+          break;
+        }
+        // Update it in our store.
+        found->Update(sync_data);
+        // Tell the notification manager to update the notification.
+        UpdateInMessageCenter(found);
         break;
-      // TODO(petewil): Implement code to add delete and update actions.
+
+      case syncer::SyncChange::ACTION_DELETE:
+        if (found == NULL) {
+          break;
+        }
+        // Remove it from our store.
+        FreeNotificationById(key);
+        // Remove it from the message center.
+        UpdateInMessageCenter(new_notification.get());
+        // TODO(petewil): Do I need to remember that it was deleted in case the
+        // add arrives after the delete?  If so, how long do I need to remember?
+        break;
 
       default:
+        NOTREACHED();
         break;
     }
   }
@@ -225,12 +252,16 @@
     return scoped_ptr<SyncedNotification>();
   }
 
-  // TODO(petewil): Is this the right set?  Should I add more?
   bool is_well_formed_unread_notification =
       (static_cast<SyncedNotification::ReadState>(
           specifics.coalesced_notification().read_state()) ==
        SyncedNotification::kUnread &&
        specifics.coalesced_notification().has_render_info());
+  bool is_well_formed_read_notification =
+      (static_cast<SyncedNotification::ReadState>(
+          specifics.coalesced_notification().read_state()) ==
+       SyncedNotification::kRead &&
+       specifics.coalesced_notification().has_render_info());
   bool is_well_formed_dismissed_notification =
       (static_cast<SyncedNotification::ReadState>(
           specifics.coalesced_notification().read_state()) ==
@@ -238,12 +269,15 @@
 
   // If the notification is poorly formed, return a null pointer.
   if (!is_well_formed_unread_notification &&
+      !is_well_formed_read_notification &&
       !is_well_formed_dismissed_notification) {
     DVLOG(1) << "Synced Notification is not well formed."
              << " unread well formed? "
              << is_well_formed_unread_notification
              << " dismissed well formed? "
-             << is_well_formed_dismissed_notification;
+             << is_well_formed_dismissed_notification
+             << " read well formed? "
+             << is_well_formed_read_notification;
     return scoped_ptr<SyncedNotification>();
   }
 
@@ -261,10 +295,9 @@
   // TODO(petewil): We can make a performance trade off here.
   // While the vector has good locality of reference, a map has faster lookup.
   // Based on how big we expect this to get, maybe change this to a map.
-  for (std::vector<SyncedNotification*>::const_iterator it =
-          notification_data_.begin();
-      it != notification_data_.end();
-      ++it) {
+  ScopedVector<SyncedNotification>::const_iterator it =
+      notification_data_.begin();
+  for (; it != notification_data_.end(); ++it) {
     SyncedNotification* notification = *it;
     if (notification_id == notification->GetKey())
       return *it;
@@ -273,6 +306,18 @@
   return NULL;
 }
 
+void ChromeNotifierService::FreeNotificationById(
+    const std::string& notification_id) {
+  ScopedVector<SyncedNotification>::iterator it = notification_data_.begin();
+  for (; it != notification_data_.end(); ++it) {
+    SyncedNotification* notification = *it;
+    if (notification_id == notification->GetKey()) {
+      notification_data_.erase(it);
+      return;
+    }
+  }
+}
+
 void ChromeNotifierService::GetSyncedNotificationServices(
     std::vector<message_center::Notifier*>* notifiers) {
   // TODO(mukai|petewil): Check the profile's eligibility before adding the
@@ -305,13 +350,13 @@
   notifiers->push_back(notifier_service);
 }
 
-void ChromeNotifierService::MarkNotificationAsDismissed(
+void ChromeNotifierService::MarkNotificationAsRead(
     const std::string& key) {
   DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
   SyncedNotification* notification = FindNotificationById(key);
   CHECK(notification != NULL);
 
-  notification->NotificationHasBeenDismissed();
+  notification->NotificationHasBeenRead();
   syncer::SyncChangeList new_changes;
 
   syncer::SyncData sync_data = CreateSyncDataFromNotification(*notification);
@@ -340,24 +385,38 @@
     return;
   }
 
-  Display(notification_copy);
+  UpdateInMessageCenter(notification_copy);
 }
 
 void ChromeNotifierService::AddForTest(
     scoped_ptr<notifier::SyncedNotification> notification) {
-    notification_data_.push_back(notification.release());
-  }
+  notification_data_.push_back(notification.release());
+}
 
-void ChromeNotifierService::Display(SyncedNotification* notification) {
+void ChromeNotifierService::UpdateInMessageCenter(
+    SyncedNotification* notification) {
   // If the feature is disabled, exit now.
   if (!notifier::ChromeNotifierServiceFactory::UseSyncedNotifications(
-          CommandLine::ForCurrentProcess()))
+      CommandLine::ForCurrentProcess()))
     return;
 
+  notification->LogNotification();
+
+  if (notification->GetReadState() == SyncedNotification::kUnread) {
+    // If the message is unread, update it.
+    Display(notification);
+  } else {
+    // If the message is read or deleted, dismiss it from the center.
+    // We intentionally ignore errors if it is not in the center.
+    notification_manager_->CancelById(notification->GetKey());
+  }
+}
+
+void ChromeNotifierService::Display(SyncedNotification* notification) {
   // Set up to fetch the bitmaps.
   notification->QueueBitmapFetchJobs(notification_manager_,
-                                          this,
-                                          profile_);
+                                     this,
+                                     profile_);
 
   // Our tests cannot use the network for reliability reasons.
   if (avoid_bitmap_fetching_for_test_) {
diff --git a/chrome/browser/notifications/sync_notifier/chrome_notifier_service.h b/chrome/browser/notifications/sync_notifier/chrome_notifier_service.h
index 13a21f0..61ff02b 100644
--- a/chrome/browser/notifications/sync_notifier/chrome_notifier_service.h
+++ b/chrome/browser/notifications/sync_notifier/chrome_notifier_service.h
@@ -67,7 +67,7 @@
 
   // Called when we dismiss a notification.  This is virtual so that test
   // subclasses can override it.
-  virtual void MarkNotificationAsDismissed(const std::string& id);
+  virtual void MarkNotificationAsRead(const std::string& id);
 
   // Called when a notier is enabled or disabled.
   void OnSyncedNotificationServiceEnabled(
@@ -91,9 +91,15 @@
   // Add a notification to our list.  This takes ownership of the pointer.
   void Add(scoped_ptr<notifier::SyncedNotification> notification);
 
+  // Display this notification in the notification center, or remove it.
+  void UpdateInMessageCenter(notifier::SyncedNotification* notification);
+
   // Display a notification in the notification center (eventually).
   void Display(notifier::SyncedNotification* notification);
 
+  // Remove a notification from our store.
+  void FreeNotificationById(const std::string& notification_id);
+
   // Back pointer to the owning profile.
   Profile* const profile_;
   NotificationUIManager* const notification_manager_;
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 17fe01f..5f5ced5 100644
--- a/chrome/browser/notifications/sync_notifier/chrome_notifier_service_unittest.cc
+++ b/chrome/browser/notifications/sync_notifier/chrome_notifier_service_unittest.cc
@@ -310,6 +310,103 @@
   // this test more robust.
 }
 
+// Process sync changes when there is no local data.
+TEST_F(ChromeNotifierServiceTest, ProcessSyncChangesNonEmptyModel) {
+  StubNotificationUIManager notification_manager;
+  ChromeNotifierService notifier(NULL, &notification_manager);
+  notifier.set_avoid_bitmap_fetching_for_test(true);
+
+  // Create some local fake data.
+  scoped_ptr<SyncedNotification> n1(CreateNotification(
+      kTitle1, kText1, kIconUrl1, kImageUrl1, kAppId1, kKey1, kUnread));
+  notifier.AddForTest(n1.Pass());
+  scoped_ptr<SyncedNotification> n2(CreateNotification(
+      kTitle2, kText2, kIconUrl2, kImageUrl2, kAppId2, kKey2, kUnread));
+  notifier.AddForTest(n2.Pass());
+  scoped_ptr<SyncedNotification> n3(CreateNotification(
+      kTitle3, kText3, kIconUrl3, kImageUrl3, kAppId3, kKey3, kUnread));
+  notifier.AddForTest(n3.Pass());
+
+  notifier.MergeDataAndStartSyncing(
+      SYNCED_NOTIFICATIONS,
+      SyncDataList(),
+      PassProcessor(),
+      scoped_ptr<syncer::SyncErrorFactory>(new syncer::SyncErrorFactoryMock()));
+
+  // Set up some ADDs, some UPDATES, and some DELETEs
+  SyncChangeList changes;
+  changes.push_back(CreateSyncChange(
+      SyncChange::ACTION_ADD, CreateNotification(
+          kTitle4, kText4, kIconUrl4, kImageUrl4, kAppId4, kKey4, kUnread)));
+  changes.push_back(CreateSyncChange(
+      SyncChange::ACTION_UPDATE, CreateNotification(
+          kTitle2, kText2, kIconUrl2, kImageUrl2, kAppId2, kKey2, kRead)));
+  changes.push_back(CreateSyncChange(
+      SyncChange::ACTION_DELETE, CreateNotification(
+          kTitle3, kText3, kIconUrl3, kImageUrl3, kAppId3, kKey3, kDismissed)));
+
+  // Simulate incoming new notifications at runtime.
+  notifier.ProcessSyncChanges(FROM_HERE, changes);
+
+  // We should find notifications 1, 2, and 4, but not 3.
+  EXPECT_EQ(3U, notifier.GetAllSyncData(SYNCED_NOTIFICATIONS).size());
+  EXPECT_TRUE(notifier.FindNotificationById(kKey1));
+  EXPECT_TRUE(notifier.FindNotificationById(kKey2));
+  EXPECT_FALSE(notifier.FindNotificationById(kKey3));
+  EXPECT_TRUE(notifier.FindNotificationById(kKey4));
+}
+
+// Process sync changes that arrive before the change they are supposed to
+// modify.
+TEST_F(ChromeNotifierServiceTest, ProcessSyncChangesOutOfOrder) {
+  StubNotificationUIManager notification_manager;
+  ChromeNotifierService notifier(NULL, &notification_manager);
+  notifier.set_avoid_bitmap_fetching_for_test(true);
+
+  // Create some local fake data.
+  scoped_ptr<SyncedNotification> n1(CreateNotification(
+      kTitle1, kText1, kIconUrl1, kImageUrl1, kAppId1, kKey1, kUnread));
+  notifier.AddForTest(n1.Pass());
+  scoped_ptr<SyncedNotification> n2(CreateNotification(
+      kTitle2, kText2, kIconUrl2, kImageUrl2, kAppId2, kKey2, kUnread));
+  notifier.AddForTest(n2.Pass());
+  scoped_ptr<SyncedNotification> n3(CreateNotification(
+      kTitle3, kText3, kIconUrl3, kImageUrl3, kAppId3, kKey3, kUnread));
+  notifier.AddForTest(n3.Pass());
+
+  notifier.MergeDataAndStartSyncing(
+      SYNCED_NOTIFICATIONS,
+      SyncDataList(),
+      PassProcessor(),
+      scoped_ptr<syncer::SyncErrorFactory>(new syncer::SyncErrorFactoryMock()));
+
+  SyncChangeList changes;
+  // UPDATE a notification we have not seen an add for.
+  changes.push_back(CreateSyncChange(
+      SyncChange::ACTION_UPDATE, CreateNotification(
+          kTitle4, kText4, kIconUrl4, kImageUrl4, kAppId4, kKey4, kUnread)));
+  // ADD a notification that we already have.
+  changes.push_back(CreateSyncChange(
+      SyncChange::ACTION_ADD, CreateNotification(
+          kTitle2, kText2, kIconUrl2, kImageUrl2, kAppId2, kKey2, kRead)));
+  // DELETE a notification we have not seen yet.
+  changes.push_back(CreateSyncChange(
+      SyncChange::ACTION_DELETE, CreateNotification(
+          kTitle5, kText5, kIconUrl5, kImageUrl5, kAppId5, kKey5, kDismissed)));
+
+  // Simulate incoming new notifications at runtime.
+  notifier.ProcessSyncChanges(FROM_HERE, changes);
+
+  // We should find notifications 1, 2, 3, and 4, but not 5.
+  EXPECT_EQ(4U, notifier.GetAllSyncData(SYNCED_NOTIFICATIONS).size());
+  EXPECT_TRUE(notifier.FindNotificationById(kKey1));
+  EXPECT_TRUE(notifier.FindNotificationById(kKey2));
+  EXPECT_TRUE(notifier.FindNotificationById(kKey3));
+  EXPECT_TRUE(notifier.FindNotificationById(kKey4));
+  EXPECT_FALSE(notifier.FindNotificationById(kKey5));
+}
+
+
 // Model has some notifications, some of them are local only. Sync has some
 // notifications. No items match up.
 TEST_F(ChromeNotifierServiceTest, LocalRemoteBothNonEmptyNoOverlap) {
diff --git a/chrome/browser/notifications/sync_notifier/synced_notification.cc b/chrome/browser/notifications/sync_notifier/synced_notification.cc
index 5c427ff..abffe93 100644
--- a/chrome/browser/notifications/sync_notifier/synced_notification.cc
+++ b/chrome/browser/notifications/sync_notifier/synced_notification.cc
@@ -191,7 +191,7 @@
   if (SyncedNotification::kRead == GetReadState() ||
       SyncedNotification::kDismissed == GetReadState() ) {
     notification_manager->CancelById(GetKey());
-    DVLOG(2) << "Dismissed notification arrived"
+    DVLOG(2) << "Dismissed or read notification arrived"
              << GetHeading() << " " << GetText();
     return;
   }
@@ -376,6 +376,19 @@
   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) {
 
@@ -393,6 +406,10 @@
     NOTREACHED();
 }
 
+void SyncedNotification::NotificationHasBeenRead() {
+  SetReadState(kRead);
+}
+
 void SyncedNotification::NotificationHasBeenDismissed() {
   SetReadState(kDismissed);
 }
diff --git a/chrome/browser/notifications/sync_notifier/synced_notification.h b/chrome/browser/notifications/sync_notifier/synced_notification.h
index cba6863..0a6842d 100644
--- a/chrome/browser/notifications/sync_notifier/synced_notification.h
+++ b/chrome/browser/notifications/sync_notifier/synced_notification.h
@@ -79,6 +79,7 @@
 
   bool EqualsIgnoringReadState(const SyncedNotification& other) const;
 
+  void NotificationHasBeenRead();
   void NotificationHasBeenDismissed();
 
   // Fill up the queue of bitmaps to fetch.
@@ -99,6 +100,9 @@
   // of the sync data.
   sync_pb::EntitySpecifics GetEntitySpecifics() const;
 
+  // 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);
diff --git a/chrome/browser/omnibox/omnibox_field_trial.cc b/chrome/browser/omnibox/omnibox_field_trial.cc
index 83b9143..ffd2f72 100644
--- a/chrome/browser/omnibox/omnibox_field_trial.cc
+++ b/chrome/browser/omnibox/omnibox_field_trial.cc
@@ -8,8 +8,11 @@
 
 #include "base/metrics/field_trial.h"
 #include "base/strings/string_number_conversions.h"
+#include "base/strings/string_split.h"
 #include "base/strings/string_util.h"
 #include "base/strings/stringprintf.h"
+#include "chrome/browser/autocomplete/autocomplete_input.h"
+#include "chrome/browser/search/search.h"
 #include "chrome/common/metrics/metrics_util.h"
 #include "chrome/common/metrics/variations/variation_ids.h"
 #include "chrome/common/metrics/variations/variations_util.h"
@@ -21,11 +24,12 @@
 const char kHUPCreateShorterMatchFieldTrialName[] =
     "OmniboxHUPCreateShorterMatch";
 const char kStopTimerFieldTrialName[] = "OmniboxStopTimer";
-const char kShortcutsScoringFieldTrialName[] = "OmniboxShortcutsScoring";
 const char kBundledExperimentFieldTrialName[] = "OmniboxBundledExperimentV1";
 
 // Rule names used by the bundled experiment.
+const char kShortcutsScoringMaxRelevanceRule[] = "ShortcutsScoringMaxRelevance";
 const char kSearchHistoryRule[] = "SearchHistory";
+const char kDemoteByTypeRule[] = "DemoteByType";
 
 // The autocomplete dynamic field trial name prefix.  Each field trial is
 // configured dynamically and is retrieved automatically by Chrome during
@@ -132,14 +136,9 @@
       continue;
     int types = 0;
     if (!base::StringToInt(base::StringPiece(
-            group_name.substr(strlen(kDisabledProviders))), &types)) {
-      LOG(WARNING) << "Malformed DisabledProviders string: " << group_name;
+            group_name.substr(strlen(kDisabledProviders))), &types))
       continue;
-    }
-    if (types == 0)
-      LOG(WARNING) << "Expecting a non-zero bitmap; group = " << group_name;
-    else
-      provider_types |= types;
+    provider_types |= types;
   }
   return provider_types;
 }
@@ -204,20 +203,18 @@
   return false;
 }
 
-// If the active group name starts with "MaxRelevance_", extract the
-// int that immediately following that, returning true on success.
-bool OmniboxFieldTrial::ShortcutsScoringMaxRelevance(int* max_relevance) {
-  std::string group_name =
-      base::FieldTrialList::FindFullName(kShortcutsScoringFieldTrialName);
-  const char kMaxRelevanceGroupPrefix[] = "MaxRelevance_";
-  if (!StartsWithASCII(group_name, kMaxRelevanceGroupPrefix, true))
+bool OmniboxFieldTrial::ShortcutsScoringMaxRelevance(
+    AutocompleteInput::PageClassification current_page_classification,
+    int* max_relevance) {
+  // The value of the rule is a string that encodes an integer containing
+  // the max relevance.
+  const std::string& max_relevance_str =
+      OmniboxFieldTrial::GetValueForRuleInContext(
+          kShortcutsScoringMaxRelevanceRule, current_page_classification);
+  if (max_relevance_str.empty())
     return false;
-  if (!base::StringToInt(base::StringPiece(
-          group_name.substr(strlen(kMaxRelevanceGroupPrefix))),
-                         max_relevance)) {
-    LOG(WARNING) << "Malformed MaxRelevance string: " << group_name;
+  if (!base::StringToInt(max_relevance_str, max_relevance))
     return false;
-  }
   return true;
 }
 
@@ -233,25 +230,67 @@
       kSearchHistoryRule, current_page_classification) == "Disable";
 }
 
+void OmniboxFieldTrial::GetDemotionsByType(
+    AutocompleteInput::PageClassification current_page_classification,
+    DemotionMultipliers* demotions_by_type) {
+  demotions_by_type->clear();
+  const std::string demotion_rule =
+      OmniboxFieldTrial::GetValueForRuleInContext(
+          kDemoteByTypeRule,
+          current_page_classification);
+  // The value of the DemoteByType rule is a comma-separated list of
+  // {ResultType + ":" + Number} where ResultType is an AutocompleteMatchType::
+  // Type enum represented as an integer and Number is an integer number
+  // between 0 and 100 inclusive.   Relevance scores of matches of that result
+  // type are multiplied by Number / 100.  100 means no change.
+  base::StringPairs kv_pairs;
+  if (base::SplitStringIntoKeyValuePairs(demotion_rule, ':', ',', &kv_pairs)) {
+    for (base::StringPairs::const_iterator it = kv_pairs.begin();
+         it != kv_pairs.end(); ++it) {
+      // This is a best-effort conversion; we trust the hand-crafted parameters
+      // downloaded from the server to be perfect.  There's no need for handle
+      // errors smartly.
+      int k, v;
+      base::StringToInt(it->first, &k);
+      base::StringToInt(it->second, &v);
+      (*demotions_by_type)[static_cast<AutocompleteMatchType::Type>(k)] =
+          static_cast<float>(v) / 100.0f;
+    }
+  }
+}
+
 // Background and implementation details:
 //
 // Each experiment group in any field trial can come with an optional set of
 // parameters (key-value pairs).  In the bundled omnibox experiment
 // (kBundledExperimentFieldTrialName), each experiment group comes with a
 // list of parameters in the form:
-//   key=<Rule>:<AutocompleteInput::PageClassification (as an int)>
+//   key=<Rule>:
+//       <AutocompleteInput::PageClassification (as an int)>:
+//       <whether Instant Extended is enabled (as a 1 or 0)>
+//     (note that there are no linebreaks in keys; this format is for
+//      presentation only>
 //   value=<arbitrary string>
-// The AutocompleteInput::PageClassification can also be "*", which means
-// this rule applies in all page classification contexts.
+// Both the AutocompleteInput::PageClassification and the Instant Extended
+// entries can be "*", which means this rule applies for all values of the
+// matching portion of the context.
 // One example parameter is
-//   key=SearchHistory:6
+//   key=SearchHistory:6:1
 //   value=PreventInlining
 // This means in page classification context 6 (a search result page doing
-// search term replacement), the SearchHistory experiment should
-// PreventInlining.
+// search term replacement) with Instant Extended enabled, the SearchHistory
+// experiment should PreventInlining.
+//
+// When an exact match to the rule in the current context is missing, we
+// give preference to a wildcard rule that matches the instant extended
+// context over a wildcard rule that matches the page classification
+// context.  Hopefully, though, users will write their field trial configs
+// so as not to rely on this fall back order.
 //
 // In short, this function tries to find the value associated with key
-// |rule|:|page_classification|, failing that it looks up |rule|:*,
+// |rule|:|page_classification|:|instant_extended|, failing that it looks up
+// |rule|:*:|instant_extended|, failing that it looks up
+// |rule|:|page_classification|:*, failing that it looks up |rule|:*:*,
 // and failing that it returns the empty string.
 std::string OmniboxFieldTrial::GetValueForRuleInContext(
     const std::string& rule,
@@ -261,13 +300,24 @@
                                              &params)) {
     return std::string();
   }
+  const std::string page_classification_str =
+      base::IntToString(static_cast<int>(page_classification));
+  const std::string instant_extended =
+      chrome::IsInstantExtendedAPIEnabled() ? "1" : "0";
   // Look up rule in this exact context.
-  std::map<std::string, std::string>::iterator it =
-      params.find(rule + ":" + base::IntToString(
-          static_cast<int>(page_classification)));
+  std::map<std::string, std::string>::iterator it = params.find(
+      rule + ":" + page_classification_str + ":" + instant_extended);
+  if (it != params.end())
+    return it->second;
+  // Fall back to the global page classification context.
+  it = params.find(rule + ":*:" + instant_extended);
+  if (it != params.end())
+    return it->second;
+  // Fall back to the global instant extended context.
+  it = params.find(rule + ":" + page_classification_str + ":*");
   if (it != params.end())
     return it->second;
   // Look up rule in the global context.
-  it = params.find(rule + ":*");
+  it = params.find(rule + ":*:*");
   return (it != params.end()) ? it->second : std::string();
 }
diff --git a/chrome/browser/omnibox/omnibox_field_trial.h b/chrome/browser/omnibox/omnibox_field_trial.h
index 1ad3b16..cde6259 100644
--- a/chrome/browser/omnibox/omnibox_field_trial.h
+++ b/chrome/browser/omnibox/omnibox_field_trial.h
@@ -5,16 +5,23 @@
 #ifndef CHROME_BROWSER_OMNIBOX_OMNIBOX_FIELD_TRIAL_H_
 #define CHROME_BROWSER_OMNIBOX_OMNIBOX_FIELD_TRIAL_H_
 
+#include <map>
 #include <string>
 #include <vector>
 
 #include "base/basictypes.h"
 #include "base/gtest_prod_util.h"
 #include "chrome/browser/autocomplete/autocomplete_input.h"
+#include "chrome/common/autocomplete_match_type.h"
 
 // This class manages the Omnibox field trials.
 class OmniboxFieldTrial {
  public:
+  // A mapping that contains multipliers indicating that matches of the
+  // specified type should have their relevance score multiplied by the
+  // given number.  Omitted types are assumed to have multipliers of 1.0.
+  typedef std::map<AutocompleteMatchType::Type, float> DemotionMultipliers;
+
   // Creates the static field trial groups.
   // *** MUST NOT BE CALLED MORE THAN ONCE. ***
   static void ActivateStaticTrials();
@@ -87,20 +94,22 @@
   static bool InZeroSuggestFieldTrial();
 
   // ---------------------------------------------------------
-  // For the ShortcutsScoring field trial.
+  // For the ShortcutsScoringMaxRelevance experiment that's part of the
+  // bundled omnibox field trial.
 
-  // If the field trial is active and the user is in an experiment
-  // group, extract from the experiment group name the maximum
-  // relevance score ShortcutsProvider:: CalculateScore() can return.
-  // Returns true on a successful extraction.  If the extraction failed,
-  // if the field trial is not active, etc., returns false.
-  // CalculateScore()'s return value is a product of this maximum
-  // relevance score and some attenuating factors that are all between
-  // 0 and 1.  (Note that Shortcuts results may have their scores
-  // reduced later if the assigned score is higher than allowed for
-  // non-inlineable results.  Shortcuts results are not allowed to be
+  // If the user is in an experiment group that, given the provided
+  // |current_page_classification| context, changes the maximum relevance
+  // ShortcutsProvider::CalculateScore() is supposed to assign, extract
+  // that maximum relevance score and put in in |max_relevance|.  Returns
+  // true on a successful extraction.  CalculateScore()'s return value is
+  // a product of this maximum relevance score and some attenuating factors
+  // that are all between 0 and 1.  (Note that Shortcuts results may have
+  // their scores reduced later if the assigned score is higher than allowed
+  // for non-inlineable results.  Shortcuts results are not allowed to be
   // inlined.)
-  static bool ShortcutsScoringMaxRelevance(int* max_relevance);
+  static bool ShortcutsScoringMaxRelevance(
+      AutocompleteInput::PageClassification current_page_classification,
+      int* max_relevance);
 
   // ---------------------------------------------------------
   // For the SearchHistory experiment that's part of the bundled omnibox
@@ -118,8 +127,20 @@
   static bool SearchHistoryDisable(
       AutocompleteInput::PageClassification current_page_classification);
 
+  // ---------------------------------------------------------
+  // For the DemoteByType experiment that's part of the bundled omnibox field
+  // trial.
+
+  // If the user is in an experiment group that, in the provided
+  // |current_page_classification| context, demotes the relevance scores
+  // of certain types of matches, populates the |demotions_by_type| map
+  // appropriately.  Otherwise, clears |demotions_by_type|.
+  static void GetDemotionsByType(
+      AutocompleteInput::PageClassification current_page_classification,
+      DemotionMultipliers* demotions_by_type);
+
  private:
-  FRIEND_TEST_ALL_PREFIXES(OmniboxFieldTrialTest, GetValueForRuleInContext);
+  friend class OmniboxFieldTrialTest;
 
   // The bundled omnibox experiment comes with a set of parameters
   // (key-value pairs).  Each key indicates a certain rule that applies in
@@ -129,14 +150,13 @@
   // prevent search history matches from inlining.
   //
   // This function returns the value associated with the |rule| that applies
-  // in the current context (which currently only consists of
-  // |page_classification| but will soon contain other features, some not
-  // passed in as parameters, such as whether Instant Extended is enabled).
-  // If no such rule exists in the current context, looks for that rule in
-  // the global context and return its value if found.  If the rule remains
-  // unfound in the global context, returns the empty string.  For more
-  // details, see the implementation.  How to interpret the value is left
-  // to the caller; this is rule-dependent.
+  // in the current context (which currently consists of |page_classification|
+  // and whether Instant Extended is enabled).  If no such rule exists in the
+  // current context, fall back to the rule in various wildcard contexts and
+  // return its value if found.  If the rule remains unfound in the global
+  // context, returns the empty string.  For more details, including how we
+  // prioritize different wildcard contexts, see the implementation.  How to
+  // interpret the value is left to the caller; this is rule-dependent.
   static std::string GetValueForRuleInContext(
       const std::string& rule,
       AutocompleteInput::PageClassification page_classification);
diff --git a/chrome/browser/omnibox/omnibox_field_trial_unittest.cc b/chrome/browser/omnibox/omnibox_field_trial_unittest.cc
index 9ccb00f..22a5387 100644
--- a/chrome/browser/omnibox/omnibox_field_trial_unittest.cc
+++ b/chrome/browser/omnibox/omnibox_field_trial_unittest.cc
@@ -5,32 +5,30 @@
 #include "chrome/browser/omnibox/omnibox_field_trial.h"
 
 #include "base/basictypes.h"
+#include "base/command_line.h"
+#include "base/memory/scoped_ptr.h"
 #include "base/metrics/field_trial.h"
 #include "base/strings/string16.h"
+#include "chrome/browser/autocomplete/autocomplete_input.h"
+#include "chrome/browser/search/search.h"
+#include "chrome/common/chrome_switches.h"
 #include "chrome/common/metrics/entropy_provider.h"
 #include "chrome/common/metrics/variations/variations_util.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 class OmniboxFieldTrialTest : public testing::Test {
  public:
-  OmniboxFieldTrialTest() {}
-
-  static void SetUpTestCase() {
+  OmniboxFieldTrialTest() {
     ResetFieldTrialList();
   }
 
-  static void TearDownTestCase() {
-    delete field_trial_list_;
-    field_trial_list_ = NULL;
-  }
-
-  static void ResetFieldTrialList() {
-    // It's important to delete the old pointer first which sets
-    // FieldTrialList::global_ to NULL.
-    if (field_trial_list_)
-      delete field_trial_list_;
-    field_trial_list_ = new base::FieldTrialList(
-        new metrics::SHA1EntropyProvider("foo"));
+  void ResetFieldTrialList() {
+    // Destroy the existing FieldTrialList before creating a new one to avoid
+    // a DCHECK.
+    field_trial_list_.reset();
+    field_trial_list_.reset(new base::FieldTrialList(
+        new metrics::SHA1EntropyProvider("foo")));
+    chrome_variations::testing::ClearAllVariationParams();
     OmniboxFieldTrial::ActivateDynamicTrials();
   }
 
@@ -43,15 +41,45 @@
     return trial;
   }
 
+  // EXPECTS that demotions[match_type] exists with value expected_value.
+  static void VerifyDemotion(
+      const OmniboxFieldTrial::DemotionMultipliers& demotions,
+      AutocompleteMatchType::Type match_type,
+      float expected_value);
+
+  // EXPECT()s that OmniboxFieldTrial::GetValueForRuleInContext(|rule|,
+  // |page_classification|) returns |rule_value|.
+  static void ExpectRuleValue(
+      const std::string& rule_value,
+      const std::string& rule,
+      AutocompleteInput::PageClassification page_classification);
+
  private:
-  // Needed for Activate{Static/Dynamic}Trials().
-  static base::FieldTrialList* field_trial_list_;
+  scoped_ptr<base::FieldTrialList> field_trial_list_;
 
   DISALLOW_COPY_AND_ASSIGN(OmniboxFieldTrialTest);
 };
 
 // static
-base::FieldTrialList* OmniboxFieldTrialTest::field_trial_list_ = NULL;
+void OmniboxFieldTrialTest::VerifyDemotion(
+    const OmniboxFieldTrial::DemotionMultipliers& demotions,
+    AutocompleteMatchType::Type match_type,
+    float expected_value) {
+  OmniboxFieldTrial::DemotionMultipliers::const_iterator demotion_it =
+      demotions.find(match_type);
+  ASSERT_TRUE(demotion_it != demotions.end());
+  EXPECT_FLOAT_EQ(expected_value, demotion_it->second);
+}
+
+// static
+void OmniboxFieldTrialTest::ExpectRuleValue(
+    const std::string& rule_value,
+    const std::string& rule,
+    AutocompleteInput::PageClassification page_classification) {
+  EXPECT_EQ(rule_value,
+            OmniboxFieldTrial::GetValueForRuleInContext(
+                rule, page_classification));
+}
 
 // Test if GetDisabledProviderTypes() properly parses various field trial
 // group names.
@@ -131,20 +159,62 @@
   }
 }
 
+TEST_F(OmniboxFieldTrialTest, GetDemotionsByTypeWithFallback) {
+  // Must be the same as kBundledExperimentFieldTrialName
+  // defined in omnibox_field_trial.cc.
+  const std::string kTrialName = "OmniboxBundledExperimentV1";
+  // Must be the same as kDemoteByTypeRule defined in
+  // omnibox_field_trial.cc.
+  const std::string kRuleName = "DemoteByType";
+  {
+    std::map<std::string, std::string> params;
+    params[kRuleName + ":1:*"] = "1:50,2:0";
+    params[kRuleName + ":3:*"] = "5:100";
+    params[kRuleName + ":*:*"] = "1:25";
+    ASSERT_TRUE(chrome_variations::AssociateVariationParams(
+        kTrialName, "A", params));
+  }
+  base::FieldTrialList::CreateFieldTrial(kTrialName, "A");
+  OmniboxFieldTrial::DemotionMultipliers demotions_by_type;
+  OmniboxFieldTrial::GetDemotionsByType(
+      AutocompleteInput::NEW_TAB_PAGE, &demotions_by_type);
+  ASSERT_EQ(2u, demotions_by_type.size());
+  VerifyDemotion(demotions_by_type, AutocompleteMatchType::HISTORY_URL, 0.5);
+  VerifyDemotion(demotions_by_type, AutocompleteMatchType::HISTORY_TITLE, 0.0);
+  OmniboxFieldTrial::GetDemotionsByType(
+      AutocompleteInput::HOMEPAGE, &demotions_by_type);
+  ASSERT_EQ(1u, demotions_by_type.size());
+  VerifyDemotion(demotions_by_type, AutocompleteMatchType::NAVSUGGEST, 1.0);
+  OmniboxFieldTrial::GetDemotionsByType(
+      AutocompleteInput::BLANK, &demotions_by_type);
+  ASSERT_EQ(1u, demotions_by_type.size());
+  VerifyDemotion(demotions_by_type, AutocompleteMatchType::HISTORY_URL, 0.25);
+}
+
 TEST_F(OmniboxFieldTrialTest, GetValueForRuleInContext) {
+  // This test starts with Instant Extended off (the default state), then
+  // enables Instant Extended and tests again on the same rules.
+
   // Must be the same as kBundledExperimentFieldTrialName
   // defined in omnibox_field_trial.cc.
   const std::string kTrialName = "OmniboxBundledExperimentV1";
   {
     std::map<std::string, std::string> params;
-    // Rule 1 has some exact matches and a global fallback.
-    params["rule1:1"] = "rule1-1-value";  // NEW_TAB_PAGE
-    params["rule1:3"] = "rule1-3-value";  // HOMEPAGE
-    params["rule1:*"] = "rule1-*-value";  // global
-    // Rule 2 has no exact matches but has a global fallback.
-    params["rule2:*"] = "rule2-*-value";  // global
-    // Rule 3 has an exact match but no global fallback.
-    params["rule3:4"] = "rule3-4-value";  // OTHER
+    // Rule 1 has some exact matches and fallbacks at every level.
+    params["rule1:1:0"] = "rule1-1-0-value";  // NEW_TAB_PAGE
+    params["rule1:3:0"] = "rule1-3-0-value";  // HOMEPAGE
+    params["rule1:4:1"] = "rule1-4-1-value";  // OTHER
+    params["rule1:4:*"] = "rule1-4-*-value";  // OTHER
+    params["rule1:*:1"] = "rule1-*-1-value";  // global
+    params["rule1:*:*"] = "rule1-*-*-value";  // global
+    // Rule 2 has no exact matches but has fallbacks.
+    params["rule2:*:0"] = "rule2-*-0-value";  // global
+    params["rule2:1:*"] = "rule2-1-*-value";  // NEW_TAB_PAGE
+    params["rule2:*:*"] = "rule2-*-*-value";  // global
+    // Rule 3 has only a global fallback.
+    params["rule3:*:*"] = "rule3-*-*-value";  // global
+    // Rule 4 has an exact match but no fallbacks.
+    params["rule4:4:0"] = "rule4-4-0-value";  // OTHER
     // Add a malformed rule to make sure it doesn't screw things up.
     params["unrecognized"] = "unrecognized-value";
     ASSERT_TRUE(chrome_variations::AssociateVariationParams(
@@ -153,51 +223,84 @@
 
   base::FieldTrialList::CreateFieldTrial(kTrialName, "A");
 
+  // Tests with Instant Extended disabled.
   // Tests for rule 1.
-  EXPECT_EQ(
-      "rule1-1-value",
-      OmniboxFieldTrial::GetValueForRuleInContext(
-          "rule1", AutocompleteInput::NEW_TAB_PAGE));  // exact match
-  EXPECT_EQ(
-      "rule1-*-value",
-      OmniboxFieldTrial::GetValueForRuleInContext(
-          "rule1", AutocompleteInput::BLANK));  // fallback to global
-  EXPECT_EQ(
-      "rule1-3-value",
-      OmniboxFieldTrial::GetValueForRuleInContext(
-          "rule1", AutocompleteInput::HOMEPAGE));  // exact match
-  EXPECT_EQ(
-      "rule1-*-value",
-      OmniboxFieldTrial::GetValueForRuleInContext(
-          "rule1", AutocompleteInput::OTHER));  // fallback to global
-
+  ExpectRuleValue("rule1-1-0-value",
+                  "rule1", AutocompleteInput::NEW_TAB_PAGE);  // exact match
+  ExpectRuleValue("rule1-1-0-value",
+                  "rule1", AutocompleteInput::NEW_TAB_PAGE);  // exact match
+  ExpectRuleValue("rule1-*-*-value",
+                  "rule1", AutocompleteInput::BLANK);     // fallback to global
+  ExpectRuleValue("rule1-3-0-value",
+                  "rule1", AutocompleteInput::HOMEPAGE);  // exact match
+  ExpectRuleValue("rule1-4-*-value",
+                  "rule1", AutocompleteInput::OTHER);     // partial fallback
+  ExpectRuleValue("rule1-*-*-value",
+                  "rule1",
+                  AutocompleteInput::                     // fallback to global
+                      SEARCH_RESULT_PAGE_DOING_SEARCH_TERM_REPLACEMENT);
   // Tests for rule 2.
-  EXPECT_EQ(
-      "rule2-*-value",
-      OmniboxFieldTrial::GetValueForRuleInContext(
-          "rule2", AutocompleteInput::HOMEPAGE));  // fallback to global
-  EXPECT_EQ(
-      "rule2-*-value",
-      OmniboxFieldTrial::GetValueForRuleInContext(
-          "rule2", AutocompleteInput::OTHER));  // fallback to global
+  ExpectRuleValue("rule2-*-0-value",
+                  "rule2", AutocompleteInput::HOMEPAGE);  // partial fallback
+  ExpectRuleValue("rule2-*-0-value",
+                  "rule2", AutocompleteInput::OTHER);     // partial fallback
 
   // Tests for rule 3.
-  EXPECT_EQ(
-      "",
-      OmniboxFieldTrial::GetValueForRuleInContext(
-          "rule3", AutocompleteInput::BLANK));  // no global fallback
-  EXPECT_EQ(
-      "",
-      OmniboxFieldTrial::GetValueForRuleInContext(
-          "rule3", AutocompleteInput::HOMEPAGE));  // no global fallback
-  EXPECT_EQ(
-      "rule3-4-value",
-      OmniboxFieldTrial::GetValueForRuleInContext(
-          "rule3", AutocompleteInput::OTHER));  // exact match
+  ExpectRuleValue("rule3-*-*-value",
+                  "rule3", AutocompleteInput::HOMEPAGE);  // fallback to global
+  ExpectRuleValue("rule3-*-*-value",
+                  "rule3", AutocompleteInput::OTHER);     // fallback to global
 
-  // Tests for rule 4 (a missing rule).
-  EXPECT_EQ(
-      "",
-      OmniboxFieldTrial::GetValueForRuleInContext(
-          "rule4", AutocompleteInput::OTHER));  // no rule at all
+  // Tests for rule 4.
+  ExpectRuleValue("",
+                  "rule4", AutocompleteInput::BLANK);     // no global fallback
+  ExpectRuleValue("",
+                  "rule4", AutocompleteInput::HOMEPAGE);  // no global fallback
+  ExpectRuleValue("rule4-4-0-value",
+                  "rule4", AutocompleteInput::OTHER);     // exact match
+
+  // Tests for rule 5 (a missing rule).
+  ExpectRuleValue("",
+                  "rule5", AutocompleteInput::OTHER);     // no rule at all
+
+  // Now change the Instant Extended state and run analogous tests.
+  // Instant Extended only works on non-mobile platforms.
+#if !defined(OS_IOS) && !defined(OS_ANDROID)
+  chrome::ResetInstantExtendedOptInStateGateForTest();
+  CommandLine::ForCurrentProcess()->AppendSwitch(
+      switches::kEnableInstantExtendedAPI);
+
+  // Tests with Instant Extended enabled.
+  // Tests for rule 1.
+  ExpectRuleValue("rule1-4-1-value",
+                  "rule1", AutocompleteInput::OTHER);     // exact match
+  ExpectRuleValue("rule1-*-1-value",
+                  "rule1", AutocompleteInput::BLANK);     // partial fallback
+  ExpectRuleValue("rule1-*-1-value",
+                  "rule1",
+                  AutocompleteInput::NEW_TAB_PAGE);       // partial fallback
+
+  // Tests for rule 2.
+  ExpectRuleValue("rule2-1-*-value",
+                  "rule2",
+                  AutocompleteInput::NEW_TAB_PAGE);       // partial fallback
+  ExpectRuleValue("rule2-*-*-value",
+                  "rule2", AutocompleteInput::OTHER);     // global fallback
+
+  // Tests for rule 3.
+  ExpectRuleValue("rule3-*-*-value",
+                  "rule3", AutocompleteInput::HOMEPAGE);  // global fallback
+  ExpectRuleValue("rule3-*-*-value",
+                  "rule3", AutocompleteInput::OTHER);     // global fallback
+
+  // Tests for rule 4.
+  ExpectRuleValue("",
+                  "rule4", AutocompleteInput::BLANK);     // no global fallback
+  ExpectRuleValue("",
+                  "rule4", AutocompleteInput::HOMEPAGE);  // no global fallback
+
+  // Tests for rule 5 (a missing rule).
+  ExpectRuleValue("",
+                  "rule5", AutocompleteInput::OTHER);     // no rule at all
+#endif  // !defined(OS_IOS) && !defined(OS_ANDROID)
 }
diff --git a/chrome/browser/pepper_flash_settings_manager.cc b/chrome/browser/pepper_flash_settings_manager.cc
index 243ea84..4061463 100644
--- a/chrome/browser/pepper_flash_settings_manager.cc
+++ b/chrome/browser/pepper_flash_settings_manager.cc
@@ -29,7 +29,6 @@
 #include "ipc/ipc_listener.h"
 #include "ppapi/proxy/ppapi_messages.h"
 #include "url/gurl.h"
-#include "webkit/plugins/plugin_constants.h"
 
 using content::BrowserThread;
 
@@ -955,7 +954,7 @@
       content::PluginService::GetInstance();
   std::vector<content::WebPluginInfo> plugins;
   plugin_service->GetPluginInfoArray(
-      GURL(), kFlashPluginSwfMimeType, false, &plugins, NULL);
+      GURL(), content::kFlashPluginSwfMimeType, false, &plugins, NULL);
 
   for (std::vector<content::WebPluginInfo>::iterator iter = plugins.begin();
        iter != plugins.end(); ++iter) {
diff --git a/chrome/browser/plugins/plugin_installer.cc b/chrome/browser/plugins/plugin_installer.cc
index 69864ad..099711e 100644
--- a/chrome/browser/plugins/plugin_installer.cc
+++ b/chrome/browser/plugins/plugin_installer.cc
@@ -10,7 +10,7 @@
 #include "base/strings/stringprintf.h"
 #include "chrome/browser/download/download_service.h"
 #include "chrome/browser/download/download_service_factory.h"
-#include "chrome/browser/download/download_util.h"
+#include "chrome/browser/download/download_stats.h"
 #include "chrome/browser/platform_util.h"
 #include "chrome/browser/plugins/plugin_installer_observer.h"
 #include "chrome/browser/profiles/profile.h"
@@ -136,8 +136,7 @@
   FOR_EACH_OBSERVER(PluginInstallerObserver, observers_, DownloadStarted());
   Profile* profile =
       Profile::FromBrowserContext(web_contents->GetBrowserContext());
-  download_util::RecordDownloadSource(
-      download_util::INITIATED_BY_PLUGIN_INSTALLER);
+  RecordDownloadSource(DOWNLOAD_INITIATED_BY_PLUGIN_INSTALLER);
   BrowserThread::PostTask(
       BrowserThread::IO, FROM_HERE,
       base::Bind(&BeginDownload,
diff --git a/chrome/browser/policy/browser_policy_connector.cc b/chrome/browser/policy/browser_policy_connector.cc
index 5d15e06..022c2e2 100644
--- a/chrome/browser/policy/browser_policy_connector.cc
+++ b/chrome/browser/policy/browser_policy_connector.cc
@@ -152,7 +152,7 @@
     scoped_refptr<net::URLRequestContextGetter> request_context) {
   // Initialization of some of the providers requires the FILE thread; make
   // sure that threading is ready at this point.
-  DCHECK(BrowserThread::IsWellKnownThread(BrowserThread::FILE));
+  DCHECK(BrowserThread::IsThreadInitialized(BrowserThread::FILE));
   DCHECK(!is_initialized()) << "BrowserPolicyConnector::Init() called twice.";
 
   local_state_ = local_state;
diff --git a/chrome/browser/policy/policy_browsertest.cc b/chrome/browser/policy/policy_browsertest.cc
index c45b476..65bb42f 100644
--- a/chrome/browser/policy/policy_browsertest.cc
+++ b/chrome/browser/policy/policy_browsertest.cc
@@ -94,6 +94,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/common/content_constants.h"
 #include "content/public/common/content_paths.h"
 #include "content/public/common/page_transition_types.h"
 #include "content/public/common/process_type.h"
@@ -120,7 +121,6 @@
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/base/resource/resource_bundle.h"
 #include "url/gurl.h"
-#include "webkit/plugins/plugin_constants.h"
 
 #if defined(OS_CHROMEOS)
 #include "ash/accelerators/accelerator_controller.h"
@@ -358,7 +358,7 @@
     const std::vector<content::WebPluginInfo>& plugins) {
   const content::WebPluginInfo* flash = NULL;
   for (size_t i = 0; i < plugins.size(); ++i) {
-    if (plugins[i].name == ASCIIToUTF16(kFlashPluginName)) {
+    if (plugins[i].name == ASCIIToUTF16(content::kFlashPluginName)) {
       flash = &plugins[i];
       break;
     }
@@ -564,7 +564,7 @@
     base::FilePath extension_path(ui_test_utils::GetTestFilePath(
         base::FilePath(kTestExtensionsDir), base::FilePath(name)));
     scoped_refptr<extensions::CrxInstaller> installer =
-        extensions::CrxInstaller::Create(extension_service(), NULL);
+        extensions::CrxInstaller::CreateSilent(extension_service());
     installer->set_allow_silent_install(true);
     installer->set_install_cause(extension_misc::INSTALL_CAUSE_UPDATE);
     installer->set_creation_flags(extensions::Extension::FROM_WEBSTORE);
@@ -1143,7 +1143,7 @@
   EXPECT_TRUE(SetPluginEnabled(plugin_prefs, flash, false));
   EXPECT_FALSE(plugin_prefs->IsPluginEnabled(*flash));
   base::ListValue plugin_list;
-  plugin_list.Append(base::Value::CreateStringValue(kFlashPluginName));
+  plugin_list.Append(base::Value::CreateStringValue(content::kFlashPluginName));
   PolicyMap policies;
   policies.Set(key::kEnabledPlugins, POLICY_LEVEL_MANDATORY,
                POLICY_SCOPE_USER, plugin_list.DeepCopy(), NULL);
diff --git a/chrome/browser/prefs/browser_prefs.cc b/chrome/browser/prefs/browser_prefs.cc
index f954807..948ba02 100644
--- a/chrome/browser/prefs/browser_prefs.cc
+++ b/chrome/browser/prefs/browser_prefs.cc
@@ -71,8 +71,6 @@
 #include "chrome/browser/translate/translate_prefs.h"
 #include "chrome/browser/ui/alternate_error_tab_observer.h"
 #include "chrome/browser/ui/app_list/app_list_service.h"
-#include "chrome/browser/ui/autofill/autofill_credit_card_bubble_controller.h"
-#include "chrome/browser/ui/autofill/autofill_dialog_controller_impl.h"
 #include "chrome/browser/ui/browser_ui_prefs.h"
 #include "chrome/browser/ui/network_profile_bubble.h"
 #include "chrome/browser/ui/prefs/prefs_tab_helper.h"
@@ -95,6 +93,10 @@
 #include "components/user_prefs/pref_registry_syncable.h"
 #include "content/public/browser/render_process_host.h"
 
+#if defined(ENABLE_AUTOFILL_DIALOG)
+#include "chrome/browser/ui/autofill/autofill_dialog_controller.h"
+#endif
+
 #if defined(ENABLE_CONFIGURATION_POLICY)
 #include "chrome/browser/policy/browser_policy_connector.h"
 #include "chrome/browser/policy/policy_statistics_collector.h"
@@ -153,6 +155,8 @@
 
 #if defined(OS_ANDROID)
 #include "chrome/browser/ui/webui/ntp/android/promo_handler.h"
+#else
+#include "chrome/browser/ui/autofill/generated_credit_card_bubble_controller.h"
 #endif
 
 #if defined(ENABLE_PLUGIN_INSTALLATION)
@@ -287,9 +291,10 @@
   // User prefs. Please keep this list alphabetized.
   AlternateErrorPageTabObserver::RegisterProfilePrefs(registry);
   apps::RegisterProfilePrefs(registry);
-  autofill::AutofillCreditCardBubbleController::RegisterUserPrefs(registry);
-  autofill::AutofillDialogControllerImpl::RegisterProfilePrefs(registry);
   autofill::AutofillManager::RegisterProfilePrefs(registry);
+#if !defined(OS_ANDROID)
+  autofill::GeneratedCreditCardBubbleController::RegisterUserPrefs(registry);
+#endif
   BookmarkPromptPrefs::RegisterProfilePrefs(registry);
   bookmark_utils::RegisterProfilePrefs(registry);
   browser_sync::SyncPrefs::RegisterProfilePrefs(registry);
@@ -321,6 +326,10 @@
   TemplateURLPrepopulateData::RegisterProfilePrefs(registry);
   TranslatePrefs::RegisterProfilePrefs(registry);
 
+#if defined(ENABLE_AUTOFILL_DIALOG)
+  autofill::AutofillDialogController::RegisterProfilePrefs(registry);
+#endif
+
 #if defined(ENABLE_CONFIGURATION_POLICY)
   policy::URLBlacklistManager::RegisterProfilePrefs(registry);
 #endif
diff --git a/chrome/browser/prefs/pref_metrics_service.cc b/chrome/browser/prefs/pref_metrics_service.cc
index bcac818..a437c8c 100644
--- a/chrome/browser/prefs/pref_metrics_service.cc
+++ b/chrome/browser/prefs/pref_metrics_service.cc
@@ -4,17 +4,39 @@
 
 #include "chrome/browser/prefs/pref_metrics_service.h"
 
+#include "base/bind.h"
 #include "base/metrics/histogram.h"
 #include "base/prefs/pref_service.h"
+#include "chrome/browser/prefs/pref_service_syncable.h"
 #include "chrome/browser/prefs/session_startup_pref.h"
+#include "chrome/browser/prefs/synced_pref_change_registrar.h"
 #include "chrome/browser/profiles/incognito_helpers.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/common/pref_names.h"
 #include "components/browser_context_keyed_service/browser_context_dependency_manager.h"
+#include "net/base/registry_controlled_domains/registry_controlled_domain.h"
+
+namespace {
+
+// Converts a host name into a domain name for easier matching.
+std::string GetDomainFromHost(const std::string& host) {
+  return net::registry_controlled_domains::GetDomainAndRegistry(
+      host,
+      net::registry_controlled_domains::EXCLUDE_PRIVATE_REGISTRIES);
+}
+
+const int kSessionStartupPrefValueMax = SessionStartupPref::kPrefValueMax;
+
+}  // namespace
 
 PrefMetricsService::PrefMetricsService(Profile* profile)
     : profile_(profile) {
   RecordLaunchPrefs();
+
+  PrefServiceSyncable* prefs = PrefServiceSyncable::FromProfile(profile_);
+  synced_pref_change_registrar_.reset(new SyncedPrefChangeRegistrar(prefs));
+
+  RegisterSyncedPrefObservers();
 }
 
 PrefMetricsService::~PrefMetricsService() {
@@ -31,7 +53,7 @@
   }
   int restore_on_startup = prefs->GetInteger(prefs::kRestoreOnStartup);
   UMA_HISTOGRAM_ENUMERATION("Settings.StartupPageLoadSettings",
-      restore_on_startup, SessionStartupPref::kPrefValueMax);
+      restore_on_startup, kSessionStartupPrefValueMax);
   if (restore_on_startup == SessionStartupPref::kPrefValueURLs) {
     const int url_list_size = prefs->GetList(
         prefs::kURLsToRestoreOnStartup)->GetSize();
@@ -40,6 +62,83 @@
   }
 }
 
+void PrefMetricsService::RegisterSyncedPrefObservers() {
+  LogHistogramValueCallback booleanHandler = base::Bind(
+      &PrefMetricsService::LogBooleanPrefChange, base::Unretained(this));
+
+  AddPrefObserver(prefs::kShowHomeButton, "ShowHomeButton", booleanHandler);
+  AddPrefObserver(prefs::kHomePageIsNewTabPage, "HomePageIsNewTabPage",
+                  booleanHandler);
+
+  AddPrefObserver(prefs::kRestoreOnStartup, "StartupPageLoadSettings",
+                  base::Bind(&PrefMetricsService::LogIntegerPrefChange,
+                             base::Unretained(this),
+                             kSessionStartupPrefValueMax));
+}
+
+void PrefMetricsService::AddPrefObserver(
+    const std::string& path,
+    const std::string& histogram_name_prefix,
+    const LogHistogramValueCallback& callback) {
+  synced_pref_change_registrar_->Add(path.c_str(),
+      base::Bind(&PrefMetricsService::OnPrefChanged,
+                 base::Unretained(this),
+                 histogram_name_prefix, callback));
+}
+
+void PrefMetricsService::OnPrefChanged(
+    const std::string& histogram_name_prefix,
+    const LogHistogramValueCallback& callback,
+    const std::string& path,
+    bool from_sync) {
+  PrefServiceSyncable* prefs = PrefServiceSyncable::FromProfile(profile_);
+  const PrefService::Preference* pref = prefs->FindPreference(path.c_str());
+  DCHECK(pref);
+  std::string source_name(
+      from_sync ? ".PulledFromSync" : ".PushedToSync");
+  std::string histogram_name("Settings." + histogram_name_prefix + source_name);
+  callback.Run(histogram_name, pref->GetValue());
+};
+
+void PrefMetricsService::LogBooleanPrefChange(const std::string& histogram_name,
+                                              const Value* value) {
+  bool boolean_value = false;
+  if (!value->GetAsBoolean(&boolean_value))
+    return;
+  base::HistogramBase* histogram = base::BooleanHistogram::FactoryGet(
+      histogram_name, base::HistogramBase::kUmaTargetedHistogramFlag);
+  histogram->Add(boolean_value);
+}
+
+void PrefMetricsService::LogIntegerPrefChange(int boundary_value,
+                                              const std::string& histogram_name,
+                                              const Value* value) {
+  int integer_value = 0;
+  if (!value->GetAsInteger(&integer_value))
+    return;
+  base::HistogramBase* histogram = base::LinearHistogram::FactoryGet(
+      histogram_name,
+      1,
+      boundary_value,
+      boundary_value + 1,
+      base::HistogramBase::kUmaTargetedHistogramFlag);
+  histogram->Add(integer_value);
+}
+
+void PrefMetricsService::LogListPrefChange(
+    const LogHistogramValueCallback& item_callback,
+    const std::string& histogram_name,
+    const Value* value) {
+  const ListValue* items = NULL;
+  if (!value->GetAsList(&items))
+    return;
+  for (size_t i = 0; i < items->GetSize(); ++i) {
+    const Value *item_value = NULL;
+    if (items->Get(i, &item_value))
+      item_callback.Run(histogram_name, item_value);
+  }
+}
+
 // static
 PrefMetricsService::Factory* PrefMetricsService::Factory::GetInstance() {
   return Singleton<PrefMetricsService::Factory>::get();
diff --git a/chrome/browser/prefs/pref_metrics_service.h b/chrome/browser/prefs/pref_metrics_service.h
index 647cd94..fc48935 100644
--- a/chrome/browser/prefs/pref_metrics_service.h
+++ b/chrome/browser/prefs/pref_metrics_service.h
@@ -5,7 +5,12 @@
 #ifndef CHROME_BROWSER_PREFS_PREF_METRICS_SERVICE_H_
 #define CHROME_BROWSER_PREFS_PREF_METRICS_SERVICE_H_
 
+#include <map>
+#include <string>
+
+#include "base/memory/scoped_ptr.h"
 #include "base/memory/singleton.h"
+#include "chrome/browser/prefs/synced_pref_change_registrar.h"
 #include "chrome/browser/profiles/profile.h"
 #include "components/browser_context_keyed_service/browser_context_keyed_service.h"
 #include "components/browser_context_keyed_service/browser_context_keyed_service_factory.h"
@@ -34,11 +39,51 @@
     virtual content::BrowserContext* GetBrowserContextToUse(
         content::BrowserContext* context) const OVERRIDE;
   };
+
  private:
+  // Use a map to convert domains to their histogram identifiers. Ids are
+  // defined in tools/metrics/histograms/histograms.xml and (usually) also in
+  // chrome/browser/search_engines/prepopulated_engines.json.
+  typedef std::map<std::string, int> DomainIdMap;
+
+  // Function to log a Value to a histogram
+  typedef base::Callback<void(const std::string&, const Value*)>
+      LogHistogramValueCallback;
+
   // Record prefs state on browser context creation.
   void RecordLaunchPrefs();
 
+  // Register callbacks for synced pref changes.
+  void RegisterSyncedPrefObservers();
+
+  // Registers a histogram logging callback for a synced pref change.
+  void AddPrefObserver(const std::string& path,
+                       const std::string& histogram_name_prefix,
+                       const LogHistogramValueCallback& callback);
+
+  // Generic callback to observe a synced pref change.
+  void OnPrefChanged(const std::string& histogram_name_prefix,
+                     const LogHistogramValueCallback& callback,
+                     const std::string& path,
+                     bool from_sync);
+
+  // Callback for a boolean pref change histogram.
+  void LogBooleanPrefChange(const std::string& histogram_name,
+                            const Value* value);
+
+  // Callback for an integer pref change histogram.
+  void LogIntegerPrefChange(int boundary_value,
+                            const std::string& histogram_name,
+                            const Value* value);
+
+  // Callback for a list pref change. Each item in the list
+  // is logged using the given histogram callback.
+  void LogListPrefChange(const LogHistogramValueCallback& item_callback,
+                         const std::string& histogram_name,
+                         const Value* value);
+
   Profile* profile_;
+  scoped_ptr<SyncedPrefChangeRegistrar> synced_pref_change_registrar_;
 };
 
 #endif  // CHROME_BROWSER_PREFS_PREF_METRICS_SERVICE_H_
diff --git a/chrome/browser/prefs/pref_model_associator.cc b/chrome/browser/prefs/pref_model_associator.cc
index 42cd194..28759a1 100644
--- a/chrome/browser/prefs/pref_model_associator.cc
+++ b/chrome/browser/prefs/pref_model_associator.cc
@@ -10,6 +10,7 @@
 #include "base/location.h"
 #include "base/logging.h"
 #include "base/prefs/pref_service.h"
+#include "base/stl_util.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/values.h"
 #include "chrome/browser/chrome_notification_types.h"
@@ -61,6 +62,10 @@
 PrefModelAssociator::~PrefModelAssociator() {
   DCHECK(CalledOnValidThread());
   pref_service_ = NULL;
+
+  STLDeleteContainerPairSecondPointers(synced_pref_observers_.begin(),
+                                       synced_pref_observers_.end());
+  synced_pref_observers_.clear();
 }
 
 void PrefModelAssociator::InitPrefAndAssociate(
@@ -395,6 +400,8 @@
     // policy controlled.
     pref_service_->Set(pref_name, *value);
 
+    NotifySyncedPrefObservers(name, true /*from_sync*/);
+
     // Keep track of any newly synced preferences.
     if (iter->change_type() == syncer::SyncChange::ACTION_ADD) {
       synced_preferences_.insert(name);
@@ -422,6 +429,26 @@
   return synced_preferences_.find(name) != synced_preferences_.end();
 }
 
+void PrefModelAssociator::AddSyncedPrefObserver(const std::string& name,
+    SyncedPrefObserver* observer) {
+  SyncedPrefObserverList* observers = synced_pref_observers_[name];
+  if (observers == NULL) {
+    observers = new SyncedPrefObserverList;
+    synced_pref_observers_[name] = observers;
+  }
+  observers->AddObserver(observer);
+}
+
+void PrefModelAssociator::RemoveSyncedPrefObserver(const std::string& name,
+    SyncedPrefObserver* observer) {
+  SyncedPrefObserverMap::iterator observer_iter =
+      synced_pref_observers_.find(name);
+  if (observer_iter == synced_pref_observers_.end())
+    return;
+  SyncedPrefObserverList* observers = observer_iter->second;
+  observers->RemoveObserver(observer);
+}
+
 std::set<std::string> PrefModelAssociator::registered_preferences() const {
   return registered_preferences_;
 }
@@ -463,6 +490,8 @@
 
   base::AutoReset<bool> processing_changes(&processing_syncer_changes_, true);
 
+  NotifySyncedPrefObservers(name, false /*from_sync*/);
+
   if (synced_preferences_.count(name) == 0) {
     // Not in synced_preferences_ means no synced data. InitPrefAndAssociate(..)
     // will determine if we care about its data (e.g. if it has a default value
@@ -489,3 +518,14 @@
   DCHECK(pref_service_ == NULL);
   pref_service_ = pref_service;
 }
+
+void PrefModelAssociator::NotifySyncedPrefObservers(const std::string& path,
+                                                    bool from_sync) const {
+  SyncedPrefObserverMap::const_iterator observer_iter =
+      synced_pref_observers_.find(path);
+  if (observer_iter == synced_pref_observers_.end())
+    return;
+  SyncedPrefObserverList* observers = observer_iter->second;
+  FOR_EACH_OBSERVER(SyncedPrefObserver, *observers,
+                    OnSyncedPrefChanged(path, from_sync));
+}
diff --git a/chrome/browser/prefs/pref_model_associator.h b/chrome/browser/prefs/pref_model_associator.h
index 584e271..539d38a 100644
--- a/chrome/browser/prefs/pref_model_associator.h
+++ b/chrome/browser/prefs/pref_model_associator.h
@@ -11,7 +11,10 @@
 
 #include "base/basictypes.h"
 #include "base/compiler_specific.h"
+#include "base/containers/hash_tables.h"
+#include "base/observer_list.h"
 #include "base/threading/non_thread_safe.h"
+#include "chrome/browser/prefs/synced_pref_observer.h"
 #include "sync/api/sync_data.h"
 #include "sync/api/syncable_service.h"
 
@@ -97,6 +100,14 @@
   // Note this does not refer to SYNCABLE_PREF.
   bool IsPrefSynced(const std::string& name) const;
 
+  // Adds a SyncedPrefObserver to watch for changes to a specific pref.
+  void AddSyncedPrefObserver(const std::string& name,
+                             SyncedPrefObserver* observer);
+
+  // Removes a SyncedPrefObserver from a pref's list of observers.
+  void RemoveSyncedPrefObserver(const std::string& name,
+                                SyncedPrefObserver* observer);
+
  protected:
   friend class ProfileSyncServicePreferenceTest;
 
@@ -157,6 +168,18 @@
   // PRIORITY_PREFERENCES.
   syncer::ModelType type_;
 
+ private:
+  // Map prefs to lists of observers. Observers will receive notification when
+  // a pref changes, including the detail of whether or not the change came
+  // from sync.
+  typedef ObserverList<SyncedPrefObserver> SyncedPrefObserverList;
+  typedef base::hash_map<std::string, SyncedPrefObserverList*>
+      SyncedPrefObserverMap;
+
+  void NotifySyncedPrefObservers(const std::string& path, bool from_sync) const;
+
+  SyncedPrefObserverMap synced_pref_observers_;
+
   DISALLOW_COPY_AND_ASSIGN(PrefModelAssociator);
 };
 
diff --git a/chrome/browser/prefs/pref_service_syncable.cc b/chrome/browser/prefs/pref_service_syncable.cc
index 0a4a455..58d040b 100644
--- a/chrome/browser/prefs/pref_service_syncable.cc
+++ b/chrome/browser/prefs/pref_service_syncable.cc
@@ -147,6 +147,20 @@
   PrefService::UpdateCommandLinePrefStore(cmd_line_store);
 }
 
+void PrefServiceSyncable::AddSyncedPrefObserver(
+    const std::string& name,
+    SyncedPrefObserver* observer) {
+  pref_sync_associator_.AddSyncedPrefObserver(name, observer);
+  priority_pref_sync_associator_.AddSyncedPrefObserver(name, observer);
+}
+
+void PrefServiceSyncable::RemoveSyncedPrefObserver(
+    const std::string& name,
+    SyncedPrefObserver* observer) {
+  pref_sync_associator_.RemoveSyncedPrefObserver(name, observer);
+  priority_pref_sync_associator_.RemoveSyncedPrefObserver(name, observer);
+}
+
 void PrefServiceSyncable::AddRegisteredSyncablePreference(
     const char* path,
     const user_prefs::PrefRegistrySyncable::PrefSyncStatus sync_status) {
diff --git a/chrome/browser/prefs/pref_service_syncable.h b/chrome/browser/prefs/pref_service_syncable.h
index 4f4715e..b8390f1 100644
--- a/chrome/browser/prefs/pref_service_syncable.h
+++ b/chrome/browser/prefs/pref_service_syncable.h
@@ -7,6 +7,7 @@
 
 #include "base/prefs/pref_service.h"
 #include "chrome/browser/prefs/pref_model_associator.h"
+#include "chrome/browser/prefs/synced_pref_observer.h"
 #include "components/user_prefs/pref_registry_syncable.h"
 
 class PrefServiceSyncableObserver;
@@ -80,6 +81,11 @@
   // Do not call this after having derived an incognito or per tab pref service.
   virtual void UpdateCommandLinePrefStore(PrefStore* cmd_line_store) OVERRIDE;
 
+  void AddSyncedPrefObserver(const std::string& name,
+                             SyncedPrefObserver* observer);
+  void RemoveSyncedPrefObserver(const std::string& name,
+                                SyncedPrefObserver* observer);
+
  private:
   friend class PrefModelAssociator;
 
diff --git a/chrome/browser/prefs/synced_pref_change_registrar.cc b/chrome/browser/prefs/synced_pref_change_registrar.cc
new file mode 100644
index 0000000..1438d21
--- /dev/null
+++ b/chrome/browser/prefs/synced_pref_change_registrar.cc
@@ -0,0 +1,66 @@
+// 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/prefs/synced_pref_change_registrar.h"
+
+#include "base/bind.h"
+
+namespace {
+
+void InvokeUnnamedCallback(
+    const SyncedPrefChangeRegistrar::ChangeCallback& callback,
+    const std::string& path,
+    bool from_sync) {
+  callback.Run(from_sync);
+}
+
+}  // namespace
+
+SyncedPrefChangeRegistrar::SyncedPrefChangeRegistrar(
+    PrefServiceSyncable* pref_service) {
+  pref_service_ = pref_service;
+}
+
+SyncedPrefChangeRegistrar::~SyncedPrefChangeRegistrar() {
+  RemoveAll();
+}
+
+void SyncedPrefChangeRegistrar::Add(const char *path,
+                                    const ChangeCallback& callback) {
+  Add(path, base::Bind(InvokeUnnamedCallback, callback));
+}
+
+void SyncedPrefChangeRegistrar::Add(const char *path,
+                                    const NamedChangeCallback& callback) {
+  DCHECK(!IsObserved(path));
+  observers_[path] = callback;
+  pref_service_->AddSyncedPrefObserver(path, this);
+}
+
+void SyncedPrefChangeRegistrar::Remove(const char *path) {
+  observers_.erase(path);
+  pref_service_->RemoveSyncedPrefObserver(path, this);
+}
+
+void SyncedPrefChangeRegistrar::RemoveAll() {
+  for (ObserverMap::iterator iter = observers_.begin();
+       iter != observers_.end(); ++iter) {
+    pref_service_->RemoveSyncedPrefObserver(iter->first, this);
+  }
+  observers_.clear();
+}
+
+bool SyncedPrefChangeRegistrar::IsObserved(const char* path) const {
+  return observers_.find(path) != observers_.end();
+}
+
+void SyncedPrefChangeRegistrar::OnSyncedPrefChanged(const std::string& path,
+                                                    bool from_sync) {
+  if (pref_service_->IsManagedPreference(path.c_str()))
+    return;
+  ObserverMap::const_iterator iter = observers_.find(path);
+  if (iter == observers_.end())
+    return;
+  iter->second.Run(path, from_sync);
+}
diff --git a/chrome/browser/prefs/synced_pref_change_registrar.h b/chrome/browser/prefs/synced_pref_change_registrar.h
new file mode 100644
index 0000000..7cadd0a
--- /dev/null
+++ b/chrome/browser/prefs/synced_pref_change_registrar.h
@@ -0,0 +1,57 @@
+// 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_PREFS_SYNCED_PREF_CHANGE_REGISTRAR_H_
+#define CHROME_BROWSER_PREFS_SYNCED_PREF_CHANGE_REGISTRAR_H_
+
+#include <map>
+#include <string>
+
+#include "base/callback.h"
+#include "chrome/browser/prefs/pref_service_syncable.h"
+#include "chrome/browser/prefs/synced_pref_observer.h"
+
+// Manages the registration of one or more SyncedPrefObservers on a
+// PrefServiceSyncable. This is modeled after base::PrefChangeRegistrar, and
+// it should be used whenever it's necessary to determine whether a pref change
+// has come from sync or from some other mechanism (managed, UI, external, etc.)
+class SyncedPrefChangeRegistrar : public SyncedPrefObserver {
+ public:
+  // Registered callbacks may optionally take a path argument.
+  // The boolean argument indicates whether (true) or not (false)
+  // the change was a result of syncing.
+  typedef base::Callback<void(bool)> ChangeCallback;
+  typedef base::Callback<void(const std::string&, bool)> NamedChangeCallback;
+
+  explicit SyncedPrefChangeRegistrar(PrefServiceSyncable* pref_service);
+  virtual ~SyncedPrefChangeRegistrar();
+
+  // Register an observer callback for sync change events on the pref at
+  // |path|. Only one callback may be registered per pref.
+  void Add(const char* path, const ChangeCallback& callback);
+  void Add(const char* path, const NamedChangeCallback& callback);
+
+  // Remove the registered observer for |path|.
+  void Remove(const char* path);
+
+  // Remove all registered observers.
+  void RemoveAll();
+
+  // Indicates whether or not an observer is already registered for |path|.
+  bool IsObserved(const char* path) const;
+
+ private:
+  // SyncedPrefObserver implementation
+  virtual void OnSyncedPrefChanged(const std::string& path, bool from_sync)
+      OVERRIDE;
+
+  typedef std::map<std::string, NamedChangeCallback> ObserverMap;
+
+  PrefServiceSyncable* pref_service_;
+  ObserverMap observers_;
+
+  DISALLOW_COPY_AND_ASSIGN(SyncedPrefChangeRegistrar);
+};
+
+#endif  // CHROME_BROWSER_PREFS_SYNCED_PREF_CHANGE_REGISTRAR_H_
diff --git a/chrome/browser/prefs/synced_pref_change_registrar_browsertest.cc b/chrome/browser/prefs/synced_pref_change_registrar_browsertest.cc
new file mode 100644
index 0000000..1dde6a8
--- /dev/null
+++ b/chrome/browser/prefs/synced_pref_change_registrar_browsertest.cc
@@ -0,0 +1,216 @@
+// 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 <string>
+
+#include "base/json/json_string_value_serializer.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/time/time.h"
+#include "base/values.h"
+#include "chrome/browser/policy/browser_policy_connector.h"
+#include "chrome/browser/policy/mock_configuration_policy_provider.h"
+#include "chrome/browser/policy/policy_map.h"
+#include "chrome/browser/prefs/synced_pref_change_registrar.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/common/pref_names.h"
+#include "chrome/test/base/in_process_browser_test.h"
+#include "chrome/test/base/testing_pref_service_syncable.h"
+#include "chrome/test/base/testing_profile.h"
+#include "content/public/test/test_utils.h"
+#include "policy/policy_constants.h"
+#include "sync/api/sync_change.h"
+#include "sync/api/sync_error_factory.h"
+#include "sync/api/sync_error_factory_mock.h"
+#include "sync/api/syncable_service.h"
+#include "sync/protocol/sync.pb.h"
+
+namespace {
+
+using testing::AnyNumber;
+using testing::Return;
+using testing::_;
+
+class TestSyncProcessorStub : public syncer::SyncChangeProcessor {
+  virtual syncer::SyncError ProcessSyncChanges(
+      const tracked_objects::Location& from_here,
+      const syncer::SyncChangeList& change_list) OVERRIDE {
+    return syncer::SyncError();
+  }
+};
+
+class SyncedPrefChangeRegistrarTest : public InProcessBrowserTest {
+ public:
+  SyncedPrefChangeRegistrarTest() : next_sync_data_id_(0) {}
+  virtual ~SyncedPrefChangeRegistrarTest() {}
+
+  void UpdateChromePolicy(const policy::PolicyMap& policies) {
+    policy_provider_.UpdateChromePolicy(policies);
+    DCHECK(base::MessageLoop::current());
+    base::RunLoop loop;
+    loop.RunUntilIdle();
+  }
+
+  void SetBooleanPrefValueFromSync(const std::string& name, bool value) {
+    std::string serialized_value;
+    JSONStringValueSerializer json(&serialized_value);
+    json.Serialize(base::FundamentalValue(value));
+
+    sync_pb::EntitySpecifics specifics;
+    sync_pb::PreferenceSpecifics* pref_specifics =
+        specifics.mutable_preference();
+    pref_specifics->set_name(name);
+    pref_specifics->set_value(serialized_value);
+
+    syncer::SyncData change_data = syncer::SyncData::CreateRemoteData(
+        ++next_sync_data_id_, specifics, base::Time());
+    syncer::SyncChange change(
+        FROM_HERE, syncer::SyncChange::ACTION_UPDATE, change_data);
+
+    syncer::SyncChangeList change_list;
+    change_list.push_back(change);
+
+    syncer_->ProcessSyncChanges(FROM_HERE, change_list);
+  }
+
+  void SetBooleanPrefValueFromLocal(const std::string& name, bool value) {
+    prefs_->SetBoolean(name.c_str(), value);
+  }
+
+  bool GetBooleanPrefValue(const std::string& name) {
+    return prefs_->GetBoolean(name.c_str());
+  }
+
+  PrefServiceSyncable* prefs() const {
+    return prefs_;
+  }
+
+  SyncedPrefChangeRegistrar* registrar() const {
+    return registrar_.get();
+  }
+
+ private:
+  virtual void SetUpInProcessBrowserTestFixture() OVERRIDE {
+    EXPECT_CALL(policy_provider_, IsInitializationComplete(_))
+        .WillRepeatedly(Return(true));
+    EXPECT_CALL(policy_provider_, RegisterPolicyDomain(_)).Times(AnyNumber());
+    policy::BrowserPolicyConnector::SetPolicyProviderForTesting(
+        &policy_provider_);
+  }
+
+  virtual void SetUpOnMainThread() OVERRIDE {
+    prefs_ = PrefServiceSyncable::FromProfile(browser()->profile());
+    syncer_ = prefs_->GetSyncableService(syncer::PREFERENCES);
+    syncer_->MergeDataAndStartSyncing(
+        syncer::PREFERENCES,
+        syncer::SyncDataList(),
+        scoped_ptr<syncer::SyncChangeProcessor>(new TestSyncProcessorStub),
+        scoped_ptr<syncer::SyncErrorFactory>(new syncer::SyncErrorFactoryMock));
+    registrar_.reset(new SyncedPrefChangeRegistrar(prefs_));
+  }
+
+  virtual void CleanUpOnMainThread() OVERRIDE {
+    registrar_.reset();
+  }
+
+  PrefServiceSyncable* prefs_;
+  syncer::SyncableService* syncer_;
+  int next_sync_data_id_;
+
+  scoped_ptr<SyncedPrefChangeRegistrar> registrar_;
+  policy::MockConfigurationPolicyProvider policy_provider_;
+};
+
+struct TestSyncedPrefObserver {
+  bool last_seen_value;
+  bool last_update_is_from_sync;
+  bool has_been_notified;
+};
+
+void TestPrefChangeCallback(PrefService* prefs,
+                            TestSyncedPrefObserver* observer,
+                            const std::string& path,
+                            bool from_sync) {
+  observer->last_seen_value = prefs->GetBoolean(path.c_str());
+  observer->last_update_is_from_sync = from_sync;
+  observer->has_been_notified = true;
+}
+
+}  // namespace
+
+IN_PROC_BROWSER_TEST_F(SyncedPrefChangeRegistrarTest,
+                       DifferentiateRemoteAndLocalChanges) {
+  TestSyncedPrefObserver observer = {};
+  registrar()->Add(prefs::kShowHomeButton,
+      base::Bind(&TestPrefChangeCallback, prefs(), &observer));
+
+  EXPECT_FALSE(observer.has_been_notified);
+
+  SetBooleanPrefValueFromSync(prefs::kShowHomeButton, true);
+  EXPECT_TRUE(observer.has_been_notified);
+  EXPECT_TRUE(GetBooleanPrefValue(prefs::kShowHomeButton));
+  EXPECT_TRUE(observer.last_update_is_from_sync);
+  EXPECT_TRUE(observer.last_seen_value);
+
+  observer.has_been_notified = false;
+  SetBooleanPrefValueFromLocal(prefs::kShowHomeButton, false);
+  EXPECT_TRUE(observer.has_been_notified);
+  EXPECT_FALSE(GetBooleanPrefValue(prefs::kShowHomeButton));
+  EXPECT_FALSE(observer.last_update_is_from_sync);
+  EXPECT_FALSE(observer.last_seen_value);
+
+  observer.has_been_notified = false;
+  SetBooleanPrefValueFromLocal(prefs::kShowHomeButton, true);
+  EXPECT_TRUE(observer.has_been_notified);
+  EXPECT_TRUE(GetBooleanPrefValue(prefs::kShowHomeButton));
+  EXPECT_FALSE(observer.last_update_is_from_sync);
+  EXPECT_TRUE(observer.last_seen_value);
+
+  observer.has_been_notified = false;
+  SetBooleanPrefValueFromSync(prefs::kShowHomeButton, false);
+  EXPECT_TRUE(observer.has_been_notified);
+  EXPECT_FALSE(GetBooleanPrefValue(prefs::kShowHomeButton));
+  EXPECT_TRUE(observer.last_update_is_from_sync);
+  EXPECT_FALSE(observer.last_seen_value);
+}
+
+IN_PROC_BROWSER_TEST_F(SyncedPrefChangeRegistrarTest,
+                       IgnoreLocalChangesToManagedPrefs) {
+  TestSyncedPrefObserver observer = {};
+  registrar()->Add(prefs::kShowHomeButton,
+      base::Bind(&TestPrefChangeCallback, prefs(), &observer));
+
+  policy::PolicyMap policies;
+  policies.Set(policy::key::kShowHomeButton,
+               policy::POLICY_LEVEL_MANDATORY,
+               policy::POLICY_SCOPE_USER,
+               base::Value::CreateBooleanValue(true),
+               NULL);
+  UpdateChromePolicy(policies);
+
+  EXPECT_TRUE(prefs()->IsManagedPreference(prefs::kShowHomeButton));
+
+  SetBooleanPrefValueFromLocal(prefs::kShowHomeButton, false);
+  EXPECT_FALSE(observer.has_been_notified);
+  EXPECT_TRUE(GetBooleanPrefValue(prefs::kShowHomeButton));
+}
+
+IN_PROC_BROWSER_TEST_F(SyncedPrefChangeRegistrarTest,
+                       IgnoreSyncChangesToManagedPrefs) {
+  TestSyncedPrefObserver observer = {};
+  registrar()->Add(prefs::kShowHomeButton,
+      base::Bind(&TestPrefChangeCallback, prefs(), &observer));
+
+  policy::PolicyMap policies;
+  policies.Set(policy::key::kShowHomeButton,
+               policy::POLICY_LEVEL_MANDATORY,
+               policy::POLICY_SCOPE_USER,
+               base::Value::CreateBooleanValue(true),
+               NULL);
+  UpdateChromePolicy(policies);
+
+  EXPECT_TRUE(prefs()->IsManagedPreference(prefs::kShowHomeButton));
+  SetBooleanPrefValueFromSync(prefs::kShowHomeButton, false);
+  EXPECT_FALSE(observer.has_been_notified);
+  EXPECT_TRUE(GetBooleanPrefValue(prefs::kShowHomeButton));
+}
diff --git a/chrome/browser/prefs/synced_pref_observer.h b/chrome/browser/prefs/synced_pref_observer.h
new file mode 100644
index 0000000..332e588
--- /dev/null
+++ b/chrome/browser/prefs/synced_pref_observer.h
@@ -0,0 +1,15 @@
+// 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_PREFS_SYNCED_PREF_OBSERVER_H_
+#define CHROME_BROWSER_PREFS_SYNCED_PREF_OBSERVER_H_
+
+#include <string>
+
+class SyncedPrefObserver {
+ public:
+  virtual void OnSyncedPrefChanged(const std::string& path, bool from_sync) = 0;
+};
+
+#endif  // CHROME_BROWSER_PREFS_SYNCED_PREF_OBSERVER_H_
diff --git a/chrome/browser/prerender/prerender_browsertest.cc b/chrome/browser/prerender/prerender_browsertest.cc
index e075cc1..7405e51 100644
--- a/chrome/browser/prerender/prerender_browsertest.cc
+++ b/chrome/browser/prerender/prerender_browsertest.cc
@@ -2475,7 +2475,8 @@
 
 // Checks that when the cache is cleared, prerenders are cancelled but
 // prerendering history is not cleared.
-IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderClearCache) {
+// Flaky/times out on linux_aura, win, mac - http://crbug.com/270948
+IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, DISABLED_PrerenderClearCache) {
   PrerenderTestURL("files/prerender/prerender_page.html",
                    FINAL_STATUS_CACHE_OR_HISTORY_CLEARED,
                    1);
diff --git a/chrome/browser/profile_resetter/profile_resetter_unittest.cc b/chrome/browser/profile_resetter/profile_resetter_unittest.cc
index 8a4993e..62cd06b 100644
--- a/chrome/browser/profile_resetter/profile_resetter_unittest.cc
+++ b/chrome/browser/profile_resetter/profile_resetter_unittest.cc
@@ -26,6 +26,7 @@
 #include "chrome/common/pref_names.h"
 #include "chrome/test/base/browser_with_test_window_test.h"
 #include "content/public/browser/web_contents.h"
+#include "content/public/test/test_browser_thread.h"
 #include "net/http/http_response_headers.h"
 #include "net/url_request/test_url_fetcher_factory.h"
 
@@ -695,39 +696,46 @@
   ResettableSettingsSnapshot empty_snap(profile());
   EXPECT_EQ(0, empty_snap.FindDifferentFields(empty_snap));
 
+  scoped_refptr<Extension> ext = CreateExtension(
+      "example",
+      base::FilePath(FILE_PATH_LITERAL("//nonexistent")),
+      Manifest::INVALID_LOCATION,
+      extensions::Manifest::TYPE_EXTENSION,
+      false);
+  ASSERT_TRUE(ext);
+  service_->AddExtension(ext.get());
+
+  std::string master_prefs(kDistributionConfig);
+  std::string ext_id = ext->id();
+  ReplaceString(&master_prefs, "placeholder_for_id", ext_id);
+
   // Reset to non organic defaults.
   ResetAndWait(ProfileResetter::DEFAULT_SEARCH_ENGINE |
                ProfileResetter::HOMEPAGE |
-               ProfileResetter::STARTUP_PAGES, kDistributionConfig);
+               ProfileResetter::STARTUP_PAGES, master_prefs);
 
   ResettableSettingsSnapshot nonorganic_snap(profile());
-  EXPECT_EQ(ResettableSettingsSnapshot::STARTUP_URLS |
-            ResettableSettingsSnapshot::STARTUP_TYPE |
-            ResettableSettingsSnapshot::HOMEPAGE |
-            ResettableSettingsSnapshot::HOMEPAGE_IS_NTP |
-            ResettableSettingsSnapshot::DSE_URL,
+  EXPECT_EQ(ResettableSettingsSnapshot::ALL_FIELDS,
             empty_snap.FindDifferentFields(nonorganic_snap));
-  empty_snap.SubtractStartupURLs(nonorganic_snap);
+  empty_snap.Subtract(nonorganic_snap);
   EXPECT_TRUE(empty_snap.startup_urls().empty());
   EXPECT_EQ(SessionStartupPref::GetDefaultStartupType(),
             empty_snap.startup_type());
   EXPECT_TRUE(empty_snap.homepage().empty());
   EXPECT_TRUE(empty_snap.homepage_is_ntp());
   EXPECT_NE(std::string::npos, empty_snap.dse_url().find("{google:baseURL}"));
+  EXPECT_EQ(std::vector<std::string>(), empty_snap.enabled_extensions());
 
   // Reset to organic defaults.
   ResetAndWait(ProfileResetter::DEFAULT_SEARCH_ENGINE |
                ProfileResetter::HOMEPAGE |
-               ProfileResetter::STARTUP_PAGES);
+               ProfileResetter::STARTUP_PAGES |
+               ProfileResetter::EXTENSIONS);
 
   ResettableSettingsSnapshot organic_snap(profile());
-  EXPECT_EQ(ResettableSettingsSnapshot::STARTUP_URLS |
-            ResettableSettingsSnapshot::STARTUP_TYPE |
-            ResettableSettingsSnapshot::HOMEPAGE |
-            ResettableSettingsSnapshot::HOMEPAGE_IS_NTP |
-            ResettableSettingsSnapshot::DSE_URL,
+  EXPECT_EQ(ResettableSettingsSnapshot::ALL_FIELDS,
             nonorganic_snap.FindDifferentFields(organic_snap));
-  nonorganic_snap.SubtractStartupURLs(organic_snap);
+  nonorganic_snap.Subtract(organic_snap);
   const GURL urls[] = {GURL("http://foo.de"), GURL("http://goo.gl")};
   EXPECT_EQ(std::vector<GURL>(urls, urls + arraysize(urls)),
             nonorganic_snap.startup_urls());
@@ -735,6 +743,8 @@
   EXPECT_EQ("http://www.foo.com", nonorganic_snap.homepage());
   EXPECT_FALSE(nonorganic_snap.homepage_is_ntp());
   EXPECT_EQ("http://www.foo.com/s?q={searchTerms}", nonorganic_snap.dse_url());
+  EXPECT_EQ(std::vector<std::string>(1, ext_id),
+            nonorganic_snap.enabled_extensions());
 }
 
 TEST_F(ProfileResetterTest, FeedbackSerializtionTest) {
@@ -743,9 +753,18 @@
                ProfileResetter::HOMEPAGE |
                ProfileResetter::STARTUP_PAGES, kDistributionConfig);
 
+  scoped_refptr<Extension> ext = CreateExtension(
+      "example",
+      base::FilePath(FILE_PATH_LITERAL("//nonexistent")),
+      Manifest::INVALID_LOCATION,
+      extensions::Manifest::TYPE_EXTENSION,
+      false);
+  ASSERT_TRUE(ext);
+  service_->AddExtension(ext.get());
+
   const ResettableSettingsSnapshot nonorganic_snap(profile());
 
-  COMPILE_ASSERT(ResettableSettingsSnapshot::ALL_FIELDS == 31,
+  COMPILE_ASSERT(ResettableSettingsSnapshot::ALL_FIELDS == 63,
                  expand_this_test);
   for (int field_mask = 0; field_mask <= ResettableSettingsSnapshot::ALL_FIELDS;
        ++field_mask) {
@@ -764,6 +783,7 @@
     std::string homepage;
     bool homepage_is_ntp = true;
     std::string default_search_engine;
+    ListValue* extensions;
 
     EXPECT_EQ(!!(field_mask & ResettableSettingsSnapshot::STARTUP_URLS),
               dict->GetList("startup_urls", &startup_urls));
@@ -775,6 +795,8 @@
               dict->GetBoolean("homepage_is_ntp", &homepage_is_ntp));
     EXPECT_EQ(!!(field_mask & ResettableSettingsSnapshot::DSE_URL),
               dict->GetString("default_search_engine", &default_search_engine));
+    EXPECT_EQ(!!(field_mask & ResettableSettingsSnapshot::EXTENSIONS),
+              dict->GetList("enabled_extensions", &extensions));
   }
 }
 
diff --git a/chrome/browser/profile_resetter/resettable_settings_snapshot.cc b/chrome/browser/profile_resetter/resettable_settings_snapshot.cc
index f6892ba..0542727 100644
--- a/chrome/browser/profile_resetter/resettable_settings_snapshot.cc
+++ b/chrome/browser/profile_resetter/resettable_settings_snapshot.cc
@@ -6,6 +6,7 @@
 
 #include "base/json/json_writer.h"
 #include "base/prefs/pref_service.h"
+#include "chrome/browser/extensions/extension_service.h"
 #include "chrome/browser/feedback/feedback_data.h"
 #include "chrome/browser/feedback/feedback_util.h"
 #include "chrome/browser/profiles/profile.h"
@@ -20,6 +21,7 @@
 
 // Dictionary keys for feedback report.
 const char kDefaultSearchEnginePath[] = "default_search_engine";
+const char kEnabledExtensions[] = "enabled_extensions";
 const char kHomepageIsNewTabPage[] = "homepage_is_ntp";
 const char kHomepagePath[] = "homepage";
 const char kStartupTypePath[] = "startup_type";
@@ -43,11 +45,23 @@
   TemplateURL* dse = service->GetDefaultSearchProvider();
   if (dse)
     dse_url_ = dse->url();
+
+  ExtensionService* extension_service = profile->GetExtensionService();
+  DCHECK(extension_service);
+  const ExtensionSet* enabled_ext = extension_service->extensions();
+  enabled_extensions_.reserve(enabled_ext->size());
+
+  for (ExtensionSet::const_iterator it = enabled_ext->begin();
+       it != enabled_ext->end(); ++it)
+    enabled_extensions_.push_back((*it)->id());
+
+  // ExtensionSet is sorted but it seems to be an implementation detail.
+  std::sort(enabled_extensions_.begin(), enabled_extensions_.end());
 }
 
 ResettableSettingsSnapshot::~ResettableSettingsSnapshot() {}
 
-void ResettableSettingsSnapshot::SubtractStartupURLs(
+void ResettableSettingsSnapshot::Subtract(
     const ResettableSettingsSnapshot& snapshot) {
   std::vector<GURL> urls;
   std::set_difference(startup_.urls.begin(), startup_.urls.end(),
@@ -55,6 +69,13 @@
                       snapshot.startup_.urls.end(),
                       std::back_inserter(urls));
   startup_.urls.swap(urls);
+
+  std::vector<std::string> extensions;
+  std::set_difference(enabled_extensions_.begin(), enabled_extensions_.end(),
+                      snapshot.enabled_extensions_.begin(),
+                      snapshot.enabled_extensions_.end(),
+                      std::back_inserter(extensions));
+  enabled_extensions_.swap(extensions);
 }
 
 int ResettableSettingsSnapshot::FindDifferentFields(
@@ -77,7 +98,10 @@
   if (dse_url_ != snapshot.dse_url_)
     bit_mask |= DSE_URL;
 
-  COMPILE_ASSERT(ResettableSettingsSnapshot::ALL_FIELDS == 31,
+  if (enabled_extensions_ != snapshot.enabled_extensions_)
+    bit_mask |= EXTENSIONS;
+
+  COMPILE_ASSERT(ResettableSettingsSnapshot::ALL_FIELDS == 63,
                  add_new_field_here);
 
   return bit_mask;
@@ -108,7 +132,16 @@
   if (field_mask & ResettableSettingsSnapshot::DSE_URL)
     dict.SetString(kDefaultSearchEnginePath, snapshot.dse_url());
 
-  COMPILE_ASSERT(ResettableSettingsSnapshot::ALL_FIELDS == 31,
+  if (field_mask & ResettableSettingsSnapshot::EXTENSIONS) {
+    ListValue* list = new ListValue;
+    const std::vector<std::string>& extensions = snapshot.enabled_extensions();
+    for (std::vector<std::string>::const_iterator i = extensions.begin();
+         i != extensions.end(); ++i)
+      list->AppendString(*i);
+    dict.Set(kEnabledExtensions, list);
+  }
+
+  COMPILE_ASSERT(ResettableSettingsSnapshot::ALL_FIELDS == 63,
                  serialize_new_field_here);
 
   std::string json;
diff --git a/chrome/browser/profile_resetter/resettable_settings_snapshot.h b/chrome/browser/profile_resetter/resettable_settings_snapshot.h
index 93aaf48..9fcf1cb 100644
--- a/chrome/browser/profile_resetter/resettable_settings_snapshot.h
+++ b/chrome/browser/profile_resetter/resettable_settings_snapshot.h
@@ -19,9 +19,10 @@
     HOMEPAGE = 1 << 2,
     HOMEPAGE_IS_NTP = 1 << 3,
     DSE_URL = 1 << 4,
+    EXTENSIONS = 1 << 5,
 
     ALL_FIELDS = STARTUP_URLS | STARTUP_TYPE | HOMEPAGE |
-                 HOMEPAGE_IS_NTP | DSE_URL,
+                 HOMEPAGE_IS_NTP | DSE_URL | EXTENSIONS,
   };
 
   explicit ResettableSettingsSnapshot(Profile* profile);
@@ -38,8 +39,14 @@
 
   const std::string& dse_url() const { return dse_url_; }
 
+  const std::vector<std::string>& enabled_extensions() const {
+    return enabled_extensions_;
+  }
+
   // Substitutes |startup_.urls| with |startup_.urls|\|snapshot.startup_.urls|.
-  void SubtractStartupURLs(const ResettableSettingsSnapshot& snapshot);
+  // Substitutes |enabled_extensions_| with
+  // |enabled_extensions_|\|snapshot.enabled_extensions_|.
+  void Subtract(const ResettableSettingsSnapshot& snapshot);
 
   // For each member 'm' compares |this->m| with |snapshot.m| and sets the
   // corresponding |ResetableSettingsSnapshot::Field| bit to 1 in case of
@@ -58,6 +65,9 @@
   // Default search engine.
   std::string dse_url_;
 
+  // Enabled extension ids. Always sorted.
+  std::vector<std::string> enabled_extensions_;
+
   DISALLOW_COPY_AND_ASSIGN(ResettableSettingsSnapshot);
 };
 
diff --git a/chrome/browser/profiles/profile_shortcut_manager_win.cc b/chrome/browser/profiles/profile_shortcut_manager_win.cc
index 9a0d9ed..48e862b 100644
--- a/chrome/browser/profiles/profile_shortcut_manager_win.cc
+++ b/chrome/browser/profiles/profile_shortcut_manager_win.cc
@@ -765,8 +765,8 @@
     CreateOrUpdateMode create_mode,
     NonProfileShortcutAction action,
     const base::Closure& callback) {
-  DCHECK(!BrowserThread::IsWellKnownThread(BrowserThread::UI) ||
-      BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK(!BrowserThread::IsThreadInitialized(BrowserThread::UI) ||
+         BrowserThread::CurrentlyOn(BrowserThread::UI));
   CreateOrUpdateShortcutsParams params(profile_path, create_mode, action);
 
   ProfileInfoCache* cache = &profile_manager_->GetProfileInfoCache();
diff --git a/chrome/browser/resources/chromeos/connectivity_diagnostics/OWNERS b/chrome/browser/resources/chromeos/connectivity_diagnostics/OWNERS
new file mode 100644
index 0000000..b03ccb6
--- /dev/null
+++ b/chrome/browser/resources/chromeos/connectivity_diagnostics/OWNERS
@@ -0,0 +1,4 @@
+dpolukhin@chromium.org
+ebeach@chromium.org
+xiaowenx@chromium.org
+zork@chromium.org
diff --git a/chrome/browser/resources/chromeos/connectivity_diagnostics/manifest.json b/chrome/browser/resources/chromeos/connectivity_diagnostics/manifest.json
index f1368d8..38a5d74 100644
--- a/chrome/browser/resources/chromeos/connectivity_diagnostics/manifest.json
+++ b/chrome/browser/resources/chromeos/connectivity_diagnostics/manifest.json
@@ -1,8 +1,8 @@
 {
   "key": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDGJWLUb83WKoDeODlrPIZu60M8bzbvrkg3Jf/5aO3ux2FL+G+/BO4Vyt/J0t8lXBtnTOvHo6KPpA042PyE9xMdlufFnJqEkvPXNzRlBWeVQqFHbMWE6o/x8diG69dNmHyFYcUjjFFDk2X2GOLQXNUGJQ6MIikbdzoWdLGttmhAIwIDAQAB",
   "manifest_version": 2,
-  "name": "Chrome Connectivity Debugger (Dev)",
-  "version": "0.2.8",
+  "name": "Connectivity Diagnostics",
+  "version": "0.5.2",
   "minimum_chrome_version": "27",
   "offline_enabled": true,
   "default_locale": "en",
@@ -21,12 +21,15 @@
    ]},
    "clipboardWrite",
    "experimental",
+   "networkingPrivate",
    "http://*.google.com/*",
-   "http://www.yahoo.com/*"
+   "https://*.google.com/*"
   ],
   "app": {
     "background": {
       "scripts": ["background.js"]
     }
-  }
+  },
+  "display_in_launcher": false,
+  "display_in_new_tab_page": false
 }
diff --git a/chrome/browser/resources/chromeos/drive_internals.html b/chrome/browser/resources/chromeos/drive_internals.html
index b704782..6b25ee5 100644
--- a/chrome/browser/resources/chromeos/drive_internals.html
+++ b/chrome/browser/resources/chromeos/drive_internals.html
@@ -11,14 +11,6 @@
     <h1>Drive Internals</h1>
     <ul id='toc'></ul>
 
-    <h2 id='drive-related-flags-section'>Drive related Flags</h2>
-    <ul id='drive-related-flags'>
-    </ul>
-
-    <h2 id='drive-related-preferences-section'>Drive related Preferences</h2>
-    <ul id='drive-related-preferences'>
-    </ul>
-
     <h2 id='authentication-status-section'>Authentication Status</h2>
     <ul>
       <li>
@@ -33,33 +25,21 @@
 
     <h2 id='account-information-section'>Account Information</h2>
     <ul>
-      <li>Quota Information: <span id='account-quota-info'></span></li>
-      <li>Largest Changestamp (remote):
+      <li>Remote Changestamp:
         <span id='account-largest-changestamp-remote'></span>
       </li>
+      <li>Quota Information: <span id='account-quota-info'></span></li>
       <li>Root Resource Id: <span id='root-resource-id'></span></li>
     </ul>
 
-    <h2 id='app-list-section'>Application List</h2>
-    <ul>
-      <li>ETag: <span id='app-list-etag'></span></li>
-    </ul>
-    <table>
-      <tbody id='app-list-items'>
-        <tr>
-          <th>App Name</th>
-          <th>App ID</th>
-          <th>Object Type</th>
-          <th>Support Create</th>
-        </tr>
-      </tbody>
-    </table>
-
     <h2 id='local-metadata-section'>Local Metadata</h2>
     <ul>
-      <li>Largest Changestamp (local):
+      <li>Local Changestamp:
         <span id='account-largest-changestamp-local'></span>
       </li>
+      <li>Local Free Space:
+        <span id='local-storage-freespace'></span> MB
+      </li>
     </ul>
 
     <h2 id='delta-update-status-section'>Delta Update Status</h2>
@@ -85,6 +65,10 @@
       </tbody>
     </table>
 
+    <h2 id='file-system-contents-section'>File System Contents</h2>
+    <button id='button-show-file-entries'>Show</button>
+    <div id='file-system-contents'></div>
+
     <h2 id='gcache-contents-section'>GCache Contents</h2>
     <table>
       <tbody id='gcache-contents'>
@@ -100,14 +84,10 @@
     <ul>
       <li>
         Total Size:
-        <span id='gcache-summary-total-size'>(calculating...)</span> bytes.
+        <span id='gcache-summary-total-size'>(calculating...)</span> MB.
       </li>
     </ul>
 
-    <h2 id='file-system-contents-section'>File System Contents</h2>
-    <button id='button-show-file-entries'>Show</button>
-    <div id='file-system-contents'></div>
-
     <h2 id='cache-contents-section'>Cache Contents</h2>
     <table>
       <tbody id='cache-contents'>
@@ -117,14 +97,32 @@
           <th>Present</th>
           <th>Pinned</th>
           <th>Dirty</th>
-          <th>Mounted</th>
-          <th>Persistent</th>
         </tr>
       </tbody>
     </table>
 
-    <h2 id='local-storage-usage-section'>Local Storage Usage</h2>
-    <div>Free space: <span id='local-storage-freespace'></span> MB</div>
+    <h2 id='drive-related-flags-section'>Drive related Flags</h2>
+    <ul id='drive-related-flags'>
+    </ul>
+
+    <h2 id='drive-related-preferences-section'>Drive related Preferences</h2>
+    <ul id='drive-related-preferences'>
+    </ul>
+
+    <h2 id='app-list-section'>Application List</h2>
+    <ul>
+      <li>ETag: <span id='app-list-etag'></span></li>
+    </ul>
+    <table>
+      <tbody id='app-list-items'>
+        <tr>
+          <th>App Name</th>
+          <th>App ID</th>
+          <th>Object Type</th>
+          <th>Support Create</th>
+        </tr>
+      </tbody>
+    </table>
 
     <h2 id='event-log-section'>Event Log</h2>
     <ul id='event-log'>
diff --git a/chrome/browser/resources/chromeos/drive_internals.js b/chrome/browser/resources/chromeos/drive_internals.js
index bb5b9e9..46c2fee 100644
--- a/chrome/browser/resources/chromeos/drive_internals.js
+++ b/chrome/browser/resources/chromeos/drive_internals.js
@@ -3,6 +3,20 @@
 // found in the LICENSE file.
 
 /**
+ * Converts a number in bytes to a string in megabytes split by comma into
+ * three digit block.
+ * @param {number} bytes The number in bytes.
+ * @return {string} Formatted string in megabytes.
+ */
+function ToMegaByteString(bytes) {
+  var mb = Math.floor(bytes / (1 << 20));
+  return mb.toString().replace(
+      /\d+?(?=(\d{3})+$)/g,  // Digit sequence (\d+) followed (?=) by 3n digits.
+      function(three_digit_block) { return three_digit_block + ','; }
+  );
+}
+
+/**
  * Updates the Drive related Flags section.
  * @param {Array} flags List of dictionaries describing flags.
  */
@@ -55,7 +69,8 @@
     tbody.appendChild(tr);
   }
 
-  $('gcache-summary-total-size').textContent = gcacheSummary['total_size'];
+  $('gcache-summary-total-size').textContent =
+      ToMegaByteString(gcacheSummary['total_size']);
 }
 
 /**
@@ -91,7 +106,7 @@
  * stogage.
  */
 function updateLocalStorageUsage(localStorageSummary) {
-  var freeSpaceInMB = localStorageSummary.free_space / (1 << 20);
+  var freeSpaceInMB = ToMegaByteString(localStorageSummary.free_space);
   $('local-storage-freespace').innerText = freeSpaceInMB;
 }
 
@@ -123,8 +138,8 @@
     tr.appendChild(createElementFromText('td', operation.state));
     var progress = operation.progress_current + '/' + operation.progress_total;
     if (operation.progress_total > 0) {
-      progress += ' (' +
-          (operation.progress_current / operation.progress_total * 100) + '%)';
+      var percent = operation.progress_current / operation.progress_total * 100;
+      progress += ' (' + Math.round(percent) + '%)';
     }
     tr.appendChild(createElementFromText('td', progress));
 
@@ -137,8 +152,8 @@
  * @param {Object} aboutResource Dictionary describing about resource.
  */
 function updateAboutResource(aboutResource) {
-  var quotaTotalInMb = aboutResource['account-quota-total'] / (1 << 20);
-  var quotaUsedInMb = aboutResource['account-quota-used'] / (1 << 20);
+  var quotaTotalInMb = ToMegaByteString(aboutResource['account-quota-total']);
+  var quotaUsedInMb = ToMegaByteString(aboutResource['account-quota-used']);
 
   $('account-quota-info').textContent =
       quotaUsedInMb + ' / ' + quotaTotalInMb + ' (MB)';
diff --git a/chrome/browser/resources/chromeos/login/demo_user_login.js b/chrome/browser/resources/chromeos/login/demo_user_login.js
index 22ce544..1fefc23 100644
--- a/chrome/browser/resources/chromeos/login/demo_user_login.js
+++ b/chrome/browser/resources/chromeos/login/demo_user_login.js
@@ -24,7 +24,6 @@
 initialize = function() {
   $('page').style.opacity = 1;
   document.addEventListener('click', onClick);
-  chrome.send('demoWebuiReady');
   // Report back sign in UI being painted.
   window.webkitRequestAnimationFrame(function() {
     chrome.send('loginVisible', ['demo']);
diff --git a/chrome/browser/resources/chromeos/login/display_manager.js b/chrome/browser/resources/chromeos/login/display_manager.js
index 9ddeee2..85c97b1 100644
--- a/chrome/browser/resources/chromeos/login/display_manager.js
+++ b/chrome/browser/resources/chromeos/login/display_manager.js
@@ -57,6 +57,36 @@
   var Bubble = cr.ui.Bubble;
 
   /**
+   * Maximum time in milliseconds to wait for step transition to finish.
+   * The value is used as the duration for ensureTransitionEndEvent below.
+   * It needs to be inline with the step screen transition duration time
+   * defined in css file. The current value in css is 200ms. To avoid emulated
+   * webkitTransitionEnd fired before real one, 250ms is used.
+   * @const
+   */
+  var MAX_SCREEN_TRANSITION_DURATION = 250;
+
+  /**
+   * webkitTransitionEnd does not always fire (e.g. when animation is aborted
+   * or when no paint happens during the animation). This function sets up
+   * a timer and emulate the event if it is not fired when the timer expires.
+   * @param {!HTMLElement} el The element to watch for webkitTransitionEnd.
+   * @param {number} timeOut The maximum wait time in milliseconds for the
+   *     webkitTransitionEnd to happen.
+   */
+  function ensureTransitionEndEvent(el, timeOut) {
+    var fired = false;
+    el.addEventListener('webkitTransitionEnd', function f(e) {
+      el.removeEventListener('webkitTransitionEnd', f);
+      fired = true;
+    });
+    window.setTimeout(function() {
+      if (!fired)
+        cr.dispatchSimpleEvent(el, 'webkitTransitionEnd');
+    }, timeOut);
+  }
+
+  /**
    * Groups of screens (screen IDs) that should have the same dimensions.
    * @type Array.<Array.<string>>
    * @const
@@ -310,6 +340,7 @@
             if (defaultControl)
               defaultControl.focus();
           });
+          ensureTransitionEndEvent(oldStep, MAX_SCREEN_TRANSITION_DURATION);
         } else {
           oldStep.classList.add('hidden');
           if (defaultControl)
@@ -330,6 +361,8 @@
                 if (defaultControl)
                   defaultControl.focus();
               });
+          ensureTransitionEndEvent(innerContainer,
+                                   MAX_SCREEN_TRANSITION_DURATION);
         } else {
           if (defaultControl)
             defaultControl.focus();
diff --git a/chrome/browser/resources/chromeos/login/oobe_screen_enable_kiosk.js b/chrome/browser/resources/chromeos/login/oobe_screen_enable_kiosk.js
index e9ad0b8..8bb2bb4 100644
--- a/chrome/browser/resources/chromeos/login/oobe_screen_enable_kiosk.js
+++ b/chrome/browser/resources/chromeos/login/oobe_screen_enable_kiosk.js
@@ -80,7 +80,7 @@
      * Cancels the reset and drops the user back to the login screen.
      */
     cancel: function() {
-      chrome.send('kioskOnCancel');
+      chrome.send('kioskOnClose');
     },
 
     /**
diff --git a/chrome/browser/resources/chromeos/login/screen_gaia_signin.css b/chrome/browser/resources/chromeos/login/screen_gaia_signin.css
index dc90711..af26cc3 100644
--- a/chrome/browser/resources/chromeos/login/screen_gaia_signin.css
+++ b/chrome/browser/resources/chromeos/login/screen_gaia_signin.css
@@ -115,6 +115,7 @@
   margin-top: 16px;
 }
 
-#createManagedUserLinkPlaceholder {
+#createManagedUserLinkPlaceholder,
+#createManagedUserNoManagerText {
   margin-top: 10px;
 }
\ No newline at end of file
diff --git a/chrome/browser/resources/chromeos/login/screen_locally_managed_user_creation.css b/chrome/browser/resources/chromeos/login/screen_locally_managed_user_creation.css
index 2aa3962..2d5bcde 100644
--- a/chrome/browser/resources/chromeos/login/screen_locally_managed_user_creation.css
+++ b/chrome/browser/resources/chromeos/login/screen_locally_managed_user_creation.css
@@ -45,7 +45,7 @@
   line-height: 24px;
 }
 
-#managed-user-creation strong {
+#managed-user-creation-created-1 strong {
   color: #000;
   font-weight: normal;
 }
@@ -85,7 +85,16 @@
 }
 
 #managed-user-creation-intro .below-marketing {
-  margin: 40px 40px 0;
+  margin: 20px 40px 0;
+}
+
+#managed-user-creation-intro-alternate-text {
+  margin-bottom: 12px;
+  margin-top: 12px;
+}
+
+#managed-user-creation-intro-text-3 {
+  margin-top: 12px;
 }
 
 #managed-user-creation-created-1 .below-marketing {
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 b912d46..5887325 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
@@ -6,16 +6,12 @@
         <img src="chrome://theme/IDR_SUPERVISED_ILLUSTRATION_START">
       </div>
       <div class="below-marketing">
-        <div i18n-content="createManagedUserIntroText1"></div>
-        <div>
-          <ul>
-            <li i18n-content="createManagedUserIntroManagerItem1"></li>
-            <li i18n-content="createManagedUserIntroManagerItem2"></li>
-            <li i18n-content="createManagedUserIntroManagerItem3"></li>
-          </ul>
+        <div class="page-title" i18n-content="createManagedUserIntroTextTitle">
         </div>
+        <div id="managed-user-creation-intro-alternate-text"></div>
         <div i18n-content="createManagedUserIntroText2"></div>
-        <div id="managed-user-creation-intro-text-3"></div>
+        <div id="managed-user-creation-intro-text-3"
+            i18n-content="createManagedUserIntroText3"></div>
       </div>
     </div>
     <div id="managed-user-creation-manager" class="page-no-marketing" hidden>
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 e8c3928..b685ed0 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
@@ -488,12 +488,14 @@
         return;
 
       var managerId = selectedPod.user.username;
+      var managerDisplayId = selectedPod.user.emailAddress;
       var managerPassword = selectedPod.passwordElement.value;
       if (managerPassword.empty)
         return;
 
       this.disabled = true;
       this.context_.managerId = managerId;
+      this.context_.managerDisplayId = managerDisplayId;
       this.context_.managerName = selectedPod.user.displayName;
       chrome.send('authenticateManagerInLocallyManagedUserCreationFlow',
           [managerId, managerPassword]);
@@ -855,19 +857,22 @@
     },
 
     updateText_: function() {
-      var managerId = this.context_.managerId;
+      var managerDisplayId = this.context_.managerDisplayId;
+      this.updateElementText_('intro-alternate-text',
+                              'createManagedUserIntroAlternateText');
       this.updateElementText_('created-1-text-1',
-          'createManagedUserCreated1Text1',
-          this.context_.managedName);
+                              'createManagedUserCreated1Text1',
+                              this.context_.managedName);
       this.updateElementText_('created-1-text-2',
-          'createManagedUserCreated1Text2',
-          loadTimeData.getString('managementURL'), this.context_.managedName);
+                              'createManagedUserCreated1Text2',
+                              loadTimeData.getString('managementURL'),
+                              this.context_.managedName);
       this.updateElementText_('created-1-text-3',
-          'createManagedUserCreated1Text3',
-          managerId);
+                              'createManagedUserCreated1Text3',
+                              managerDisplayId);
       this.updateElementText_('name-explanation',
-          'createManagedUserNameExplanation',
-          managerId);
+                              'createManagedUserNameExplanation',
+                              managerDisplayId);
     },
 
     updateElementText_: function(localId, templateName) {
diff --git a/chrome/browser/resources/chromeos/login/user_pod_row.js b/chrome/browser/resources/chromeos/login/user_pod_row.js
index cb91bd8..85502c1 100644
--- a/chrome/browser/resources/chromeos/login/user_pod_row.js
+++ b/chrome/browser/resources/chromeos/login/user_pod_row.js
@@ -1537,7 +1537,6 @@
       this.podsWithPendingImages_.splice(index, 1);
       if (this.podsWithPendingImages_.length == 0) {
         this.classList.remove('images-loading');
-        chrome.send('userImagesLoaded');
       }
     }
   };
diff --git a/chrome/browser/resources/chromeos/slow.css b/chrome/browser/resources/chromeos/slow.css
new file mode 100644
index 0000000..fec2369
--- /dev/null
+++ b/chrome/browser/resources/chromeos/slow.css
@@ -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.
+ */
+
+body {
+  background-color: #E6E6E6;
+  font-family: Helvetica, Arial, sans-serif;
+  font-size: 12pt;
+  margin: 50px 40px 20px 40px;
+  text-align: center;
+}
+
+#container {
+  background-color: #fbfbfb;
+  border: 1px solid #AAA;
+  border-bottom: 1px solid #888;
+  border-radius: 3px;
+  box-shadow: 0 2px 2px #AAA;
+  color: #666;
+  margin: auto;
+  max-width: 540px;
+  min-height: 29px;
+  min-width: 200px;
+  padding: 20px 60px;
+  text-align: start;
+}
+
+#container-inner {
+  background-color: #fbfbfb;
+  margin-top: 25px;
+  text-align: center;
+}
+
+button {
+  -webkit-user-select: none;
+  background-image: -webkit-linear-gradient(#ededed, #ededed 38%, #dedede);
+  border: 1px solid rgba(0, 0, 0, 0.25);
+  border-radius: 2px;
+  box-shadow: 0 1px 0 rgba(0, 0, 0, 0.08),
+    inset 0 1px 2px rgba(255, 255, 255, 0.75);
+  margin-top: 10px;
+  min-height: 29px;
+  min-width: 65px;
+  padding: 8px 13px;
+  text-shadow: 0 1px 0 rgb(240, 240, 240);
+}
+
diff --git a/chrome/browser/resources/chromeos/slow.html b/chrome/browser/resources/chromeos/slow.html
new file mode 100644
index 0000000..4a1eebb
--- /dev/null
+++ b/chrome/browser/resources/chromeos/slow.html
@@ -0,0 +1,28 @@
+<!DOCTYPE HTML>
+<html i18n-values="dir:textdirection">
+<head>
+<meta name="viewport" content="width=device-width, initial-scale=1.0,
+                               maximum-scale=1.0, user-scalable=no">
+<link rel="stylesheet" href="chrome://resources/css/widgets.css">
+<link rel="stylesheet" href="slow.css">
+<script src="chrome://resources/js/load_time_data.js"></script>
+<script src="chrome://resources/js/cr.js"></script>
+<script src="chrome://resources/js/cr/event_target.js"></script>
+<script src="chrome://resources/js/util.js"></script>
+<script src="chrome://slow/slow.js"></script>
+<script src="chrome://slow/strings.js"></script>
+</head>
+<body i18n-values=".style.fontFamily:fontfamily;">
+  <div id="container" class="container">
+    <div i18n-content="slowDescription"></div>
+    <br>
+    <div i18n-values=".innerHTML:slowWarning"></div>
+    <div id="container-inner" width=100% class="container-inner">
+      <button id="slow-disable" i18n-content="slowDisable" hidden></button>
+      <button id="slow-enable" i18n-content="slowEnable" hidden></button>
+    </div>
+  </div>
+<script src="chrome://resources/js/i18n_template2.js"></script>
+<script src="chrome://resources/js/jstemplate_compiled.js"></script>
+</body>
+</html>
diff --git a/chrome/browser/resources/chromeos/slow.js b/chrome/browser/resources/chromeos/slow.js
new file mode 100644
index 0000000..14a5e82
--- /dev/null
+++ b/chrome/browser/resources/chromeos/slow.js
@@ -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.
+
+cr.define('options', function() {
+  function Slow() {
+  }
+  cr.addSingletonGetter(Slow);
+
+  Slow.prototype = {
+    initialized_: false
+  };
+
+  Slow.initialize = function() {
+    $('slow-disable').addEventListener('click', function(event) {
+      Slow.disableTracing();
+    });
+    $('slow-enable').addEventListener('click', function(event) {
+      Slow.enableTracing();
+    });
+    this.initialized_ = true;
+  };
+
+  Slow.disableTracing = function() {
+    chrome.send('disableTracing');
+  };
+
+  Slow.enableTracing = function() {
+    chrome.send('enableTracing');
+  };
+
+  Slow.tracingPrefChanged = function(enabled) {
+    $('slow-disable').hidden = !enabled;
+    $('slow-enable').hidden = enabled;
+  };
+
+  // Export
+  return {
+    Slow: Slow
+  };
+});
+
+function load() {
+  options.Slow.initialize();
+    chrome.send('loadComplete');
+}
+
+document.addEventListener('DOMContentLoaded', load);
diff --git a/chrome/browser/resources/downloads/downloads.js b/chrome/browser/resources/downloads/downloads.js
index c6a6253..d50f5eb 100644
--- a/chrome/browser/resources/downloads/downloads.js
+++ b/chrome/browser/resources/downloads/downloads.js
@@ -423,6 +423,7 @@
   this.state_ = download.state;
   this.fileExternallyRemoved_ = download.file_externally_removed;
   this.dangerType_ = download.danger_type;
+  this.finchString_ = download.finch_string;
   this.lastReasonDescription_ = download.last_reason_text;
   this.byExtensionId_ = download.by_ext_id;
   this.byExtensionName_ = download.by_ext_name;
@@ -452,6 +453,10 @@
       this.dangerDesc_.textContent = loadTimeData.getStringF(
           'danger_potentially_unwanted_desc', this.fileName_);
     }
+    if (this.finchString_) {
+      // Finch trial overrides the normal display string.
+      this.dangerDesc_.textContent = this.finchString_;
+    }
     this.danger_.style.display = 'block';
     this.safe_.style.display = 'none';
   } else {
@@ -753,7 +758,19 @@
 function setSearch(searchText) {
   fifoResults.length = 0;
   downloads.setSearchText(searchText);
-  chrome.send('getDownloads', [searchText.toString()]);
+  searchText = searchText.toString().match(/(?:[^\s"]+|"[^"]*")+/g);
+  if (searchText) {
+    searchText = searchText.map(function(term) {
+      // strip quotes
+      return (term.match(/\s/) &&
+              term[0].match(/["']/) &&
+              term[term.length - 1] == term[0]) ?
+        term.substr(1, term.length - 2) : term;
+    });
+  } else {
+    searchText = [];
+  }
+  chrome.send('getDownloads', searchText);
 }
 
 function clearAll() {
diff --git a/chrome/browser/resources/extensions/extensions.html b/chrome/browser/resources/extensions/extensions.html
index c6418d8..b6ff0f0 100644
--- a/chrome/browser/resources/extensions/extensions.html
+++ b/chrome/browser/resources/extensions/extensions.html
@@ -101,10 +101,10 @@
     </span>
   </div>
   <div id="footer-section">
-    <a target="blank_" class="more-extensions-link"
+    <a target="_blank" class="more-extensions-link"
         i18n-values="href:extensionSettingsGetMoreExtensionsUrl"
         i18n-content="extensionSettingsGetMoreExtensions"></a>
-    <a target="blank_" hidden
+    <a target="_blank" hidden
         class="extension-commands-config"
         i18n-content="extensionSettingsCommandsLink"
         href="#"></a>
diff --git a/chrome/browser/resources/feedback.html b/chrome/browser/resources/feedback.html
index ba0c501..d548824 100644
--- a/chrome/browser/resources/feedback.html
+++ b/chrome/browser/resources/feedback.html
@@ -73,6 +73,15 @@
         </span>
       </label>
     </div>
+
+    <!-- Performance Feedback -->
+    <div class="checkbox" id="performance-info-area" hidden>
+      <label>
+        <input id="performance-info-checkbox" type="checkbox">
+        <span id="performance-info-label" i18n-content="performance-trace">
+        </span>
+      </label>
+    </div>
 </if>
     <!-- Screenshot -->
     <div id="screenshot-row" hidden>
diff --git a/chrome/browser/resources/feedback.js b/chrome/browser/resources/feedback.js
index c5e183e..34e9645 100644
--- a/chrome/browser/resources/feedback.js
+++ b/chrome/browser/resources/feedback.js
@@ -18,6 +18,7 @@
 var categoryTag = '';
 var filePath = '';
 var forceDisableScreenshots = false;
+var traceId = 0;
 
 // Globals to manage reading data from the attach a file option.
 var attachFileBinaryData = '';
@@ -184,6 +185,10 @@
   // Add chromeos data if it exists.
   if ($('sys-info-checkbox')) {
     reportArray = reportArray.concat([String($('sys-info-checkbox').checked)]);
+    if (!$('performance-info-checkbox').checked) {
+      traceId = 0;
+    }
+    reportArray = reportArray.concat([String(traceId)]);
   }
 
   if ($('attach-file-checkbox') &&
@@ -274,6 +279,24 @@
   currentSelected();
 }
 
+<if expr="pp_ifdef('chromeos')">
+/**
+ * Update the page when performance feedback state is changed.
+ */
+function performanceFeedbackChanged() {
+  if ($('performance-info-checkbox').checked) {
+    $('attach-file-checkbox').disabled = true;
+    $('attach-file-checkbox').checked = false;
+
+    $('screenshot-checkbox').disabled = true;
+    $('screenshot-checkbox').checked = false;
+  } else {
+    $('attach-file-checkbox').disabled = false;
+    $('screenshot-checkbox').disabled = false;
+  }
+}
+</if>
+
 ///////////////////////////////////////////////////////////////////////////////
 // Document Functions:
 /**
@@ -293,6 +316,9 @@
 <if expr="pp_ifdef('chromeos')">
   $('screenshot-link-tosaved').onclick = changeToSaved;
   $('screenshot-link-tocurrent').onclick = changeToCurrent;
+
+  $('performance-info-checkbox').addEventListener(
+      'change', performanceFeedbackChanged);
 </if>
   $('send-report-button').onclick = sendReport;
   $('cancel-button').onclick = cancel;
@@ -304,6 +330,7 @@
     'categoryTag': '',
     'customPageUrl': '',
     'filePath': '',
+    'traceId': 0,
   };
 
   var loc = window.location;
@@ -357,6 +384,13 @@
     }
   }
 
+  traceId = parameters['traceId'];
+  if (traceId != 0 && ($('performance-info-area'))) {
+    $('performance-info-area').hidden = false;
+    $('performance-info-checkbox').checked = true;
+    performanceFeedbackChanged();
+  }
+
   chrome.send('getDialogDefaults');
   chrome.send('refreshCurrentScreenshot');
 }
diff --git a/chrome/browser/resources/file_manager/css/file_manager.css b/chrome/browser/resources/file_manager/css/file_manager.css
index ae84a63..a8da017 100644
--- a/chrome/browser/resources/file_manager/css/file_manager.css
+++ b/chrome/browser/resources/file_manager/css/file_manager.css
@@ -792,6 +792,8 @@
   min-width: 22px;
   opacity: 0.6;
   padding-left: 26px;
+  position: relative;
+  z-index: 10;
 }
 
 .downloads-warning {
diff --git a/chrome/browser/resources/file_manager/js/directory_model.js b/chrome/browser/resources/file_manager/js/directory_model.js
index 77dda39..f1c5f97 100644
--- a/chrome/browser/resources/file_manager/js/directory_model.js
+++ b/chrome/browser/resources/file_manager/js/directory_model.js
@@ -226,7 +226,7 @@
   this.taskQueue_.run(this.updateRoots_.bind(this));
   if (!enabled && (this.getCurrentRootType() == RootType.DRIVE ||
                    this.getCurrentRootType() == RootType.DRIVE_OFFLINE))
-    this.changeDirectory(this.getDefaultDirectory());
+    this.changeDirectory(PathUtil.DEFAULT_DIRECTORY);
 };
 
 /**
@@ -1077,7 +1077,7 @@
   var EXISTS = true;
 
   var changeToDefault = function(leafName) {
-    var def = self.getDefaultDirectory();
+    var def = PathUtil.DEFAULT_DIRECTORY;
     self.resolveDirectory(def, function(directoryEntry) {
       resolveCallback(def, leafName, !EXISTS);
       changeDirectoryEntry(directoryEntry, INITIAL);
@@ -1130,20 +1130,6 @@
 };
 
 /**
- * Sets up the default path.
- */
-DirectoryModel.prototype.setupDefaultPath = function() {
-  this.setupPath(this.getDefaultDirectory());
-};
-
-/**
- * @return {string} The default directory.
- */
-DirectoryModel.prototype.getDefaultDirectory = function() {
-  return RootDirectory.DOWNLOADS;
-};
-
-/**
  * @param {string} name Filename.
  */
 DirectoryModel.prototype.selectEntry = function(name) {
@@ -1223,7 +1209,7 @@
 
     if ((rootType == RootType.ARCHIVE || rootType == RootType.REMOVABLE) &&
         !this.volumeManager_.isMounted(this.getCurrentRootPath())) {
-      this.changeDirectory(this.getDefaultDirectory());
+      this.changeDirectory(PathUtil.DEFAULT_DIRECTORY);
     }
 
     callback();
@@ -1413,7 +1399,7 @@
 
     } else {
       // Unknown path.
-      this.changeDirectory(this.getDefaultDirectory());
+      this.changeDirectory(PathUtil.DEFAULT_DIRECTORY);
       return;
     }
 
diff --git a/chrome/browser/resources/file_manager/js/directory_tree.js b/chrome/browser/resources/file_manager/js/directory_tree.js
index 9214d23..981089e 100644
--- a/chrome/browser/resources/file_manager/js/directory_tree.js
+++ b/chrome/browser/resources/file_manager/js/directory_tree.js
@@ -108,39 +108,22 @@
 };
 
 /**
- * Modifies a list of the directory entries to match the new UI sepc.
- *
- * TODO(yoshiki): remove this after the old UI is removed.
- *
- * @param {Array.<DirectoryEntry>} entries The list of entty.
- * @return {Array.<DirectoryEntries>} Modified entries.
+ * Generate a list of the directory entries for the top level on the tree.
+ * @return {Array.<DirectoryEntry>} Entries for the top level on the tree.
  */
-DirectoryTreeUtil.addAndRemoveDriveSpecialDirs = function(entries) {
-  var modifiedEntries = [];
+DirectoryTreeUtil.generateTopLevelEntries = function() {
+  var entries = [
+    DirectoryModel.fakeDriveEntry_,
+    DirectoryModel.fakeDriveOfflineEntry_,
+    DirectoryModel.fakeDriveSharedWithMeEntry_,
+    DirectoryModel.fakeDriveRecentEntry_,
+  ];
+
   for (var i in entries) {
-    // Removes '/drive/other'.
-    var entry = entries[i];
-    if (entry.fullPath ==
-        (RootDirectory.DRIVE + '/' + DriveSubRootDirectory.OTHER)) {
-      continue;
-    }
-
-    // Changes the label of '/drive/root' to 'My Drive'.
-    if (entry.fullPath == DirectoryModel.fakeDriveEntry_.fullPath) {
-      entry.label = str('DRIVE_MY_DRIVE_LABEL');
-    }
-
-    modifiedEntries.push(entry);
+    entries[i]['label'] = PathUtil.getRootLabel(entries[i].fullPath);
   }
 
-  // Adds the special directories.
-  var specialDirs = DirectoryModel.FAKE_DRIVE_SPECIAL_SEARCH_ENTRIES;
-  for (var i in specialDirs) {
-    var dir = specialDirs[i];
-    dir['label'] = PathUtil.getRootLabel(dir.fullPath);
-    modifiedEntries.push(dir);
-  }
-  return modifiedEntries;
+  return entries;
 };
 
 /**
@@ -180,12 +163,8 @@
   var readEntry = function() {
     reader.readEntries(function(results) {
       if (!results.length) {
-        if (item.entry.fullPath == RootDirectory.DRIVE)
-          successCallback(
-              DirectoryTreeUtil.addAndRemoveDriveSpecialDirs(entries));
-        else
-          successCallback(
-              DirectoryTreeUtil.sortEntries(item.fileFilter_, entries));
+        successCallback(
+            DirectoryTreeUtil.sortEntries(item.fileFilter_, entries));
         return;
       }
 
@@ -215,14 +194,14 @@
 };
 
 /**
- * Checks if tre tree should be hidden on the given directory.
+ * Checks if the given directory can be on the tree or not.
  *
  * @param {string} path Path to be checked.
- * @return {boolean} True if the tree should NOT be visible on the given
- *     directory. Otherwise, false.
+ * @return {boolean} True if the path is eligible for the directory tree.
+ *     Otherwise, false.
  */
-DirectoryTreeUtil.shouldHideTree = function(path) {
-  return !PathUtil.isDriveBasedPath(path);
+DirectoryTreeUtil.isEligiblePathForDirectoryTree = function(path) {
+  return PathUtil.isDriveBasedPath(path);
 };
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -492,16 +471,6 @@
    */
   set expanded(value) {},
 
-  /**
-   * The DirectoryEntry corresponding to this DirectoryItem. This may be
-   * a dummy DirectoryEntry.
-   * @type {DirectoryEntry|Object}
-   * @override
-   **/
-  get entry() {
-      return this.dirEntry_;
-  },
-
   get directoryModel() {
     return this.directoryModel_;
   }
@@ -517,24 +486,11 @@
   cr.ui.Tree.prototype.decorate.call(this);
 
   this.directoryModel_ = directoryModel;
-  this.entries_ = [];
+  this.entries_ = DirectoryTreeUtil.generateTopLevelEntries();
 
   this.fileFilter_ = this.directoryModel_.getFileFilter();
   this.fileFilter_.addEventListener('changed',
                                     this.onFilterChanged_.bind(this));
-  /**
-   * The path of the root directory.
-   * @type {string}
-   */
-  this.fullPath = '/';
-  this.dirEntry_ = null;
-
-  /**
-   * The currently selected entry.
-   * For special search entries, this could be a fake DirectoryEntry.
-   * @type {DirectoryEntry|Object}
-   */
-  this.currentEntry_ = null;
 
   this.directoryModel_.addEventListener('directory-changed',
       this.onCurrentDirectoryChanged_.bind(this));
@@ -557,6 +513,8 @@
 
   this.scrollBar_ = MainPanelScrollBar();
   this.scrollBar_.initialize(this.parentNode, this);
+
+  this.redraw(false /* recursive */);
 };
 
 /**
@@ -565,53 +523,10 @@
  *     be a fake.
  */
 DirectoryTree.prototype.selectByEntry = function(entry) {
-  if ((this.entry && util.isSameEntry(this.entry, entry)) ||
-      (this.currentEntry_ && util.isSameEntry(this.currentEntry_, entry)))
+  // If the target directory is not in the tree, do nothing.
+  if (!DirectoryTreeUtil.isEligiblePathForDirectoryTree(entry.fullPath))
     return;
 
-  this.currentEntry_ = entry;
-  if (DirectoryTreeUtil.shouldHideTree(entry.fullPath))
-    return;
-
-  this.selectByEntryInternal_(entry);
-};
-
-/**
- * Select the item corresponding to the given entry. This method is used
- * internally.
- * @param {DirectoryEntry|Object} entry The directory entry to be selected.
- * @private
- */
-DirectoryTree.prototype.selectByEntryInternal_ = function(entry) {
-  var rootDirPath = PathUtil.getRootPath(entry.fullPath);
-
-  if (PathUtil.isSpecialSearchRoot(rootDirPath) ||
-      PathUtil.getRootType(rootDirPath) == RootType.DRIVE) {
-    rootDirPath = RootDirectory.DRIVE;
-  }
-
-  var onError = function() {
-    this.clearTree_(true);
-  }.bind(this);
-
-  if (this.fullPath != rootDirPath || !this.dirEntry_) {
-    // The old root is not the one for the new entry. So, first we try to set
-    // the root, then retry.
-    this.fullPath = rootDirPath;
-
-    this.directoryModel_.resolveDirectory(
-        rootDirPath,
-        function(rootDirEntry) {
-          if (this.fullPath != rootDirPath)
-            return;
-
-          this.dirEntry_ = rootDirEntry;
-          this.selectByEntryInternal_(entry);
-        }.bind(this),
-        onError);
-    return;
-  }
-
   if (this.selectedItem && util.isSameEntry(entry, this.selectedItem.entry))
     return;
 
@@ -621,13 +536,11 @@
   this.selectedItem = null;
   this.updateSubDirectories(
       false /* recursive */,
+      // Success callback, failure is not handled.
       function() {
-        if (!DirectoryTreeUtil.searchAndSelectByEntry(
-            this.items, this.currentEntry_))
+        if (!DirectoryTreeUtil.searchAndSelectByEntry(this.items, entry))
           this.selectedItem = null;
-        cr.dispatchSimpleEvent(this, 'content-updated');
-      }.bind(this),
-      onError);
+      }.bind(this));
 };
 
 /**
@@ -638,11 +551,9 @@
  */
 DirectoryTree.prototype.updateSubDirectories = function(
     recursive, opt_successCallback, opt_errorCallback) {
-  if (!this.currentEntry_)
-    return;
-
+  var myDriveItem = this.items[0];
   DirectoryTreeUtil.updateSubDirectories(
-      this,
+      myDriveItem,
       this.directoryModel_,
       function(entries) {
         this.entries_ = entries;
@@ -672,12 +583,10 @@
  */
 DirectoryTree.prototype.onFilterChanged_ = function() {
   // Returns immediately, if the tree is hidden.
-  if (!this.currentEntry_ ||
-      DirectoryTreeUtil.shouldHideTree(this.currentEntry_.fullPath))
+  if (this.hidden)
     return;
 
   this.redraw(true /* recursive */);
-  cr.dispatchSimpleEvent(this, 'content-updated');
 };
 
 /**
@@ -686,14 +595,13 @@
  * @private
  */
 DirectoryTree.prototype.onDirectoryContentChanged_ = function(event) {
-  // Returns immediately, if the tree is hidden.
-  if (!this.currentEntry_ ||
-      DirectoryTreeUtil.shouldHideTree(this.currentEntry_.fullPath))
-    return;
-
   if (event.eventType == 'changed') {
     var path = util.extractFilePath(event.directoryUrl);
-    DirectoryTreeUtil.updateChangedDirectoryItem(path, this);
+    if (!DirectoryTreeUtil.isEligiblePathForDirectoryTree(path))
+      return;
+
+    var myDriveItem = this.items[0];
+    DirectoryTreeUtil.updateChangedDirectoryItem(path, myDriveItem);
   }
 };
 
@@ -707,31 +615,6 @@
 };
 
 /**
- * Returns the path of the selected item.
- * @return {string} The current path.
- */
-DirectoryTree.prototype.getCurrentPath = function() {
-  return this.selectedItem ? this.selectedItem.fullPath : null;
-};
-
-/**
- * Clears the tree.
- * @param {boolean} redraw Redraw the tree if true.
- * @private
- */
-DirectoryTree.prototype.clearTree_ = function(redraw) {
-  this.dirEntry_ = null;
-  this.fullPath = '';
-  this.selectedItem = null;
-  this.entries_ = [];
-
-  if (redraw) {
-    this.redraw(false);
-    cr.dispatchSimpleEvent(this, 'content-updated');
-  }
-};
-
-/**
  * Sets the margin height for the transparent preview panel at the bottom.
  * @param {number} margin Margin to be set in px.
  */
diff --git a/chrome/browser/resources/file_manager/js/file_manager.js b/chrome/browser/resources/file_manager/js/file_manager.js
index 657a7f2..9ef23dc 100644
--- a/chrome/browser/resources/file_manager/js/file_manager.js
+++ b/chrome/browser/resources/file_manager/js/file_manager.js
@@ -1181,35 +1181,35 @@
   FileManager.prototype.initSidebar_ = function() {
     this.directoryTree_ = this.dialogDom_.querySelector('#directory-tree');
     DirectoryTree.decorate(this.directoryTree_, this.directoryModel_);
-    this.directoryTree_.addEventListener('content-updated', function() {
-      this.updateMiddleBarVisibility_(true);
-    }.bind(this));
 
     this.navigationList_ = this.dialogDom_.querySelector('#volume-list');
-    NavigationList.decorate(this.navigationList_,
-                            this.directoryModel_,
-                            this.folderShortcutsModel_);
+    NavigationList.decorate(this.navigationList_, this.directoryModel_);
+    this.navigationList_.fileManager = this;
+    this.navigationList_.dataModel =
+        new NavigationListModel(this.directoryModel_.getRootsList(),
+                                this.folderShortcutsModel_);
+
+    this.navigationList_.addEventListener(
+        'shortcut-target-not-found',
+        function(e) {
+          var path = e.path;
+          var label = e.label;
+          this.confirm.showWithTitle(
+            label,
+            str('SHORTCUT_TARGET_UNAVAILABLE'),
+            // 'Yes' is clicked.
+            function() {
+              this.removeFolderShortcut(path);
+            }.bind(this));
+        }.bind(this));
   };
 
   /**
-   * @param {boolean=} opt_delayed If true, updating is delayed by 500ms.
    * @private
    */
-  FileManager.prototype.updateMiddleBarVisibility_ = function(opt_delayed) {
-    if (this.updateMiddleBarVisibilityTimer_) {
-      clearTimeout(this.updateMiddleBarVisibilityTimer_);
-      this.updateMiddleBarVisibilityTimer_ = null;
-    }
-
-    if (opt_delayed) {
-      this.updateMiddleBarVisibilityTimer_ =
-          setTimeout(this.updateMiddleBarVisibility_.bind(this, false), 500);
-      return;
-    }
+  FileManager.prototype.updateMiddleBarVisibility_ = function() {
     var currentPath = this.directoryModel_.getCurrentDirPath();
-    var visible =
-        (this.directoryTree_.items.length > 0) &&
-        (!DirectoryTreeUtil.shouldHideTree(currentPath));
+    var visible = DirectoryTreeUtil.isEligiblePathForDirectoryTree(currentPath);
     this.dialogDom_.
         querySelector('.dialog-middlebar-contents').hidden = !visible;
     this.dialogDom_.querySelector('#middlebar-splitter').hidden = !visible;
@@ -1591,10 +1591,10 @@
       return;
 
     if (!path) {
-      path = this.directoryModel_.getDefaultDirectory();
+      path = PathUtil.DEFAULT_DIRECTORY;
     } else if (path.indexOf('/') == -1) {
       // Path is a file name.
-      path = this.directoryModel_.getDefaultDirectory() + '/' + path;
+      path = PathUtil.DEFAULT_DIRECTORY + '/' + path;
     }
 
     // In the FULL_PAGE mode if the hash path points to a file we might have
@@ -2015,10 +2015,8 @@
 
   FileManager.prototype.isDriveEnabled = function() {
     // Auto resolving to local path does not work for folders (e.g., dialog for
-    // loading unpacked extensions) and saving.
-    // TODO(kinaba): make it work for the save dialog http://crbug.com/140425
+    // loading unpacked extensions).
     var noLocalPathResolution =
-      this.params_.type == DialogType.SELECT_SAVEAS_FILE ||
       this.params_.type == DialogType.SELECT_FOLDER ||
       this.params_.type == DialogType.SELECT_UPLOAD_FOLDER;
     if (noLocalPathResolution && this.params_.shouldReturnLocalPath)
@@ -2685,9 +2683,8 @@
       this.scanUpdatedTimer_ = null;
     }
 
-    if (!this.spinner_.hidden) {
+    if (this.spinner_.hidden) {
       this.cancelSpinnerTimeout_();
-      this.showSpinner_(false);
       this.showSpinnerTimeout_ =
           setTimeout(this.showSpinner_.bind(this, true), 500);
     }
diff --git a/chrome/browser/resources/file_manager/js/folder_shortcuts_data_model.js b/chrome/browser/resources/file_manager/js/folder_shortcuts_data_model.js
index 113a5f2..25895f9 100644
--- a/chrome/browser/resources/file_manager/js/folder_shortcuts_data_model.js
+++ b/chrome/browser/resources/file_manager/js/folder_shortcuts_data_model.js
@@ -56,6 +56,7 @@
       if (this.array_.length == list.length) {
         var changed = false;
         for (var i = 0; i < this.array_.length; i++) {
+          // Same item check: must be exact match.
           if (this.array_[i] != list[i]) {
             changed = true;
             break;
@@ -103,7 +104,8 @@
    */
   getIndex: function(value) {
     for (var i = 0; i < this.length; i++) {
-      if (this.array_[i].localeCompare(value) == 0) {
+      // Same item check: must be exact match.
+      if (this.array_[i] == value) {
         return i;
       }
     }
@@ -111,6 +113,21 @@
   },
 
   /**
+   * Compares 2 strings and returns a number indicating one string comes before
+   * or after or is the same as the other string in sort order.
+   *
+   * @param {string} a String1.
+   * @param {string} b String2.
+   * @return {boolean} Return -1, if String1 < String2. Return 0, if String1 ==
+   *     String2. Otherwise, return 1.
+   */
+  compare: function(a, b) {
+    return a.localeCompare(b,
+                           undefined,  // locale parameter, use default locale.
+                           {usage: 'sort', numeric: true});
+  },
+
+  /**
    * Adds the given item to the array. If there were already same item in the
    * list, return the index of the existing item without adding a duplicate
    * item.
@@ -122,11 +139,13 @@
     var oldArray = this.array_.slice(0);  // Shallow copy.
     var addedIndex = -1;
     for (var i = 0; i < this.length; i++) {
-      // Since the array is sorted, new item will be added just before the first
-      // larger item. If the same item exists, do nothing.
-      if (this.array_[i].localeCompare(value) == 0) {
+      // Same item check: must be exact match.
+      if (this.array_[i] == value)
         return i;
-      } else if (this.array_[i].localeCompare(value) >= 0) {
+
+      // Since the array is sorted, new item will be added just before the first
+      // larger item.
+      if (this.compare(this.array_[i], value) >= 0) {
         this.array_.splice(i, 0, value);
         addedIndex = i;
         break;
@@ -153,6 +172,7 @@
     var removedIndex = -1;
     var oldArray = this.array_.slice(0);  // Shallow copy.
     for (var i = 0; i < this.length; i++) {
+      // Same item check: must be exact match.
       if (this.array_[i] == value) {
         this.array_.splice(i, 1);
         removedIndex = i;
@@ -214,20 +234,23 @@
       }
 
       while (newIndex < newArray.length) {
+        // Unchanged item, which exists in both new and old array. But the
+        // index may be changed.
         if (oldArray[oldIndex] == newArray[newIndex]) {
-          // Unchanged item, which exists in both new and old array. But the
-          // index may be changed.
           permutation[oldIndex] = newIndex;
           newIndex++;
           break;
-        } else if (oldArray[oldIndex] < newArray[newIndex]) {
-          // oldArray[oldIndex] is deleted, which is not in the new array.
+        }
+
+        // oldArray[oldIndex] is deleted, which is not in the new array.
+        if (this.compare(oldArray[oldIndex], newArray[newIndex]) < 0) {
           permutation[oldIndex] = -1;
           break;
-        } else {  // oldArray[oldIndex] > newArray[newIndex]
-          // newArray[newIndex] is added, which is not in the old array.
-          newIndex++;
         }
+
+        // In the case of this.compare(oldArray[oldIndex]) > 0:
+        // newArray[newIndex] is added, which is not in the old array.
+        newIndex++;
       }
     }
     return permutation;
diff --git a/chrome/browser/resources/file_manager/js/navigation_list.js b/chrome/browser/resources/file_manager/js/navigation_list.js
index 476fe6d..16bd17b 100644
--- a/chrome/browser/resources/file_manager/js/navigation_list.js
+++ b/chrome/browser/resources/file_manager/js/navigation_list.js
@@ -66,7 +66,8 @@
  */
 NavigationListModel.prototype = {
   __proto__: cr.EventTarget.prototype,
-  get length() { return this.length_(); }
+  get length() { return this.length_(); },
+  get folderShortcutList() { return this.pinnedList_; }
 };
 
 /**
@@ -213,29 +214,50 @@
 /**
  * NavigationList inherits cr.ui.List.
  */
-NavigationList.prototype.__proto__ = cr.ui.List.prototype;
+NavigationList.prototype = {
+  __proto__: cr.ui.List.prototype,
+
+  set dataModel(dataModel) {
+    if (!this.boundHandleListChanged_)
+      this.boundHandleListChanged_ = this.onListContentChanged_.bind(this);
+
+    if (this.dataModel_) {
+      dataModel.removeEventListener('change', this.boundHandleListChanged_);
+      dataModel.removeEventListener('permuted', this.boundHandleListChanged_);
+    }
+
+    dataModel.addEventListener('change', this.boundHandleListChanged_);
+    dataModel.addEventListener('permuted', this.boundHandleListChanged_);
+
+    var parentSetter = cr.ui.List.prototype.__lookupSetter__('dataModel');
+    return parentSetter.call(this, dataModel);
+  },
+
+  get dataModel() {
+    return this.dataModel_;
+  },
+
+  // TODO(yoshiki): Add a setter of 'directoryModel'.
+};
 
 /**
  * @param {HTMLElement} el Element to be DirectoryItem.
  * @param {DirectoryModel} directoryModel Current DirectoryModel.
- * @param {cr.ui.ArrayDataModel} pinnedFolderModel Current model of the pinned
  *     folders.
  */
-NavigationList.decorate = function(el, directoryModel, pinnedFolderModel) {
+NavigationList.decorate = function(el, directoryModel) {
   el.__proto__ = NavigationList.prototype;
-  el.decorate(directoryModel, pinnedFolderModel);
+  el.decorate(directoryModel);
 };
 
 /**
  * @param {DirectoryModel} directoryModel Current DirectoryModel.
- * @param {cr.ui.ArrayDataModel} pinnedFolderModel Current model of the pinned
- *     folders.
  */
-NavigationList.prototype.decorate =
-    function(directoryModel, pinnedFolderModel) {
+NavigationList.prototype.decorate = function(directoryModel) {
   cr.ui.List.decorate(this);
   this.__proto__ = NavigationList.prototype;
 
+  this.fileManager_ = null;
   this.directoryModel_ = directoryModel;
   this.volumeManager_ = VolumeManager.getInstance();
   this.selectionModel = new cr.ui.ListSingleSelectionModel();
@@ -258,16 +280,6 @@
   this.itemConstructor = function(path) {
     return self.renderRoot_(path);
   };
-
-  this.pinnedItemList_ = pinnedFolderModel;
-
-  this.dataModel =
-      new NavigationListModel(this.directoryModel_.getRootsList(),
-                              this.pinnedItemList_);
-  this.dataModel.addEventListener(
-      'change', this.onDataModelChanged_.bind(this));
-  this.dataModel.addEventListener(
-      'permuted', this.onDataModelChanged_.bind(this));
 };
 
 /**
@@ -282,9 +294,8 @@
   item.setPath(path);
 
   var handleClick = function() {
-    if (item.selected && path !== this.directoryModel_.getCurrentDirPath()) {
-      this.directoryModel_.changeDirectory(path);
-    }
+    if (item.selected && path !== this.directoryModel_.getCurrentDirPath())
+      this.changeDirectory_(path);
   }.bind(this);
   item.addEventListener('click', handleClick);
 
@@ -304,6 +315,25 @@
 };
 
 /**
+ * Changes the current directory to the given path.
+ * If the given path is not found, a 'shortcut-target-not-found' event is
+ * fired.
+ *
+ * @param {string} path Path of the directory to be chagned to.
+ * @private
+ */
+NavigationList.prototype.changeDirectory_ = function(path) {
+  var onErrorCallback = function() {
+    var e = new Event('shortcut-target-not-found');
+    e.path = path;
+    e.label = PathUtil.getFolderLabel(path);
+    this.dispatchEvent(e);
+  }.bind(this);
+
+  this.directoryModel_.changeDirectory(path, onErrorCallback);
+};
+
+/**
  * Sets a context menu. Context menu is enabled only on archive and removable
  * volumes as of now.
  *
@@ -334,7 +364,7 @@
   if (this.directoryModel_.getCurrentDirEntry().fullPath == newPath)
     return false;
 
-  this.directoryModel_.changeDirectory(newPath);
+  this.changeDirectory_(newPath);
   return true;
 };
 
@@ -376,7 +406,7 @@
  * @param {Event} event The event.
  * @private
  */
-NavigationList.prototype.onDataModelChanged_ = function(event) {
+NavigationList.prototype.onListContentChanged_ = function(event) {
   this.selectBestMatchItem_();
 };
 
diff --git a/chrome/browser/resources/file_manager/js/path_util.js b/chrome/browser/resources/file_manager/js/path_util.js
index 774cb13..1517377 100644
--- a/chrome/browser/resources/file_manager/js/path_util.js
+++ b/chrome/browser/resources/file_manager/js/path_util.js
@@ -45,6 +45,13 @@
 var PathUtil = {};
 
 /**
+ * The path to the default directory.
+ * @type {string}
+ * @const
+ */
+PathUtil.DEFAULT_DIRECTORY = RootDirectory.DOWNLOADS;
+
+/**
  * Checks if the given path represents a special search. Fake entries in
  * RootDirectory correspond to special searches.
  * @param {string} path Path to check.
diff --git a/chrome/browser/resources/google_now/background.js b/chrome/browser/resources/google_now/background.js
index 188545b..893bfef 100644
--- a/chrome/browser/resources/google_now/background.js
+++ b/chrome/browser/resources/google_now/background.js
@@ -114,33 +114,29 @@
   return false;
 }
 
-var googleGeolocationAccessEnabledPref =
-    chrome.preferencesPrivate.googleGeolocationAccessEnabled;
-
 var tasks = buildTaskManager(areTasksConflicting);
 
 // Add error processing to API calls.
-tasks.instrumentApiFunction(chrome.location.onLocationUpdate, 'addListener', 0);
-tasks.instrumentApiFunction(chrome.notifications, 'create', 2);
-tasks.instrumentApiFunction(chrome.notifications, 'update', 2);
-tasks.instrumentApiFunction(chrome.notifications, 'getAll', 0);
-tasks.instrumentApiFunction(
-    chrome.notifications.onButtonClicked, 'addListener', 0);
-tasks.instrumentApiFunction(chrome.notifications.onClicked, 'addListener', 0);
-tasks.instrumentApiFunction(chrome.notifications.onClosed, 'addListener', 0);
-tasks.instrumentApiFunction(chrome.omnibox.onInputEntered, 'addListener', 0);
-tasks.instrumentApiFunction(
-    googleGeolocationAccessEnabledPref,
-    'get',
+tasks.instrumentChromeApiFunction('location.onLocationUpdate.addListener', 0);
+tasks.instrumentChromeApiFunction('metricsPrivate.getVariationParams', 1);
+tasks.instrumentChromeApiFunction('notifications.create', 2);
+tasks.instrumentChromeApiFunction('notifications.update', 2);
+tasks.instrumentChromeApiFunction('notifications.getAll', 0);
+tasks.instrumentChromeApiFunction(
+    'notifications.onButtonClicked.addListener', 0);
+tasks.instrumentChromeApiFunction('notifications.onClicked.addListener', 0);
+tasks.instrumentChromeApiFunction('notifications.onClosed.addListener', 0);
+tasks.instrumentChromeApiFunction('omnibox.onInputEntered.addListener', 0);
+tasks.instrumentChromeApiFunction(
+    'preferencesPrivate.googleGeolocationAccessEnabled.get',
     1);
-tasks.instrumentApiFunction(
-    googleGeolocationAccessEnabledPref.onChange,
-    'addListener',
+tasks.instrumentChromeApiFunction(
+    'preferencesPrivate.googleGeolocationAccessEnabled.onChange.addListener',
     0);
-tasks.instrumentApiFunction(chrome.runtime.onInstalled, 'addListener', 0);
-tasks.instrumentApiFunction(chrome.runtime.onStartup, 'addListener', 0);
-tasks.instrumentApiFunction(chrome.tabs, 'create', 1);
-tasks.instrumentApiFunction(storage, 'get', 1);
+tasks.instrumentChromeApiFunction('runtime.onInstalled.addListener', 0);
+tasks.instrumentChromeApiFunction('runtime.onStartup.addListener', 0);
+tasks.instrumentChromeApiFunction('tabs.create', 1);
+tasks.instrumentChromeApiFunction('storage.local.get', 1);
 
 var updateCardsAttempts = buildAttemptManager(
     'cards-update',
@@ -255,80 +251,84 @@
   }
 
   tasks.debugSetStepName('parseAndShowNotificationCards-storage-get');
-  storage.get(['notificationsData', 'recentDismissals'], function(items) {
-    console.log('parseAndShowNotificationCards-get ' + JSON.stringify(items));
-    items.notificationsData = items.notificationsData || {};
-    items.recentDismissals = items.recentDismissals || {};
+  instrumented.storage.local.get(['notificationsData', 'recentDismissals'],
+      function(items) {
+        console.log('parseAndShowNotificationCards-get ' +
+            JSON.stringify(items));
+        items.notificationsData = items.notificationsData || {};
+        items.recentDismissals = items.recentDismissals || {};
 
-    tasks.debugSetStepName(
-        'parseAndShowNotificationCards-notifications-getAll');
-    chrome.notifications.getAll(function(notifications) {
-      console.log('parseAndShowNotificationCards-getAll ' +
-          JSON.stringify(notifications));
-      // TODO(vadimt): Figure out what to do when notifications are disabled for
-      // our extension.
-      notifications = notifications || {};
+        tasks.debugSetStepName(
+            'parseAndShowNotificationCards-notifications-getAll');
+        instrumented.notifications.getAll(function(notifications) {
+          console.log('parseAndShowNotificationCards-getAll ' +
+              JSON.stringify(notifications));
+          // TODO(vadimt): Figure out what to do when notifications are
+          // disabled for our extension.
+          notifications = notifications || {};
 
-      // Build a set of non-expired recent dismissals. It will be used for
-      // client-side filtering of cards.
-      var updatedRecentDismissals = {};
-      var currentTimeMs = Date.now();
-      for (var notificationId in items.recentDismissals) {
-        if (currentTimeMs - items.recentDismissals[notificationId] <
-            DISMISS_RETENTION_TIME_MS) {
-          updatedRecentDismissals[notificationId] =
-              items.recentDismissals[notificationId];
-        }
-      }
+          // Build a set of non-expired recent dismissals. It will be used for
+          // client-side filtering of cards.
+          var updatedRecentDismissals = {};
+          var currentTimeMs = Date.now();
+          for (var notificationId in items.recentDismissals) {
+            if (currentTimeMs - items.recentDismissals[notificationId] <
+                DISMISS_RETENTION_TIME_MS) {
+              updatedRecentDismissals[notificationId] =
+                  items.recentDismissals[notificationId];
+            }
+          }
 
-      // Mark existing notifications that received an update in this server
-      // response.
-      var updatedNotifications = {};
+          // Mark existing notifications that received an update in this server
+          // response.
+          var updatedNotifications = {};
 
-      for (var i = 0; i < cards.length; ++i) {
-        var notificationId = cards[i].notificationId;
-        if (!(notificationId in updatedRecentDismissals) &&
-            notificationId in notifications) {
-          updatedNotifications[notificationId] = true;
-        }
-      }
+          for (var i = 0; i < cards.length; ++i) {
+            var notificationId = cards[i].notificationId;
+            if (!(notificationId in updatedRecentDismissals) &&
+                notificationId in notifications) {
+              updatedNotifications[notificationId] = true;
+            }
+          }
 
-      // Delete notifications that didn't receive an update.
-      for (var notificationId in notifications) {
-        console.log('parseAndShowNotificationCards-delete-check ' +
-                    notificationId);
-        if (!(notificationId in updatedNotifications)) {
-          console.log('parseAndShowNotificationCards-delete ' + notificationId);
-          cardSet.clear(notificationId);
-        }
-      }
+          // Delete notifications that didn't receive an update.
+          for (var notificationId in notifications) {
+            console.log('parseAndShowNotificationCards-delete-check ' +
+                        notificationId);
+            if (!(notificationId in updatedNotifications)) {
+              console.log('parseAndShowNotificationCards-delete ' +
+                  notificationId);
+              cardSet.clear(notificationId);
+            }
+          }
 
-      recordEvent(GoogleNowEvent.CARDS_PARSE_SUCCESS);
+          recordEvent(GoogleNowEvent.CARDS_PARSE_SUCCESS);
 
-      // Create/update notifications and store their new properties.
-      var newNotificationsData = {};
-      for (var i = 0; i < cards.length; ++i) {
-        var card = cards[i];
-        if (!(card.notificationId in updatedRecentDismissals)) {
-          var notificationData = items.notificationsData[card.notificationId];
-          var previousVersion = notifications[card.notificationId] &&
-                                notificationData &&
-                                notificationData.cardCreateInfo &&
-                                notificationData.cardCreateInfo.version;
-          newNotificationsData[card.notificationId] =
-              cardSet.update(card, previousVersion);
-        }
-      }
+          // Create/update notifications and store their new properties.
+          var newNotificationsData = {};
+          for (var i = 0; i < cards.length; ++i) {
+            var card = cards[i];
+            if (!(card.notificationId in updatedRecentDismissals)) {
+              var notificationData =
+                  items.notificationsData[card.notificationId];
+              var previousVersion = notifications[card.notificationId] &&
+                                    notificationData &&
+                                    notificationData.cardCreateInfo &&
+                                    notificationData.cardCreateInfo.version;
+              newNotificationsData[card.notificationId] =
+                  cardSet.update(card, previousVersion);
+            }
+          }
 
-      updateCardsAttempts.start(parsedResponse.next_poll_seconds);
+          updateCardsAttempts.start(parsedResponse.next_poll_seconds);
 
-      storage.set({
-        notificationsData: newNotificationsData,
-        recentDismissals: updatedRecentDismissals
+          chrome.storage.local.set({
+            notificationsData: newNotificationsData,
+            recentDismissals: updatedRecentDismissals
+          });
+          callback();
+        });
       });
-      callback();
-    });
-  });
 }
 
 /**
@@ -342,11 +342,11 @@
   // TODO(robliao): Once Google Now clears its own checkbox in the
   // notifications center and bug 260376 is fixed, the below clearing
   // code is no longer necessary.
-  chrome.notifications.getAll(function(notifications) {
+  instrumented.notifications.getAll(function(notifications) {
     for (var notificationId in notifications) {
       chrome.notifications.clear(notificationId, function() {});
     }
-    storage.set({notificationsData: {}});
+    chrome.storage.local.set({notificationsData: {}});
   });
 }
 
@@ -401,11 +401,19 @@
 function requestLocation() {
   console.log('requestLocation');
   recordEvent(GoogleNowEvent.LOCATION_REQUEST);
-  // TODO(vadimt): Figure out location request options. Use experiments
-  // framework to enable setting these parameters remotely.
-  chrome.location.watchLocation(LOCATION_WATCH_NAME, {
-    minDistanceInMeters: 100,
-    minTimeInMilliseconds: 180000  // 3 minutes.
+  // TODO(vadimt): Figure out location request options.
+  chrome.metricsPrivate.getVariationParams('GoogleNow', function(params) {
+    var minDistanceInMeters =
+        parseInt(params && params.minDistanceInMeters, 10) ||
+        100;
+    var minTimeInMilliseconds =
+        parseInt(params && params.minTimeInMilliseconds, 10) ||
+        180000;  // 3 minutes.
+
+    chrome.location.watchLocation(LOCATION_WATCH_NAME, {
+      minDistanceInMeters: minDistanceInMeters,
+      minTimeInMilliseconds: minTimeInMilliseconds
+    });
   });
 }
 
@@ -503,52 +511,53 @@
  */
 function processPendingDismissals(callbackBoolean) {
   tasks.debugSetStepName('processPendingDismissals-storage-get');
-  storage.get(['pendingDismissals', 'recentDismissals'], function(items) {
-    console.log('processPendingDismissals-storage-get ' +
-                JSON.stringify(items));
-    items.pendingDismissals = items.pendingDismissals || [];
-    items.recentDismissals = items.recentDismissals || {};
+  instrumented.storage.local.get(['pendingDismissals', 'recentDismissals'],
+      function(items) {
+        console.log('processPendingDismissals-storage-get ' +
+                    JSON.stringify(items));
+        items.pendingDismissals = items.pendingDismissals || [];
+        items.recentDismissals = items.recentDismissals || {};
 
-    var dismissalsChanged = false;
+        var dismissalsChanged = false;
 
-    function onFinish(success) {
-      if (dismissalsChanged) {
-        storage.set({
-          pendingDismissals: items.pendingDismissals,
-          recentDismissals: items.recentDismissals
-        });
-      }
-      callbackBoolean(success);
-    }
+        function onFinish(success) {
+          if (dismissalsChanged) {
+            chrome.storage.local.set({
+              pendingDismissals: items.pendingDismissals,
+              recentDismissals: items.recentDismissals
+            });
+          }
+          callbackBoolean(success);
+        }
 
-    function doProcessDismissals() {
-      if (items.pendingDismissals.length == 0) {
-        dismissalAttempts.stop();
-        onFinish(true);
-        return;
-      }
+        function doProcessDismissals() {
+          if (items.pendingDismissals.length == 0) {
+            dismissalAttempts.stop();
+            onFinish(true);
+            return;
+          }
 
-      // Send dismissal for the first card, and if successful, repeat
-      // recursively with the rest.
-      var dismissal = items.pendingDismissals[0];
-      requestCardDismissal(
-          dismissal.notificationId,
-          dismissal.time,
-          dismissal.parameters,
-          function(done) {
-            if (done) {
-              dismissalsChanged = true;
-              items.pendingDismissals.splice(0, 1);
-              items.recentDismissals[dismissal.notificationId] = Date.now();
-              doProcessDismissals();
-            } else {
-              onFinish(false);
-            }
-          });
-    }
+          // Send dismissal for the first card, and if successful, repeat
+          // recursively with the rest.
+          var dismissal = items.pendingDismissals[0];
+          requestCardDismissal(
+              dismissal.notificationId,
+              dismissal.time,
+              dismissal.parameters,
+              function(done) {
+                if (done) {
+                  dismissalsChanged = true;
+                  items.pendingDismissals.splice(0, 1);
+                  items.recentDismissals[dismissal.notificationId] = Date.now();
+                  doProcessDismissals();
+                } else {
+                  onFinish(false);
+                }
+              });
+        }
 
-    doProcessDismissals();
-  });
+        doProcessDismissals();
+      });
 }
 
 /**
@@ -569,7 +578,7 @@
  *     the clicked area from the button action URLs info.
  */
 function onNotificationClicked(notificationId, selector) {
-  storage.get('notificationsData', function(items) {
+  instrumented.storage.local.get('notificationsData', function(items) {
     items.notificationsData = items.notificationsData || {};
 
     var notificationData = items.notificationsData[notificationId];
@@ -590,7 +599,7 @@
     if (typeof url != 'string')
       return;
 
-    chrome.tabs.create({url: url}, function(tab) {
+    instrumented.tabs.create({url: url}, function(tab) {
       if (!tab)
         chrome.windows.create({url: url});
     });
@@ -602,11 +611,11 @@
  * @param {number} buttonIndex The index of the button which was clicked.
  */
 function onToastNotificationClicked(buttonIndex) {
-  storage.set({userRespondedToToast: true});
+  chrome.storage.local.set({userRespondedToToast: true});
 
   if (buttonIndex == ToastButtonIndex.YES) {
     chrome.metricsPrivate.recordUserAction('GoogleNow.WelcomeToastClickedYes');
-    googleGeolocationAccessEnabledPref.set({value: true});
+    chrome.preferencesPrivate.googleGeolocationAccessEnabled.set({value: true});
     // The googlegeolocationaccessenabled preference change callback
     // will take care of starting the poll for cards.
   } else {
@@ -628,7 +637,7 @@
     // Even though they only closed the notification without clicking no, treat
     // it as though they clicked No anwyay, and don't show the toast again.
     chrome.metricsPrivate.recordUserAction('GoogleNow.WelcomeToastDismissed');
-    storage.set({userRespondedToToast: true});
+    chrome.storage.local.set({userRespondedToToast: true});
     return;
   }
 
@@ -643,21 +652,23 @@
     cardSet.clear(notificationId);
 
     tasks.debugSetStepName('onNotificationClosed-storage-get');
-    storage.get(['pendingDismissals', 'notificationsData'], function(items) {
-      items.pendingDismissals = items.pendingDismissals || [];
-      items.notificationsData = items.notificationsData || {};
+    instrumented.storage.local.get(['pendingDismissals', 'notificationsData'],
+        function(items) {
+          items.pendingDismissals = items.pendingDismissals || [];
+          items.notificationsData = items.notificationsData || {};
 
-      var notificationData = items.notificationsData[notificationId];
+          var notificationData = items.notificationsData[notificationId];
 
-      var dismissal = {
-        notificationId: notificationId,
-        time: Date.now(),
-        parameters: notificationData && notificationData.dismissalParameters
-      };
-      items.pendingDismissals.push(dismissal);
-      storage.set({pendingDismissals: items.pendingDismissals});
-      processPendingDismissals(function(success) { callback(); });
-    });
+          var dismissal = {
+            notificationId: notificationId,
+            time: Date.now(),
+            parameters: notificationData && notificationData.dismissalParameters
+          };
+          items.pendingDismissals.push(dismissal);
+          chrome.storage.local.set(
+              {pendingDismissals: items.pendingDismissals});
+          processPendingDismissals(function(success) { callback(); });
+        });
   });
 }
 
@@ -714,6 +725,9 @@
         startPollingCards();
       else
         stopPollingCards();
+    } else {
+      console.log(
+          'Action Ignored setShouldPollCards=' + shouldPollCardsRequest);
     }
     callback();
   });
@@ -728,7 +742,7 @@
 function setToastVisible(visibleRequest, callback) {
   tasks.debugSetStepName(
       'setToastVisible-shouldSetToastVisible-getAllNotifications');
-  chrome.notifications.getAll(function(notifications) {
+  instrumented.notifications.getAll(function(notifications) {
     // TODO(vadimt): Figure out what to do when notifications are disabled for
     // our extension.
     notifications = notifications || {};
@@ -739,6 +753,8 @@
         showWelcomeToast();
       else
         hideWelcomeToast();
+    } else {
+      console.log('Action Ignored setToastVisible=' + visibleRequest);
     }
 
     callback();
@@ -775,7 +791,7 @@
         // If the user enabled geolocation independently of Google Now,
         // the user has implicitly responded to the toast.
         // We do not want to show it again.
-        storage.set({userRespondedToToast: true});
+        chrome.storage.local.set({userRespondedToToast: true});
       }
 
       shouldPollCards = true;
@@ -810,19 +826,24 @@
       var signedIn = !!token && !!NOTIFICATION_CARDS_URL;
       tasks.debugSetStepName(
           'onStateChange-get-googleGeolocationAccessEnabledPref');
-      googleGeolocationAccessEnabledPref.get({}, function(prefValue) {
-        var geolocationEnabled = !!prefValue.value;
-        tasks.debugSetStepName(
-          'onStateChange-get-userRespondedToToast');
-        storage.get('userRespondedToToast', function(items) {
-          var userRespondedToToast = !!items.userRespondedToToast;
-          updateRunningState(
-              signedIn,
-              geolocationEnabled,
-              userRespondedToToast,
-              callback);
-        });
-      });
+      instrumented.
+          preferencesPrivate.
+          googleGeolocationAccessEnabled.
+          get({}, function(prefValue) {
+            var geolocationEnabled = !!prefValue.value;
+            tasks.debugSetStepName(
+              'onStateChange-get-userRespondedToToast');
+            instrumented.storage.local.get(
+                'userRespondedToToast',
+                function(items) {
+                  var userRespondedToToast = !!items.userRespondedToToast;
+                  updateRunningState(
+                      signedIn,
+                      geolocationEnabled,
+                      userRespondedToToast,
+                      callback);
+                });
+          });
     });
   });
 }
@@ -845,7 +866,7 @@
     priority: 2,
     buttons: buttons
   };
-  chrome.notifications.create(WELCOME_TOAST_NOTIFICATION_ID, options,
+  instrumented.notifications.create(WELCOME_TOAST_NOTIFICATION_ID, options,
       function(notificationId) {});
 }
 
@@ -858,21 +879,26 @@
       function() {});
 }
 
-chrome.runtime.onInstalled.addListener(function(details) {
+instrumented.runtime.onInstalled.addListener(function(details) {
   console.log('onInstalled ' + JSON.stringify(details));
   if (details.reason != 'chrome_update') {
     initialize();
   }
 });
 
-chrome.runtime.onStartup.addListener(function() {
+instrumented.runtime.onStartup.addListener(function() {
   console.log('onStartup');
   initialize();
 });
 
-googleGeolocationAccessEnabledPref.onChange.addListener(function(prefValue) {
-  console.log('googleGeolocationAccessEnabledPref onChange ' + prefValue.value);
-  onStateChange();
+instrumented.
+    preferencesPrivate.
+    googleGeolocationAccessEnabled.
+    onChange.
+    addListener(function(prefValue) {
+      console.log('googleGeolocationAccessEnabled Pref onChange ' +
+          prefValue.value);
+      onStateChange();
 });
 
 authenticationManager.addListener(function() {
@@ -880,7 +906,7 @@
   onStateChange();
 });
 
-chrome.notifications.onClicked.addListener(
+instrumented.notifications.onClicked.addListener(
     function(notificationId) {
       chrome.metricsPrivate.recordUserAction('GoogleNow.MessageClicked');
       onNotificationClicked(notificationId, function(actionUrls) {
@@ -888,7 +914,7 @@
       });
     });
 
-chrome.notifications.onButtonClicked.addListener(
+instrumented.notifications.onButtonClicked.addListener(
     function(notificationId, buttonIndex) {
       if (notificationId == WELCOME_TOAST_NOTIFICATION_ID) {
         onToastNotificationClicked(buttonIndex);
@@ -904,14 +930,14 @@
       }
     });
 
-chrome.notifications.onClosed.addListener(onNotificationClosed);
+instrumented.notifications.onClosed.addListener(onNotificationClosed);
 
-chrome.location.onLocationUpdate.addListener(function(position) {
+instrumented.location.onLocationUpdate.addListener(function(position) {
   recordEvent(GoogleNowEvent.LOCATION_UPDATE);
   updateNotificationsCards(position);
 });
 
-chrome.omnibox.onInputEntered.addListener(function(text) {
+instrumented.omnibox.onInputEntered.addListener(function(text) {
   localStorage['server_url'] = NOTIFICATION_CARDS_URL = text;
   initialize();
 });
diff --git a/chrome/browser/resources/google_now/background_test_util.js b/chrome/browser/resources/google_now/background_test_util.js
index 3e52dd7..3d59e0f 100644
--- a/chrome/browser/resources/google_now/background_test_util.js
+++ b/chrome/browser/resources/google_now/background_test_util.js
@@ -9,7 +9,7 @@
 function buildTaskManager() {
   return {
     debugSetStepName: emptyMock,
-    instrumentApiFunction: emptyMock,
+    instrumentChromeApiFunction: emptyMock,
   };
 }
 
@@ -23,21 +23,21 @@
 var buildAttemptManager = emptyMock;
 var buildCardSet = emptyMock;
 var emptyListener = {addListener: emptyMock};
-chrome['location'] = {onLocationUpdate: emptyListener};
-chrome['notifications'] = {
+var instrumented = {};
+instrumented['location'] = {onLocationUpdate: emptyListener};
+instrumented['notifications'] = {
   onButtonClicked: emptyListener,
   onClicked: emptyListener,
   onClosed: emptyListener
 };
-chrome['omnibox'] = {onInputEntered: emptyListener};
-chrome['preferencesPrivate'] = {
+instrumented['omnibox'] = {onInputEntered: emptyListener};
+instrumented['preferencesPrivate'] = {
   googleGeolocationAccessEnabled: {
     onChange: emptyListener
   }
 };
-chrome['runtime'] = {
+instrumented['runtime'] = {
   onInstalled: emptyListener,
   onStartup: emptyListener
 };
 
-var storage = {};
diff --git a/chrome/browser/resources/google_now/background_unittest.gtestjs b/chrome/browser/resources/google_now/background_unittest.gtestjs
index 5ad7050..a99ff5f 100644
--- a/chrome/browser/resources/google_now/background_unittest.gtestjs
+++ b/chrome/browser/resources/google_now/background_unittest.gtestjs
@@ -61,10 +61,10 @@
   fixture.makeAndRegisterMockApis([
     'authenticationManager.isSignedIn',
     'chrome.location.clearWatch',
-    'chrome.notifications.getAll',
-    'chrome.preferencesPrivate.googleGeolocationAccessEnabled.get',
-    'storage.get',
-    'storage.set',
+    'chrome.storage.local.set',
+    'instrumented.notifications.getAll',
+    'instrumented.preferencesPrivate.googleGeolocationAccessEnabled.get',
+    'instrumented.storage.local.get',
     'tasks.add',
     'updateCardsAttempts.isRunning',
     'updateCardsAttempts.stop'
@@ -99,7 +99,7 @@
 
   var googleGeolocationPrefGetSavedArgs = new SaveMockArguments();
   mockApisObj.expects(once()).
-      chrome_preferencesPrivate_googleGeolocationAccessEnabled_get(
+      instrumented_preferencesPrivate_googleGeolocationAccessEnabled_get(
           googleGeolocationPrefGetSavedArgs.match(eqJSON({})),
           googleGeolocationPrefGetSavedArgs.match(ANYTHING)).
       will(invokeCallback(
@@ -107,7 +107,7 @@
 
   var storageGetSavedArgs = new SaveMockArguments();
   mockApisObj.expects(once()).
-      storage_get(
+      instrumented_storage_local_get(
           storageGetSavedArgs.match(eq('userRespondedToToast')),
           storageGetSavedArgs.match(ANYTHING)).
       will(invokeCallback(storageGetSavedArgs, 1, testUserRespondedToToast));
@@ -126,7 +126,7 @@
   mockApisObj.expects(once()).
       updateCardsAttempts_stop();
   mockApisObj.expects(once()).
-      storage_set(eqJSON({notificationsData: {}}));
+      chrome_storage_local_set(eqJSON({notificationsData: {}}));
   var tasksAddSavedArgs = new SaveMockArguments();
   mockApisObj.expects(once()).
       tasks_add(
@@ -174,7 +174,7 @@
 
       var chromeNotificationGetAllSavedArgs = new SaveMockArguments();
       this.mockApis.expects(exactly(2)).
-          chrome_notifications_getAll(
+          instrumented_notifications_getAll(
               chromeNotificationGetAllSavedArgs.match(ANYTHING)).
           will(
               invokeCallback(chromeNotificationGetAllSavedArgs, 0, {}),
@@ -218,7 +218,7 @@
 
       var chromeNotificationGetAllSavedArgs = new SaveMockArguments();
       this.mockApis.expects(exactly(2)).
-          chrome_notifications_getAll(
+          instrumented_notifications_getAll(
               chromeNotificationGetAllSavedArgs.match(ANYTHING)).
           will(
               invokeCallback(chromeNotificationGetAllSavedArgs, 0, {}),
@@ -257,7 +257,7 @@
 
       var chromeNotificationGetAllSavedArgs = new SaveMockArguments();
       this.mockApis.expects(exactly(2)).
-          chrome_notifications_getAll(
+          instrumented_notifications_getAll(
               chromeNotificationGetAllSavedArgs.match(ANYTHING)).
           will(
               invokeCallback(chromeNotificationGetAllSavedArgs, 0, {}),
@@ -294,7 +294,7 @@
 
   var chromeNotificationGetAllSavedArgs = new SaveMockArguments();
   this.mockApis.expects(exactly(2)).
-      chrome_notifications_getAll(
+      instrumented_notifications_getAll(
           chromeNotificationGetAllSavedArgs.match(ANYTHING)).
       will(
           invokeCallback(chromeNotificationGetAllSavedArgs, 0, {}),
@@ -334,7 +334,7 @@
 
   var chromeNotificationGetAllSavedArgs = new SaveMockArguments();
   this.mockApis.expects(exactly(2)).
-      chrome_notifications_getAll(
+      instrumented_notifications_getAll(
           chromeNotificationGetAllSavedArgs.match(ANYTHING)).
       will(
           invokeCallback(chromeNotificationGetAllSavedArgs, 0, {}),
@@ -350,9 +350,9 @@
  */
 function mockOnNotificationClickedDependencies(fixture) {
   fixture.makeAndRegisterMockApis([
-      'storage.get',
-      'chrome.tabs.create',
-      'chrome.windows.create']);
+      'chrome.windows.create',
+      'instrumented.storage.local.get',
+      'instrumented.tabs.create']);
 }
 
 TEST_F(
@@ -371,7 +371,7 @@
 
       var storageGetSavedArgs = new SaveMockArguments();
       this.mockApis.expects(once()).
-          storage_get(
+          instrumented_storage_local_get(
               storageGetSavedArgs.match(eq('notificationsData')),
               storageGetSavedArgs.match(ANYTHING)).
           will(invokeCallback(storageGetSavedArgs, 1, testNotificationData));
@@ -401,7 +401,7 @@
 
       var storageGetSavedArgs = new SaveMockArguments();
       this.mockApis.expects(once()).
-          storage_get(
+          instrumented_storage_local_get(
               storageGetSavedArgs.match(eq('notificationsData')),
               storageGetSavedArgs.match(ANYTHING)).
           will(invokeCallback(storageGetSavedArgs, 1, testNotificationData));
@@ -432,7 +432,7 @@
 
       var storageGetSavedArgs = new SaveMockArguments();
       this.mockApis.expects(once()).
-          storage_get(
+          instrumented_storage_local_get(
               storageGetSavedArgs.match(eq('notificationsData')),
               storageGetSavedArgs.match(ANYTHING)).
           will(invokeCallback(storageGetSavedArgs, 1, testNotificationData));
@@ -464,7 +464,7 @@
 
       var storageGetSavedArgs = new SaveMockArguments();
       this.mockApis.expects(once()).
-          storage_get(
+          instrumented_storage_local_get(
               storageGetSavedArgs.match(eq('notificationsData')),
               storageGetSavedArgs.match(ANYTHING)).
           will(invokeCallback(storageGetSavedArgs, 1, testNotificationData));
@@ -472,7 +472,7 @@
           returnValue(testActionUrl));
       var chromeTabsCreateSavedArgs = new SaveMockArguments();
       this.mockApis.expects(once()).
-          chrome_tabs_create(
+          instrumented_tabs_create(
               chromeTabsCreateSavedArgs.match(eqJSON({url: testActionUrl})),
               chromeTabsCreateSavedArgs.match(ANYTHING)).
           will(invokeCallback(chromeTabsCreateSavedArgs, 1, testCreatedTab));
@@ -504,7 +504,7 @@
 
       var storageGetSavedArgs = new SaveMockArguments();
       this.mockApis.expects(once()).
-          storage_get(
+          instrumented_storage_local_get(
               storageGetSavedArgs.match(eq('notificationsData')),
               storageGetSavedArgs.match(ANYTHING)).
           will(invokeCallback(storageGetSavedArgs, 1, testNotificationData));
@@ -512,7 +512,7 @@
           returnValue(testActionUrl));
       var chromeTabsCreateSavedArgs = new SaveMockArguments();
       this.mockApis.expects(once()).
-          chrome_tabs_create(
+          instrumented_tabs_create(
               chromeTabsCreateSavedArgs.match(eqJSON({url: testActionUrl})),
               chromeTabsCreateSavedArgs.match(ANYTHING)).
           will(invokeCallback(chromeTabsCreateSavedArgs, 1, testCreatedTab));
diff --git a/chrome/browser/resources/google_now/cards.js b/chrome/browser/resources/google_now/cards.js
index 09ca6e1..5e24819 100644
--- a/chrome/browser/resources/google_now/cards.js
+++ b/chrome/browser/resources/google_now/cards.js
@@ -43,7 +43,7 @@
       try {
         // Delete a notification with the specified id if it already exists, and
         // then create a notification.
-        chrome.notifications.create(
+        instrumented.notifications.create(
             cardId,
             cardCreateInfo.notification,
             function(newNotificationId) {
@@ -63,7 +63,7 @@
     } else {
       try {
         // Update existing notification.
-        chrome.notifications.update(
+        instrumented.notifications.update(
             cardId,
             cardCreateInfo.notification,
             function(wasUpdated) {
@@ -147,13 +147,13 @@
     chrome.alarms.clear(cardHidePrefix + cardId);
   }
 
-  chrome.alarms.onAlarm.addListener(function(alarm) {
+  instrumented.alarms.onAlarm.addListener(function(alarm) {
     console.log('cardManager.onAlarm ' + JSON.stringify(alarm));
 
     if (alarm.name.indexOf(cardShowPrefix) == 0) {
       // Alarm to show the card.
       var cardId = alarm.name.substring(cardShowPrefix.length);
-      storage.get('notificationsData', function(items) {
+      instrumented.storage.local.get('notificationsData', function(items) {
         items.notificationsData = items.notificationsData || {};
         console.log('cardManager.onAlarm.get ' + JSON.stringify(items));
         var notificationData = items.notificationsData[cardId];
diff --git a/chrome/browser/resources/google_now/cards_unittest.gtestjs b/chrome/browser/resources/google_now/cards_unittest.gtestjs
index 01cb789..50375c4 100644
--- a/chrome/browser/resources/google_now/cards_unittest.gtestjs
+++ b/chrome/browser/resources/google_now/cards_unittest.gtestjs
@@ -29,20 +29,20 @@
 
 function setUpCardManagerTest(fixture) {
   fixture.makeAndRegisterMockApis([
-      'chrome.alarms.onAlarm.addListener',
       'chrome.alarms.clear',
       'chrome.alarms.create',
       'chrome.notifications.clear',
-      'chrome.notifications.create',
-      'chrome.notifications.update',
-      'storage.get'
+      'instrumented.alarms.onAlarm.addListener',
+      'instrumented.notifications.create',
+      'instrumented.notifications.update',
+      'instrumented.storage.local.get'
   ]);
 
   chrome.runtime = {}; // No error.
 
   var onAlarmSavedArgs = new SaveMockArguments();
   fixture.mockApis.expects(once()).
-      chrome_alarms_onAlarm_addListener(
+      instrumented_alarms_onAlarm_addListener(
           onAlarmSavedArgs.match(ANYTHING));
 
   var cardSet = buildCardSet();
@@ -78,7 +78,7 @@
       chrome_alarms_clear(expectedShowAlarmId);
   var chromeNotificationsCreateSavedArgs = new SaveMockArguments();
   this.mockApis.expects(once()).
-      chrome_notifications_create(
+      instrumented_notifications_create(
           chromeNotificationsCreateSavedArgs.match(eq(testCardId)),
           chromeNotificationsCreateSavedArgs.match(eqJSON(testNotification)),
           chromeNotificationsCreateSavedArgs.match(ANYTHING)).
@@ -101,7 +101,7 @@
           timeHide: undefined,
           version: 0
         },
-        dismissalParameters: testDismissal 
+        dismissalParameters: testDismissal
       }),
     JSON.stringify(notificationData));
 });
@@ -116,7 +116,7 @@
   this.mockApis.expects(once()).
       chrome_alarms_clear(expectedShowAlarmId);
   this.mockApis.expects(once()).
-      chrome_notifications_create(
+      instrumented_notifications_create(
           testCardId, eqJSON(testNotification), ANYTHING);
 
   // Call tested method.
@@ -153,7 +153,7 @@
       chrome_alarms_clear(expectedShowAlarmId);
   var chromeNotificationsCreateSavedArgs = new SaveMockArguments();
   this.mockApis.expects(once()).
-      chrome_notifications_create(
+      instrumented_notifications_create(
           chromeNotificationsCreateSavedArgs.match(eq(testCardId)),
           chromeNotificationsCreateSavedArgs.match(eqJSON(testNotification)),
           chromeNotificationsCreateSavedArgs.match(ANYTHING)).
@@ -195,7 +195,7 @@
       chrome_alarms_clear(expectedShowAlarmId);
   var chromeNotificationsCreateSavedArgs = new SaveMockArguments();
   this.mockApis.expects(once()).
-      chrome_notifications_update(
+      instrumented_notifications_update(
           chromeNotificationsCreateSavedArgs.match(eq(testCardId)),
           chromeNotificationsCreateSavedArgs.match(eqJSON(testNotification)),
           chromeNotificationsCreateSavedArgs.match(ANYTHING)).
@@ -236,7 +236,7 @@
       chrome_alarms_clear(expectedShowAlarmId);
   var chromeNotificationsCreateSavedArgs = new SaveMockArguments();
   this.mockApis.expects(once()).
-      chrome_notifications_update(
+      instrumented_notifications_update(
           chromeNotificationsCreateSavedArgs.match(eq(testCardId)),
           chromeNotificationsCreateSavedArgs.match(eqJSON(testNotification)),
           chromeNotificationsCreateSavedArgs.match(ANYTHING)).
@@ -265,7 +265,7 @@
   this.mockApis.expects(once()).
       chrome_alarms_clear(expectedShowAlarmId);
   this.mockApis.expects(once()).
-      chrome_notifications_create(
+      instrumented_notifications_create(
           testCardId, eqJSON(testNotification), ANYTHING);
 
   // Call tested method.
@@ -288,7 +288,7 @@
   this.mockApis.expects(once()).
       chrome_alarms_clear(expectedShowAlarmId);
   this.mockApis.expects(once()).
-      chrome_notifications_create(
+      instrumented_notifications_create(
           testCardId, eqJSON(testNotification), ANYTHING);
 
   // Call tested method.
@@ -351,7 +351,7 @@
   var test = setUpCardManagerTest(this);
   var storageGetSavedArgs = new SaveMockArguments();
   this.mockApis.expects(once()).
-      storage_get(
+      instrumented_storage_local_get(
           storageGetSavedArgs.match(eq('notificationsData')),
           storageGetSavedArgs.match(ANYTHING)).
       will(invokeCallback(storageGetSavedArgs, 1, {}));
@@ -366,7 +366,7 @@
   var test = setUpCardManagerTest(this);
   var storageGetSavedArgs = new SaveMockArguments();
   this.mockApis.expects(once()).
-      storage_get(
+      instrumented_storage_local_get(
           storageGetSavedArgs.match(eq('notificationsData')),
           storageGetSavedArgs.match(ANYTHING)).
       will(invokeCallback(
@@ -382,7 +382,7 @@
                 version: 0}}}}));
   var chromeNotificationsCreateSavedArgs = new SaveMockArguments();
   this.mockApis.expects(once()).
-      chrome_notifications_create(
+      instrumented_notifications_create(
           chromeNotificationsCreateSavedArgs.match(eq(testCardId)),
           chromeNotificationsCreateSavedArgs.match(eqJSON(testNotification)),
           chromeNotificationsCreateSavedArgs.match(ANYTHING)).
@@ -400,7 +400,7 @@
   var test = setUpCardManagerTest(this);
   var storageGetSavedArgs = new SaveMockArguments();
   this.mockApis.expects(once()).
-      storage_get(
+      instrumented_storage_local_get(
           storageGetSavedArgs.match(eq('notificationsData')),
           storageGetSavedArgs.match(ANYTHING)).
       will(invokeCallback(
@@ -417,7 +417,7 @@
                 previousVersion:0}}}}));
   var chromeNotificationsCreateSavedArgs = new SaveMockArguments();
   this.mockApis.expects(once()).
-      chrome_notifications_update(
+      instrumented_notifications_update(
           testCardId, eqJSON(testNotification), ANYTHING);
 
   // Call tested method.
diff --git a/chrome/browser/resources/google_now/utility.js b/chrome/browser/resources/google_now/utility.js
index 0ab7c4b..12e9f93 100644
--- a/chrome/browser/resources/google_now/utility.js
+++ b/chrome/browser/resources/google_now/utility.js
@@ -55,6 +55,9 @@
   return request;
 }
 
+// Partial mirror of chrome.* for all instrumented functions.
+var instrumented = {};
+
 /**
  * Builds the object to manage tasks (mutually exclusive chains of events).
  * @param {function(string, string): boolean} areConflicting Function that
@@ -296,37 +299,75 @@
   }
 
   /**
-   * Instruments an API function to add error processing to its user
-   * code-provided callback.
-   * @param {Object} namespace Namespace of the API function.
-   * @param {string} functionName Name of the API function.
+   * Returns an instrumented function.
+   * @param {array} functionIdentifierParts Path to the chrome.* function.
+   * @param {string} functionName Name of the chrome API function.
    * @param {number} callbackParameter Index of the callback parameter to this
    *     API function.
+   * @return {function} An instrumented function.
    */
-  function instrumentApiFunction(namespace, functionName, callbackParameter) {
-    var originalFunction = namespace[functionName];
-
-    if (!originalFunction)
-      debugAlert('Cannot instrument ' + functionName);
-
-    namespace[functionName] = function() {
+  function createInstrumentedFunction(
+      functionIdentifierParts,
+      functionName,
+      callbackParameter) {
+    return function() {
       // This is the wrapper for the API function. Pass the wrapped callback to
       // the original function.
       var callback = arguments[callbackParameter];
       if (typeof callback != 'function') {
-        debugAlert('Argument ' + callbackParameter + ' of ' + functionName +
-              ' is not a function');
+        debugAlert('Argument ' + callbackParameter + ' of ' +
+                   functionIdentifierParts.join('.') + '.' + functionName +
+                   ' is not a function');
       }
       arguments[callbackParameter] = wrapCallback(
           callback, functionName == 'addListener');
-      return originalFunction.apply(namespace, arguments);
+
+      var chromeContainer = chrome;
+      functionIdentifierParts.map(function(fragment) {
+        chromeContainer = chromeContainer[fragment];
+      });
+      return chromeContainer[functionName].
+          apply(chromeContainer, arguments);
     };
   }
 
-  instrumentApiFunction(chrome.alarms, 'get', 1);
-  instrumentApiFunction(chrome.alarms.onAlarm, 'addListener', 0);
-  instrumentApiFunction(chrome.identity, 'getAuthToken', 1);
-  instrumentApiFunction(chrome.runtime.onSuspend, 'addListener', 0);
+  /**
+   * Instruments an API function to add error processing to its user
+   * code-provided callback.
+   * @param {string} functionIdentifier Full identifier of the function without
+   *     the 'chrome.' portion.
+   * @param {number} callbackParameter Index of the callback parameter to this
+   *     API function.
+   */
+  function instrumentChromeApiFunction(functionIdentifier, callbackParameter) {
+    var functionIdentifierParts = functionIdentifier.split('.');
+    var functionName = functionIdentifierParts.pop();
+    var chromeContainer = chrome;
+    var instrumentedContainer = instrumented;
+    functionIdentifierParts.map(function(fragment) {
+      chromeContainer = chromeContainer[fragment];
+      if (!(fragment in instrumentedContainer))
+        instrumentedContainer[fragment] = {};
+
+      instrumentedContainer = instrumentedContainer[fragment];
+    });
+
+    var targetFunction = chromeContainer[functionName];
+
+    if (!targetFunction)
+      debugAlert('Cannot instrument ' + functionName);
+
+    instrumentedContainer[functionName] = createInstrumentedFunction(
+        functionIdentifierParts,
+        functionName,
+        callbackParameter);
+  }
+
+  instrumentChromeApiFunction('alarms.get', 1);
+  instrumentChromeApiFunction('alarms.onAlarm.addListener', 0);
+  instrumentChromeApiFunction('identity.getAuthToken', 1);
+  instrumentChromeApiFunction('identity.removeCachedAuthToken', 1);
+  instrumentChromeApiFunction('runtime.onSuspend.addListener', 0);
 
   chrome.runtime.onSuspend.addListener(function() {
     var stringifiedPendingCallbacks = JSON.stringify(pendingCallbacks);
@@ -340,13 +381,11 @@
   return {
     add: add,
     debugSetStepName: function() {},  // TODO(vadimt): remove
-    instrumentApiFunction: instrumentApiFunction,
+    instrumentChromeApiFunction: instrumentChromeApiFunction,
     wrapCallback: wrapCallback
   };
 }
 
-var storage = chrome.storage.local;
-
 /**
  * Builds an object to manage retrying activities with exponential backoff.
  * @param {string} name Name of this attempt manager.
@@ -380,7 +419,7 @@
    *     true if the attempt manager has started, false otherwise.
    */
   function isRunning(callback) {
-    chrome.alarms.get(alarmName, function(alarmInfo) {
+    instrumented.alarms.get(alarmName, function(alarmInfo) {
       callback(!!alarmInfo);
     });
   }
@@ -401,7 +440,7 @@
 
     var items = {};
     items[currentDelayStorageKey] = newRetryDelaySeconds;
-    storage.set(items);
+    chrome.storage.local.set(items);
   }
 
   /**
@@ -413,7 +452,7 @@
   function start(opt_firstDelaySeconds) {
     if (opt_firstDelaySeconds) {
       createAlarm(opt_firstDelaySeconds);
-      storage.remove(currentDelayStorageKey);
+      chrome.storage.local.remove(currentDelayStorageKey);
     } else {
       scheduleNextAttempt();
     }
@@ -424,7 +463,7 @@
    */
   function stop() {
     chrome.alarms.clear(alarmName);
-    storage.remove(currentDelayStorageKey);
+    chrome.storage.local.remove(currentDelayStorageKey);
   }
 
   /**
@@ -433,14 +472,14 @@
    *     the planning is done.
    */
   function planForNext(callback) {
-    storage.get(currentDelayStorageKey, function(items) {
+    instrumented.storage.local.get(currentDelayStorageKey, function(items) {
       console.log('planForNext-get-storage ' + JSON.stringify(items));
       scheduleNextAttempt(items[currentDelayStorageKey]);
       callback();
     });
   }
 
-  chrome.alarms.onAlarm.addListener(function(alarm) {
+  instrumented.alarms.onAlarm.addListener(function(alarm) {
     if (alarm.name == alarmName)
       isRunning(function(running) {
         if (running)
@@ -474,7 +513,7 @@
    *     If the user is signed in, the string contains the token.
    */
   function isSignedIn(callback) {
-    chrome.identity.getAuthToken({interactive: false}, function(token) {
+    instrumented.identity.getAuthToken({interactive: false}, function(token) {
       token = chrome.runtime.lastError ? undefined : token;
       callback(token);
       checkAndNotifyListeners(!!token);
@@ -487,7 +526,7 @@
    * @param {function} onSuccess Called on completion.
    */
   function removeToken(token, onSuccess) {
-    chrome.identity.removeCachedAuthToken({token: token}, function() {
+    instrumented.identity.removeCachedAuthToken({token: token}, function() {
       // Removing the token from the cache will change the sign in state.
       // Repoll now to check the state and notify listeners.
       // This also lets Chrome now about a possible problem with the token.
@@ -522,7 +561,7 @@
     lastReturnedSignedInState = currentSignedInState;
   }
 
-  chrome.alarms.onAlarm.addListener(function(alarm) {
+  instrumented.alarms.onAlarm.addListener(function(alarm) {
     if (alarm.name == alarmName)
       isSignedIn(function() {});
   });
diff --git a/chrome/browser/resources/history/history.css b/chrome/browser/resources/history/history.css
index c929298..61bddb3 100644
--- a/chrome/browser/resources/history/history.css
+++ b/chrome/browser/resources/history/history.css
@@ -352,6 +352,7 @@
   text-align: right;
   text-overflow: ellipsis;
   white-space: nowrap;
+  width: 60px;
 }
 
 html[dir='rtl'] .entry .time {
diff --git a/chrome/browser/resources/history/history.js b/chrome/browser/resources/history/history.js
index 1f688e5..1227c99 100644
--- a/chrome/browser/resources/history/history.js
+++ b/chrome/browser/resources/history/history.js
@@ -17,6 +17,9 @@
 // with IDs greater than this will be included in this bucket.
 /** @const */ var UMA_MAX_BUCKET_VALUE = 1000;
 
+// The largest bucket value for a UMA histogram that is a subset of above.
+/** @const */ var UMA_MAX_SUBSET_BUCKET_VALUE = 100;
+
 // TODO(glen): Get rid of these global references, replace with a controller
 //     or just make the classes own more of the page.
 var historyModel;
@@ -62,14 +65,15 @@
  * Record a histogram value in UMA. If specified value is larger than the max
  * bucket value, record the value in the largest bucket.
  * @param {string} histogram The name of the histogram to be recorded in.
+ * @param {integer} maxBucketValue The max value for the last histogram bucket.
  * @param {integer} value The value to record in the histogram.
  */
 
-function recordUmaHistogram(histogram, value) {
+function recordUmaHistogram(histogram, maxBucketValue, value) {
   chrome.send('metricsHandler:recordInHistogram',
               [histogram,
-              ((value > UMA_MAX_BUCKET_VALUE) ? UMA_MAX_BUCKET_VALUE : value),
-              UMA_MAX_BUCKET_VALUE]);
+              ((value > maxBucketValue) ? maxBucketValue : value),
+              maxBucketValue]);
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -343,7 +347,14 @@
     recordUmaAction('HistoryPage_EntryLinkClick');
     // Record the ID of the entry to signify how many entries are above this
     // link on the page.
-    recordUmaHistogram('HistoryPage.ClickPosition', integerId);
+    recordUmaHistogram('HistoryPage.ClickPosition',
+                       UMA_MAX_BUCKET_VALUE,
+                       integerId);
+    if (integerId <= UMA_MAX_SUBSET_BUCKET_VALUE) {
+      recordUmaHistogram('HistoryPage.ClickPositionSubset',
+                         UMA_MAX_SUBSET_BUCKET_VALUE,
+                         integerId);
+    }
   });
   link.addEventListener('contextmenu', function() {
     recordUmaAction('HistoryPage_EntryLinkRightClick');
@@ -1508,6 +1519,9 @@
     });
   }
 
+  if (!loadTimeData.getBoolean('showDeleteVisitUI'))
+    $('remove-visit').hidden = true;
+
   searchField.addEventListener('search', doSearch);
   $('search-button').addEventListener('click', doSearch);
 
@@ -1658,7 +1672,14 @@
     var integerId = parseInt(entry.visit.id_, 10);
     // Record the ID of the entry to signify how many entries are above this
     // link on the page.
-    recordUmaHistogram('HistoryPage.RemoveEntryPosition', integerId);
+    recordUmaHistogram('HistoryPage.RemoveEntryPosition',
+                       UMA_MAX_BUCKET_VALUE,
+                       integerId);
+    if (integerId <= UMA_MAX_SUBSET_BUCKET_VALUE) {
+      recordUmaHistogram('HistoryPage.RemoveEntryPositionSubset',
+                         UMA_MAX_SUBSET_BUCKET_VALUE,
+                         integerId);
+    }
     if (entry.parentNode.className == 'search-results')
       recordUmaAction('HistoryPage_SearchResultRemove');
   }
diff --git a/chrome/browser/resources/history/history_focus_manager.js b/chrome/browser/resources/history/history_focus_manager.js
index 540f331..2d01f5c 100644
--- a/chrome/browser/resources/history/history_focus_manager.js
+++ b/chrome/browser/resources/history/history_focus_manager.js
@@ -20,6 +20,8 @@
 
   /** @override */
   getFocusParent: function() {
-    return document.querySelector('#overlay .showing') || $('history-page');
+    return document.querySelector('#overlay .showing') ||
+        document.querySelector('menu:not([hidden])') ||
+        $('history-page');
   },
 };
diff --git a/chrome/browser/resources/history/history_mobile.css b/chrome/browser/resources/history/history_mobile.css
index dc7681f..41268f5 100644
--- a/chrome/browser/resources/history/history_mobile.css
+++ b/chrome/browser/resources/history/history_mobile.css
@@ -52,7 +52,7 @@
   -webkit-padding-start: 64px;
   background-image:
       url('../../../../ui/webui/resources/images/2x/search.png');
-  background-position: left 16px center;
+  background-position: 16px center;
   background-repeat: no-repeat;
   background-size: 32px;
   border: 0;
@@ -242,6 +242,13 @@
   display: none;
 }
 
+.entry .time {
+  line-height: 60px;
+  min-width: 90px;
+  text-align: inherit;
+  width: 90px;
+}
+
 @media only screen and (max-width:600px) {
 
 /* Omit the time on very small screens. */
diff --git a/chrome/browser/resources/local_ntp/local_ntp.css b/chrome/browser/resources/local_ntp/local_ntp.css
index 8c1dec4..14d5275 100644
--- a/chrome/browser/resources/local_ntp/local_ntp.css
+++ b/chrome/browser/resources/local_ntp/local_ntp.css
@@ -108,6 +108,11 @@
     opacity: 0;
   }
 }
+
+body.fakebox-drag-focused #cursor {
+  visibility: inherit;
+}
+
 body.fakebox-focused #cursor {
   -webkit-animation: blink 1.3s step-end infinite;
   visibility: inherit;
diff --git a/chrome/browser/resources/local_ntp/local_ntp.js b/chrome/browser/resources/local_ntp/local_ntp.js
index ab514df..b387819 100644
--- a/chrome/browser/resources/local_ntp/local_ntp.js
+++ b/chrome/browser/resources/local_ntp/local_ntp.js
@@ -28,6 +28,8 @@
   DELAYED_HIDE_NOTIFICATION: 'mv-notice-delayed-hide',
   FAKEBOX_DISABLE: 'fakebox-disable', // Makes fakebox non-interactive
   FAKEBOX_FOCUS: 'fakebox-focused', // Applies focus styles to the fakebox
+  // Applies drag focus style to the fakebox
+  FAKEBOX_DRAG_FOCUS: 'fakebox-drag-focused',
   FAVICON: 'mv-favicon',
   HIDE_BLACKLIST_BUTTON: 'mv-x-hide', // hides blacklist button during animation
   HIDE_FAKEBOX_AND_LOGO: 'hide-fakebox-logo',
@@ -55,6 +57,7 @@
   ATTRIBUTION_TEXT: 'attribution-text',
   CUSTOM_THEME_STYLE: 'ct-style',
   FAKEBOX: 'fakebox',
+  FAKEBOX_INPUT: 'fakebox-input',
   LOGO: 'logo',
   NOTIFICATION: 'mv-notice',
   NOTIFICATION_CLOSE_BUTTON: 'mv-notice-x',
@@ -770,6 +773,7 @@
 function onInputStart() {
   if (fakebox && isFakeboxFocused()) {
     setFakeboxFocus(false);
+    setFakeboxDragFocus(false);
     disposeNtp(true);
   } else if (!isFakeboxFocused()) {
     disposeNtp(false);
@@ -806,12 +810,19 @@
   document.body.classList.toggle(CLASSES.FAKEBOX_FOCUS, focus);
 }
 
+/**
+ * @param {boolean} focus True to show a dragging focus to the fakebox.
+ */
+function setFakeboxDragFocus(focus) {
+  document.body.classList.toggle(CLASSES.FAKEBOX_DRAG_FOCUS, focus);
+}
 
 /**
  * @return {boolean} True if the fakebox has focus.
  */
 function isFakeboxFocused() {
-  return document.body.classList.contains(CLASSES.FAKEBOX_FOCUS);
+  return document.body.classList.contains(CLASSES.FAKEBOX_FOCUS) ||
+      document.body.classList.contains(CLASSES.FAKEBOX_DRAG_FOCUS);
 }
 
 
@@ -947,7 +958,8 @@
     fakebox = document.createElement('div');
     fakebox.id = IDS.FAKEBOX;
     fakebox.innerHTML =
-        '<input autocomplete="off" tabindex="-1" aria-hidden="true">' +
+        '<input id="' + IDS.FAKEBOX_INPUT +
+            '" autocomplete="off" tabindex="-1" aria-hidden="true">' +
         '<div id=cursor></div>';
 
     ntpContents.insertBefore(fakebox, ntpContents.firstChild);
@@ -1011,7 +1023,7 @@
 
   if (fakebox) {
     // Listener for updating the key capture state.
-    document.body.onclick = function(event) {
+    document.body.onmousedown = function(event) {
       if (isFakeboxClick(event))
         searchboxApiHandle.startCapturingKeyStrokes();
       else if (isFakeboxFocused())
@@ -1020,6 +1032,26 @@
     searchboxApiHandle.onkeycapturechange = function() {
       setFakeboxFocus(searchboxApiHandle.isKeyCaptureEnabled);
     };
+    var inputbox = $(IDS.FAKEBOX_INPUT);
+    if (inputbox) {
+      inputbox.onpaste = function(event) {
+        event.preventDefault();
+        searchboxApiHandle.paste();
+      };
+      inputbox.ondrop = function(event) {
+        event.preventDefault();
+        var text = event.dataTransfer.getData('text/plain');
+        if (text) {
+          searchboxApiHandle.paste(text);
+        }
+      };
+      inputbox.ondragenter = function() {
+        setFakeboxDragFocus(true);
+      };
+      inputbox.ondragleave = function() {
+        setFakeboxDragFocus(false);
+      };
+    }
   }
 
   if (searchboxApiHandle.rtl) {
diff --git a/chrome/browser/resources/managed_mode_block_interstitial.js b/chrome/browser/resources/managed_mode_block_interstitial.js
index f6d1049..313ba6e 100644
--- a/chrome/browser/resources/managed_mode_block_interstitial.js
+++ b/chrome/browser/resources/managed_mode_block_interstitial.js
@@ -8,10 +8,14 @@
 }
 
 function initialize() {
-  $('request-access-button').onclick = function(event) {
-    updateAfterRequestSent();
-    sendCommand('request');
-  };
+  if (loadTimeData.getBoolean('allowAccessRequests')) {
+    $('request-access-button').onclick = function(event) {
+      updateAfterRequestSent();
+      sendCommand('request');
+    };
+  } else {
+    $('request-access-button').hidden = true;
+  }
   $('back-button').onclick = function(event) {
     sendCommand('back');
   };
diff --git a/chrome/browser/resources/net_internals/quic_view.html b/chrome/browser/resources/net_internals/quic_view.html
index 3f4a4b8..b40cedd 100644
--- a/chrome/browser/resources/net_internals/quic_view.html
+++ b/chrome/browser/resources/net_internals/quic_view.html
@@ -15,6 +15,7 @@
           <thead>
             <tr>
               <th>Host</th>
+              <th>Version</th>
               <th>Peer address</th>
               <th>GUID</th>
               <th>Active streams</th>
@@ -26,6 +27,7 @@
               <td><span jscontent="host_port_pair"></span>
                 <span jscontent="$this.aliases ? $this.aliases.join(' ') : ''"></span>
               </td>
+              <td jscontent="version"></td>
               <td jscontent="peer_address"></td>
               <td jscontent="guid"></td>
               <td jscontent="open_streams"></td>
diff --git a/chrome/browser/resources/options/browser_options.js b/chrome/browser/resources/options/browser_options.js
index 70830b0..e2e80fd 100644
--- a/chrome/browser/resources/options/browser_options.js
+++ b/chrome/browser/resources/options/browser_options.js
@@ -178,7 +178,9 @@
         options.browser_options.ProfileList.decorate(profilesList);
         profilesList.autoExpands = true;
 
+        // The profiles info data in |loadTimeData| might be stale.
         this.setProfilesInfo_(loadTimeData.getValue('profilesInfo'));
+        chrome.send('requestProfilesInfo');
 
         profilesList.addEventListener('change',
             this.setProfileViewButtonsStatus_);
diff --git a/chrome/browser/resources/options/chromeos/internet_detail.js b/chrome/browser/resources/options/chromeos/internet_detail.js
index 45cc551..c3a8f36 100644
--- a/chrome/browser/resources/options/chromeos/internet_detail.js
+++ b/chrome/browser/resources/options/chromeos/internet_detail.js
@@ -820,7 +820,9 @@
     if (data.type != Constants.TYPE_ETHERNET)
       $('details-internet-disconnect').hidden = !data.connected;
 
-    if (data.type == Constants.TYPE_WIMAX)
+    if (data.type == Constants.TYPE_WIMAX ||
+        data.type == Constants.TYPE_WIFI ||
+        data.type == Constants.TYPE_VPN)
       $('details-internet-configure').hidden = false;
     else
       $('details-internet-configure').hidden = true;
@@ -879,7 +881,9 @@
       $('details-internet-disconnect').hidden = true;
     else
       $('details-internet-disconnect').hidden = !data.connected;
-    if (data.type == Constants.TYPE_WIMAX)
+    if (data.type == Constants.TYPE_WIMAX ||
+        data.type == Constants.TYPE_WIFI ||
+        data.type == Constants.TYPE_VPN)
       $('details-internet-configure').hidden = false;
     else
       $('details-internet-configure').hidden = true;
diff --git a/chrome/browser/resources/options/clear_browser_data_overlay.html b/chrome/browser/resources/options/clear_browser_data_overlay.html
index 1c386d4..cde999e 100644
--- a/chrome/browser/resources/options/clear_browser_data_overlay.html
+++ b/chrome/browser/resources/options/clear_browser_data_overlay.html
@@ -12,21 +12,21 @@
         data-type="number">
     </select>
     <div id="clear-data-checkboxes">
-      <div class="checkbox">
+      <div id="delete-browsing-history-container" class="checkbox">
         <label>
           <input id="delete-browsing-history-checkbox"
               pref="browser.clear_data.browsing_history" type="checkbox">
           <span i18n-content="deleteBrowsingHistoryCheckbox"></span>
         </label>
       </div>
-      <div class="checkbox">
+      <div id="delete-download-history-container" class="checkbox">
         <label>
           <input id="delete-download-history-checkbox"
               pref="browser.clear_data.download_history" type="checkbox">
           <span i18n-content="deleteDownloadHistoryCheckbox"></span>
         </label>
       </div>
-      <div class="checkbox">
+      <div id="delete-cookies-container" class="checkbox">
         <label>
           <input id="delete-cookies-checkbox"
               pref="browser.clear_data.cookies" type="checkbox">
@@ -36,35 +36,36 @@
               class="clear-plugin-lso-data-disabled"></span>
         </label>
       </div>
-      <div class="checkbox">
+      <div id="delete-cache-container" class="checkbox">
         <label>
           <input id="delete-cache-checkbox"
               pref="browser.clear_data.cache" type="checkbox">
           <span i18n-content="deleteCacheCheckbox"></span>
         </label>
       </div>
-      <div class="checkbox">
+      <div id="delete-passwords-container" class="checkbox">
         <label>
           <input id="delete-passwords-checkbox"
               pref="browser.clear_data.passwords" type="checkbox">
           <span i18n-content="deletePasswordsCheckbox"></span>
         </label>
       </div>
-      <div class="checkbox">
+      <div id="delete-form-data-container" class="checkbox">
         <label>
           <input id="delete-form-data-checkbox"
               pref="browser.clear_data.form_data" type="checkbox">
           <span i18n-content="deleteFormDataCheckbox"></span>
         </label>
       </div>
-      <div class="checkbox">
+      <div id="delete-hosted-apps-data-container" class="checkbox">
         <label>
           <input id="delete-hosted-apps-data-checkbox"
               pref="browser.clear_data.hosted_apps_data" type="checkbox">
           <span i18n-content="deleteHostedAppsDataCheckbox"></span>
         </label>
       </div>
-      <div class="checkbox pepper-flash-settings">
+      <div id="deauthorize-content-licenses-container"
+          class="checkbox pepper-flash-settings">
         <label>
           <input id="deauthorize-content-licenses-checkbox"
               pref="browser.clear_data.content_licenses" type="checkbox">
diff --git a/chrome/browser/resources/options/clear_browser_data_overlay.js b/chrome/browser/resources/options/clear_browser_data_overlay.js
index c12315d..5fb745b 100644
--- a/chrome/browser/resources/options/clear_browser_data_overlay.js
+++ b/chrome/browser/resources/options/clear_browser_data_overlay.js
@@ -59,6 +59,9 @@
         ClearBrowserDataOverlay.setClearingState(true);
         chrome.send('performClearBrowserData');
       };
+
+      var show = loadTimeData.getBoolean('showDeleteBrowsingHistoryCheckboxes');
+      this.showDeleteHistoryCheckboxes_(show);
     },
 
     // Set the enabled state of the commit button.
@@ -79,6 +82,13 @@
       this.allowDeletingHistory_ = allowed;
     },
 
+    showDeleteHistoryCheckboxes_: function(show) {
+      if (!show) {
+        $('delete-browsing-history-container').hidden = true;
+        $('delete-download-history-container').hidden = true;
+      }
+    },
+
     /** @override */
     didShowPage: function() {
       var allowed = ClearBrowserDataOverlay.getInstance().allowDeletingHistory_;
diff --git a/chrome/browser/resources/options/import_data_overlay.css b/chrome/browser/resources/options/import_data_overlay.css
index 7bea409..d7c076d 100644
--- a/chrome/browser/resources/options/import_data_overlay.css
+++ b/chrome/browser/resources/options/import_data_overlay.css
@@ -2,6 +2,10 @@
  * Use of this source code is governed by a BSD-style license that can be
  * found in the LICENSE file. */
 
+#import-data-overlay {
+  width: 400px;
+}
+
 #import-from-div {
   margin-bottom: 20px;
 }
diff --git a/chrome/browser/resources/options/import_data_overlay.html b/chrome/browser/resources/options/import_data_overlay.html
index 2b78735..5721508 100644
--- a/chrome/browser/resources/options/import_data_overlay.html
+++ b/chrome/browser/resources/options/import_data_overlay.html
@@ -98,6 +98,8 @@
         <div id="import-throbber" class="throbber"></div>
         <div class="button-strip">
           <button id="import-data-cancel" i18n-content="cancel"></button>
+          <button id="import-choose-file" i18n-content="importChooseFile">
+          </button>
           <button id="import-data-commit" class="default-button"
               i18n-content="importCommit">
           </button>
@@ -114,4 +116,7 @@
       </div>
     </div>
   </div>
+  <div id="mac-password-keychain" class="gray-bottom-bar">
+    <span i18n-content="macPasswordKeychain"></span>
+  </div>
 </div>
diff --git a/chrome/browser/resources/options/import_data_overlay.js b/chrome/browser/resources/options/import_data_overlay.js
index 8841b73..36bc866 100644
--- a/chrome/browser/resources/options/import_data_overlay.js
+++ b/chrome/browser/resources/options/import_data_overlay.js
@@ -42,6 +42,7 @@
       $('import-browsers').onchange = function() {
         self.updateCheckboxes_();
         self.validateCommitButton_();
+        self.updateBottomBar_();
       };
 
       $('import-data-commit').onclick = function() {
@@ -57,6 +58,10 @@
         ImportDataOverlay.dismiss();
       };
 
+      $('import-choose-file').onclick = function() {
+        chrome.send('chooseBookmarksFile');
+      };
+
       $('import-data-show-bookmarks-bar').onchange = function() {
         // Note: The callback 'toggleShowBookmarksBar' is handled within the
         // browser options handler -- rather than the import data handler --
@@ -93,6 +98,7 @@
       for (var i = 0; i < checkboxes.length; i++)
         this.setUpCheckboxState_(checkboxes[i], enabled);
       $('import-data-commit').disabled = !enabled;
+      $('mac-password-keychain').hidden = !enabled;
     },
 
     /**
@@ -115,6 +121,10 @@
      */
     updateCheckboxes_: function() {
       var index = $('import-browsers').selectedIndex;
+      var bookmarksFileSelected = index == this.browserProfiles.length - 1;
+      $('import-choose-file').hidden = !bookmarksFileSelected;
+      $('import-data-commit').hidden = bookmarksFileSelected;
+
       var browserProfile;
       if (this.browserProfiles.length > index)
         browserProfile = this.browserProfiles[index];
@@ -122,6 +132,7 @@
       for (var i = 0; i < importOptions.length; i++) {
         var checkbox = $('import-' + importOptions[i]);
         var enable = browserProfile && browserProfile[importOptions[i]];
+        checkbox.checked = enable;
         this.setUpCheckboxState_(checkbox, enable);
         var checkboxWithLabel = $('import-' + importOptions[i] + '-with-label');
         checkboxWithLabel.style.display = enable ? '' : 'none';
@@ -129,6 +140,19 @@
     },
 
     /**
+     * Show or hide gray message at the bottom.
+     * @private
+     */
+    updateBottomBar_: function() {
+      var index = $('import-browsers').selectedIndex;
+      var browserProfile;
+      if (this.browserProfiles.length > index)
+        browserProfile = this.browserProfiles[index];
+      var enable = browserProfile && browserProfile['show_bottom_bar'];
+      $('mac-password-keychain').hidden = !enable;
+    },
+
+    /**
      * Update the supported browsers popup with given entries.
      * @param {array} browsers List of supported browsers name.
      * @private
@@ -155,6 +179,7 @@
 
         this.updateCheckboxes_();
         this.validateCommitButton_();
+        this.updateBottomBar_();
       }
     },
 
diff --git a/chrome/browser/resources/options/manage_profile_overlay.css b/chrome/browser/resources/options/manage_profile_overlay.css
index 5b5f093..4bbdb02 100644
--- a/chrome/browser/resources/options/manage_profile_overlay.css
+++ b/chrome/browser/resources/options/manage_profile_overlay.css
@@ -120,7 +120,8 @@
   color: #999;
 }
 
-#create-profile-managed-not-signed-in-label {
+#create-profile-managed-not-signed-in-label,
+#create-profile-managed-account-details-out-of-date-label {
   white-space: pre-wrap;
   word-wrap: break-word;
 }
diff --git a/chrome/browser/resources/options/manage_profile_overlay.html b/chrome/browser/resources/options/manage_profile_overlay.html
index 2982a65..c81d543 100644
--- a/chrome/browser/resources/options/manage_profile_overlay.html
+++ b/chrome/browser/resources/options/manage_profile_overlay.html
@@ -79,9 +79,16 @@
           <input id="create-profile-managed" type="checkbox">
           <span id="create-profile-managed-signed-in">
             <span id="create-profile-managed-signed-in-label"></span>
-            <button id="create-profile-managed-signed-in-link"
+            <span id="create-profile-managed-account-details-out-of-date-label"
+                hidden>
+            </span>
+            <button id="create-profile-managed-signed-in-learn-more-link"
                 class="link-button" i18n-content="learnMore">
             </button>
+            <button id="create-profile-managed-sign-in-again-link"
+                class="link-button"
+                i18n-content="manageProfilesManagedSignInAgainLink" hidden>
+            </button>
           </span>
           <span id="create-profile-managed-not-signed-in" hidden>
             <span id="create-profile-managed-not-signed-in-label"
diff --git a/chrome/browser/resources/options/manage_profile_overlay.js b/chrome/browser/resources/options/manage_profile_overlay.js
index 497ca1e..533d029 100644
--- a/chrome/browser/resources/options/manage_profile_overlay.js
+++ b/chrome/browser/resources/options/manage_profile_overlay.js
@@ -82,7 +82,8 @@
         chrome.send('removeProfileShortcut', [self.profileInfo_.filePath]);
       };
 
-      $('create-profile-managed-signed-in-link').onclick = function(event) {
+      $('create-profile-managed-signed-in-learn-more-link').onclick =
+          function(event) {
         OptionsPage.navigateToPage('managedUserLearnMore');
         return false;
       };
@@ -97,6 +98,11 @@
         SyncSetupOverlay.startSignIn();
       };
 
+      $('create-profile-managed-sign-in-again-link').onclick = function(event) {
+        OptionsPage.closeOverlay();
+        SyncSetupOverlay.showSetupUI();
+      };
+
       $('create-profile-managed').onchange = function(event) {
         var createManagedProfile = $('create-profile-managed').checked;
         $('select-existing-managed-profile-checkbox').disabled =
@@ -601,10 +607,13 @@
      * will update additional UI elements.
      * @param {string} email The email address of the currently signed-in user.
      *     An empty string indicates that the user is not signed in.
+     * @param {boolean} hasError Whether the user's sign-in credentials are
+     *     still valid.
      * @private
      */
-    updateSignedInStatus_: function(email) {
+    updateSignedInStatus_: function(email, hasError) {
       this.signedInEmail_ = email;
+      this.hasError_ = hasError;
       var isSignedIn = email !== '';
       $('create-profile-managed-signed-in').hidden = !isSignedIn;
       $('create-profile-managed-not-signed-in').hidden = isSignedIn;
@@ -612,9 +621,19 @@
       $('choose-existing-managed-profile').hidden = !isSignedIn;
 
       if (isSignedIn) {
+        var accountDetailsOutOfDate =
+            $('create-profile-managed-account-details-out-of-date-label');
+        accountDetailsOutOfDate.textContent = loadTimeData.getStringF(
+            'manageProfilesManagedAccountDetailsOutOfDate', email);
+        accountDetailsOutOfDate.hidden = !hasError;
+
         $('create-profile-managed-signed-in-label').textContent =
             loadTimeData.getStringF(
                 'manageProfilesManagedSignedInLabel', email);
+        $('create-profile-managed-signed-in-label').hidden = hasError;
+
+        $('create-profile-managed-sign-in-again-link').hidden = !hasError;
+        $('create-profile-managed-signed-in-learn-more-link').hidden = hasError;
       }
     },
 
@@ -629,7 +648,8 @@
      */
     updateManagedUsersAllowed_: function(allowed) {
       var isSignedIn = this.signedInEmail_ !== '';
-      $('create-profile-managed').disabled = !isSignedIn || !allowed;
+      $('create-profile-managed').disabled =
+          !isSignedIn || !allowed || this.hasError_;
 
       $('create-profile-managed-not-signed-in-link').hidden = !allowed;
       if (!allowed) {
diff --git a/chrome/browser/resources/options/options_page.js b/chrome/browser/resources/options/options_page.js
index 67fbe2f..a9b7c84 100644
--- a/chrome/browser/resources/options/options_page.js
+++ b/chrome/browser/resources/options/options_page.js
@@ -3,6 +3,8 @@
 // found in the LICENSE file.
 
 cr.define('options', function() {
+  /** @const */ var FocusOutlineManager = cr.ui.FocusOutlineManager;
+
   /////////////////////////////////////////////////////////////////////////////
   // OptionsPage class:
 
@@ -279,8 +281,7 @@
     // Change focus to the overlay if any other control was focused by keyboard
     // before. Otherwise, no one should have focus.
     if (document.activeElement != document.body) {
-      if (document.documentElement.classList.contains(
-          cr.ui.FocusOutlineManager.CLASS_NAME)) {
+      if (FocusOutlineManager.forDocument(document).visible) {
         overlay.focus();
       } else {
         document.activeElement.blur();
@@ -648,7 +649,7 @@
   OptionsPage.initialize = function() {
     chrome.send('coreOptionsInitialize');
     uber.onContentFrameLoaded();
-    cr.ui.FocusOutlineManager.forDocument(document);
+    FocusOutlineManager.forDocument(document);
     document.addEventListener('scroll', this.handleScroll_.bind(this));
 
     // Trigger the scroll handler manually to set the initial state.
diff --git a/chrome/browser/resources/options/reset_profile_settings_overlay.css b/chrome/browser/resources/options/reset_profile_settings_overlay.css
index f8b838c..9fa3b8e 100644
--- a/chrome/browser/resources/options/reset_profile_settings_overlay.css
+++ b/chrome/browser/resources/options/reset_profile_settings_overlay.css
@@ -11,13 +11,3 @@
   vertical-align: middle;
   visibility: hidden;
 }
-
-.feedback-area {
-  background-color: #f5f5f5;
-  border-color: #e7e7e7;
-  border-top-style: solid;
-  border-width: 1px;
-  color: #888;
-  display: -webkit-box;
-  padding: 14px 17px;
-}
diff --git a/chrome/browser/resources/options/reset_profile_settings_overlay.html b/chrome/browser/resources/options/reset_profile_settings_overlay.html
index b2fa0bc..5c96eaa 100644
--- a/chrome/browser/resources/options/reset_profile_settings_overlay.html
+++ b/chrome/browser/resources/options/reset_profile_settings_overlay.html
@@ -21,7 +21,7 @@
       </div>
     </div>
   </div>
-  <div class="feedback-area checkbox">
+  <div class="gray-bottom-bar checkbox">
     <input id="send-settings" type="checkbox" checked=true>
     <label for="send-settings" i18n-content="resetProfileSettingsFeedback">
     </label>
diff --git a/chrome/browser/resources/performance_monitor/chart.html b/chrome/browser/resources/performance_monitor/chart.html
index 2f2faed..38f1f6a 100644
--- a/chrome/browser/resources/performance_monitor/chart.html
+++ b/chrome/browser/resources/performance_monitor/chart.html
@@ -20,7 +20,7 @@
       <div id="warnings-text">
         <span id="flag-not-enabled-warning" class="warning">
           <span i18n-content="flagNotEnabledWarning"></span>&nbsp;
-          <a target="blank_" i18n-content="enableFlag"
+          <a target="_blank" i18n-content="enableFlag"
               i18n-values="href:enableFlagsURL">
           </a>
         </span>
diff --git a/chrome/browser/resources/user_chooser/control_bar.css b/chrome/browser/resources/user_manager/control_bar.css
similarity index 100%
rename from chrome/browser/resources/user_chooser/control_bar.css
rename to chrome/browser/resources/user_manager/control_bar.css
diff --git a/chrome/browser/resources/user_chooser/control_bar.html b/chrome/browser/resources/user_manager/control_bar.html
similarity index 100%
rename from chrome/browser/resources/user_chooser/control_bar.html
rename to chrome/browser/resources/user_manager/control_bar.html
diff --git a/chrome/browser/resources/user_chooser/control_bar.js b/chrome/browser/resources/user_manager/control_bar.js
similarity index 100%
rename from chrome/browser/resources/user_chooser/control_bar.js
rename to chrome/browser/resources/user_manager/control_bar.js
diff --git a/chrome/browser/resources/user_chooser/user_chooser.html b/chrome/browser/resources/user_manager/user_manager.html
similarity index 93%
rename from chrome/browser/resources/user_chooser/user_chooser.html
rename to chrome/browser/resources/user_manager/user_manager.html
index 024693a..bb656f7 100644
--- a/chrome/browser/resources/user_chooser/user_chooser.html
+++ b/chrome/browser/resources/user_manager/user_manager.html
@@ -8,7 +8,7 @@
 <link rel="stylesheet" href="../chromeos/login/screen_container.css">
 <link rel="stylesheet" href="../chromeos/login/oobe.css">
 <link rel="stylesheet" href="../chromeos/login/user_pod_row.css">
-<!-- desktop user chooser specific overrides -->
+<!-- desktop user manager specific overrides -->
 <link rel="stylesheet" href="control_bar.css">
 <!-- framework imports -->
 <!-- as per chrome/browser/resources/chromeos/login/login_resources.html -->
@@ -28,8 +28,8 @@
 <script src="chrome://resources/js/cr/ui/menu_button.js"></script>
 <script src="chrome://resources/js/load_time_data.js"></script>
 <script src="chrome://resources/js/util.js"></script>
-<script src="user_chooser.js"></script>
-<script src="chrome://user-chooser/strings.js"></script>
+<script src="user_manager.js"></script>
+<script src="chrome://user-manager/strings.js"></script>
 </head>
 <body class="login-display" i18n-values=".style.fontFamily:fontfamily;">
   <div id="outer-container">
diff --git a/chrome/browser/resources/user_chooser/user_chooser.js b/chrome/browser/resources/user_manager/user_manager.js
similarity index 93%
rename from chrome/browser/resources/user_chooser/user_chooser.js
rename to chrome/browser/resources/user_manager/user_manager.js
index a98e703..c1da909 100644
--- a/chrome/browser/resources/user_chooser/user_chooser.js
+++ b/chrome/browser/resources/user_manager/user_manager.js
@@ -31,7 +31,7 @@
    * Shows the given screen.
    * @param {Object} screen Screen params dict, e.g. {id: screenId, data: data}
    */
-  Oobe.showUserChooserScreen = function() {
+  Oobe.showUserManagerScreen = function() {
     Oobe.getInstance().showScreen({id: 'account-picker',
                                    data: {disableAddUser: false}});
     // The ChromeOS account-picker will hide the AddUser button if a user is
@@ -89,14 +89,14 @@
   };
 });
 
-cr.define('UserChooser', function() {
+cr.define('UserManager', function() {
   'use strict';
 
   function initialize() {
     login.AccountPickerScreen.register();
     cr.ui.Bubble.decorate($('bubble'));
     login.HeaderBar.decorate($('login-header-bar'));
-    chrome.send('userChooserInitialize');
+    chrome.send('userManagerInitialize');
   }
 
   // Return an object with all of the exports.
@@ -116,4 +116,4 @@
          /text|password|search/.test(src.type);
 });
 
-document.addEventListener('DOMContentLoaded', UserChooser.initialize);
+document.addEventListener('DOMContentLoaded', UserManager.initialize);
diff --git a/chrome/browser/rlz/rlz.cc b/chrome/browser/rlz/rlz.cc
index dd153fd..4aa8b5f 100644
--- a/chrome/browser/rlz/rlz.cc
+++ b/chrome/browser/rlz/rlz.cc
@@ -337,10 +337,11 @@
 }
 
 void RLZTracker::ScheduleFinancialPing() {
-  BrowserThread::GetBlockingPool()->PostSequencedWorkerTask(
+  BrowserThread::GetBlockingPool()->PostSequencedWorkerTaskWithShutdownBehavior(
       worker_pool_token_,
       FROM_HERE,
-      base::Bind(&RLZTracker::PingNowImpl, base::Unretained(this)));
+      base::Bind(&RLZTracker::PingNowImpl, base::Unretained(this)),
+      base::SequencedWorkerPool::SKIP_ON_SHUTDOWN);
 }
 
 void RLZTracker::PingNowImpl() {
@@ -436,11 +437,12 @@
   if (!BrowserThread::CurrentlyOn(BrowserThread::UI))
     return false;
 
-  BrowserThread::GetBlockingPool()->PostSequencedWorkerTask(
+  BrowserThread::GetBlockingPool()->PostSequencedWorkerTaskWithShutdownBehavior(
       worker_pool_token_,
       FROM_HERE,
       base::Bind(base::IgnoreResult(&RLZTracker::RecordProductEvent),
-                 product, point, event_id));
+                 product, point, event_id),
+      base::SequencedWorkerPool::SKIP_ON_SHUTDOWN);
 
   return true;
 }
@@ -465,11 +467,12 @@
 bool RLZTracker::ScheduleRecordFirstSearch(rlz_lib::AccessPoint point) {
   if (!BrowserThread::CurrentlyOn(BrowserThread::UI))
     return false;
-  BrowserThread::GetBlockingPool()->PostSequencedWorkerTask(
+  BrowserThread::GetBlockingPool()->PostSequencedWorkerTaskWithShutdownBehavior(
       worker_pool_token_,
       FROM_HERE,
       base::Bind(&RLZTracker::RecordFirstSearch,
-                 base::Unretained(this), point));
+                 base::Unretained(this), point),
+      base::SequencedWorkerPool::SKIP_ON_SHUTDOWN);
   return true;
 }
 
@@ -534,11 +537,12 @@
     return false;
 
   string16* not_used = NULL;
-  BrowserThread::GetBlockingPool()->PostSequencedWorkerTask(
+  BrowserThread::GetBlockingPool()->PostSequencedWorkerTaskWithShutdownBehavior(
       worker_pool_token_,
       FROM_HERE,
       base::Bind(base::IgnoreResult(&RLZTracker::GetAccessPointRlz), point,
-                 not_used));
+                 not_used),
+      base::SequencedWorkerPool::SKIP_ON_SHUTDOWN);
   return true;
 }
 
@@ -558,11 +562,12 @@
   if (!BrowserThread::CurrentlyOn(BrowserThread::UI))
     return false;
 
-  BrowserThread::GetBlockingPool()->PostSequencedWorkerTask(
+  BrowserThread::GetBlockingPool()->PostSequencedWorkerTaskWithShutdownBehavior(
       worker_pool_token_,
       FROM_HERE,
       base::Bind(&RLZTracker::ClearRlzStateImpl,
-                 base::Unretained(this)));
+                 base::Unretained(this)),
+      base::SequencedWorkerPool::SKIP_ON_SHUTDOWN);
   return true;
 }
 #endif
diff --git a/chrome/browser/safe_browsing/malware_details_unittest.cc b/chrome/browser/safe_browsing/malware_details_unittest.cc
index 7389893..251ce98 100644
--- a/chrome/browser/safe_browsing/malware_details_unittest.cc
+++ b/chrome/browser/safe_browsing/malware_details_unittest.cc
@@ -117,7 +117,6 @@
       GetCache()->GetBackend(&cache, cb.callback());
   ASSERT_EQ(net::OK, cb.GetResult(rv));
 
-  std::string empty;
   WriteToEntry(cache, kMalwareURL, kMalwareHeaders, kMalwareData);
   WriteToEntry(cache, kLandingURL, kLandingHeaders, kLandingData);
 }
diff --git a/chrome/browser/search/search.cc b/chrome/browser/search/search.cc
index dca93cd..1328ffe 100644
--- a/chrome/browser/search/search.cc
+++ b/chrome/browser/search/search.cc
@@ -11,6 +11,7 @@
 #include "base/rand_util.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_split.h"
+#include "base/strings/utf_string_conversions.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/google/google_util.h"
 #include "chrome/browser/profiles/profile.h"
@@ -73,6 +74,34 @@
 // Remember if we reported metrics about opt-in/out state.
 bool instant_extended_opt_in_state_gate = false;
 
+// Used to set the Instant support state of the Navigation entry.
+const char kInstantSupportStateKey[] = "instant_support_state";
+
+const char kInstantSupportEnabled[] = "Instant support enabled";
+const char kInstantSupportDisabled[] = "Instant support disabled";
+const char kInstantSupportUnknown[] = "Instant support unknown";
+
+InstantSupportState StringToInstantSupportState(const string16& value) {
+  if (value == ASCIIToUTF16(kInstantSupportEnabled))
+    return INSTANT_SUPPORT_YES;
+  else if (value == ASCIIToUTF16(kInstantSupportDisabled))
+    return INSTANT_SUPPORT_NO;
+  else
+    return INSTANT_SUPPORT_UNKNOWN;
+}
+
+string16 InstantSupportStateToString(InstantSupportState state) {
+  switch (state) {
+    case INSTANT_SUPPORT_NO:
+      return ASCIIToUTF16(kInstantSupportDisabled);
+    case INSTANT_SUPPORT_YES:
+      return ASCIIToUTF16(kInstantSupportEnabled);
+    case INSTANT_SUPPORT_UNKNOWN:
+      return ASCIIToUTF16(kInstantSupportUnknown);
+  }
+  return ASCIIToUTF16(kInstantSupportUnknown);
+}
+
 TemplateURL* GetDefaultSearchProviderTemplateURL(Profile* profile) {
   TemplateURLService* template_url_service =
       TemplateURLServiceFactory::GetForProfile(profile);
@@ -197,7 +226,7 @@
 
 string16 GetSearchTermsImpl(const content::WebContents* contents,
                             const content::NavigationEntry* entry) {
-  if (!IsQueryExtractionEnabled())
+  if (!contents || !IsQueryExtractionEnabled())
     return string16();
 
   // For security reasons, don't extract search terms if the page is not being
@@ -299,6 +328,14 @@
   if (!entry)
     return string16();
 
+#if !defined(OS_IOS) && !defined(OS_ANDROID)
+  // iOS and Android doesn't use the Instant framework, disable this check for
+  // the two platforms.
+  InstantSupportState state = GetInstantSupportStateFromNavigationEntry(*entry);
+  if (state == INSTANT_SUPPORT_NO)
+    return string16();
+#endif  // !defined(OS_IOS) && !defined(OS_ANDROID)
+
   return GetSearchTermsImpl(contents, entry);
 }
 
@@ -556,6 +593,23 @@
   return true;
 }
 
+void SetInstantSupportStateInNavigationEntry(InstantSupportState state,
+                                             content::NavigationEntry* entry) {
+  if (!entry)
+    return;
+
+  entry->SetExtraData(kInstantSupportStateKey,
+                      InstantSupportStateToString(state));
+}
+
+InstantSupportState GetInstantSupportStateFromNavigationEntry(
+    const content::NavigationEntry& entry) {
+  string16 value;
+  if (!entry.GetExtraData(kInstantSupportStateKey, &value))
+    return INSTANT_SUPPORT_UNKNOWN;
+
+  return StringToInstantSupportState(value);
+}
 
 void EnableInstantExtendedAPIForTesting() {
   CommandLine* cl = CommandLine::ForCurrentProcess();
diff --git a/chrome/browser/search/search.h b/chrome/browser/search/search.h
index 83e660a..094f660 100644
--- a/chrome/browser/search/search.h
+++ b/chrome/browser/search/search.h
@@ -11,6 +11,7 @@
 
 #include "base/basictypes.h"
 #include "base/strings/string16.h"
+#include "chrome/browser/ui/search/search_model.h"
 
 class GURL;
 class Profile;
@@ -59,21 +60,25 @@
 
 // Extracts and returns search terms from |url|. Returns empty string if the URL
 // is not secure or doesn't have a search term replacement key.  Does not
-// consider IsQueryExtractionEnabled() and does not check for a privileged
-// process, so most callers should use GetSearchTerms() below instead.
+// consider IsQueryExtractionEnabled() and Instant support state of the page and
+// does not check for a privileged process, so most callers should use
+// GetSearchTerms() below instead.
 string16 GetSearchTermsFromURL(Profile* profile, const GURL& url);
 
 // Returns the search terms attached to a specific NavigationEntry, or empty
-// string otherwise. Does not consider IsQueryExtractionEnabled(), so most
-// callers should use GetSearchTerms() below instead.
+// string otherwise. Does not consider IsQueryExtractionEnabled() and does not
+// check Instant support, so most callers should use GetSearchTerms() below
+// instead.
 string16 GetSearchTermsFromNavigationEntry(
     const content::NavigationEntry* entry);
 
 // Returns search terms if this WebContents is a search results page. It looks
 // in the visible NavigationEntry first, to see if search terms have already
 // been extracted. Failing that, it tries to extract search terms from the URL.
+//
 // Returns a blank string if search terms were not found, or if search terms
-// extraction is disabled for this WebContents or profile.
+// extraction is disabled for this WebContents or profile, or if |contents|
+// does not support Instant.
 string16 GetSearchTerms(const content::WebContents* contents);
 
 // Returns true if |url| should be rendered in the Instant renderer process.
@@ -168,6 +173,15 @@
 bool HandleNewTabURLReverseRewrite(GURL* url,
                                    content::BrowserContext* browser_context);
 
+// Sets the Instant support |state| in the navigation |entry|.
+void SetInstantSupportStateInNavigationEntry(InstantSupportState state,
+                                             content::NavigationEntry* entry);
+
+// Returns the Instant support state attached to the NavigationEntry, or
+// INSTANT_SUPPORT_UNKNOWN otherwise.
+InstantSupportState GetInstantSupportStateFromNavigationEntry(
+    const content::NavigationEntry& entry);
+
 // -----------------------------------------------------
 // The following APIs are exposed for use in tests only.
 // -----------------------------------------------------
diff --git a/chrome/browser/search_engines/prepopulated_engines.json b/chrome/browser/search_engines/prepopulated_engines.json
index a4e7c94..c0fce8b 100644
--- a/chrome/browser/search_engines/prepopulated_engines.json
+++ b/chrome/browser/search_engines/prepopulated_engines.json
@@ -9,8 +9,8 @@
 // definitions.
 
 // The following unique IDs are available:
-//    53, 56, 58, 60, 61, 64, 65, 66, 70, 74, 78, 79, 80, 81, 84, 86, 88, 91,
-//    92, 93, 94, 95, 96, 97, 98, 99, 102+
+//    11, 12, 14, 18, 19, 20, 22, 24, 26, 28, 29, 30, 32, 33, 34, 39, 37, 38,
+//    40, 41, 42, 46, 47, 48, 49, 51, 52, 59, 71, 72, 82, 84, 86, 88, 89, 91+
 //
 // IDs > 1000 are reserved for distribution custom engines.
 //
@@ -22,114 +22,42 @@
   "int_variables": {
     // The following id is for UMA stats only. Please update it if you add new
     // engines outside the current range or it will not be counted in stats.
-    "kMaxPrepopulatedEngineID": 101,
+    "kMaxPrepopulatedEngineID": 90,
 
     // Increment this if you change the data in ways that mean users with
     // existing data should get a new version.
-    "kCurrentDataVersion": 58
+    "kCurrentDataVersion": 60
   },
 
   // The following engines are included in country lists and are added to the
   // list of search engines on the first run depending on user's country.
   "elements": {
-    "abcsok": {
-      "name": "ABC S\u00f8k",
-      "keyword": "abcsok.no",
-      "favicon_url": "http://abcsok.no/favicon.ico",
-      "search_url": "http://abcsok.no/index.html?q={searchTerms}",
-      "type": "SEARCH_ENGINE_ABCSOK",
-      "id": 72
-    },
-
-    "altavista": {
-      "name": "AltaVista",
-      "keyword": "altavista.com",
-      "favicon_url": "http://www.altavista.com/favicon.ico",
-      "search_url": "http://www.altavista.com/web/results?q={searchTerms}",
-      "type": "SEARCH_ENGINE_ALTAVISTA",
-      "id": 89
-    },
-
-    "altavista_ar": {
-      "name": "AltaVista",
-      "keyword": "ar.altavista.com",
-      "favicon_url": "http://ar.altavista.com/favicon.ico",
-      "search_url": "http://ar.altavista.com/web/results?q={searchTerms}",
-      "type": "SEARCH_ENGINE_ALTAVISTA",
-      "id": 89
-    },
-
-    "altavista_se": {
-      "name": "AltaVista",
-      "keyword": "se.altavista.com",
-      "favicon_url": "http://se.altavista.com/favicon.ico",
-      "search_url": "http://se.altavista.com/web/results?q={searchTerms}",
-      "type": "SEARCH_ENGINE_ALTAVISTA",
-      "id": 89
-    },
-
     "aol": {
       "name": "AOL",
       "keyword": "aol.com",
       "favicon_url": "http://search.aol.com/favicon.ico",
       "search_url": "http://search.aol.com/aol/search?query={searchTerms}",
+      "suggest_url": "http://autocomplete.search.aol.com/autocomplete/get?output=json&it=&q={searchTerms}",
+      "type": "SEARCH_ENGINE_AOL",
       "id": 35
     },
 
-    "araby": {
-      "name": "\u0639\u0631\u0628\u064a",
-      "keyword": "araby.com",
-      "favicon_url": "http://araby.com/favicon.ico",
-      "search_url": "http://araby.com/?q={searchTerms}",
-      "id": 12
-    },
-
     "ask": {
       "name": "Ask",
       "keyword": "ask.com",
-      "favicon_url": "http://www.ask.com/favicon.ico",
+      "favicon_url": "http://sp.ask.com/sh/i/a16/favicon/favicon.ico",
       "search_url": "http://www.ask.com/web?q={searchTerms}",
       "suggest_url": "http://ss.ask.com/query?q={searchTerms}&li=ff",
       "type": "SEARCH_ENGINE_ASK",
       "id": 4
     },
 
-    "ask_de": {
-      "name": "Ask.com Deutschland",
-      "keyword": "de.ask.com",
-      "favicon_url": "http://de.ask.com/favicon.ico",
-      "search_url": "http://de.ask.com/web?q={searchTerms}",
-      "suggest_url": "http://ss.de.ask.com/query?q={searchTerms}&li=ff",
-      "type": "SEARCH_ENGINE_ASK",
-      "id": 4
-    },
-
-    "ask_es": {
-      "name": "Ask.com Espa\u00f1a",
-      "keyword": "es.ask.com",
-      "favicon_url": "http://es.ask.com/favicon.ico",
-      "search_url": "http://es.ask.com/web?q={searchTerms}",
-      "suggest_url": "http://ss.es.ask.com/query?q={searchTerms}&li=ff",
-      "type": "SEARCH_ENGINE_ASK",
-      "id": 4
-    },
-
-    "ask_it": {
-      "name": "Ask.com Italia",
-      "keyword": "it.ask.com",
-      "favicon_url": "http://it.ask.com/favicon.ico",
-      "search_url": "http://it.ask.com/web?q={searchTerms}",
-      "suggest_url": "http://ss.it.ask.com/query?q={searchTerms}&li=ff",
-      "type": "SEARCH_ENGINE_ASK",
-      "id": 4
-    },
-
-    "ask_nl": {
-      "name": "Ask.com Nederland",
-      "keyword": "nl.ask.com",
-      "favicon_url": "http://nl.ask.com/favicon.ico",
-      "search_url": "http://nl.ask.com/web?q={searchTerms}",
-      "suggest_url": "http://ss.nl.ask.com/query?q={searchTerms}&li=ff",
+    "ask_br": {
+      "name": "Ask Brasil",
+      "keyword": "br.ask.com",
+      "favicon_url": "http://sp.br.ask.com/sh/i/a14/favicon/favicon.ico",
+      "search_url": "http://br.ask.com/web?q={searchTerms}",
+      "suggest_url": "http://ss.ask.com/query?q={searchTerms}&li=ff",
       "type": "SEARCH_ENGINE_ASK",
       "id": 4
     },
@@ -137,36 +65,18 @@
     "ask_uk": {
       "name": "Ask Jeeves",
       "keyword": "uk.ask.com",
-      "favicon_url": "http://uk.ask.com/favicon.ico",
+      "favicon_url": "http://sp.uk.ask.com/sh/i/a16/favicon/favicon.ico",
       "search_url": "http://uk.ask.com/web?q={searchTerms}",
       "suggest_url": "http://ss.uk.ask.com/query?q={searchTerms}&li=ff",
       "type": "SEARCH_ENGINE_ASK",
       "id": 4
     },
 
-    "atlas_cz": {
-      "name": "Atlas",
-      "keyword": "atlas.cz",
-      "favicon_url": "http://img.atlas.cz/favicon.ico",
-      "search_url": "http://search.atlas.cz/?q={searchTerms}",
-      "encoding": "windows-1250",
-      "id": 27
-    },
-
-    "atlas_sk": {
-      "name": "ATLAS.SK",
-      "keyword": "atlas.sk",
-      "favicon_url": "http://www.atlas.sk/images/favicon.ico",
-      "search_url": "http://hladaj.atlas.sk/fulltext/?phrase={searchTerms}",
-      "id": 27
-    },
-
     "baidu": {
       "name": "\u767e\u5ea6",
       "keyword": "baidu.com",
       "favicon_url": "http://www.baidu.com/favicon.ico",
-      "search_url": "http://www.baidu.com/s?wd={searchTerms}",
-      "encoding": "GB2312",
+      "search_url": "http://www.baidu.com/s?ie={inputEncoding}&wd={searchTerms}",
       "type": "SEARCH_ENGINE_BAIDU",
       "id": 21
     },
@@ -182,7 +92,7 @@
     },
 
     "bing_ar_XA": {
-      "name": "Bing",
+      "name": "Bing (\u0627\u0644\u0639\u0631\u0628\u064a\u0629)",
       "keyword": "bing.com_",  // bing.com is taken by bing_en_XA.
       "favicon_url": "http://www.bing.com/s/wlflag.ico",
       "search_url": "http://www.bing.com/search?setmkt=ar-XA&q={searchTerms}",
@@ -192,26 +102,6 @@
                // lists alongside bing_en_XA.
     },
 
-    "bing_bg_BG": {
-      "name": "Bing",
-      "keyword": "bing.com",
-      "favicon_url": "http://www.bing.com/s/wlflag.ico",
-      "search_url": "http://www.bing.com/search?setmkt=bg-BG&q={searchTerms}",
-      "suggest_url": "http://api.bing.com/osjson.aspx?query={searchTerms}&language={language}",
-      "type": "SEARCH_ENGINE_BING",
-      "id": 3
-    },
-
-    "bing_cs_CZ": {
-      "name": "Bing",
-      "keyword": "bing.com",
-      "favicon_url": "http://www.bing.com/s/wlflag.ico",
-      "search_url": "http://www.bing.com/search?setmkt=cs-CZ&q={searchTerms}",
-      "suggest_url": "http://api.bing.com/osjson.aspx?query={searchTerms}&language={language}",
-      "type": "SEARCH_ENGINE_BING",
-      "id": 3
-    },
-
     "bing_da_DK": {
       "name": "Bing",
       "keyword": "bing.com",
@@ -233,7 +123,7 @@
     },
 
     "bing_de_CH": {
-      "name": "Bing",
+      "name": "Bing (Deutsch)",
       "keyword": "bing.com",
       "favicon_url": "http://www.bing.com/s/wlflag.ico",
       "search_url": "http://www.bing.com/search?setmkt=de-CH&q={searchTerms}",
@@ -252,16 +142,6 @@
       "id": 3
     },
 
-    "bing_el_GR": {
-      "name": "Bing",
-      "keyword": "bing.com",
-      "favicon_url": "http://www.bing.com/s/wlflag.ico",
-      "search_url": "http://www.bing.com/search?setmkt=el-GR&q={searchTerms}",
-      "suggest_url": "http://api.bing.com/osjson.aspx?query={searchTerms}&language={language}",
-      "type": "SEARCH_ENGINE_BING",
-      "id": 3
-    },
-
     "bing_en_AU": {
       "name": "Bing",
       "keyword": "bing.com",
@@ -273,7 +153,7 @@
     },
 
     "bing_en_CA": {
-      "name": "Bing",
+      "name": "Bing (English)",
       "keyword": "bing.com",
       "favicon_url": "http://www.bing.com/s/wlflag.ico",
       "search_url": "http://www.bing.com/search?setmkt=en-CA&q={searchTerms}",
@@ -292,16 +172,6 @@
       "id": 3
     },
 
-    "bing_en_ID": {
-      "name": "Bing",
-      "keyword": "bing.com",
-      "favicon_url": "http://www.bing.com/s/wlflag.ico",
-      "search_url": "http://www.bing.com/search?setmkt=en-ID&q={searchTerms}",
-      "suggest_url": "http://api.bing.com/osjson.aspx?query={searchTerms}&language={language}",
-      "type": "SEARCH_ENGINE_BING",
-      "id": 3
-    },
-
     "bing_en_IE": {
       "name": "Bing",
       "keyword": "bing.com",
@@ -322,16 +192,6 @@
       "id": 3
     },
 
-    "bing_en_MY": {
-      "name": "Bing",
-      "keyword": "bing.com",
-      "favicon_url": "http://www.bing.com/s/wlflag.ico",
-      "search_url": "http://www.bing.com/search?setmkt=en-MY&q={searchTerms}",
-      "suggest_url": "http://api.bing.com/osjson.aspx?query={searchTerms}&language={language}",
-      "type": "SEARCH_ENGINE_BING",
-      "id": 3
-    },
-
     "bing_en_NZ": {
       "name": "Bing",
       "keyword": "bing.com",
@@ -373,7 +233,7 @@
     },
 
     "bing_en_XA": {
-      "name": "Bing",
+      "name": "Bing (English)",
       "keyword": "bing.com",
       "favicon_url": "http://www.bing.com/s/wlflag.ico",
       "search_url": "http://www.bing.com/search?setmkt=en-XA&q={searchTerms}",
@@ -382,16 +242,6 @@
       "id": 3
     },
 
-    "bing_en_ZA": {
-      "name": "Bing",
-      "keyword": "bing.com",
-      "favicon_url": "http://www.bing.com/s/wlflag.ico",
-      "search_url": "http://www.bing.com/search?setmkt=en-ZA&q={searchTerms}",
-      "suggest_url": "http://api.bing.com/osjson.aspx?query={searchTerms}&language={language}",
-      "type": "SEARCH_ENGINE_BING",
-      "id": 3
-    },
-
     "bing_es_AR": {
       "name": "Bing",
       "keyword": "bing.com",
@@ -442,16 +292,6 @@
       "id": 3
     },
 
-    "bing_et_EE": {
-      "name": "Bing",
-      "keyword": "bing.com",
-      "favicon_url": "http://www.bing.com/s/wlflag.ico",
-      "search_url": "http://www.bing.com/search?setmkt=et-EE&q={searchTerms}",
-      "suggest_url": "http://api.bing.com/osjson.aspx?query={searchTerms}&language={language}",
-      "type": "SEARCH_ENGINE_BING",
-      "id": 3
-    },
-
     "bing_fi_FI": {
       "name": "Bing",
       "keyword": "bing.com",
@@ -463,7 +303,7 @@
     },
 
     "bing_fr_BE": {
-      "name": "Bing",
+      "name": "Bing (Fran\u00e7ais)",
       "keyword": "bing.com_",  // bing.com is taken by bing_nl_BE.
       "favicon_url": "http://www.bing.com/s/wlflag.ico",
       "search_url": "http://www.bing.com/search?setmkt=fr-BE&q={searchTerms}",
@@ -473,7 +313,7 @@
     },
 
     "bing_fr_CA": {
-      "name": "Bing",
+      "name": "Bing (Fran\u00e7ais)",
       "keyword": "bing.com_",  // bing.com is taken by bing_en_CA.
       "favicon_url": "http://www.bing.com/s/wlflag.ico",
       "search_url": "http://www.bing.com/search?setmkt=fr-CA&q={searchTerms}",
@@ -483,7 +323,7 @@
     },
 
     "bing_fr_CH": {
-      "name": "Bing",
+      "name": "Bing (Fran\u00e7ais)",
       "keyword": "bing.com_",  // bing.com is taken by bing_de_CH.
       "favicon_url": "http://www.bing.com/s/wlflag.ico",
       "search_url": "http://www.bing.com/search?setmkt=fr-CH&q={searchTerms}",
@@ -502,36 +342,6 @@
       "id": 3
     },
 
-    "bing_he_IL": {
-      "name": "Bing",
-      "keyword": "bing.com",
-      "favicon_url": "http://www.bing.com/s/wlflag.ico",
-      "search_url": "http://www.bing.com/search?setmkt=he-IL&q={searchTerms}",
-      "suggest_url": "http://api.bing.com/osjson.aspx?query={searchTerms}&language={language}",
-      "type": "SEARCH_ENGINE_BING",
-      "id": 3
-    },
-
-    "bing_hr_HR": {
-      "name": "Bing",
-      "keyword": "bing.com",
-      "favicon_url": "http://www.bing.com/s/wlflag.ico",
-      "search_url": "http://www.bing.com/search?setmkt=hr-HR&q={searchTerms}",
-      "suggest_url": "http://api.bing.com/osjson.aspx?query={searchTerms}&language={language}",
-      "type": "SEARCH_ENGINE_BING",
-      "id": 3
-    },
-
-    "bing_hu_HU": {
-      "name": "Bing",
-      "keyword": "bing.com",
-      "favicon_url": "http://www.bing.com/s/wlflag.ico",
-      "search_url": "http://www.bing.com/search?setmkt=hu-HU&q={searchTerms}",
-      "suggest_url": "http://api.bing.com/osjson.aspx?query={searchTerms}&language={language}",
-      "type": "SEARCH_ENGINE_BING",
-      "id": 3
-    },
-
     "bing_it_IT": {
       "name": "Bing",
       "keyword": "bing.com",
@@ -552,26 +362,6 @@
       "id": 3
     },
 
-    "bing_ko_KR": {
-      "name": "Bing",
-      "keyword": "bing.com",
-      "favicon_url": "http://www.bing.com/s/wlflag.ico",
-      "search_url": "http://www.bing.com/search?setmkt=ko-KR&q={searchTerms}",
-      "suggest_url": "http://api.bing.com/osjson.aspx?query={searchTerms}&language={language}",
-      "type": "SEARCH_ENGINE_BING",
-      "id": 3
-    },
-
-    "bing_lt_LT": {
-      "name": "Bing",
-      "keyword": "bing.com",
-      "favicon_url": "http://www.bing.com/s/wlflag.ico",
-      "search_url": "http://www.bing.com/search?setmkt=lt-LT&q={searchTerms}",
-      "suggest_url": "http://api.bing.com/osjson.aspx?query={searchTerms}&language={language}",
-      "type": "SEARCH_ENGINE_BING",
-      "id": 3
-    },
-
     "bing_lv_LV": {
       "name": "Bing",
       "keyword": "bing.com",
@@ -593,7 +383,7 @@
     },
 
     "bing_nl_BE": {
-      "name": "Bing",
+      "name": "Bing (Nederlandstalige)",
       "keyword": "bing.com",
       "favicon_url": "http://www.bing.com/s/wlflag.ico",
       "search_url": "http://www.bing.com/search?setmkt=nl-BE&q={searchTerms}",
@@ -602,16 +392,6 @@
       "id": 3
     },
 
-    "bing_nl_NL": {
-      "name": "Bing",
-      "keyword": "bing.com",
-      "favicon_url": "http://www.bing.com/s/wlflag.ico",
-      "search_url": "http://www.bing.com/search?setmkt=nl-NL&q={searchTerms}",
-      "suggest_url": "http://api.bing.com/osjson.aspx?query={searchTerms}&language={language}",
-      "type": "SEARCH_ENGINE_BING",
-      "id": 3
-    },
-
     "bing_pl_PL": {
       "name": "Bing",
       "keyword": "bing.com",
@@ -642,16 +422,6 @@
       "id": 3
     },
 
-    "bing_ro_RO": {
-      "name": "Bing",
-      "keyword": "bing.com",
-      "favicon_url": "http://www.bing.com/s/wlflag.ico",
-      "search_url": "http://www.bing.com/search?setmkt=ro-RO&q={searchTerms}",
-      "suggest_url": "http://api.bing.com/osjson.aspx?query={searchTerms}&language={language}",
-      "type": "SEARCH_ENGINE_BING",
-      "id": 3
-    },
-
     "bing_ru_RU": {
       "name": "Bing",
       "keyword": "bing.com",
@@ -662,26 +432,6 @@
       "id": 3
     },
 
-    "bing_sl_SI": {
-      "name": "Bing",
-      "keyword": "bing.com",
-      "favicon_url": "http://www.bing.com/s/wlflag.ico",
-      "search_url": "http://www.bing.com/search?setmkt=sl-SI&q={searchTerms}",
-      "suggest_url": "http://api.bing.com/osjson.aspx?query={searchTerms}&language={language}",
-      "type": "SEARCH_ENGINE_BING",
-      "id": 3
-    },
-
-    "bing_sk_SK": {
-      "name": "Bing",
-      "keyword": "bing.com",
-      "favicon_url": "http://www.bing.com/s/wlflag.ico",
-      "search_url": "http://www.bing.com/search?setmkt=sk-SK&q={searchTerms}",
-      "suggest_url": "http://api.bing.com/osjson.aspx?query={searchTerms}&language={language}",
-      "type": "SEARCH_ENGINE_BING",
-      "id": 3
-    },
-
     "bing_sv_SE": {
       "name": "Bing",
       "keyword": "bing.com",
@@ -692,16 +442,6 @@
       "id": 3
     },
 
-    "bing_th_TH": {
-      "name": "Bing",
-      "keyword": "bing.com",
-      "favicon_url": "http://www.bing.com/s/wlflag.ico",
-      "search_url": "http://www.bing.com/search?setmkt=th-TH&q={searchTerms}",
-      "suggest_url": "http://api.bing.com/osjson.aspx?query={searchTerms}&language={language}",
-      "type": "SEARCH_ENGINE_BING",
-      "id": 3
-    },
-
     "bing_tr_TR": {
       "name": "Bing",
       "keyword": "bing.com",
@@ -712,26 +452,6 @@
       "id": 3
     },
 
-    "bing_uk_UA": {
-      "name": "Bing",
-      "keyword": "bing.com",
-      "favicon_url": "http://www.bing.com/s/wlflag.ico",
-      "search_url": "http://www.bing.com/search?setmkt=uk-UA&q={searchTerms}",
-      "suggest_url": "http://api.bing.com/osjson.aspx?query={searchTerms}&language={language}",
-      "type": "SEARCH_ENGINE_BING",
-      "id": 3
-    },
-
-    "bing_zh_CN": {
-      "name": "Bing",
-      "keyword": "bing.com",
-      "favicon_url": "http://www.bing.com/s/wlflag.ico",
-      "search_url": "http://www.bing.com/search?setmkt=zh-CN&q={searchTerms}",
-      "suggest_url": "http://api.bing.com/osjson.aspx?query={searchTerms}&language={language}",
-      "type": "SEARCH_ENGINE_BING",
-      "id": 3
-    },
-
     "bing_zh_HK": {
       "name": "Bing",
       "keyword": "bing.com",
@@ -752,106 +472,25 @@
       "id": 3
     },
 
-    "centrum_cz": {
-      "name": "Centrum.cz",
-      "keyword": "centrum.cz",
-      "favicon_url": "http://img.centrum.cz/6/vy2/o/favicon.ico",
-      "search_url": "http://search.centrum.cz/index.php?charset={inputEncoding}&q={searchTerms}",
-      "type": "SEARCH_ENGINE_CENTRUM",
-      "id": 26
-    },
-
-    "centrum_sk": {
-      "name": "Centrum.sk",
-      "keyword": "centrum.sk",
-      "favicon_url": "http://img.centrum.sk/4/favicon.ico",
-      "search_url": "http://search.centrum.sk/index.php?charset={inputEncoding}&q={searchTerms}",
-      "type": "SEARCH_ENGINE_CENTRUM",
-      "id": 26
-    },
-
     "daum": {
       "name": "Daum",
       "keyword": "daum.net",
-      "favicon_url": "http://icon.daum-img.net/favicon.ico",
-      "search_url": "http://search.daum.net/search?q={searchTerms}",
-      "suggest_url": "http://sug.search.daum.net/search_nsuggest?mod=fxjson&code=utf_in_out&q={searchTerms}",
+      "favicon_url": "http://search.daum.net/favicon.ico",
+      "search_url": "http://search.daum.net/search?ie={inputEncoding}&q={searchTerms}",
+      "suggest_url": "http://sug.search.daum.net/search_nsuggest?mod=fxjson&ie={inputEncoding}&code=utf_in_out&q={searchTerms}",
       "type": "SEARCH_ENGINE_DAUM",
       "id": 68
     },
 
-    "delfi_lt": {
-      "name": "DELFI",
-      "keyword": "delfi.lt",
-      "favicon_url": "http://search.delfi.lt/img/favicon.png",
-      "search_url": "http://search.delfi.lt/search.php?q={searchTerms}",
-      "type": "SEARCH_ENGINE_DELFI",
-      "id": 45
-    },
-
-    "delfi_lv": {
-      "name": "DELFI",
-      "keyword": "delfi.lv",
-      "favicon_url": "http://smart.delfi.lv/img/smart_search.png",
-      "search_url": "http://smart.delfi.lv/i.php?enc={inputEncoding}&q={searchTerms}",
-      "type": "SEARCH_ENGINE_DELFI",
-      "id": 45
-    },
-
-    "diri": {
-      "name": "diri",
-      "keyword": "diri.bg",
-      "favicon_url": "http://i.dir.bg/diri/images/favicon.ico",
-      "search_url": "http://diri.bg/search.php?textfield={searchTerms}",
-      "encoding": "windows-1251",
-      "type": "SEARCH_ENGINE_DIRI",
-      "id": 32
-    },
-
-    "eniro_fi": {
-      "name": "Eniro",
-      "keyword": "eniro.fi",
-      "favicon_url": "http://eniro.fi/favicon.ico",
-      "search_url": "http://eniro.fi/query?search_word={searchTerms}&what=web_local",
-      "encoding": "ISO-8859-1",
-      "id": 29
-    },
-
-    "eniro_se": {
-      "name": "Eniro",
-      "keyword": "eniro.se",
-      "favicon_url": "http://eniro.se/favicon.ico",
-      "search_url": "http://eniro.se/query?search_word={searchTerms}&what=web_local",
-      "encoding": "ISO-8859-1",
-      "id": 29
-    },
-
-    "fonecta_02_fi": {
-      "name": "Fonecta 02.fi",
-      "keyword": "www.fi",
-      "favicon_url": "http://www.02.fi/img/favicon.ico",
-      "search_url": "http://www.02.fi/haku/{searchTerms}",
-      "id": 46
-    },
-
-    "goo": {
-      "name": "goo",
-      "keyword": "search.goo.ne.jp",
-      "favicon_url": "http://goo.ne.jp/favicon.ico",
-      "search_url": "http://search.goo.ne.jp/web.jsp?MT={searchTerms}&IE={inputEncoding}",
-      "type": "SEARCH_ENGINE_GOO",
-      "id": 23
-    },
-
     "google": {
       "name": "Google",
       "keyword": "google.com",
       "favicon_url": "http://www.google.com/favicon.ico",
       "search_url": "{google:baseURL}search?q={searchTerms}&{google:RLZ}{google:originalQueryForSuggestion}{google:assistedQueryStats}{google:searchFieldtrialParameter}{google:searchClient}{google:sourceId}{google:instantExtendedEnabledParameter}{google:omniboxStartMarginParameter}ie={inputEncoding}",
-      "suggest_url": "{google:baseSuggestURL}search?{google:searchFieldtrialParameter}client={google:suggestClient}&q={searchTerms}&{google:cursorPosition}{google:zeroPrefixUrl}sugkey={google:suggestAPIKeyParameter}",
+      "suggest_url": "{google:baseSuggestURL}search?{google:searchFieldtrialParameter}client={google:suggestClient}&q={searchTerms}&{google:cursorPosition}{google:zeroPrefixUrl}{google:pageClassification}sugkey={google:suggestAPIKeyParameter}",
       "instant_url": "{google:baseURL}webhp?sourceid=chrome-instant&{google:RLZ}{google:instantEnabledParameter}{google:instantExtendedEnabledParameter}{google:ntpIsThemedParameter}{google:omniboxStartMarginParameter}ie={inputEncoding}",
       "image_url": "{google:baseURL}searchbyimage/upload",
-      "image_url_post_params": "encoded_image={google:imageThumbnail},image_url={google:imageURL},sbisrc={google:imageSearchSource}",
+      "image_url_post_params": "image_content={google:imageThumbnail},image_url={google:imageURL},sbisrc={google:imageSearchSource}",
       "alternate_urls": [
         "{google:baseURL}#q={searchTerms}",
         "{google:baseURL}search#q={searchTerms}",
@@ -862,85 +501,15 @@
       "id": 1
     },
 
-    "guruji": {
-      "name": "guruji",
-      "keyword": "guruji.com",
-      "favicon_url": "http://guruji.com/favicon.ico",
-      "search_url": "http://guruji.com/search?q={searchTerms}",
-      "id": 38
-    },
-
-    "hispavista": {
-      "name": "hispavista",
-      "keyword": "hispavista.com",
-      "favicon_url": "http://buscar.hispavista.com/favicon.ico",
-      "search_url": "http://buscar.hispavista.com/?cadena={searchTerms}",
-      "encoding": "iso-8859-1",
-      "id": 18
-    },
-
-    "in": {
-      "name": "in.gr",
-      "keyword": "in.gr",
-      "favicon_url": "http://www.in.gr/favicon.ico",
-      "search_url": "http://find.in.gr/?qs={searchTerms}",
-      "encoding": "ISO-8859-7",
-      "type": "SEARCH_ENGINE_IN",
-      "id": 54
-    },
-
-    "jabse": {
-      "name": "Jabse",
-      "keyword": "jabse.com",
-      "favicon_url": "http://www.jabse.com/favicon.ico",
-      "search_url": "http://www.jabse.com/searchmachine.php?query={searchTerms}",
-      "id": 19
-    },
-
-    "jubii": {
-      "name": "Jubii",
-      "keyword": "jubii.dk",
-      "favicon_url": "http://search.jubii.dk/favicon_jubii.ico",
-      "search_url": "http://search.jubii.dk/cgi-bin/pursuit?query={searchTerms}",
-      "encoding": "ISO-8859-1",
-      "id": 28
-    },
-
     "kvasir": {
       "name": "Kvasir",
       "keyword": "kvasir.no",
-      "favicon_url": "http://www.kvasir.no/img/favicon.ico",
-      "search_url": "http://www.kvasir.no/nettsok/searchResult.html?searchExpr={searchTerms}",
-      "encoding": "ISO-8859-1",
+      "favicon_url": "http://www.kvasir.no/grafikk/favicon.ico",
+      "search_url": "http://www.kvasir.no/alle?q={searchTerms}",
+      "type": "SEARCH_ENGINE_KVASIR",
       "id": 73
     },
 
-    "latne": {
-      "name": "LATNE",
-      "keyword": "latne.lv",
-      "favicon_url": "http://latne.lv/favicon.ico",
-      "search_url": "http://latne.lv/siets.php?q={searchTerms}",
-      "id": 71
-    },
-
-    "leit": {
-      "name": "leit.is",
-      "keyword": "leit.is",
-      "favicon_url": "http://leit.is/leit.ico",
-      "search_url": "http://leit.is/query.aspx?qt={searchTerms}",
-      "encoding": "ISO-8859-1",
-      "id": 59
-    },
-
-    "libero": {
-      "name": "Libero",
-      "keyword": "libero.it",
-      "favicon_url": "http://arianna.libero.it/favicon.ico",
-      "search_url": "http://arianna.libero.it/search/abin/integrata.cgi?query={searchTerms}",
-      "encoding": "ISO-8859-1",
-      "id": 63
-    },
-
     "mail_ru": {
       "name": "@MAIL.RU",
       "keyword": "mail.ru",
@@ -952,177 +521,44 @@
       "id": 83
     },
 
-    "maktoob": {
-      "name": "\u0645\u0643\u062a\u0648\u0628",
-      "keyword": "maktoob.com",
-      "favicon_url": "http://www.maktoob.com/favicon.ico",
-      "search_url": "http://www.maktoob.com/searchResult.php?q={searchTerms}",
-      "id": 13
-    },
-
-    "masrawy": {
-      "name": "\u0645\u0635\u0631\u0627\u0648\u064a",
-      "keyword": "masrawy.com",
-      "favicon_url": "http://www.masrawy.com/new/images/masrawy.ico",
-      "search_url": "http://masrawy.com/new/search.aspx?sr={searchTerms}",
-      "encoding": "windows-1256",
-      "id": 14
-    },
-
-    "mynet": {
-      "name": "MYNET",
-      "keyword": "mynet.com",
-      "favicon_url": "http://img.mynet.com/mynetfavori.ico",
-      "search_url": "http://arama.mynet.com/search.aspx?q={searchTerms}&pg=q",
-      "encoding": "windows-1254",
-      "id": 101
-    },
-
     "najdi": {
       "name": "Najdi.si",
       "keyword": "najdi.si",
-      "favicon_url": "http://www.najdi.si/master/favicon.ico",
+      "favicon_url": "http://nsi2.sdn.si/master/v2/favicon.ico",
       "search_url": "http://www.najdi.si/search.jsp?q={searchTerms}",
       "type": "SEARCH_ENGINE_NAJDI",
       "id": 87
     },
 
     "nate": {
-      "name": "\ub124\uc774\ud2b8\ub2f7\ucef4",
+      "name": "\ub124\uc774\ud2b8",
       "keyword": "nate.com",
-      "favicon_url": "http://nate.search.empas.com/favicon.ico",
-      "search_url": "http://nate.search.empas.com/search/all.html?q={searchTerms}",
+      "favicon_url": "http://search.nate.com/favicon.ico",
+      "search_url": "http://search.nate.com/search/all.html?q={searchTerms}",
       "encoding": "EUC-KR",
+      "type": "SEARCH_ENGINE_NATE",
       "id": 69
     },
 
     "naver": {
       "name": "\ub124\uc774\ubc84",
       "keyword": "naver.com",
-      "favicon_url": "http://search.naver.com/favicon.ico",
+      "favicon_url": "http://static.naver.net/www/favicon.ico",
       "search_url": "http://search.naver.com/search.naver?ie={inputEncoding}&query={searchTerms}",
-      "suggest_url": "http://ac.search.naver.com/autocompl?m=s&ie={inputEncoding}&oe=utf-8&q={searchTerms}",
+      "suggest_url": "http://ac.search.naver.com/autocompl?m=s&ie={inputEncoding}&oe={outputEncoding}&q={searchTerms}",
       "type": "SEARCH_ENGINE_NAVER",
       "id": 67
     },
 
-    "neti": {
-      "name": "NETI",
-      "keyword": "neti.ee",
-      "favicon_url": "http://www.neti.ee/favicon.ico",
-      "search_url": "http://www.neti.ee/cgi-bin/otsing?query={searchTerms}",
-      "encoding": "ISO-8859-1",
-      "type": "SEARCH_ENGINE_NETI",
-      "id": 44
-    },
-
-    "netsprint": {
-      "name": "NetSprint",
-      "keyword": "netsprint.pl",
-      "favicon_url": "http://netsprint.pl/favicon.ico",
-      "search_url": "http://www.netsprint.pl/serwis/search?q={searchTerms}",
-      "type": "SEARCH_ENGINE_NETSPRINT",
-      "id": 30
-    },
-
-    "nur_kz": {
-      "name": "NUR.KZ",
-      "keyword": "nur.kz",
-      "favicon_url": "http://www.nur.kz/favicon_kz.ico",
-      "search_url": "http://search.nur.kz/?encoding={inputEncoding}&query={searchTerms}",
-      "id": 20
-    },
-
-    "ok": {
-      "name": "OK.hu",
-      "keyword": "ok.hu",
-      "favicon_url": "http://ok.hu/gfx/favicon.ico",
-      "search_url": "http://ok.hu/katalogus?q={searchTerms}",
-      "encoding": "ISO-8859-2",
-      "type": "SEARCH_ENGINE_OK",
-      "id": 6
-    },
-
     "onet": {
       "name": "Onet.pl",
       "keyword": "onet.pl",
       "favicon_url": "http://szukaj.onet.pl/favicon.ico",
-      "search_url": "http://szukaj.onet.pl/query.html?qt={searchTerms}",
-      "encoding": "ISO-8859-2",
+      "search_url": "http://szukaj.onet.pl/wyniki.html?qt={searchTerms}",
+      "type": "SEARCH_ENGINE_ONET",
       "id": 75
     },
 
-    "pogodak_rs": {
-      "name": "Pogodak!",
-      "keyword": "pogodak.rs",
-      "favicon_url": "http://www.pogodak.rs/favicon.ico",
-      "search_url": "http://www.pogodak.rs/search.jsp?q={searchTerms}",
-      "type": "SEARCH_ENGINE_POGODAK",
-      "id": 24
-    },
-
-    "rambler": {
-      "name": "Rambler",
-      "keyword": "rambler.ru",
-      "favicon_url": "http://www.rambler.ru/favicon.ico",
-      "search_url": "http://www.rambler.ru/srch?words={searchTerms}",
-      "encoding": "windows-1251",
-      "type": "SEARCH_ENGINE_RAMBLER",
-      "id": 16
-    },
-
-    "rediff": {
-      "name": "Rediff",
-      "keyword": "rediff.com",
-      "favicon_url": "http://search1.rediff.com/favicon.ico",
-      "search_url": "http://search1.rediff.com/dirsrch/default.asp?MT={searchTerms}",
-      "id": 37
-    },
-
-    "rednano": {
-      "name": "Rednano",
-      "keyword": "rednano.sg",
-      "favicon_url": "http://rednano.sg/favicon.ico",
-      "search_url": "http://rednano.sg/sfe/lwi.action?querystring={searchTerms}",
-      "id": 41
-    },
-
-    "sanook": {
-      "name": "\u0e2a\u0e19\u0e38\u0e01!",
-      "keyword": "sanook.com",
-      "favicon_url": "http://search.sanook.com/favicon.ico",
-      "search_url": "http://search.sanook.com/search.php?q={searchTerms}",
-      "type": "SEARCH_ENGINE_SANOOK",
-      "id": 100
-    },
-
-    "sapo": {
-      "name": "SAPO",
-      "keyword": "sapo.pt",
-      "favicon_url": "http://imgs.sapo.pt/images/sapo.ico",
-      "search_url": "http://pesquisa.sapo.pt/?q={searchTerms}",
-      "suggest_url": "http://pesquisa.sapo.pt/livesapo?q={searchTerms}",
-      "type": "SEARCH_ENGINE_SAPO",
-      "id": 77
-    },
-
-    "search_de_CH": {
-      "name": "search.ch",
-      "keyword": "search.ch",
-      "favicon_url": "http://www.search.ch/favicon.ico",
-      "search_url": "http://www.search.ch/index.de.html?q={searchTerms}",
-      "encoding": "ISO-8859-1",
-      "id": 51
-    },
-
-    "search_fr_CH": {
-      "name": "search.ch",
-      "keyword": "search.ch_",  // search.ch is taken by search_de_CH.
-      "favicon_url": "http://www.search.ch/favicon.ico",
-      "search_url": "http://www.search.ch/index.fr.html?q={searchTerms}",
-      "id": 22
-    },
-
     "seznam": {
       "name": "Seznam",
       "keyword": "seznam.cz",
@@ -1133,72 +569,43 @@
       "id": 25
     },
 
-    "terra_ar": {
-      "name": "Terra Argentina",
-      "keyword": "terra.com.ar",
-      "favicon_url": "http://buscar.terra.com.ar/favicon.ico",
-      "search_url": "http://buscar.terra.com.ar/Default.aspx?query={searchTerms}&source=Search",
-      "encoding": "ISO-8859-1",
-      "id": 90
+    "sogou": {
+      "name": "\u641c\u72d7",
+      "keyword": "sogou.com",
+      "favicon_url": "http://www.sogou.com/favicon.ico",
+      "search_url": "http://www.sogou.com/web?ie={inputEncoding}&query={searchTerms}",
+      "type": "SEARCH_ENGINE_SOGOU",
+      "id": 56
     },
 
-    "terra_es": {
-      "name": "Terra",
-      "keyword": "terra.es",
-      "favicon_url": "http://buscador.terra.es/favicon.ico",
-      "search_url": "http://buscador.terra.es/Default.aspx?query={searchTerms}&source=Search",
-      "encoding": "ISO-8859-1",
-      "id": 90
+    "soso": {
+      "name": "\u641c\u641c",
+      "keyword": "soso.com",
+      "favicon_url": "http://www.soso.com/favicon.ico",
+      "search_url": "http://www.soso.com/q?ie={inputEncoding}&w={searchTerms}",
+      "type": "SEARCH_ENGINE_SOSO",
+      "id": 58
     },
 
-    "tut": {
-      "name": "TUT.BY",
-      "keyword": "tut.by",
-      "favicon_url": "http://www.tut.by/favicon.ico",
-      "search_url": "http://search.tut.by/?query={searchTerms}",
-      "encoding": "windows-1251",
-      "type": "SEARCH_ENGINE_TUT",
-      "id": 17
-    },
-
-    "uol": {
-      "name": "UOL Busca",
-      "keyword": "busca.uol.com.br",
-      "favicon_url": "http://busca.uol.com.br/favicon.ico",
-      "search_url": "http://busca.uol.com.br/www/index.html?q={searchTerms}",
-      "encoding": "ISO-8859-1",
-      "id": 82
+    "vinden": {
+      "name": "Vinden.nl",
+      "keyword": "vinden.nl",
+      "favicon_url": "http://www.vinden.nl/favicon.ico",
+      "search_url": "http://www.vinden.nl/?q={searchTerms}",
+      "type": "SEARCH_ENGINE_VINDEN",
+      "id": 53
     },
 
     "virgilio": {
       "name": "Virgilio",
       "keyword": "virgilio.it",
-      "favicon_url": "http://ricerca.alice.it/favicon.ico",
-      "search_url": "http://ricerca.alice.it/ricerca?qs={searchTerms}",
+      "favicon_url": "http://ricerca.virgilio.it/common/favicon.ico",
+      "search_url": "http://ricerca.virgilio.it/ricerca?qs={searchTerms}",
       "encoding": "ISO-8859-1",
       "type": "SEARCH_ENGINE_VIRGILIO",
       "id": 62
     },
 
-    "walla": {
-      "name": "\u05d5\u05d5\u05d0\u05dc\u05d4!",
-      "keyword": "walla.co.il",
-      "favicon_url": "http://www.walla.co.il/favicon.ico",
-      "search_url": "http://search.walla.co.il/?e=hew&q={searchTerms}",
-      "encoding": "windows-1255",
-      "type": "SEARCH_ENGINE_WALLA",
-      "id": 55
-    },
-
-    "wp": {
-      "name": "Wirtualna Polska",
-      "keyword": "wp.pl",
-      "favicon_url": "http://szukaj.wp.pl/favicon.ico",
-      "search_url": "http://szukaj.wp.pl/szukaj.html?szukaj={searchTerms}",
-      "encoding": "ISO-8859-2",
-      "id": 76
-    },
-
     "yahoo": {
       "name": "Yahoo!",
       "keyword": "yahoo.com",
@@ -1209,9 +616,6 @@
       "id": 2
     },
 
-    // For regional Yahoo variants without region-specific suggestion service,
-    // suggestion is disabled. For some of them, we might consider
-    // using a fallback (e.g. de for at/ch, ca or fr for qc, en for nl, no, hk).
     "yahoo_ar": {
       "name": "Yahoo! Argentina",
       "keyword": "ar.yahoo.com",
@@ -1223,10 +627,11 @@
     },
 
     "yahoo_at": {
-      "name": "Yahoo! Suche",
+      "name": "Yahoo! \u00d6sterreich",
       "keyword": "at.yahoo.com",
       "favicon_url": "http://at.search.yahoo.com/favicon.ico",
       "search_url": "http://at.search.yahoo.com/search?ei={inputEncoding}&fr=crmas&p={searchTerms}",
+      "suggest_url": "http://de-sayt.ff.search.yahoo.com/gossip-de-sayt?output=fxjson&command={searchTerms}",
       "type": "SEARCH_ENGINE_YAHOO",
       "id": 2
     },
@@ -1241,6 +646,18 @@
       "id": 2
     },
 
+    // For regional Yahoo variants without a region-specific suggestion service,
+    // suggestion is disabled. For some of them, we might consider using one of
+    // the other language/country URLs as a fallback.
+    "yahoo_be": {
+      "name": "Yahoo! Belgi\u00eb",
+      "keyword": "be.yahoo.com",
+      "favicon_url": "http://be.search.yahoo.com/favicon.ico",
+      "search_url": "http://be.search.yahoo.com/search?ei={inputEncoding}&fr=crmas&p={searchTerms}",
+      "type": "SEARCH_ENGINE_YAHOO",
+      "id": 2
+    },
+
     "yahoo_br": {
       "name": "Yahoo! Brasil",
       "keyword": "br.yahoo.com",
@@ -1262,10 +679,11 @@
     },
 
     "yahoo_ch": {
-      "name": "Yahoo! Suche",
+      "name": "Yahoo! Schweiz",
       "keyword": "ch.yahoo.com",
       "favicon_url": "http://ch.search.yahoo.com/favicon.ico",
       "search_url": "http://ch.search.yahoo.com/search?ei={inputEncoding}&fr=crmas&p={searchTerms}",
+      "suggest_url": "http://de-sayt.ff.search.yahoo.com/gossip-de-sayt?output=fxjson&command={searchTerms}",
       "type": "SEARCH_ENGINE_YAHOO",
       "id": 2
     },
@@ -1280,16 +698,6 @@
       "id": 2
     },
 
-    "yahoo_cn": {
-      "name": "\u4e2d\u56fd\u96c5\u864e",
-      "keyword": "cn.yahoo.com",
-      "favicon_url": "http://search.cn.yahoo.com/favicon.ico",
-      "search_url": "http://search.cn.yahoo.com/search?ei={inputEncoding}&fr=crmas&p={searchTerms}",
-      "encoding": "GB2312",
-      "type": "SEARCH_ENGINE_YAHOO",
-      "id": 2
-    },
-
     "yahoo_co": {
       "name": "Yahoo! Colombia",
       "keyword": "co.yahoo.com",
@@ -1330,7 +738,7 @@
     },
 
     "yahoo_fi": {
-      "name": "Yahoo!-haku",
+      "name": "Yahoo! Suomi",
       "keyword": "fi.yahoo.com",
       "favicon_url": "http://fi.search.yahoo.com/favicon.ico",
       "search_url": "http://fi.search.yahoo.com/search?ei={inputEncoding}&fr=crmas&p={searchTerms}",
@@ -1348,11 +756,32 @@
       "id": 2
     },
 
+    "yahoo_fr_be": {
+      "name": "Yahoo! Belgique",
+      "keyword": "fr-be.yahoo.com",
+      "favicon_url": "http://fr.search.yahoo.com/favicon.ico",
+      "search_url": "http://fr.search.yahoo.com/search?ei={inputEncoding}&fr=crmas&p={searchTerms}",
+      "suggest_url": "http://fr-sayt.ff.search.yahoo.com/gossip-fr-sayt?output=fxjson&command={searchTerms}",
+      "type": "SEARCH_ENGINE_YAHOO",
+      "id": 5  // Can't be 2 as this has to appear in the Belgium list alongside
+               // yahoo_be.
+    },
+
+    "yahoo_gr": {
+      "name": "Yahoo! \u0395\u03bb\u03bb\u03ac\u03b4\u03b1\u03c2",
+      "keyword": "gr.yahoo.com",
+      "favicon_url": "http://gr.search.yahoo.com/favicon.ico",
+      "search_url": "http://gr.search.yahoo.com/search?ei={inputEncoding}&fr=crmas&p={searchTerms}",
+      "type": "SEARCH_ENGINE_YAHOO",
+      "id": 2
+    },
+
     "yahoo_hk": {
       "name": "Yahoo! Hong Kong",
       "keyword": "hk.yahoo.com",
       "favicon_url": "http://hk.search.yahoo.com/favicon.ico",
       "search_url": "http://hk.search.yahoo.com/search?ei={inputEncoding}&fr=crmas&p={searchTerms}",
+      "suggest_url": "http://hk-sayt.ff.search.yahoo.com/gossip-hk-sayt?output=fxjson&command={searchTerms}",
       "type": "SEARCH_ENGINE_YAHOO",
       "id": 2
     },
@@ -1377,43 +806,23 @@
       "id": 2
     },
 
-    "yahoo_it": {
-      "name": "Yahoo! Italia",
-      "keyword": "it.yahoo.com",
-      "favicon_url": "http://it.search.yahoo.com/favicon.ico",
-      "search_url": "http://it.search.yahoo.com/search?ei={inputEncoding}&fr=crmas&p={searchTerms}",
-      "suggest_url": "http://it-sayt.ff.search.yahoo.com/gossip-it-sayt?output=fxjson&command={searchTerms}",
-      "type": "SEARCH_ENGINE_YAHOO",
-      "id": 2
-    },
-
     "yahoo_jp": {
       "name": "Yahoo! JAPAN",
       "keyword": "yahoo.co.jp",
       "favicon_url": "http://search.yahoo.co.jp/favicon.ico",
       "search_url": "http://search.yahoo.co.jp/search?ei={inputEncoding}&fr=crmas&p={searchTerms}",
-      "type": "SEARCH_ENGINE_YAHOOJP",
-      "id": 2
-    },
-
-    "yahoo_kr": {
-      "name": "\uc57c\ud6c4! \ucf54\ub9ac\uc544",
-      "keyword": "kr.yahoo.com",
-      "favicon_url": "http://kr.search.yahoo.com/favicon.ico",
-      "search_url": "http://kr.search.yahoo.com/search?ei={inputEncoding}&fr=crmas&p={searchTerms}",
-      "suggest_url": "http://kr.atc.search.yahoo.com/atcx.php?property=main&ot=fxjson&ei=utf8&eo=utf8&command={searchTerms}",
+      "suggest_url": "http://search.yahooapis.jp/AssistSearchService/V2/webassistSearch?p={searchTerms}&appid=oQsoxcyxg66enp0TYoirkKoryq6rF8bK76mW0KYxZ0v0WPLtn.Lix6wy8F_LwGWHUII-&output=fxjson&fr=crmas",
       "type": "SEARCH_ENGINE_YAHOO",
       "id": 2
     },
 
-    "yahoo_malaysia": {
-      "name": "Yahoo! Malaysia",
-      "keyword": "malaysia.yahoo.com",
-      "favicon_url": "http://malaysia.search.yahoo.com/favicon.ico",
-      "search_url": "http://malaysia.search.yahoo.com/search?ei={inputEncoding}&fr=crmas&p={searchTerms}",
-      "suggest_url": "http://my-sayt.ff.search.yahoo.com/gossip-my-sayt?output=fxjson&command={searchTerms}",
+    "yahoo_maktoob": {
+      "name": "Yahoo!\u200e \u0645\u0643\u062a\u0648\u0628",
+      "keyword": "maktoob.yahoo.com",
+      "favicon_url": "http://maktoob.yahoo.com/favicon.ico",
+      "search_url": "http://maktoob.search.yahoo.com/search?ei={inputEncoding}&fr=crmas&p={searchTerms}",
       "type": "SEARCH_ENGINE_YAHOO",
-      "id": 2
+      "id": 13  // Should be 2, but is 13 due to historical reasons.
     },
 
     "yahoo_mx": {
@@ -1426,26 +835,28 @@
       "id": 2
     },
 
+    "yahoo_my": {
+      "name": "Yahoo! Malaysia",
+      "keyword": "malaysia.yahoo.com",
+      "favicon_url": "http://malaysia.search.yahoo.com/favicon.ico",
+      "search_url": "http://malaysia.search.yahoo.com/search?ei={inputEncoding}&fr=crmas&p={searchTerms}",
+      "suggest_url": "http://my-sayt.ff.search.yahoo.com/gossip-my-sayt?output=fxjson&command={searchTerms}",
+      "type": "SEARCH_ENGINE_YAHOO",
+      "id": 2
+    },
+
     "yahoo_nl": {
       "name": "Yahoo! Nederland",
       "keyword": "nl.yahoo.com",
       "favicon_url": "http://nl.search.yahoo.com/favicon.ico",
       "search_url": "http://nl.search.yahoo.com/search?ei={inputEncoding}&fr=crmas&p={searchTerms}",
-      "type": "SEARCH_ENGINE_YAHOO",
-      "id": 2
-    },
-
-    "yahoo_no": {
-      "name": "Yahoo! Norge",
-      "keyword": "no.yahoo.com",
-      "favicon_url": "http://no.search.yahoo.com/favicon.ico",
-      "search_url": "http://no.search.yahoo.com/search?ei={inputEncoding}&fr=crmas&p={searchTerms}",
+      "suggest_url": "http://ff.search.yahoo.com/gossip?output=fxjson&command={searchTerms}",
       "type": "SEARCH_ENGINE_YAHOO",
       "id": 2
     },
 
     "yahoo_nz": {
-      "name": "Yahoo!Xtra",
+      "name": "Yahoo! New Zealand",
       "keyword": "nz.yahoo.com",
       "favicon_url": "http://nz.search.yahoo.com/favicon.ico",
       "search_url": "http://nz.search.yahoo.com/search?ei={inputEncoding}&fr=crmas&p={searchTerms}",
@@ -1479,11 +890,21 @@
       "keyword": "qc.yahoo.com",
       "favicon_url": "http://qc.search.yahoo.com/favicon.ico",
       "search_url": "http://qc.search.yahoo.com/search?ei={inputEncoding}&fr=crmas&p={searchTerms}",
-      "type": "SEARCH_ENGINE_YAHOOQC",
+      "suggest_url": "http://gossip.ca.yahoo.com/gossip-ca-sayt?output=fxjsonp&command={searchTerms}",
+      "type": "SEARCH_ENGINE_YAHOO",
       "id": 5  // Can't be 2 as this has to appear in the Canada list alongside
                // yahoo_ca.
     },
 
+    "yahoo_ro": {
+      "name": "Yahoo! Rom\u00e2nia",
+      "keyword": "ro.yahoo.com",
+      "favicon_url": "http://ro.search.yahoo.com/favicon.ico",
+      "search_url": "http://ro.search.yahoo.com/search?ei={inputEncoding}&fr=crmas&p={searchTerms}",
+      "type": "SEARCH_ENGINE_YAHOO",
+      "id": 2
+    },
+
     "yahoo_ru": {
       "name": "Yahoo! \u043f\u043e-\u0440\u0443\u0441\u0441\u043a\u0438",
       "keyword": "ru.yahoo.com",
@@ -1522,11 +943,21 @@
       "id": 2
     },
 
+    "yahoo_tr": {
+      "name": "Yahoo! T\u00fcrkiye",
+      "keyword": "tr.yahoo.com",
+      "favicon_url": "http://tr.search.yahoo.com/favicon.ico",
+      "search_url": "http://tr.search.yahoo.com/search?ei={inputEncoding}&fr=crmas&p={searchTerms}",
+      "type": "SEARCH_ENGINE_YAHOO",
+      "id": 2
+    },
+
     "yahoo_tw": {
       "name": "Yahoo!\u5947\u6469",
       "keyword": "tw.yahoo.com",
       "favicon_url": "http://tw.search.yahoo.com/favicon.ico",
       "search_url": "http://tw.search.yahoo.com/search?ei={inputEncoding}&fr=crmas&p={searchTerms}",
+      "suggest_url": "http://hk-sayt.ff.search.yahoo.com/gossip-hk-sayt?output=fxjson&command={searchTerms}",
       "type": "SEARCH_ENGINE_YAHOO",
       "id": 2
     },
@@ -1561,12 +992,13 @@
       "id": 2
     },
 
-    "yamli": {
-      "name": "Yamli",
-      "keyword": "yamli.com",
-      "favicon_url": "http://www.yamli.com/favicon.ico",
-      "search_url": "http://www.yamli.com/#q={searchTerms}",
-      "id": 11
+    "yahoo_za": {
+      "name": "Yahoo! South Africa",
+      "keyword": "sa.yahoo.com",
+      "favicon_url": "http://sa.search.yahoo.com/favicon.ico",
+      "search_url": "http://sa.search.yahoo.com/search?ei={inputEncoding}&fr=crmas&p={searchTerms}",
+      "type": "SEARCH_ENGINE_YAHOO",
+      "id": 2
     },
 
     "yandex_ru": {
@@ -1589,16 +1021,6 @@
       "id": 15
     },
 
-    "zoznam": {
-      "name": "Zoznam",
-      "keyword": "zoznam.sk",
-      "favicon_url": "http://zoznam.sk/favicon.ico",
-      "search_url": "http://zoznam.sk/hladaj.fcgi?s={searchTerms}",
-      "encoding": "windows-1250",
-      "type": "SEARCH_ENGINE_ZOZNAM",
-      "id": 85
-    },
-
 
     // UMA-only engines ////////////////////////////////////////////////////////
 
@@ -1606,122 +1028,369 @@
     // are listed in |kAllEngines|, however, so that GetEngineType can find them
     // for UMA reporting purposes.
 
-    "all_by": {
-      "name": "ALL.BY",
-      "keyword": "all.by",
-      "favicon_url": "http://all.by/favicon.ico",
-      "search_url": "http://www.all.by/cgi-bin/search.cgi?mode=by&query={searchTerms}",
-      "type": "SEARCH_ENGINE_ALL_BY",
-      "id": 33
+    "atlas_cz": {
+      "name": "Atlas.cz",
+      "keyword": "atlas.cz",
+      "favicon_url": "http://searchatlas.centrum.cz/favicon.ico",
+      "search_url": "http://searchatlas.centrum.cz/?q={searchTerms}",
+      "suggest_url": "http://radce.centrum.cz/?q={searchTerms}&of=1",
+      "type": "SEARCH_ENGINE_ATLAS",
+      "id": 27
     },
 
-    "aport": {
-      "name": "Aport",
-      "keyword": "aport.ru",
-      "favicon_url": "http://www.aport.ru/favicon.png",
-      "search_url": "http://www.aport.ru/search/?r={searchTerms}",
-      "type": "SEARCH_ENGINE_APORT",
-      "id": 34
+    "atlas_sk": {
+      "name": "ATLAS.SK",
+      "keyword": "atlas.sk",
+      "favicon_url": "http://static.mediacentrum.sk/katalog/atlas.sk/images/favicon.ico",
+      "search_url": "http://hladaj.atlas.sk/fulltext/?phrase={searchTerms}",
+      "id": 27
     },
 
     "avg": {
-      "name": "AVG Secure Search",
+      "name": "AVG",
       "keyword": "search.avg.com",
       "favicon_url": "http://search.avg.com/favicon.ico",
-      "search_url": "http://search.avg.com/route/?q={searchTerms}&lng={language}",
+      "search_url": "http://search.avg.com/search?q={searchTerms}",
+      "alternate_urls": [
+        "http://isearch.avg.com/search?q={searchTerms}",
+        "http://search.avg.com/route/?q={searchTerms}&lng={language}"
+      ],
       "type": "SEARCH_ENGINE_AVG",
       "id": 50
     },
 
-    "avg_i": {
-      "name": "AVG Secure Search",
-      "keyword": "isearch.avg.com",
-      "favicon_url": "http://isearch.avg.com/favicon.ico",
-      "search_url": "http://isearch.avg.com/search?q={searchTerms}&lng={language}",
-      "type": "SEARCH_ENGINE_AVG",
-      "id": 52
+    "babylon": {
+      "name": "Babylon",
+      "keyword": "search.babylon.com",
+      "favicon_url": "http://search.babylon.com/favicon.ico",
+      "search_url": "http://search.babylon.com/home?q={searchTerms}",
+      "alternate_urls": [
+        "http://search.babylon.com/?q={searchTerms}"
+      ],
+      "type": "SEARCH_ENGINE_BABYLON",
+      "id": 64
     },
 
     "conduit": {
       "name": "Conduit",
       "keyword": "conduit.com",
-      "favicon_url": "http://search.conduit.com/favicon.ico",
-      "search_url": "http://search.conduit.com/Results.aspx?q={searchTerms}",
+      "favicon_url": "http://www.conduit.com/favicon.ico",
+      "search_url": "http://www.conduit.com/search?q={searchTerms}&ie={inputEncoding}&cx=010301873083402539744%3Anxaq5wgrtuo&cof=forid%3A11",
+      "alternate_urls": [
+        "http://search.conduit.com/Results.aspx?q={searchTerms}"
+      ],
       "type": "SEARCH_ENGINE_CONDUIT",
       "id": 36
     },
 
-    "icq": {
-      "name": "ICQ",
-      "keyword": "icq.com",
-      "favicon_url": "http://www.icq.com/favicon.ico",
-      "search_url": "http://search.icq.com/search/results.php?q={searchTerms}",
-      "type": "SEARCH_ENGINE_ICQ",
-      "id": 39
+    "delfi_lt": {
+      "name": "DELFI",
+      "keyword": "delfi.lt",
+      "favicon_url": "http://www.delfi.lt/favicon.ico",
+      "search_url": "http://www.delfi.lt/paieska/?q={searchTerms}",
+      "type": "SEARCH_ENGINE_DELFI",
+      "id": 45
     },
 
-    "meta_ua": {
-      "name": "Meta-Ukraine",
-      "keyword": "meta.ua",
-      "favicon_url": "http://meta.ua/favicon.ico",
-      "search_url": "http://meta.ua/search.asp?q={searchTerms}",
-      "type": "SEARCH_ENGINE_META_UA",
-      "id": 40
+    "delfi_lv": {
+      "name": "DELFI",
+      "keyword": "delfi.lv",
+      "favicon_url": "http://g1.delphi.lv/favicon.ico",
+      "search_url": "http://www.delfi.lv/search_all/?ie={inputEncoding}&q={searchTerms}&lang={language}&cx=partner-pub-7754285690273419%3A1507605038&cof=FORID%3A10",
+      "type": "SEARCH_ENGINE_DELFI",
+      "id": 45
     },
 
-    "metabot_ru": {
-      "name": "Metabot",
-      "keyword": "metabot.ru",
-      "favicon_url": "http://www.metabot.ru/favicon.ico",
-      "search_url": "http://results.metabot.ru/?st={searchTerms}",
-      "type": "SEARCH_ENGINE_METABOT_RU",
-      "id": 42
+    "delta": {
+      "name": "Delta",
+      "keyword": "delta-search.com",
+      "favicon_url": "http://www.delta-search.com/favicon.ico",
+      "search_url": "http://www.delta-search.com/home?q={searchTerms}",
+      "alternate_urls": [
+        "http://www.delta-search.com/?q={searchTerms}",
+        "http://www1.delta-search.com/home?q={searchTerms}",
+        "http://www1.delta-search.com/?q={searchTerms}",
+        "http://www2.delta-search.com/home?q={searchTerms}",
+        "http://www2.delta-search.com/?q={searchTerms}",
+        "http://www.search.delta-search.com/home?q={searchTerms}",
+        "http://www.search.delta-search.com/?q={searchTerms}",
+        "http://www.yhs.delta-search.com/home?q={searchTerms}",
+        "http://www.yhs.delta-search.com/?q={searchTerms}",
+        "http://mixidj.delta-search.com/home?q={searchTerms}",
+        "http://mixidj.delta-search.com/?q={searchTerms}",
+        "http://www.search.delta-search.com/home?q={searchTerms}",
+        "http://www.search.delta-search.com/?q={searchTerms}"
+      ],
+      "type": "SEARCH_ENGINE_DELTA",
+      "id": 66
+    },
+
+    "funmoods": {
+      "name": "Funmoods",
+      "keyword": "searchfunmoods.com",
+      "favicon_url": "http://searchfunmoods.com/favicon.ico",
+      "search_url": "http://searchfunmoods.com/results.php?q={searchTerms}",
+      "type": "SEARCH_ENGINE_FUNMOODS",
+      "id": 60
+    },
+
+    "goo": {
+      "name": "goo",
+      "keyword": "search.goo.ne.jp",
+      "favicon_url": "http://goo.ne.jp/favicon.ico",
+      "search_url": "http://search.goo.ne.jp/web.jsp?MT={searchTerms}&IE={inputEncoding}",
+      "suggest_url": "http://search.goo.ne.jp/sgt.jsp?MT={searchTerms}&CL=plugin&FM=json&IE={inputEncoding}",
+      "encoding": "EUC-JP",
+      "type": "SEARCH_ENGINE_GOO",
+      "id": 23
+    },
+
+    "imesh": {
+      "name": "IMesh",
+      "keyword": "search.imesh.net",
+      "favicon_url": "http://search.imesh.net/favicon.ico",
+      "search_url": "http://search.imesh.net/music?hl={language}&si={searchTerms}",
+      "type": "SEARCH_ENGINE_IMESH",
+      "id": 81
+    },
+
+    "iminent": {
+      "name": "SearchTheWeb",
+      "keyword": "iminent.com",
+      "favicon_url": "http://search.iminent.com/Shared/Images/favicon_gl.ico",
+      "search_url": "http://search.iminent.com/?q={searchTerms}",
+      "alternate_urls": [
+        "http://search.iminent.com/SearchTheWeb/v6/1033/homepage/Default.aspx#q={searchTerms}",
+        "http://search.iminent.com/SearchTheWeb/v6/1033/homepage/Result.aspx#q={searchTerms}",
+        "http://start.iminent.com/?q={searchTerms}",
+        "http://start.iminent.com/StartWeb/1033/homepage/#q={searchTerms}"
+      ],
+      "type": "SEARCH_ENGINE_IMINENT",
+      "id": 79
+    },
+
+    "in": {
+      "name": "in.gr",
+      "keyword": "in.gr",
+      "favicon_url": "http://find.in.gr/Themes/1/Default/Media/Layout/icon_in.png",
+      "search_url": "http://find.in.gr/?q={searchTerms}&ie={inputEncoding}&cx=partner-pub-3451081775397713%3Aklnvxp4nycj&cof=FORID%3A9",
+      "type": "SEARCH_ENGINE_IN",
+      "id": 54
+    },
+
+    "incredibar": {
+      "name": "MyStart",
+      "keyword": "mystart.incredibar.com",
+      "favicon_url": "http://search.incredibar.com/favicon.ico",
+      "search_url": "http://search.incredibar.com/search.php?q={searchTerms}",
+      "alternate_urls": [
+        "http://search.incredibar.com/?q={searchTerms}",
+        "http://mystart.incredibar.com/?search={searchTerms}"
+      ],
+      "type": "SEARCH_ENGINE_INCREDIBAR",
+      "id": 74
+    },
+
+    "libero": {
+      "name": "Libero",
+      "keyword": "libero.it",
+      "favicon_url": "http://ms1.iol.it/graph_hf/v.8.3.04/themes/default/img/favicon.ico",
+      "search_url": "http://arianna.libero.it/search/abin/integrata.cgi?query={searchTerms}",
+      "encoding": "ISO-8859-1",
+      "type": "SEARCH_ENGINE_LIBERO",
+      "id": 63
+    },
+
+    "neti": {
+      "name": "NETI",
+      "keyword": "neti.ee",
+      "favicon_url": "http://www.neti.ee/favicon.ico",
+      "search_url": "http://www.neti.ee/cgi-bin/otsing?query={searchTerms}",
+      "suggest_url": "http://www.neti.ee/api/suggestOS?suggestQuery={searchTerms}",
+      "encoding": "ISO-8859-1",
+      "type": "SEARCH_ENGINE_NETI",
+      "id": 44
     },
 
     "nigma": {
-      "name": "Nigma",
+      "name": "\u041d\u0438\u0433\u043c\u0430",
       "keyword": "nigma.ru",
-      "favicon_url": "http://nigma.ru/favicon.ico",
-      "search_url": "http://www.nigma.ru/?s={searchTerms}",
+      "favicon_url": "http://nigma.ru/themes/nigma/img/favicon.ico",
+      "search_url": "http://nigma.ru/?s={searchTerms}",
+      "suggest_url": "http://autocomplete.nigma.ru/complete/query_help.php?suggest=true&q={searchTerms}",
       "type": "SEARCH_ENGINE_NIGMA",
       "id": 43
     },
 
-    "qip": {
-      "name": "QIP",
-      "keyword": "qip.ru",
-      "favicon_url": "http://search.qip.ru/favicon.ico",
-      "search_url": "http://search.qip.ru/?query={searchTerms}",
-      "type": "SEARCH_ENGINE_QIP",
-      "id": 47
+    "ok": {
+      "name": "OK.hu",
+      "keyword": "ok.hu",
+      "favicon_url": "http://ok.hu/gfx/favicon.ico",
+      "search_url": "http://ok.hu/katalogus?q={searchTerms}",
+      "encoding": "ISO-8859-2",
+      "type": "SEARCH_ENGINE_OK",
+      "id": 6
     },
 
-    "ukr_net": {
-      "name": "Ukr.net",
-      "keyword": "ukr.net",
-      "favicon_url": "http://search.ukr.net/i/favicon.ico",
-      "search_url": "http://search.ukr.net/google/search.php?q={searchTerms}",
-      "type": "SEARCH_ENGINE_UKR_NET",
-      "id": 48
+    "rambler": {
+      "name": "\u0420\u0430\u043c\u0431\u043b\u0435\u0440",
+      "keyword": "rambler.ru",
+      "favicon_url": "http://nova.rambler.ru/static/blocks/images/favicon.ico",
+      "search_url": "http://nova.rambler.ru/search?query={searchTerms}",
+      "suggest_url": "http://nova.rambler.ru/suggest?v=3&query={searchTerms}",
+      "type": "SEARCH_ENGINE_RAMBLER",
+      "id": 16
     },
 
-    "webalta": {
-      "name": "Webalta",
-      "keyword": "webalta.ru",
-      "favicon_url": "http://webalta.ru/favicon.ico",
-      "search_url": "http://webalta.ru/search?q={searchTerms}",
-      "type": "SEARCH_ENGINE_WEBALTA",
-      "id": 49
+    "sapo": {
+      "name": "SAPO",
+      "keyword": "sapo.pt",
+      "favicon_url": "http://imgs.sapo.pt/images/sapo.ico",
+      "search_url": "http://pesquisa.sapo.pt/?q={searchTerms}",
+      "suggest_url": "http://pesquisa.sapo.pt/livesapo?q={searchTerms}",
+      "type": "SEARCH_ENGINE_SAPO",
+      "id": 77
+    },
+
+    "searchnu": {
+      "name": "searchnu",
+      "keyword": "searchnu.com",
+      "favicon_url": "http://www.searchnu.com/favicon.ico",
+      "search_url": "http://www.searchnu.com/web?hl={language}&si={searchTerms}",
+      "type": "SEARCH_ENGINE_SEARCHNU",
+      "id": 61
+    },
+
+    "search_results": {
+      "name": "Search-results",
+      "keyword": "search-results.com",
+      "favicon_url": "http://ak.apnstatic.com/media/images/favicon_search-results.ico",
+      "search_url": "http://dts.search-results.com/sr?lng={language}&src=hmp&q={searchTerms}",
+      "alternate_urls": [
+        "http://www.search-results.com/web?q={searchTerms}"
+      ],
+      "type": "SEARCH_ENGINE_SEARCH_RESULTS",
+      "id": 78
+    },
+
+    "snapdo": {
+      "name": "SnapDo",
+      "keyword": "search.snapdo.com",
+      "favicon_url": "http://linkurystoragenorthus.blob.core.windows.net/static/favicon.ico",
+      "search_url": "http://search.snapdo.com/?q={searchTerms}",
+      "alternate_urls": [
+        "http://search.snap.do/?q={searchTerms}",
+        "http://feed.snapdo.com/?q={searchTerms}",
+        "http://feed.snap.do/?q={searchTerms}"
+      ],
+      "type": "SEARCH_ENGINE_SNAPDO",
+      "id": 70
+    },
+
+    "softonic": {
+      "name": "softonic",
+      "keyword": "search.softonic.com",
+      "favicon_url": "http://search.softonic.com/img/favicon.ico",
+      "search_url": "http://search.softonic.com/?q={searchTerms}",
+      "alternate_urls": [
+        "http://en.softonic.com/s/{searchTerms}",
+        "http://www.softonic.com/s/{searchTerms}",
+        "http://www.softonic.com.br/s/{searchTerms}",
+        "http://buscador.softonic.com/?q={searchTerms}",
+        "http://nl.softonic.com/s/{searchTerms}"
+      ],
+      "type": "SEARCH_ENGINE_SOFTONIC",
+      "id": 80
+    },
+
+    "sweetim": {
+      "name": "SweetIM",
+      "keyword": "home.sweetim.com",
+      "favicon_url": "http://search.sweetim.com/favicon.ico",
+      "search_url": "http://search.sweetim.com/search.asp?q={searchTerms}&ln={language}",
+      "type": "SEARCH_ENGINE_SWEETPACKS",
+      "id": 65
+    },
+
+    "sweetpacks": {
+      "name": "Sweetpacks",
+      "keyword": "start.sweetpacks.com",
+      "favicon_url": "http://start.sweetpacks.com/favicon.ico",
+      "search_url": "http://start.sweetpacks.com/search.asp?q={searchTerms}&ln={language}",
+      "alternate_urls": [
+        "http://start.sweetpacks.com/?q={searchTerms}",
+        "http://mysearch.sweetpacks.com/?q={searchTerms}"
+      ],
+      "type": "SEARCH_ENGINE_SWEETPACKS",
+      "id": 65
+    },
+
+    "terra_ar": {
+      "name": "Terra Argentina",
+      "keyword": "terra.com.ar",
+      "favicon_url": "http://buscar.terra.com.ar/favicon.ico",
+      "search_url": "http://buscar.terra.com.ar/Default.aspx?source=Search&ca=s&query={searchTerms}",
+      "encoding": "ISO-8859-1",
+      "type": "SEARCH_ENGINE_TERRA",
+      "id": 90
+    },
+
+    "terra_es": {
+      "name": "Terra",
+      "keyword": "terra.es",
+      "favicon_url": "http://buscador.terra.es/favicon.ico",
+      "search_url": "http://buscador.terra.es/Default.aspx?source=Search&ca=s&query={searchTerms}",
+      "encoding": "ISO-8859-1",
+      "type": "SEARCH_ENGINE_TERRA",
+      "id": 90
+    },
+
+    "tut": {
+      "name": "TUT.BY",
+      "keyword": "tut.by",
+      "favicon_url": "http://search.tut.by/favicon.ico",
+      "search_url": "http://search.tut.by/?ru=1&query={searchTerms}",
+      "suggest_url": "http://suggest.yandex.ru/suggest-ff.cgi?part={searchTerms}&limit=10",
+      "type": "SEARCH_ENGINE_TUT",
+      "id": 17
+    },
+
+    "walla": {
+      "name": "\u05d5\u05d5\u05d0\u05dc\u05d4!",
+      "keyword": "walla.co.il",
+      "favicon_url": "http://www.walla.co.il/favicon.ico",
+      "search_url": "http://search.walla.co.il/?q={searchTerms}",
+      "type": "SEARCH_ENGINE_WALLA",
+      "id": 55
+    },
+
+    "wp": {
+      "name": "Wirtualna Polska",
+      "keyword": "wp.pl",
+      "favicon_url": "http://i.wp.pl/a/i/stg/500/favicon.ico",
+      "search_url": "http://szukaj.wp.pl/szukaj.html?q={searchTerms}",
+      "type": "SEARCH_ENGINE_WP",
+      "id": 76
     },
 
     "yandex_tr": {
       "name": "Yandex",
       "keyword": "yandex.com.tr",
-      "favicon_url": "http://yandex.com.tr/favicon.ico",
-      "search_url": "http://yandex.com.tr/yandsearch?text={searchTerms}",
-      "suggest_url": "http://suggest.yandex.net/suggest-ff.cgi?part={searchTerms}",
+      "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",
+      "favicon_url": "http://www.zoznam.sk/favicon.ico",
+      "search_url": "http://www.zoznam.sk/hladaj.fcgi?s={searchTerms}",
+      "encoding": "windows-1250",
+      "type": "SEARCH_ENGINE_ZOZNAM",
+      "id": 85
     }
   }
 }
diff --git a/chrome/browser/search_engines/search_engine_type.h b/chrome/browser/search_engines/search_engine_type.h
index 6aea298..1541848 100644
--- a/chrome/browser/search_engines/search_engine_type.h
+++ b/chrome/browser/search_engines/search_engine_type.h
@@ -9,52 +9,56 @@
 // search engines at the bottom and do not delete from this list, so as not
 // to disrupt UMA data already recorded.
 enum SearchEngineType {
-  SEARCH_ENGINE_OTHER = 0,  // At the top in case of future list changes.
-  SEARCH_ENGINE_GOOGLE,
-  SEARCH_ENGINE_YAHOO,
-  SEARCH_ENGINE_YAHOOJP,
-  SEARCH_ENGINE_BING,
+  // Prepopulated engines.
+  SEARCH_ENGINE_OTHER = 0,   // At the top in case of future list changes.
+  SEARCH_ENGINE_AOL,
   SEARCH_ENGINE_ASK,
-  SEARCH_ENGINE_YANDEX,
-  SEARCH_ENGINE_SEZNAM,
-  SEARCH_ENGINE_CENTRUM,
-  SEARCH_ENGINE_NETSPRINT,
-  SEARCH_ENGINE_VIRGILIO,
-  SEARCH_ENGINE_MAILRU,
-  SEARCH_ENGINE_ABCSOK,
-  SEARCH_ENGINE_ALTAVISTA,
+  SEARCH_ENGINE_ATLAS,
+  SEARCH_ENGINE_AVG,
   SEARCH_ENGINE_BAIDU,
+  SEARCH_ENGINE_BABYLON,
+  SEARCH_ENGINE_BING,
+  SEARCH_ENGINE_CONDUIT,
   SEARCH_ENGINE_DAUM,
   SEARCH_ENGINE_DELFI,
-  SEARCH_ENGINE_DIRI,
+  SEARCH_ENGINE_DELTA,
+  SEARCH_ENGINE_FUNMOODS,
   SEARCH_ENGINE_GOO,
+  SEARCH_ENGINE_GOOGLE,
+  SEARCH_ENGINE_IMINENT,
+  SEARCH_ENGINE_IMESH,
   SEARCH_ENGINE_IN,
+  SEARCH_ENGINE_INCREDIBAR,
+  SEARCH_ENGINE_KVASIR,
+  SEARCH_ENGINE_LIBERO,
+  SEARCH_ENGINE_MAILRU,
   SEARCH_ENGINE_NAJDI,
+  SEARCH_ENGINE_NATE,
   SEARCH_ENGINE_NAVER,
   SEARCH_ENGINE_NETI,
-  SEARCH_ENGINE_OK,
-  SEARCH_ENGINE_POGODAK,
-  SEARCH_ENGINE_POGODOK_MK,  // Defunct. Deletion would corrupt UMA stats.
-  SEARCH_ENGINE_RAMBLER,
-  SEARCH_ENGINE_SANOOK,
-  SEARCH_ENGINE_SAPO,
-  SEARCH_ENGINE_TUT,
-  SEARCH_ENGINE_WALLA,
-  SEARCH_ENGINE_ZOZNAM,
-  SEARCH_ENGINE_YAHOOQC,
-  SEARCH_ENGINE_NONE,  // Defunct. Deletion would corrupt UMA stats.
-  SEARCH_ENGINE_CONDUIT,
-  SEARCH_ENGINE_ALL_BY,
-  SEARCH_ENGINE_APORT,
-  SEARCH_ENGINE_ICQ,
-  SEARCH_ENGINE_METABOT_RU,
-  SEARCH_ENGINE_META_UA,
   SEARCH_ENGINE_NIGMA,
-  SEARCH_ENGINE_QIP,
-  SEARCH_ENGINE_UKR_NET,
-  SEARCH_ENGINE_WEBALTA,
-  SEARCH_ENGINE_AVG,
-  SEARCH_ENGINE_MAX  // Bounding max value needed for UMA histogram macro.
+  SEARCH_ENGINE_OK,
+  SEARCH_ENGINE_ONET,
+  SEARCH_ENGINE_RAMBLER,
+  SEARCH_ENGINE_SAPO,
+  SEARCH_ENGINE_SEARCHNU,
+  SEARCH_ENGINE_SEARCH_RESULTS,
+  SEARCH_ENGINE_SEZNAM,
+  SEARCH_ENGINE_SNAPDO,
+  SEARCH_ENGINE_SOFTONIC,
+  SEARCH_ENGINE_SOGOU,
+  SEARCH_ENGINE_SOSO,
+  SEARCH_ENGINE_SWEETPACKS,
+  SEARCH_ENGINE_TERRA,
+  SEARCH_ENGINE_TUT,
+  SEARCH_ENGINE_VINDEN,
+  SEARCH_ENGINE_VIRGILIO,
+  SEARCH_ENGINE_WALLA,
+  SEARCH_ENGINE_WP,
+  SEARCH_ENGINE_YAHOO,
+  SEARCH_ENGINE_YANDEX,
+  SEARCH_ENGINE_ZOZNAM,
+  SEARCH_ENGINE_MAX          // Bounding value needed for UMA histogram macro.
 };
 
 #endif  // CHROME_BROWSER_SEARCH_ENGINES_SEARCH_ENGINE_TYPE_H_
diff --git a/chrome/browser/search_engines/search_terms_data.cc b/chrome/browser/search_engines/search_terms_data.cc
index 32b6100..29d10f6 100644
--- a/chrome/browser/search_engines/search_terms_data.cc
+++ b/chrome/browser/search_engines/search_terms_data.cc
@@ -90,12 +90,12 @@
 
 UIThreadSearchTermsData::UIThreadSearchTermsData(Profile* profile)
     : profile_(profile) {
-  DCHECK(!BrowserThread::IsWellKnownThread(BrowserThread::UI) ||
+  DCHECK(!BrowserThread::IsThreadInitialized(BrowserThread::UI) ||
       BrowserThread::CurrentlyOn(BrowserThread::UI));
 }
 
 std::string UIThreadSearchTermsData::GoogleBaseURLValue() const {
-  DCHECK(!BrowserThread::IsWellKnownThread(BrowserThread::UI) ||
+  DCHECK(!BrowserThread::IsThreadInitialized(BrowserThread::UI) ||
       BrowserThread::CurrentlyOn(BrowserThread::UI));
   if (google_base_url_)
     return *google_base_url_;
@@ -108,7 +108,7 @@
 }
 
 std::string UIThreadSearchTermsData::GetApplicationLocale() const {
-  DCHECK(!BrowserThread::IsWellKnownThread(BrowserThread::UI) ||
+  DCHECK(!BrowserThread::IsThreadInitialized(BrowserThread::UI) ||
       BrowserThread::CurrentlyOn(BrowserThread::UI));
   return g_browser_process->GetApplicationLocale();
 }
@@ -116,7 +116,7 @@
 // Android implementations are located in search_terms_data_android.cc.
 #if !defined(OS_ANDROID)
 string16 UIThreadSearchTermsData::GetRlzParameterValue() const {
-  DCHECK(!BrowserThread::IsWellKnownThread(BrowserThread::UI) ||
+  DCHECK(!BrowserThread::IsThreadInitialized(BrowserThread::UI) ||
       BrowserThread::CurrentlyOn(BrowserThread::UI));
   string16 rlz_string;
 #if defined(ENABLE_RLZ)
@@ -138,26 +138,26 @@
 // search client string.  There is already a unit test in place for Android
 // called TemplateURLTest::SearchClient.
 std::string UIThreadSearchTermsData::GetSearchClient() const {
-  DCHECK(!BrowserThread::IsWellKnownThread(BrowserThread::UI) ||
+  DCHECK(!BrowserThread::IsThreadInitialized(BrowserThread::UI) ||
       BrowserThread::CurrentlyOn(BrowserThread::UI));
   return std::string();
 }
 #endif
 
 std::string UIThreadSearchTermsData::GetSuggestClient() const {
-  DCHECK(!BrowserThread::IsWellKnownThread(BrowserThread::UI) ||
+  DCHECK(!BrowserThread::IsThreadInitialized(BrowserThread::UI) ||
       BrowserThread::CurrentlyOn(BrowserThread::UI));
   return chrome::IsInstantExtendedAPIEnabled() ? "chrome-omni" : "chrome";
 }
 
 std::string UIThreadSearchTermsData::InstantEnabledParam() const {
-  DCHECK(!BrowserThread::IsWellKnownThread(BrowserThread::UI) ||
+  DCHECK(!BrowserThread::IsThreadInitialized(BrowserThread::UI) ||
          BrowserThread::CurrentlyOn(BrowserThread::UI));
   return chrome::IsInstantExtendedAPIEnabled() ? std::string() : "ion=1&";
 }
 
 std::string UIThreadSearchTermsData::InstantExtendedEnabledParam() const {
-  DCHECK(!BrowserThread::IsWellKnownThread(BrowserThread::UI) ||
+  DCHECK(!BrowserThread::IsThreadInitialized(BrowserThread::UI) ||
          BrowserThread::CurrentlyOn(BrowserThread::UI));
   uint64 instant_extended_api_version = chrome::EmbeddedSearchPageVersion();
   if (instant_extended_api_version) {
@@ -168,7 +168,7 @@
 }
 
 std::string UIThreadSearchTermsData::NTPIsThemedParam() const {
-  DCHECK(!BrowserThread::IsWellKnownThread(BrowserThread::UI) ||
+  DCHECK(!BrowserThread::IsThreadInitialized(BrowserThread::UI) ||
          BrowserThread::CurrentlyOn(BrowserThread::UI));
 #if defined(ENABLE_THEMES)
   if (!chrome::IsInstantExtendedAPIEnabled())
diff --git a/chrome/browser/search_engines/search_terms_data_android.cc b/chrome/browser/search_engines/search_terms_data_android.cc
index 0eb9047..521aaeb 100644
--- a/chrome/browser/search_engines/search_terms_data_android.cc
+++ b/chrome/browser/search_engines/search_terms_data_android.cc
@@ -13,17 +13,17 @@
     SearchTermsDataAndroid::search_client_ = LAZY_INSTANCE_INITIALIZER;
 
 string16 UIThreadSearchTermsData::GetRlzParameterValue() const {
-  DCHECK(
-      !content::BrowserThread::IsWellKnownThread(content::BrowserThread::UI) ||
-      content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+  DCHECK(!content::BrowserThread::IsThreadInitialized(
+             content::BrowserThread::UI) ||
+         content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
   // Android doesn't use the rlz library.  Instead, it manages the rlz string
   // on its own.
   return SearchTermsDataAndroid::rlz_parameter_value_.Get();
 }
 
 std::string UIThreadSearchTermsData::GetSearchClient() const {
-  DCHECK(
-      !content::BrowserThread::IsWellKnownThread(content::BrowserThread::UI) ||
-      content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+  DCHECK(!content::BrowserThread::IsThreadInitialized(
+             content::BrowserThread::UI) ||
+         content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
   return SearchTermsDataAndroid::search_client_.Get();
 }
diff --git a/chrome/browser/search_engines/template_url.cc b/chrome/browser/search_engines/template_url.cc
index 1991d2c..3d0bea9 100644
--- a/chrome/browser/search_engines/template_url.cc
+++ b/chrome/browser/search_engines/template_url.cc
@@ -73,6 +73,7 @@
     "google:omniboxStartMarginParameter";
 const char kGoogleOriginalQueryForSuggestionParameter[] =
     "google:originalQueryForSuggestion";
+const char kGooglePageClassificationParameter[] = "google:pageClassification";
 const char kGoogleRLZParameter[] = "google:RLZ";
 const char kGoogleSearchClient[] = "google:searchClient";
 const char kGoogleSearchFieldtrialParameter[] =
@@ -192,6 +193,7 @@
       accepted_suggestion(NO_SUGGESTIONS_AVAILABLE),
       cursor_position(string16::npos),
       omnibox_start_margin(-1),
+      page_classification(AutocompleteInput::INVALID_SPEC),
       append_extra_query_params(false) {
 }
 
@@ -561,6 +563,8 @@
   } else if (parameter == kGoogleOriginalQueryForSuggestionParameter) {
     replacements->push_back(Replacement(GOOGLE_ORIGINAL_QUERY_FOR_SUGGESTION,
                                         start));
+  } else if (parameter == kGooglePageClassificationParameter) {
+    replacements->push_back(Replacement(GOOGLE_PAGE_CLASSIFICATION, start));
   } else if (parameter == kGoogleRLZParameter) {
     replacements->push_back(Replacement(GOOGLE_RLZ, start));
   } else if (parameter == kGoogleSearchClient) {
@@ -866,6 +870,15 @@
         }
         break;
 
+      case GOOGLE_PAGE_CLASSIFICATION:
+        if (search_terms_args.page_classification !=
+            AutocompleteInput::INVALID_SPEC) {
+          HandleReplacement(
+              "pgcl", base::IntToString(search_terms_args.page_classification),
+              *i, &url);
+        }
+        break;
+
       case GOOGLE_RLZ: {
         DCHECK(!i->is_post_param);
         // On platforms that don't have RLZ, we still want this branch
diff --git a/chrome/browser/search_engines/template_url.h b/chrome/browser/search_engines/template_url.h
index c192e04..1d874bb 100644
--- a/chrome/browser/search_engines/template_url.h
+++ b/chrome/browser/search_engines/template_url.h
@@ -11,6 +11,7 @@
 
 #include "base/gtest_prod_util.h"
 #include "base/time/time.h"
+#include "chrome/browser/autocomplete/autocomplete_input.h"
 #include "chrome/browser/search_engines/template_url_id.h"
 #include "url/gurl.h"
 #include "url/url_parse.h"
@@ -95,6 +96,9 @@
     // suggestions.
     std::string zero_prefix_url;
 
+    // Which omnibox the user used to type the prefix.
+    AutocompleteInput::PageClassification page_classification;
+
     // If set, ReplaceSearchTerms() will automatically append any extra query
     // params specified via the --extra-search-query-params command-line
     // argument.  Generally, this should be set when dealing with the search or
@@ -238,6 +242,7 @@
     GOOGLE_NTP_IS_THEMED,
     GOOGLE_OMNIBOX_START_MARGIN,
     GOOGLE_ORIGINAL_QUERY_FOR_SUGGESTION,
+    GOOGLE_PAGE_CLASSIFICATION,
     GOOGLE_RLZ,
     GOOGLE_SEARCH_CLIENT,
     GOOGLE_SEARCH_FIELDTRIAL_GROUP,
diff --git a/chrome/browser/search_engines/template_url_prepopulate_data.cc b/chrome/browser/search_engines/template_url_prepopulate_data.cc
index 31c7505..064b65e 100644
--- a/chrome/browser/search_engines/template_url_prepopulate_data.cc
+++ b/chrome/browser/search_engines/template_url_prepopulate_data.cc
@@ -20,7 +20,6 @@
 #include "chrome/browser/google/google_util.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/search_engines/prepopulated_engines.h"
-#include "chrome/browser/search_engines/search_engine_type.h"
 #include "chrome/browser/search_engines/search_terms_data.h"
 #include "chrome/browser/search_engines/template_url.h"
 #include "chrome/browser/search_engines/template_url_service.h"
@@ -30,6 +29,7 @@
 #include "content/public/browser/browser_thread.h"
 #include "grit/generated_resources.h"
 #include "grit/theme_resources.h"
+#include "net/base/registry_controlled_domains/registry_controlled_domain.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "url/gurl.h"
 
@@ -41,34 +41,37 @@
 
 namespace TemplateURLPrepopulateData {
 
+
+// Helpers --------------------------------------------------------------------
+
+namespace {
+
 // NOTE: You should probably not change the data in this file without changing
 // |kCurrentDataVersion| in prepopulated_engines.json. See comments in
 // GetDataVersion() below!
 
-// Lists of engines per country ////////////////////////////////////////////////
-
-// Put these in order with most interesting/important first.  The default will
-// be the first engine.
+// Put the engines within each country in order with most interesting/important
+// first.  The default will be the first engine.
 
 // Default (for countries with no better engine set)
 const PrepopulatedEngine* engines_default[] =
-    { &google, &yahoo, &bing, };
+    { &google, &bing, &yahoo, };
 
 // United Arab Emirates
 const PrepopulatedEngine* engines_AE[] =
-    { &google, &yahoo, &bing_en_XA, &bing_ar_XA, &araby, &maktoob, };
+    { &google, &yahoo_maktoob, &bing_ar_XA, &bing_en_XA, };
 
 // Albania
 const PrepopulatedEngine* engines_AL[] =
-    { &google, &yahoo, &bing_en_XA, };
+    { &google, &yahoo, &bing_en_XA, &bing_ar_XA, };
 
 // Argentina
 const PrepopulatedEngine* engines_AR[] =
-    { &google, &yahoo_ar, &bing_es_AR, &terra_ar, &altavista_ar, };
+    { &google, &bing_es_AR, &yahoo_ar, };
 
 // Austria
 const PrepopulatedEngine* engines_AT[] =
-    { &google, &yahoo_at, &bing_de_AT, };
+    { &google, &bing_de_AT, &yahoo_at, };
 
 // Australia
 const PrepopulatedEngine* engines_AU[] =
@@ -80,15 +83,15 @@
 
 // Belgium
 const PrepopulatedEngine* engines_BE[] =
-    { &google, &bing_nl_BE, &yahoo, &bing_fr_BE, };
+    { &google, &bing_nl_BE, &bing_fr_BE, &yahoo_be, &yahoo_fr_be, };
 
 // Bulgaria
 const PrepopulatedEngine* engines_BG[] =
-    { &google, &bing_bg_BG, &yahoo, &diri, &jabse, };
+    { &google, &bing, &ask, };
 
 // Bahrain
 const PrepopulatedEngine* engines_BH[] =
-    { &google, &yahoo, &bing_en_XA, &bing_ar_XA, };
+    { &google, &yahoo_maktoob, &bing_en_XA, &bing_ar_XA, };
 
 // Burundi
 const PrepopulatedEngine* engines_BI[] =
@@ -96,40 +99,39 @@
 
 // Brunei
 const PrepopulatedEngine* engines_BN[] =
-    { &google, &yahoo_malaysia, &bing_en_MY, };
+    { &google, &yahoo_my, &bing, };
 
 // Bolivia
 const PrepopulatedEngine* engines_BO[] =
-    { &google, &altavista, &bing_es_XL, &yahoo, };
+    { &google, &bing_es_XL, &yahoo, };
 
 // Brazil
 const PrepopulatedEngine* engines_BR[] =
-    { &google, &bing_pt_BR, &yahoo_br, &uol, };
+    { &google, &ask_br, &bing_pt_BR, &yahoo_br, };
 
 // Belarus
 const PrepopulatedEngine* engines_BY[] =
-    { &google, &tut, &yandex_ru, &rambler, &yahoo, };
+    { &google, &yahoo_ru, &bing_ru_RU, };
 
 // Belize
 const PrepopulatedEngine* engines_BZ[] =
-    { &google, &yahoo, &bing, &aol, };
+    { &google, &yahoo, &bing, };
 
 // Canada
 const PrepopulatedEngine* engines_CA[] =
-    { &google, &yahoo_ca, &yahoo_qc, &bing_en_CA, &bing_fr_CA, };
+    { &google, &bing_en_CA, &bing_fr_CA, &ask, &yahoo_ca, &yahoo_qc, };
 
 // Switzerland
 const PrepopulatedEngine* engines_CH[] =
-    { &google, &yahoo_ch, &bing_de_CH, &bing_fr_CH, &search_de_CH,
-      &search_fr_CH, };
+    { &google, &bing_de_CH, &bing_fr_CH, &yahoo_ch, };
 
 // Chile
 const PrepopulatedEngine* engines_CL[] =
-    { &google, &yahoo_cl, &bing_es_CL, };
+    { &google, &bing_es_CL, &yahoo_cl, };
 
 // China
 const PrepopulatedEngine* engines_CN[] =
-    { &google, &baidu, &yahoo_cn, &bing_zh_CN, };
+    { &google, &baidu, &sogou, &soso, };
 
 // Colombia
 const PrepopulatedEngine* engines_CO[] =
@@ -137,15 +139,15 @@
 
 // Costa Rica
 const PrepopulatedEngine* engines_CR[] =
-    { &google, &bing_es_XL, &yahoo, };
+    { &google, &yahoo, &bing_es_XL, };
 
 // Czech Republic
 const PrepopulatedEngine* engines_CZ[] =
-    { &google, &seznam, &bing_cs_CZ, &centrum_cz, &atlas_cz, };
+    { &google, &seznam, &bing, };
 
 // Germany
 const PrepopulatedEngine* engines_DE[] =
-    { &google, &ask_de, &bing_de_DE, &yahoo_de };
+    { &google, &bing_de_DE, &yahoo_de };
 
 // Denmark
 const PrepopulatedEngine* engines_DK[] =
@@ -153,11 +155,11 @@
 
 // Dominican Republic
 const PrepopulatedEngine* engines_DO[] =
-    { &google, &bing_es_XL, &yahoo, };
+    { &google, &yahoo, &bing_es_XL, };
 
 // Algeria
 const PrepopulatedEngine* engines_DZ[] =
-    { &google, &bing_en_XA, &yahoo, &bing_ar_XA, &maktoob, };
+    { &google, &bing_ar_XA, &bing_en_XA, &yahoo_maktoob, };
 
 // Ecuador
 const PrepopulatedEngine* engines_EC[] =
@@ -165,87 +167,87 @@
 
 // Estonia
 const PrepopulatedEngine* engines_EE[] =
-    { &google, &bing_et_EE, &neti, &yahoo, };
+    { &google, &bing, &yahoo, };
 
 // Egypt
 const PrepopulatedEngine* engines_EG[] =
-    { &google, &yahoo, &bing_en_XA, &bing_ar_XA, &masrawy, };
+    { &google, &yahoo_maktoob, &bing_ar_XA, &bing_en_XA, };
 
 // Spain
 const PrepopulatedEngine* engines_ES[] =
-    { &google, &ask_es, &bing_es_ES, &yahoo_es, &terra_es, &hispavista, };
+    { &google, &bing_es_ES, &yahoo_es, };
 
 // Faroe Islands
 const PrepopulatedEngine* engines_FO[] =
-    { &google, &bing_da_DK, &yahoo_dk, &jubii };
+    { &google, &bing_da_DK, &ask, };
 
 // Finland
 const PrepopulatedEngine* engines_FI[] =
-    { &google, &bing_fi_FI, &yahoo_fi, &eniro_fi, &fonecta_02_fi, };
+    { &google, &bing_fi_FI, &yahoo_fi, };
 
 // France
 const PrepopulatedEngine* engines_FR[] =
-    { &google, &yahoo_fr, &bing_fr_FR, };
+    { &google, &bing_fr_FR, &yahoo_fr, };
 
 // United Kingdom
 const PrepopulatedEngine* engines_GB[] =
-    { &google, &ask_uk, &yahoo_uk, &bing_en_GB, };
+    { &google, &bing_en_GB, &yahoo_uk, &ask_uk, };
 
 // Greece
 const PrepopulatedEngine* engines_GR[] =
-    { &google, &yahoo, &in, &bing_el_GR };
+    { &google, &bing, &yahoo_gr, };
 
 // Guatemala
 const PrepopulatedEngine* engines_GT[] =
-    { &google, &bing_es_XL, &yahoo, &ask_es, };
+    { &google, &yahoo, &bing_es_XL, };
 
 // Hong Kong
 const PrepopulatedEngine* engines_HK[] =
-    { &google, &yahoo_hk, &bing_zh_HK, &baidu, };
+    { &google, &yahoo_hk, &baidu, &bing_zh_HK, };
 
 // Honduras
 const PrepopulatedEngine* engines_HN[] =
-    { &google, &bing_es_XL, &yahoo, &ask_es, };
+    { &google, &yahoo, &bing_es_XL, };
 
 // Croatia
 const PrepopulatedEngine* engines_HR[] =
-    { &google, &yahoo, &bing_hr_HR, };
+    { &google, &bing, &yahoo, };
 
 // Hungary
 const PrepopulatedEngine* engines_HU[] =
-    { &google, &ok, &bing_hu_HU, };
+    { &google, &bing, &yahoo, };
 
 // Indonesia
 const PrepopulatedEngine* engines_ID[] =
-    { &google, &yahoo_id, &bing_en_ID, };
+    { &google, &yahoo_id, &bing, };
 
 // Ireland
 const PrepopulatedEngine* engines_IE[] =
-    { &google, &yahoo_uk, &bing_en_IE, };
+    { &google, &bing_en_IE, &yahoo_uk, };
 
 // Israel
 const PrepopulatedEngine* engines_IL[] =
-    { &google, &walla, &bing_he_IL, };
+    { &google, &yahoo, &bing, };
 
 // India
 const PrepopulatedEngine* engines_IN[] =
-    { &google, &yahoo_in, &bing_en_IN, &rediff, &guruji, };
+    { &google, &bing_en_IN, &yahoo_in, };
 
 // Iraq
 const PrepopulatedEngine* engines_IQ[] =
-    { &google, &yahoo, &bing_en_XA, &bing_ar_XA, &maktoob, &ask, };
+    { &google, &yahoo_maktoob, &bing_ar_XA, &bing_en_XA, };
 
 // Iran
 const PrepopulatedEngine* engines_IR[] =
-    { &google, &yahoo, };
+    { &google, &yahoo, &bing, };
 
 // Iceland
 const PrepopulatedEngine* engines_IS[] =
-    { &google, &yahoo, &bing, &leit, };
+    { &google, &bing, &yahoo, };
 
 // Italy
 const PrepopulatedEngine* engines_IT[] =
-    { &google, &ask_it, &virgilio, &bing_it_IT, &yahoo_it, &libero, };
+    { &google, &virgilio, &bing_it_IT, };
 
 // Jamaica
 const PrepopulatedEngine* engines_JM[] =
@@ -253,11 +255,11 @@
 
 // Jordan
 const PrepopulatedEngine* engines_JO[] =
-    { &google, &yahoo, &bing_en_XA, &bing_ar_XA, &maktoob, &araby, };
+    { &google, &yahoo_maktoob, &bing_ar_XA, &bing_en_XA, };
 
 // Japan
 const PrepopulatedEngine* engines_JP[] =
-    { &google, &yahoo_jp, &bing_ja_JP, &goo, };
+    { &google, &yahoo_jp, &bing_ja_JP, };
 
 // Kenya
 const PrepopulatedEngine* engines_KE[] =
@@ -265,19 +267,19 @@
 
 // Kuwait
 const PrepopulatedEngine* engines_KW[] =
-    { &google, &bing_en_XA, &yahoo, &bing_ar_XA, &maktoob, &araby, };
+    { &google, &yahoo_maktoob, &bing_ar_XA, &bing_en_XA, };
 
 // South Korea
 const PrepopulatedEngine* engines_KR[] =
-    { &google, &naver, &daum, &yahoo_kr, &nate, };
+    { &google, &naver, &daum, &nate, };
 
 // Kazakhstan
 const PrepopulatedEngine* engines_KZ[] =
-    { &google, &rambler, &yandex_ru, &nur_kz, };
+    { &google, &bing, &yahoo, };
 
 // Lebanon
 const PrepopulatedEngine* engines_LB[] =
-    { &google, &yahoo, &bing_en_XA, &bing_ar_XA, &maktoob, &araby, };
+    { &google, &yahoo_maktoob, &bing_ar_XA, &bing_en_XA, };
 
 // Liechtenstein
 const PrepopulatedEngine* engines_LI[] =
@@ -285,7 +287,7 @@
 
 // Lithuania
 const PrepopulatedEngine* engines_LT[] =
-    { &google, &delfi_lt, &yahoo, &bing_lt_LT, };
+    { &google, &bing, &yandex_ru, };
 
 // Luxembourg
 const PrepopulatedEngine* engines_LU[] =
@@ -293,27 +295,27 @@
 
 // Latvia
 const PrepopulatedEngine* engines_LV[] =
-    { &google, &bing, &yandex_ru, &yahoo, &latne, };
+    { &google, &yandex_ru, &bing, };
 
 // Libya
 const PrepopulatedEngine* engines_LY[] =
-    { &google, &yahoo, &bing_en_XA, &bing_ar_XA, &maktoob, &ask, };
+    { &google, &yahoo_maktoob, &bing_ar_XA, &bing_en_XA, };
 
 // Morocco
 const PrepopulatedEngine* engines_MA[] =
-    { &google, &bing_en_XA, &yahoo, &bing_ar_XA, };
+    { &google, &bing_ar_XA, &bing_en_XA, &yahoo_maktoob, };
 
 // Monaco
 const PrepopulatedEngine* engines_MC[] =
-    { &google, &bing_fr_FR, &yahoo_fr, };
+    { &google, &yahoo_fr, &bing_fr_FR, };
 
 // Moldova
 const PrepopulatedEngine* engines_MD[] =
-    { &google, &yandex_ru, &yahoo, &bing, };
+    { &google, &bing, &yahoo, };
 
 // Montenegro
 const PrepopulatedEngine* engines_ME[] =
-    { &google, &yahoo, &bing };
+    { &google, &bing, &yahoo, };
 
 // Macedonia
 const PrepopulatedEngine* engines_MK[] =
@@ -325,31 +327,31 @@
 
 // Malaysia
 const PrepopulatedEngine* engines_MY[] =
-    { &google, &yahoo_malaysia, &bing_en_MY, };
+    { &google, &yahoo_my, &bing, };
 
 // Nicaragua
 const PrepopulatedEngine* engines_NI[] =
-    { &google, &bing_es_XL, &yahoo, &ask_es, };
+    { &google, &yahoo, &bing_es_XL, };
 
 // Netherlands
 const PrepopulatedEngine* engines_NL[] =
-    { &google, &bing_nl_NL, &yahoo_nl, &ask_nl, };
+    { &google, &yahoo_nl, &vinden, };
 
 // Norway
 const PrepopulatedEngine* engines_NO[] =
-    { &google, &bing_nb_NO, &abcsok, &yahoo_no, &kvasir, };
+    { &google, &bing_nb_NO, &kvasir, };
 
 // New Zealand
 const PrepopulatedEngine* engines_NZ[] =
-    { &google, &yahoo_nz, &bing_en_NZ, };
+    { &google, &bing_en_NZ, &yahoo_nz, };
 
 // Oman
 const PrepopulatedEngine* engines_OM[] =
-    { &google, &yahoo, &bing_en_XA, &bing_ar_XA, };
+    { &google, &bing_ar_XA, &yahoo_maktoob, &bing_en_XA, };
 
 // Panama
 const PrepopulatedEngine* engines_PA[] =
-    { &google, &bing_es_XL, &yahoo, &ask_es, };
+    { &google, &yahoo, &bing_es_XL, };
 
 // Peru
 const PrepopulatedEngine* engines_PE[] =
@@ -365,15 +367,15 @@
 
 // Puerto Rico
 const PrepopulatedEngine* engines_PR[] =
-    { &google, &bing_es_XL, &yahoo, &ask_es, };
+    { &google, &yahoo, &bing_es_XL, };
 
 // Poland
 const PrepopulatedEngine* engines_PL[] =
-    { &google, &bing_pl_PL, &netsprint, &yahoo_uk, &onet, &wp,  };
+    { &google, &onet, &bing_pl_PL, };
 
 // Portugal
 const PrepopulatedEngine* engines_PT[] =
-    { &google, &sapo, &bing_pt_PT, &yahoo, };
+    { &google, &bing_pt_PT, &yahoo, };
 
 // Paraguay
 const PrepopulatedEngine* engines_PY[] =
@@ -381,67 +383,67 @@
 
 // Qatar
 const PrepopulatedEngine* engines_QA[] =
-    { &google, &yahoo, &bing_en_XA, &bing_ar_XA, &maktoob, &araby };
+    { &google, &yahoo_maktoob, &bing_ar_XA, &bing_en_XA, };
 
 // Romania
 const PrepopulatedEngine* engines_RO[] =
-    { &google, &yahoo_uk, &bing_ro_RO, };
+    { &google, &yahoo_ro, &bing, };
 
 // Serbia
 const PrepopulatedEngine* engines_RS[] =
-    { &google, &pogodak_rs, &bing, };
+    { &google, &bing, &yahoo, };
 
 // Russia
 const PrepopulatedEngine* engines_RU[] =
-    { &google, &yandex_ru, &mail_ru, &tut, &rambler, &bing_ru_RU, };
+    { &google, &yandex_ru, &mail_ru, };
 
 // Rwanda
 const PrepopulatedEngine* engines_RW[] =
-    { &google, &yahoo, &bing, };
+    { &google, &bing, &yahoo, };
 
 // Saudi Arabia
 const PrepopulatedEngine* engines_SA[] =
-    { &google, &yahoo, &bing_en_XA, &bing_ar_XA, };
+    { &google, &yahoo_maktoob, &bing_ar_XA, &bing_en_XA, };
 
 // Sweden
 const PrepopulatedEngine* engines_SE[] =
-    { &google, &bing_sv_SE, &yahoo_se, &altavista_se, &eniro_se };
+    { &google, &bing_sv_SE, &yahoo_se, };
 
 // Singapore
 const PrepopulatedEngine* engines_SG[] =
-    { &google, &yahoo_sg, &bing_en_SG, &rednano, };
+    { &google, &yahoo_sg, &bing_en_SG, };
 
 // Slovenia
 const PrepopulatedEngine* engines_SI[] =
-    { &google, &najdi, &yahoo, &bing_sl_SI, };
+    { &google, &najdi, &ask, };
 
 // Slovakia
 const PrepopulatedEngine* engines_SK[] =
-    { &google, &zoznam, &bing_sk_SK, &atlas_sk, &centrum_sk };
+    { &google, &bing, &yahoo, };
 
 // El Salvador
 const PrepopulatedEngine* engines_SV[] =
-    { &google, &bing_es_XL, &yahoo, };
+    { &google, &yahoo, &bing_es_XL, };
 
 // Syria
 const PrepopulatedEngine* engines_SY[] =
-    { &google, &bing_en_XA, &yahoo, &bing_ar_XA, &maktoob, &yamli, };
+    { &google, &bing_ar_XA, &bing_en_XA, &yahoo_maktoob, };
 
 // Thailand
 const PrepopulatedEngine* engines_TH[] =
-    { &google, &sanook, &yahoo_th, &bing_th_TH, };
+    { &google, &yahoo_th, &bing, };
 
 // Tunisia
 const PrepopulatedEngine* engines_TN[] =
-    { &google, &bing_en_XA, &yahoo, &bing_ar_XA, &maktoob, &yamli };
+    { &google, &bing_ar_XA, &bing_en_XA, &yahoo_maktoob, };
 
 // Turkey
 const PrepopulatedEngine* engines_TR[] =
-    { &google, &bing_tr_TR, &yahoo, &mynet, };
+    { &google, &bing_tr_TR, &yahoo_tr, };
 
 // Trinidad and Tobago
 const PrepopulatedEngine* engines_TT[] =
-    { &google, &bing, &yahoo, &aol, };
+    { &google, &bing, &yahoo, };
 
 // Taiwan
 const PrepopulatedEngine* engines_TW[] =
@@ -453,11 +455,11 @@
 
 // Ukraine
 const PrepopulatedEngine* engines_UA[] =
-    { &google, &yandex_ua, &mail_ru, &rambler, };
+    { &google, &yandex_ua, &bing_ru_RU, };
 
 // United States
 const PrepopulatedEngine* engines_US[] =
-    { &google, &yahoo, &bing_en_US, };
+    { &google, &bing_en_US, &yahoo, &aol, &ask, };
 
 // Uruguay
 const PrepopulatedEngine* engines_UY[] =
@@ -469,57 +471,61 @@
 
 // Vietnam
 const PrepopulatedEngine* engines_VN[] =
-    { &google, &yahoo_vn, };
+    { &google, &yahoo_vn, &bing, };
 
 // Yemen
 const PrepopulatedEngine* engines_YE[] =
-    { &google, &yahoo, &bing_en_XA, &bing_ar_XA, &maktoob, &araby, };
+    { &google, &bing_ar_XA, &bing_en_XA, &yahoo_maktoob, };
 
 // South Africa
 const PrepopulatedEngine* engines_ZA[] =
-    { &google, &yahoo, &bing_en_ZA, };
+    { &google, &bing, &yahoo_za, };
 
 // Zimbabwe
 const PrepopulatedEngine* engines_ZW[] =
-    { &google, &yahoo, &bing, };
-
+    { &google, &bing, &yahoo, &ask, };
 
 // A list of all the engines that we know about.
-const PrepopulatedEngine* kAllEngines[] =
-    { // Prepopulated engines:
-      &abcsok, &altavista, &altavista_ar, &altavista_se, &aol, &araby, &ask,
-      &ask_de, &ask_es, &ask_it, &ask_nl, &ask_uk, &atlas_cz, &atlas_sk, &baidu,
-      &bing, &bing_ar_XA, &bing_bg_BG, &bing_cs_CZ, &bing_da_DK, &bing_de_AT,
-      &bing_de_CH, &bing_de_DE, &bing_el_GR, &bing_en_AU, &bing_en_CA,
-      &bing_en_GB, &bing_en_ID, &bing_en_IE, &bing_en_IN, &bing_en_MY,
-      &bing_en_NZ, &bing_en_PH, &bing_en_SG, &bing_en_US, &bing_en_XA,
-      &bing_en_ZA, &bing_es_AR, &bing_es_CL, &bing_es_ES, &bing_es_MX,
-      &bing_es_XL, &bing_et_EE, &bing_fi_FI, &bing_fr_BE, &bing_fr_CA,
-      &bing_fr_CH, &bing_fr_FR, &bing_he_IL, &bing_hr_HR, &bing_hu_HU,
-      &bing_it_IT, &bing_ja_JP, &bing_ko_KR, &bing_lt_LT, &bing_lv_LV,
-      &bing_nb_NO, &bing_nl_BE, &bing_nl_NL, &bing_pl_PL, &bing_pt_BR,
-      &bing_pt_PT, &bing_ro_RO, &bing_ru_RU, &bing_sl_SI, &bing_sk_SK,
-      &bing_sv_SE, &bing_th_TH, &bing_tr_TR, &bing_uk_UA, &bing_zh_CN,
-      &bing_zh_HK, &bing_zh_TW, &centrum_cz, &centrum_sk, &daum, &delfi_lt,
-      &delfi_lv, &diri, &eniro_fi, &eniro_se, &fonecta_02_fi, &goo, &google,
-      &guruji, &hispavista, &in, &jabse, &jubii, &kvasir, &latne, &leit,
-      &libero, &mail_ru, &maktoob, &masrawy, &mynet, &najdi, &nate, &naver,
-      &neti, &netsprint, &nur_kz, &ok, &onet, &pogodak_rs, &rambler, &rediff,
-      &rednano, &sanook, &sapo, &search_de_CH, &search_fr_CH, &seznam,
-      &terra_ar, &terra_es, &tut, &uol, &virgilio, &walla, &wp, &yahoo,
-      &yahoo_ar, &yahoo_at, &yahoo_au, &yahoo_br, &yahoo_ca, &yahoo_ch,
-      &yahoo_cl, &yahoo_cn, &yahoo_co, &yahoo_de, &yahoo_dk, &yahoo_es,
-      &yahoo_fi, &yahoo_fr, &yahoo_hk, &yahoo_id, &yahoo_in, &yahoo_it,
-      &yahoo_jp, &yahoo_kr, &yahoo_malaysia, &yahoo_mx, &yahoo_nl, &yahoo_no,
-      &yahoo_nz, &yahoo_pe, &yahoo_ph, &yahoo_qc, &yahoo_ru, &yahoo_se,
-      &yahoo_sg, &yahoo_th, &yahoo_tw, &yahoo_uk, &yahoo_ve, &yahoo_vn, &yamli,
-      &yandex_ru, &yandex_ua, &zoznam,
-      // UMA-only engines:
-      &all_by, &aport, &avg, &avg_i, &conduit, &icq, &meta_ua, &metabot_ru,
-      &nigma, &qip, &ukr_net, &webalta, &yandex_tr };
+const PrepopulatedEngine* kAllEngines[] = {
+  // Prepopulated engines:
+  &aol,          &ask,          &ask_br,       &ask_uk,       &baidu,
+  &bing,         &bing_ar_XA,   &bing_da_DK,   &bing_de_AT,   &bing_de_CH,
+  &bing_de_DE,   &bing_en_AU,   &bing_en_CA,   &bing_en_GB,   &bing_en_IE,
+  &bing_en_IN,   &bing_en_NZ,   &bing_en_PH,   &bing_en_SG,   &bing_en_US,
+  &bing_en_XA,   &bing_es_AR,   &bing_es_CL,   &bing_es_ES,   &bing_es_MX,
+  &bing_es_XL,   &bing_fi_FI,   &bing_fr_BE,   &bing_fr_CA,   &bing_fr_CH,
+  &bing_fr_FR,   &bing_it_IT,   &bing_ja_JP,   &bing_lv_LV,   &bing_nb_NO,
+  &bing_nl_BE,   &bing_pl_PL,   &bing_pt_BR,   &bing_pt_PT,   &bing_ru_RU,
+  &bing_sv_SE,   &bing_tr_TR,   &bing_zh_HK,   &bing_zh_TW,   &daum,
+  &google,       &kvasir,       &mail_ru,      &najdi,        &nate,
+  &naver,        &onet,         &seznam,       &sogou,        &soso,
+  &vinden,       &virgilio,     &yahoo,        &yahoo_ar,     &yahoo_at,
+  &yahoo_au,     &yahoo_be,     &yahoo_br,     &yahoo_ca,     &yahoo_ch,
+  &yahoo_cl,     &yahoo_co,     &yahoo_de,     &yahoo_dk,     &yahoo_es,
+  &yahoo_fi,     &yahoo_fr,     &yahoo_fr_be,  &yahoo_gr,     &yahoo_hk,
+  &yahoo_id,     &yahoo_in,     &yahoo_jp,     &yahoo_maktoob, &yahoo_mx,
+  &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,
 
+  // UMA-only engines:
+  &atlas_cz,     &atlas_sk,     &avg,          &babylon,      &conduit,
+  &delfi_lt,     &delfi_lv,     &delta,        &funmoods,     &goo,
+  &imesh,        &iminent,      &in,           &incredibar,   &libero,
+  &neti,         &nigma,        &ok,           &rambler,      &sapo,
+  &search_results, &searchnu,   &snapdo,       &softonic,     &sweetim,
+  &terra_ar,     &terra_es,     &tut,          &walla,        &wp,
+  &yandex_tr,    &zoznam,
+};
 
-// Geographic mappings /////////////////////////////////////////////////////////
+const struct LogoURLs {
+  const char* const logo_100_percent_url;
+  const char* const logo_200_percent_url;
+} google_logos = {
+  "https://www.google.com/images/chrome_search/google_logo.png",
+  "https://www.google.com/images/chrome_search/google_logo_2x.png",
+};
 
 // Please refer to ISO 3166-1 for information about the two-character country
 // codes; http://en.wikipedia.org/wiki/ISO_3166-1_alpha-2 is useful. In the
@@ -641,16 +647,6 @@
   return g_country_code_at_install;
 }
 
-void InitCountryCode(const std::string& country_code) {
-  if (country_code.size() != 2) {
-    DLOG(ERROR) << "Invalid country code: " << country_code;
-    g_country_code_at_install = kCountryIDUnknown;
-  } else {
-    g_country_code_at_install =
-        CountryCharsToCountryIDWithUpdate(country_code[0], country_code[1]);
-  }
-}
-
 #elif defined(OS_POSIX)
 
 int GetCurrentCountryID() {
@@ -1073,47 +1069,6 @@
   }
 }
 
-
-// Logo URLs ///////////////////////////////////////////////////////////////////
-
-struct LogoURLs {
-  const char* const logo_100_percent_url;
-  const char* const logo_200_percent_url;
-};
-
-const LogoURLs google_logos = {
-  "https://www.google.com/images/chrome_search/google_logo.png",
-  "https://www.google.com/images/chrome_search/google_logo_2x.png",
-};
-
-
-////////////////////////////////////////////////////////////////////////////////
-
-void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry) {
-  registry->RegisterIntegerPref(
-      prefs::kCountryIDAtInstall,
-      kCountryIDUnknown,
-      user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
-  registry->RegisterListPref(prefs::kSearchProviderOverrides,
-                             user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
-  registry->RegisterIntegerPref(
-      prefs::kSearchProviderOverridesVersion,
-      -1,
-      user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
-  // Obsolete pref, for migration.
-  registry->RegisterIntegerPref(
-      prefs::kGeoIDAtInstall,
-      -1,
-      user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
-}
-
-int GetDataVersion(PrefService* prefs) {
-  // Allow tests to override the local version.
-  return (prefs && prefs->HasPrefPath(prefs::kSearchProviderOverridesVersion)) ?
-      prefs->GetInteger(prefs::kSearchProviderOverridesVersion) :
-      kCurrentDataVersion;
-}
-
 TemplateURL* MakePrepopulatedTemplateURL(
     Profile* profile,
     const string16& name,
@@ -1220,16 +1175,6 @@
   }
 }
 
-void ClearPrepopulatedEnginesInPrefs(Profile* profile) {
-  if (!profile)
-    return;
-
-  PrefService* prefs = profile->GetPrefs();
-  DCHECK(prefs);
-  prefs->ClearPref(prefs::kSearchProviderOverrides);
-  prefs->ClearPref(prefs::kSearchProviderOverridesVersion);
-}
-
 // The caller owns the returned TemplateURL.
 TemplateURL* MakePrepopulatedTemplateURLFromPrepopulateEngine(
     Profile* profile,
@@ -1249,6 +1194,55 @@
       alternate_urls, engine.search_terms_replacement_key, engine.id);
 }
 
+bool SameDomain(const GURL& given_url, const GURL& prepopulated_url) {
+  return prepopulated_url.is_valid() &&
+      net::registry_controlled_domains::SameDomainOrHost(
+          given_url, prepopulated_url,
+          net::registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES);
+}
+
+}  // namespace
+
+
+// Global functions -----------------------------------------------------------
+
+#if defined(OS_ANDROID)
+void InitCountryCode(const std::string& country_code) {
+  if (country_code.size() != 2) {
+    DLOG(ERROR) << "Invalid country code: " << country_code;
+    g_country_code_at_install = kCountryIDUnknown;
+  } else {
+    g_country_code_at_install =
+        CountryCharsToCountryIDWithUpdate(country_code[0], country_code[1]);
+  }
+}
+#endif
+
+void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry) {
+  registry->RegisterIntegerPref(
+      prefs::kCountryIDAtInstall,
+      kCountryIDUnknown,
+      user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
+  registry->RegisterListPref(prefs::kSearchProviderOverrides,
+                             user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
+  registry->RegisterIntegerPref(
+      prefs::kSearchProviderOverridesVersion,
+      -1,
+      user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
+  // Obsolete pref, for migration.
+  registry->RegisterIntegerPref(
+      prefs::kGeoIDAtInstall,
+      -1,
+      user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
+}
+
+int GetDataVersion(PrefService* prefs) {
+  // Allow tests to override the local version.
+  return (prefs && prefs->HasPrefPath(prefs::kSearchProviderOverridesVersion)) ?
+      prefs->GetInteger(prefs::kSearchProviderOverridesVersion) :
+      kCurrentDataVersion;
+}
+
 void GetPrepopulatedEngines(Profile* profile,
                             std::vector<TemplateURL*>* t_urls,
                             size_t* default_search_provider_index) {
@@ -1269,6 +1263,16 @@
   }
 }
 
+void ClearPrepopulatedEnginesInPrefs(Profile* profile) {
+  if (!profile)
+    return;
+
+  PrefService* prefs = profile->GetPrefs();
+  DCHECK(prefs);
+  prefs->ClearPref(prefs::kSearchProviderOverrides);
+  prefs->ClearPref(prefs::kSearchProviderOverridesVersion);
+}
+
 TemplateURL* GetPrepopulatedDefaultSearch(Profile* profile) {
   TemplateURL* default_search_provider = NULL;
   ScopedVector<TemplateURL> loaded_urls;
@@ -1286,7 +1290,7 @@
 SearchEngineType GetEngineType(const std::string& url) {
   // Restricted to UI thread because ReplaceSearchTerms() is so restricted.
   using content::BrowserThread;
-  DCHECK(!BrowserThread::IsWellKnownThread(BrowserThread::UI) ||
+  DCHECK(!BrowserThread::IsThreadInitialized(BrowserThread::UI) ||
          BrowserThread::CurrentlyOn(BrowserThread::UI));
 
   // We may get a valid URL, or we may get the Google prepopulate URL which
@@ -1302,8 +1306,8 @@
   if (!as_gurl.is_valid())
     return SEARCH_ENGINE_OTHER;
 
-  // Check using origins, in order to more aggressively match search engine
-  // types for data imported from other browsers.
+  // Check using TLD+1s, in order to more aggressively match search engine types
+  // for data imported from other browsers.
   //
   // First special-case Google, because the prepopulate URL for it will not
   // convert to a GURL and thus won't have an origin.  Instead see if the
@@ -1313,11 +1317,16 @@
     return google.type;
 
   // Now check the rest of the prepopulate data.
-  GURL origin(as_gurl.GetOrigin());
   for (size_t i = 0; i < arraysize(kAllEngines); ++i) {
-    GURL engine_url(kAllEngines[i]->search_url);
-    if (engine_url.is_valid() && (origin == engine_url.GetOrigin()))
+    // First check the main search URL.
+    if (SameDomain(as_gurl, GURL(kAllEngines[i]->search_url)))
       return kAllEngines[i]->type;
+
+    // Then check the alternate URLs.
+    for (size_t j = 0; j < kAllEngines[i]->alternate_urls_size; ++j) {
+      if (SameDomain(as_gurl, GURL(kAllEngines[i]->alternate_urls[j])))
+        return kAllEngines[i]->type;
+    }
   }
 
   return SEARCH_ENGINE_OTHER;
diff --git a/chrome/browser/search_engines/template_url_prepopulate_data.h b/chrome/browser/search_engines/template_url_prepopulate_data.h
index cfd614b..ef07dd0 100644
--- a/chrome/browser/search_engines/template_url_prepopulate_data.h
+++ b/chrome/browser/search_engines/template_url_prepopulate_data.h
@@ -32,11 +32,9 @@
 };
 
 #if defined(OS_ANDROID)
-
 // This must be called early only once. |country_code| is the country code at
 // install following the ISO-3166 specification.
 void InitCountryCode(const std::string& country_code);
-
 #endif
 
 void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry);
diff --git a/chrome/browser/search_engines/template_url_prepopulate_data_unittest.cc b/chrome/browser/search_engines/template_url_prepopulate_data_unittest.cc
index 140d700..d1f69fd 100644
--- a/chrome/browser/search_engines/template_url_prepopulate_data_unittest.cc
+++ b/chrome/browser/search_engines/template_url_prepopulate_data_unittest.cc
@@ -226,7 +226,8 @@
   EXPECT_FALSE(t_urls[default_index]->instant_url().empty());
   EXPECT_FALSE(t_urls[default_index]->image_url().empty());
   EXPECT_FALSE(t_urls[default_index]->image_url_post_params().empty());
-  EXPECT_EQ(SEARCH_ENGINE_GOOGLE,
+  EXPECT_EQ(
+      SEARCH_ENGINE_GOOGLE,
       TemplateURLPrepopulateData::GetEngineType(t_urls[default_index]->url()));
 }
 
@@ -263,7 +264,8 @@
   EXPECT_GT(t_urls[default_index]->alternate_urls().size(), 1u);
   for (size_t i = 0; i < t_urls[default_index]->alternate_urls().size(); ++i)
     EXPECT_FALSE(t_urls[default_index]->alternate_urls()[i].empty());
-  EXPECT_EQ(SEARCH_ENGINE_GOOGLE,
+  EXPECT_EQ(
+      SEARCH_ENGINE_GOOGLE,
       TemplateURLPrepopulateData::GetEngineType(t_urls[default_index]->url()));
   EXPECT_FALSE(t_urls[default_index]->search_terms_replacement_key().empty());
 }
@@ -297,20 +299,29 @@
     EXPECT_EQ(SEARCH_ENGINE_GOOGLE,
               TemplateURLPrepopulateData::GetEngineType(kGoogleURLs[i]));
   }
+
   // Non-Google URLs.
   const char* kYahooURLs[] = {
       "http://search.yahoo.com/search?"
       "ei={inputEncoding}&fr=crmas&p={searchTerms}",
-      "http://search.yahoo.com/search?p={searchTerms}"
+      "http://search.yahoo.com/search?p={searchTerms}",
+      // Aggressively match types by checking just TLD+1.
+      "http://someothersite.yahoo.com/",
   };
   for (size_t i = 0; i < arraysize(kYahooURLs); ++i) {
     EXPECT_EQ(SEARCH_ENGINE_YAHOO,
               TemplateURLPrepopulateData::GetEngineType(kYahooURLs[i]));
   }
+
   // URLs for engines not present in country-specific lists.
   EXPECT_EQ(SEARCH_ENGINE_NIGMA,
             TemplateURLPrepopulateData::GetEngineType(
-                "http://www.nigma.ru/?s={searchTerms}&arg1=value1"));
+                "http://nigma.ru/?s={searchTerms}&arg1=value1"));
+  // Also test matching against alternate URLs (and TLD+1 matching).
+  EXPECT_EQ(SEARCH_ENGINE_SOFTONIC,
+            TemplateURLPrepopulateData::GetEngineType(
+                "http://test.softonic.com.br/?{searchTerms}"));
+
   // Search URL for which no prepopulated search provider exists.
   EXPECT_EQ(SEARCH_ENGINE_OTHER,
             TemplateURLPrepopulateData::GetEngineType(
diff --git a/chrome/browser/search_engines/template_url_service.cc b/chrome/browser/search_engines/template_url_service.cc
index 8ae629a..34a3b8e 100644
--- a/chrome/browser/search_engines/template_url_service.cc
+++ b/chrome/browser/search_engines/template_url_service.cc
@@ -690,6 +690,12 @@
   return initial_default_search_provider_.get();
 }
 
+bool TemplateURLService::IsSearchResultsPageFromDefaultSearchProvider(
+    const GURL& url) {
+  TemplateURL* default_provider = GetDefaultSearchProvider();
+  return default_provider && default_provider->IsSearchURL(url);
+}
+
 TemplateURL* TemplateURLService::FindNewDefaultSearchProvider() {
   // See if the prepopulated default still exists.
   scoped_ptr<TemplateURL> prepopulated_default(
diff --git a/chrome/browser/search_engines/template_url_service.h b/chrome/browser/search_engines/template_url_service.h
index a7e3e24..7da1932 100644
--- a/chrome/browser/search_engines/template_url_service.h
+++ b/chrome/browser/search_engines/template_url_service.h
@@ -228,6 +228,10 @@
   // NOTE: At least in unittest mode, this may return NULL.
   TemplateURL* GetDefaultSearchProvider();
 
+  // Returns true if the |url| is a search results page from the default search
+  // provider.
+  bool IsSearchResultsPageFromDefaultSearchProvider(const GURL& url);
+
   // Returns true if the default search is managed through group policy.
   bool is_default_search_managed() const { return is_default_search_managed_; }
 
diff --git a/chrome/browser/search_engines/template_url_unittest.cc b/chrome/browser/search_engines/template_url_unittest.cc
index a4d38a5..708da7e 100644
--- a/chrome/browser/search_engines/template_url_unittest.cc
+++ b/chrome/browser/search_engines/template_url_unittest.cc
@@ -1168,3 +1168,58 @@
   EXPECT_EQ("http://www.google.com/search?q=abc#oq=def&x",
             url.url_ref().ReplaceSearchTerms(search_terms));
 }
+
+// Tests replacing pageClassification.
+TEST_F(TemplateURLTest, ReplacePageClassification) {
+  TemplateURLData data;
+  data.input_encodings.push_back("UTF-8");
+  data.SetURL("{google:baseURL}?{google:pageClassification}q={searchTerms}");
+  TemplateURL url(NULL, data);
+  EXPECT_TRUE(url.url_ref().IsValid());
+  ASSERT_TRUE(url.url_ref().SupportsReplacement());
+  TemplateURLRef::SearchTermsArgs search_terms_args(ASCIIToUTF16("foo"));
+
+  std::string result = url.url_ref().ReplaceSearchTerms(search_terms_args);
+  EXPECT_EQ("http://www.google.com/?q=foo", result);
+
+  search_terms_args.page_classification = AutocompleteInput::NEW_TAB_PAGE;
+  result = url.url_ref().ReplaceSearchTerms(search_terms_args);
+  EXPECT_EQ("http://www.google.com/?pgcl=1&q=foo", result);
+
+  search_terms_args.page_classification =
+      AutocompleteInput::HOMEPAGE;
+  result = url.url_ref().ReplaceSearchTerms(search_terms_args);
+  EXPECT_EQ("http://www.google.com/?pgcl=3&q=foo", result);
+}
+
+// Test the IsSearchResults function.
+TEST_F(TemplateURLTest, IsSearchResults) {
+  TemplateURLData data;
+  data.SetURL("http://bar/search?q={searchTerms}");
+  data.instant_url = "http://bar/instant#q={searchTerms}";
+  data.alternate_urls.push_back("http://bar/?q={searchTerms}");
+  data.alternate_urls.push_back("http://bar/#q={searchTerms}");
+  data.alternate_urls.push_back("http://bar/search#q{searchTerms}");
+  data.alternate_urls.push_back("http://bar/webhp#q={searchTerms}");
+  TemplateURL search_provider(NULL, data);
+
+  const struct {
+    const char* const url;
+    bool result;
+  } url_data[] = {
+    { "http://bar/search?q=foo&oq=foo", true, },
+    { "http://bar/?q=foo&oq=foo", true, },
+    { "http://bar/#output=search&q=foo&oq=foo", true, },
+    { "http://bar/webhp#q=foo&oq=foo", true, },
+    { "http://bar/#q=foo&oq=foo", true, },
+    { "http://bar/?ext=foo&q=foo#ref=bar", true, },
+    { "http://bar/url?url=http://www.foo.com/&q=foo#ref=bar", false, },
+    { "http://bar/", false, },
+    { "http://foo/", false, },
+  };
+
+  for (size_t i = 0; i < ARRAYSIZE_UNSAFE(url_data); ++i) {
+    EXPECT_EQ(url_data[i].result,
+              search_provider.IsSearchURL(GURL(url_data[i].url)));
+  }
+}
diff --git a/chrome/browser/signin/signin_browsertest.cc b/chrome/browser/signin/signin_browsertest.cc
index aef931c..1aa32ce 100644
--- a/chrome/browser/signin/signin_browsertest.cc
+++ b/chrome/browser/signin/signin_browsertest.cc
@@ -207,8 +207,13 @@
   content::WebContents* web_contents =
       browser()->tab_strip_model()->GetActiveWebContents();
 
-  // Simulate clicking on the Skip for now link by navigating to the URL.
-  ui_test_utils::NavigateToURL(browser(), skip_url);
+  // Simulate clicking on the Skip for now link. It's important to have a
+  // link transition so that OneClickSigninHelper removes the blank page
+  // from the history.
+  chrome::NavigateParams navigate_params(browser(),
+                                         skip_url,
+                                         content::PAGE_TRANSITION_LINK);
+  ui_test_utils::NavigateToURL(&navigate_params);
 
   // Register an observer that will navigate back immediately on the commit of
   // the NTP. This will allow us to hit the race condition of navigating back
diff --git a/chrome/browser/speech/extension_api/tts_engine_extension_api.cc b/chrome/browser/speech/extension_api/tts_engine_extension_api.cc
index ae3fa1d..ba5e65b 100644
--- a/chrome/browser/speech/extension_api/tts_engine_extension_api.cc
+++ b/chrome/browser/speech/extension_api/tts_engine_extension_api.cc
@@ -188,7 +188,6 @@
 
 bool ExtensionTtsEngineSendTtsEventFunction::RunImpl() {
   int utterance_id;
-  std::string error_message;
   EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &utterance_id));
 
   DictionaryValue* event;
diff --git a/chrome/browser/ssl/ssl_blocking_page.cc b/chrome/browser/ssl/ssl_blocking_page.cc
index 33ef570..1e8ab90 100644
--- a/chrome/browser/ssl/ssl_blocking_page.cc
+++ b/chrome/browser/ssl/ssl_blocking_page.cc
@@ -10,6 +10,7 @@
 #include "base/strings/string_piece.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/values.h"
+#include "chrome/browser/history/history_service_factory.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/renderer_preferences_util.h"
 #include "chrome/browser/ssl/ssl_error_info.h"
@@ -70,6 +71,8 @@
   SHOW_UNDERSTAND,
   SHOW_INTERNAL_HOSTNAME,
   PROCEED_INTERNAL_HOSTNAME,
+  SHOW_NEW_SITE,
+  PROCEED_NEW_SITE,
   UNUSED_BLOCKING_PAGE_EVENT,
 };
 
@@ -84,7 +87,8 @@
     int cert_error,
     bool overridable,
     bool internal,
-    const base::TimeTicks& start_time) {
+    const base::TimeTicks& start_time,
+    int num_visits) {
   UMA_HISTOGRAM_ENUMERATION("interstitial.ssl_error_type",
      SSLErrorInfo::NetErrorToErrorType(cert_error), SSLErrorInfo::END_OF_ENUM);
   if (start_time.is_null() || !overridable) {
@@ -93,10 +97,14 @@
     // back. In either case, we don't want to record some of our metrics.
     return;
   }
+  if (num_visits == 0)
+    RecordSSLBlockingPageEventStats(SHOW_NEW_SITE);
   if (proceed) {
     RecordSSLBlockingPageEventStats(PROCEED_OVERRIDABLE);
     if (internal)
       RecordSSLBlockingPageEventStats(PROCEED_INTERNAL_HOSTNAME);
+    if (num_visits == 0)
+      RecordSSLBlockingPageEventStats(PROCEED_NEW_SITE);
   } else if (!proceed) {
     RecordSSLBlockingPageEventStats(DONT_PROCEED_OVERRIDABLE);
   }
@@ -158,17 +166,28 @@
       request_url_(request_url),
       overridable_(overridable),
       strict_enforcement_(strict_enforcement),
-      internal_(false) {
+      internal_(false),
+      num_visits_(-1) {
   trialCondition_ = base::FieldTrialList::FindFullName(kStudyName);
 
+  // For UMA stats.
   if (net::IsHostnameNonUnique(request_url_.HostNoBrackets()))
     internal_ = true;
-
   RecordSSLBlockingPageEventStats(SHOW_ALL);
   if (overridable_ && !strict_enforcement_) {
     RecordSSLBlockingPageEventStats(SHOW_OVERRIDABLE);
     if (internal_)
       RecordSSLBlockingPageEventStats(SHOW_INTERNAL_HOSTNAME);
+    HistoryService* history_service = HistoryServiceFactory::GetForProfile(
+        Profile::FromBrowserContext(web_contents->GetBrowserContext()),
+        Profile::EXPLICIT_ACCESS);
+    if (history_service) {
+      history_service->GetVisibleVisitCountToHost(
+          request_url_,
+          &request_consumer_,
+          base::Bind(&SSLBlockingPage::OnGotHistoryCount,
+                    base::Unretained(this)));
+    }
   }
 
   interstitial_page_ = InterstitialPage::Create(
@@ -183,7 +202,8 @@
                                        cert_error_,
                                        overridable_ && !strict_enforcement_,
                                        internal_,
-                                       display_start_time_);
+                                       display_start_time_,
+                                       num_visits_);
     // The page is closed without the user having chosen what to do, default to
     // deny.
     NotifyDenyCertificate();
@@ -310,7 +330,8 @@
                                      cert_error_,
                                      overridable_ && !strict_enforcement_,
                                      internal_,
-                                     display_start_time_);
+                                     display_start_time_,
+                                     num_visits_);
   // Accepting the certificate resumes the loading of the page.
   NotifyAllowCertificate();
 }
@@ -320,7 +341,8 @@
                                      cert_error_,
                                      overridable_ && !strict_enforcement_,
                                      internal_,
-                                     display_start_time_);
+                                     display_start_time_,
+                                     num_visits_);
   NotifyDenyCertificate();
 }
 
@@ -358,3 +380,10 @@
     strings->SetString(keys[i], std::string());
   }
 }
+
+void SSLBlockingPage::OnGotHistoryCount(HistoryService::Handle handle,
+                                        bool success,
+                                        int num_visits,
+                                        base::Time first_visit) {
+  num_visits_ = num_visits;
+}
diff --git a/chrome/browser/ssl/ssl_blocking_page.h b/chrome/browser/ssl/ssl_blocking_page.h
index af24412..d4703f4 100644
--- a/chrome/browser/ssl/ssl_blocking_page.h
+++ b/chrome/browser/ssl/ssl_blocking_page.h
@@ -11,6 +11,7 @@
 #include "base/callback.h"
 #include "base/strings/string16.h"
 #include "base/time/time.h"
+#include "chrome/browser/history/history_service.h"
 #include "content/public/browser/interstitial_page_delegate.h"
 #include "net/ssl/ssl_info.h"
 #include "url/gurl.h"
@@ -60,6 +61,12 @@
   void NotifyDenyCertificate();
   void NotifyAllowCertificate();
 
+  // Used to query the HistoryService to see if the URL is in history. For UMA.
+  void OnGotHistoryCount(HistoryService::Handle handle,
+                         bool success,
+                         int num_visits,
+                         base::Time first_visit);
+
   base::Callback<void(bool)> callback_;
 
   content::WebContents* web_contents_;
@@ -74,6 +81,10 @@
   content::InterstitialPage* interstitial_page_;  // Owns us.
   // Is the hostname for an internal network?
   bool internal_;
+  // How many times is this same URL in history?
+  int num_visits_;
+  // Used for getting num_visits_.
+  CancelableRequestConsumer request_consumer_;
 
   // For the FieldTrial: this contains the name of the condition.
   std::string trialCondition_;
diff --git a/chrome/browser/storage_monitor/storage_monitor.h b/chrome/browser/storage_monitor/storage_monitor.h
index cf9767e..f008dca 100644
--- a/chrome/browser/storage_monitor/storage_monitor.h
+++ b/chrome/browser/storage_monitor/storage_monitor.h
@@ -29,10 +29,6 @@
 class MediaTransferProtocolManager;
 }
 
-namespace extensions {
-class StorageInfoProviderTest;
-}
-
 namespace chrome {
 
 class MediaFileSystemRegistryTest;
@@ -145,7 +141,6 @@
   friend class MediaFileSystemRegistryTest;
   friend class ::SystemStorageApiTest;
   friend class ::SystemStorageEjectApiTest;
-  friend class extensions::StorageInfoProviderTest;
 
   StorageMonitor();
 
diff --git a/chrome/browser/sxs_linux.cc b/chrome/browser/sxs_linux.cc
new file mode 100644
index 0000000..daf6f93
--- /dev/null
+++ b/chrome/browser/sxs_linux.cc
@@ -0,0 +1,97 @@
+// 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/sxs_linux.h"
+
+#include <vector>
+
+#include "base/logging.h"
+#include "base/file_util.h"
+#include "base/files/file_path.h"
+#include "base/files/important_file_writer.h"
+#include "base/path_service.h"
+#include "base/strings/string_split.h"
+#include "base/strings/string_util.h"
+#include "chrome/common/chrome_paths.h"
+#include "chrome/common/chrome_version_info.h"
+#include "content/public/browser/browser_thread.h"
+
+namespace {
+
+bool DoAddChannelMarkToUserDataDir(const base::FilePath& user_data_dir) {
+  std::string product_channel_name;
+  chrome::VersionInfo::Channel product_channel(
+      chrome::VersionInfo::GetChannel());
+  switch (product_channel) {
+    case chrome::VersionInfo::CHANNEL_UNKNOWN: {
+      // Add the channel mark even for Chromium builds (which do not have
+      // channel) to better handle possibility of users using Chromium builds
+      // with their Google Chrome profiles. Include version string modifier
+      // as additional piece of information for debugging (it can't make
+      // a meaningful difference for the code since unknown does not match any
+      // real channel name).
+      std::string version_string_modifier(
+          chrome::VersionInfo::GetVersionStringModifier());
+      product_channel_name = "unknown (" + version_string_modifier + ")";
+      break;
+    }
+    case chrome::VersionInfo::CHANNEL_CANARY:
+      product_channel_name = "canary";
+      break;
+    case chrome::VersionInfo::CHANNEL_DEV:
+      product_channel_name = "dev";
+      break;
+    case chrome::VersionInfo::CHANNEL_BETA:
+      product_channel_name = "beta";
+      break;
+    case chrome::VersionInfo::CHANNEL_STABLE:
+      product_channel_name = "stable";
+      break;
+    // Rely on -Wswitch compiler warning to detect unhandled enum values.
+  }
+
+  base::FilePath channels_path(user_data_dir.AppendASCII("Channels"));
+  std::vector<std::string> user_data_dir_channels;
+
+  // Note: failure to read the channels file is not fatal. It's possible
+  // and legitimate that it doesn't exist, e.g. for new profile or for profile
+  // existing before channel marks have been introduced.
+  std::string channels_contents;
+  if (file_util::ReadFileToString(channels_path, &channels_contents))
+    base::SplitString(channels_contents, '\n', &user_data_dir_channels);
+
+  if (std::find(user_data_dir_channels.begin(),
+                user_data_dir_channels.end(),
+                product_channel_name) != user_data_dir_channels.end()) {
+    // No need to do further disk writes if our channel mark is already present.
+    return true;
+  }
+
+  user_data_dir_channels.push_back(product_channel_name);
+  return base::ImportantFileWriter::WriteFileAtomically(
+      channels_path,
+      JoinString(user_data_dir_channels, "\n"));
+}
+
+}  // namespace
+
+namespace sxs_linux {
+
+void AddChannelMarkToUserDataDir() {
+  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::FILE));
+  base::FilePath user_data_dir;
+  if (!PathService::Get(chrome::DIR_USER_DATA, &user_data_dir)) {
+    LOG(ERROR) << "Failed to get user data dir path. The profile will not be "
+               << "automatically migrated for updated Linux packages.";
+    return;
+  }
+
+  if (!DoAddChannelMarkToUserDataDir(user_data_dir)) {
+    LOG(ERROR) << "Failed to add channel mark to the user data dir ("
+               << user_data_dir.value() << "). This profile will not be "
+               << "automatically migrated for updated Linux packages.";
+  }
+}
+
+}  // namespace sxs_linux
diff --git a/chrome/browser/sxs_linux.h b/chrome/browser/sxs_linux.h
new file mode 100644
index 0000000..a6d7b42
--- /dev/null
+++ b/chrome/browser/sxs_linux.h
@@ -0,0 +1,24 @@
+// 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_SXS_LINUX_H_
+#define CHROME_BROWSER_SXS_LINUX_H_
+
+#include "base/compiler_specific.h"
+
+namespace base {
+class FilePath;
+}
+
+namespace sxs_linux {
+
+// Records channel of the running browser in user data dir. This is needed
+// to support a seamless and automatic upgrade from non-side-by-side
+// to side-by-side Linux packages (the latter use different default data dirs).
+// Must be run on FILE thread.
+void AddChannelMarkToUserDataDir();
+
+}  // namespace sxs_linux
+
+#endif  // CHROME_BROWSER_SXS_LINUX_H_
diff --git a/chrome/browser/sync/glue/session_model_associator.cc b/chrome/browser/sync/glue/session_model_associator.cc
index 916ccfb..0598340 100644
--- a/chrome/browser/sync/glue/session_model_associator.cc
+++ b/chrome/browser/sync/glue/session_model_associator.cc
@@ -285,8 +285,7 @@
     }
   }
 
-  // Free old sync nodes.
-  local_tab_pool_.FreeUnassociatedTabNodes();
+  local_tab_pool_.DeleteUnassociatedTabNodes();
   // Free memory for closed windows and tabs.
   synced_session_tracker_.CleanupSession(local_tag);
 
@@ -749,9 +748,7 @@
         } else {
           // This is a valid old tab node, add it to the pool so it can be
           // reused for reassociation.
-          SessionID tab_id;
-          tab_id.set_id(specifics.tab().tab_id());
-          local_tab_pool_.AddTabNode(specifics.tab_node_id(), tab_id);
+          local_tab_pool_.AddTabNode(specifics.tab_node_id());
         }
       }
     }
diff --git a/chrome/browser/sync/glue/session_model_associator.h b/chrome/browser/sync/glue/session_model_associator.h
index 2b3aac4..5fd7ca5 100644
--- a/chrome/browser/sync/glue/session_model_associator.h
+++ b/chrome/browser/sync/glue/session_model_associator.h
@@ -224,6 +224,8 @@
   FRIEND_TEST_ALL_PREFIXES(ProfileSyncServiceSessionTest, MissingLocalTabNode);
   FRIEND_TEST_ALL_PREFIXES(ProfileSyncServiceSessionTest,
                            TabPoolFreeNodeLimits);
+  FRIEND_TEST_ALL_PREFIXES(ProfileSyncServiceSessionTest,
+                           TabNodePoolDeleteUnassociatedNodes);
   FRIEND_TEST_ALL_PREFIXES(SyncSessionModelAssociatorTest,
                            PopulateSessionHeader);
   FRIEND_TEST_ALL_PREFIXES(SyncSessionModelAssociatorTest,
diff --git a/chrome/browser/sync/glue/synced_session_tracker.cc b/chrome/browser/sync/glue/synced_session_tracker.cc
index 402800c..083aac4 100644
--- a/chrome/browser/sync/glue/synced_session_tracker.cc
+++ b/chrome/browser/sync/glue/synced_session_tracker.cc
@@ -313,12 +313,6 @@
       // node for this session before actually associating the tab itself, so
       // the tab node id wasn't available at the time.  Update it.
 
-      // TODO(shashishekhar): Make sure the following constraint works.
-      // All nodes either have unique tab_ids or have kInvalidTabID as their
-      // tab_id. There can be multiple nodes associated with kInvalidTabID but
-      // there is always one-to-one mapping between valid tab_ids and
-      // tab_node_ids.
-
       if (iter->second.tab_node_id != tab_node_id &&
           iter->second.tab_node_id != TabNodePool::kInvalidTabNodeID) {
         // We are updating tab_node_id for a valid tab_id, ideally this should
diff --git a/chrome/browser/sync/glue/tab_node_pool.cc b/chrome/browser/sync/glue/tab_node_pool.cc
index 4d981f3..a16bb57 100644
--- a/chrome/browser/sync/glue/tab_node_pool.cc
+++ b/chrome/browser/sync/glue/tab_node_pool.cc
@@ -39,10 +39,8 @@
   return base::StringPrintf("%s %d", machine_tag.c_str(), tab_node_id);
 }
 
-void TabNodePool::AddTabNode(int tab_node_id,
-                             const SessionID& tab_id) {
+void TabNodePool::AddTabNode(int tab_node_id) {
   DCHECK_GT(tab_node_id, kInvalidTabNodeID);
-  DCHECK_GT(tab_id.id(), kInvalidTabID);
   DCHECK(nodeid_tabid_map_.find(tab_node_id) == nodeid_tabid_map_.end());
   unassociated_nodes_.insert(tab_node_id);
   if (max_used_tab_node_id_ < tab_node_id)
@@ -168,10 +166,18 @@
   return kInvalidTabID;
 }
 
-void TabNodePool::FreeUnassociatedTabNodes() {
+void TabNodePool::DeleteUnassociatedTabNodes() {
+  syncer::WriteTransaction trans(FROM_HERE, sync_service_->GetUserShare());
   for (std::set<int>::iterator it = unassociated_nodes_.begin();
        it != unassociated_nodes_.end();) {
-    FreeTabNodeInternal(*it);
+    syncer::WriteNode tab_node(&trans);
+    const std::string tab_node_tag = TabIdToTag(machine_tag_, *it);
+    if (tab_node.InitByClientTagLookup(syncer::SESSIONS, tab_node_tag) !=
+        syncer::BaseNode::INIT_OK) {
+      LOG(ERROR) << "Could not find sync node with tag: " << tab_node_tag;
+    } else {
+      tab_node.Tombstone();
+    }
     unassociated_nodes_.erase(it++);
   }
   DCHECK(unassociated_nodes_.empty());
diff --git a/chrome/browser/sync/glue/tab_node_pool.h b/chrome/browser/sync/glue/tab_node_pool.h
index 6435175..64b34d2 100644
--- a/chrome/browser/sync/glue/tab_node_pool.h
+++ b/chrome/browser/sync/glue/tab_node_pool.h
@@ -32,7 +32,7 @@
 //                   restart. Nodes are only unassociated temporarily while the
 //                   model associator figures out which tabs belong to which
 //                   nodes. Eventually any remaining unassociated nodes are
-//                   freed.
+//                   deleted.
 // 3. Free         : Sync node is unused.
 
 class TabNodePool {
@@ -77,7 +77,7 @@
   // Note: this should only be called when we discover tab sync nodes from
   // previous sessions, not for freeing tab nodes we created through
   // GetFreeTabNode (use FreeTabNode below for that).
-  void AddTabNode(int tab_node_id, const SessionID& tab_id);
+  void AddTabNode(int tab_node_id);
 
   // Returns the tab_id for |tab_node_id| if it is associated else returns
   // kInvalidTabID.
@@ -90,8 +90,8 @@
   // Returns true if |tab_node_id| is an unassociated tab node.
   bool IsUnassociatedTabNode(int tab_node_id);
 
-  // Returns any unassociated nodes to the free node pool.
-  void FreeUnassociatedTabNodes();
+  // Deletes any unassociated nodes.
+  void DeleteUnassociatedTabNodes();
 
   // Clear tab pool.
   void Clear();
diff --git a/chrome/browser/sync/glue/tab_node_pool_unittest.cc b/chrome/browser/sync/glue/tab_node_pool_unittest.cc
index 093e520..f93de85 100644
--- a/chrome/browser/sync/glue/tab_node_pool_unittest.cc
+++ b/chrome/browser/sync/glue/tab_node_pool_unittest.cc
@@ -3,6 +3,7 @@
 // found in the LICENSE file.
 
 #include "chrome/browser/sync/glue/tab_node_pool.h"
+#include "base/logging.h"
 
 #include "testing/gtest/include/gtest/gtest.h"
 
@@ -14,53 +15,57 @@
 
   int GetMaxUsedTabNodeId() const { return pool_.max_used_tab_node_id_; }
 
+  void AddFreeTabNodes(size_t size, const int node_ids[]);
+
   TabNodePool pool_;
 };
 
+void SyncTabNodePoolTest::AddFreeTabNodes(size_t size, const int node_ids[]) {
+  for (size_t i = 0; i < size; ++i) {
+    pool_.free_nodes_pool_.insert(node_ids[i]);
+  }
+}
+
 namespace {
 
 TEST_F(SyncTabNodePoolTest, TabNodeIdIncreases) {
   // max_used_tab_node_ always increases.
-  SessionID session_id;
-  session_id.set_id(1);
-  pool_.AddTabNode(10, session_id);
+  pool_.AddTabNode(10);
   EXPECT_EQ(10, GetMaxUsedTabNodeId());
-  session_id.set_id(2);
-  pool_.AddTabNode(1, session_id);
+  pool_.AddTabNode(5);
   EXPECT_EQ(10, GetMaxUsedTabNodeId());
-  session_id.set_id(3);
-  pool_.AddTabNode(1000, session_id);
+  pool_.AddTabNode(1000);
   EXPECT_EQ(1000, GetMaxUsedTabNodeId());
-  pool_.ReassociateTabNode(1000, 500);
-
+  pool_.ReassociateTabNode(1000, 1);
+  pool_.ReassociateTabNode(5, 2);
+  pool_.ReassociateTabNode(10, 3);
   // Freeing a tab node does not change max_used_tab_node_id_.
   pool_.FreeTabNode(1000);
-  pool_.FreeUnassociatedTabNodes();
-  EXPECT_EQ(1000, GetMaxUsedTabNodeId());
+  pool_.FreeTabNode(5);
+  pool_.FreeTabNode(10);
   for (int i = 0; i < 3; ++i) {
     pool_.AssociateTabNode(pool_.GetFreeTabNode(), i + 1);
     EXPECT_EQ(1000, GetMaxUsedTabNodeId());
   }
 
   EXPECT_EQ(1000, GetMaxUsedTabNodeId());
+  EXPECT_TRUE(pool_.Empty());
 }
 
 TEST_F(SyncTabNodePoolTest, OldTabNodesAddAndRemove) {
   // VerifyOldTabNodes are added.
-  // tab_node_id = 1, tab_id = 1
-  SessionID session_id;
-  session_id.set_id(1);
-  pool_.AddTabNode(1, session_id);
-  // tab_node_id = 2, tab_id = 2
-  session_id.set_id(2);
-  pool_.AddTabNode(2, session_id);
+  pool_.AddTabNode(1);
+  pool_.AddTabNode(2);
   EXPECT_EQ(2u, pool_.Capacity());
   EXPECT_TRUE(pool_.Empty());
   EXPECT_TRUE(pool_.IsUnassociatedTabNode(1));
+  EXPECT_TRUE(pool_.IsUnassociatedTabNode(2));
   pool_.ReassociateTabNode(1, 2);
   EXPECT_TRUE(pool_.Empty());
-  // Check FreeUnassociatedTabNodes returns the node to free node pool_.
-  pool_.FreeUnassociatedTabNodes();
+  pool_.AssociateTabNode(2, 3);
+  EXPECT_FALSE(pool_.IsUnassociatedTabNode(1));
+  EXPECT_FALSE(pool_.IsUnassociatedTabNode(2));
+  pool_.FreeTabNode(2);
   // 2 should be returned to free node pool_.
   EXPECT_EQ(2u, pool_.Capacity());
   // Should be able to free 1.
@@ -77,19 +82,18 @@
 
 TEST_F(SyncTabNodePoolTest, OldTabNodesReassociation) {
   // VerifyOldTabNodes are reassociated correctly.
-  SessionID session_id;
-  session_id.set_id(1);
-  pool_.AddTabNode(4, session_id);
-  session_id.set_id(2);
-  pool_.AddTabNode(5, session_id);
-  session_id.set_id(3);
-  pool_.AddTabNode(6, session_id);
+  pool_.AddTabNode(4);
+  pool_.AddTabNode(5);
+  pool_.AddTabNode(6);
   EXPECT_EQ(3u, pool_.Capacity());
   EXPECT_TRUE(pool_.Empty());
   EXPECT_TRUE(pool_.IsUnassociatedTabNode(4));
   pool_.ReassociateTabNode(4, 5);
+  pool_.AssociateTabNode(5, 6);
+  pool_.AssociateTabNode(6, 7);
   // Free 5 and 6.
-  pool_.FreeUnassociatedTabNodes();
+  pool_.FreeTabNode(5);
+  pool_.FreeTabNode(6);
   // 5 and 6 nodes should not be unassociated.
   EXPECT_FALSE(pool_.IsUnassociatedTabNode(5));
   EXPECT_FALSE(pool_.IsUnassociatedTabNode(6));
@@ -121,15 +125,10 @@
 }
 
 TEST_F(SyncTabNodePoolTest, AddGet) {
-  SessionID session_id;
-  session_id.set_id(1);
-  pool_.AddTabNode(5, session_id);
-  session_id.set_id(2);
-  pool_.AddTabNode(10, session_id);
-  pool_.FreeUnassociatedTabNodes();
+  int free_nodes[] = {5, 10};
+  AddFreeTabNodes(2, free_nodes);
   EXPECT_FALSE(pool_.Empty());
   EXPECT_TRUE(pool_.Full());
-
   EXPECT_EQ(2U, pool_.Capacity());
   EXPECT_EQ(5, pool_.GetFreeTabNode());
   pool_.AssociateTabNode(5, 1);
@@ -144,13 +143,8 @@
   EXPECT_TRUE(pool_.Empty());
   EXPECT_TRUE(pool_.Full());
   EXPECT_EQ(0U, pool_.Capacity());
-  SessionID session_id;
-  session_id.set_id(1);
-  pool_.AddTabNode(5, session_id);
-  session_id.set_id(2);
-  pool_.AddTabNode(10, session_id);
-  // Free added nodes.
-  pool_.FreeUnassociatedTabNodes();
+  int free_nodes[] = {5, 10};
+  AddFreeTabNodes(2, free_nodes);
   EXPECT_FALSE(pool_.Empty());
   EXPECT_TRUE(pool_.Full());
   EXPECT_EQ(2U, pool_.Capacity());
diff --git a/chrome/browser/sync/profile_sync_service_session_unittest.cc b/chrome/browser/sync/profile_sync_service_session_unittest.cc
index c7aa28f..592a826 100644
--- a/chrome/browser/sync/profile_sync_service_session_unittest.cc
+++ b/chrome/browser/sync/profile_sync_service_session_unittest.cc
@@ -792,13 +792,13 @@
   ASSERT_TRUE(create_root.success());
 
   const size_t num_starting_nodes = 3;
-  SessionID session_id;
   for (size_t i = 0; i < num_starting_nodes; ++i) {
-    session_id.set_id(i + 1);
-    model_associator_->local_tab_pool_.AddTabNode(i + 1, session_id);
+    size_t node_id = i + 1;
+    model_associator_->local_tab_pool_.AddTabNode(node_id);
+    model_associator_->local_tab_pool_.AssociateTabNode(node_id, i);
+    model_associator_->local_tab_pool_.FreeTabNode(node_id);
   }
 
-  model_associator_->local_tab_pool_.FreeUnassociatedTabNodes();
   std::vector<int> node_ids;
   ASSERT_EQ(num_starting_nodes, model_associator_->local_tab_pool_.Capacity());
   ASSERT_FALSE(model_associator_->local_tab_pool_.Empty());
@@ -1372,4 +1372,33 @@
             model_associator_->local_tab_pool_.Capacity());
 }
 
+TEST_F(ProfileSyncServiceSessionTest, TabNodePoolDeleteUnassociatedNodes) {
+  CreateRootHelper create_root(this);
+  ASSERT_TRUE(StartSyncService(create_root.callback(), false));
+  std::string local_tag = model_associator_->GetCurrentMachineTag();
+  syncer::SyncError error;
+  // Create a free node and then dissassociate sessions so that it ends up
+  // unassociated.
+  int tab_node_id = model_associator_->local_tab_pool_.GetFreeTabNode();
+  // Update the tab_id of the node, so that it is considered a valid
+  // unassociated node otherwise it will be mistaken for a corrupted node and
+  // will be deleted before being added to the tab node pool.
+  {
+    std::string tab_tag = TabNodePool::TabIdToTag(local_tag, tab_node_id);
+    syncer::WriteTransaction trans(FROM_HERE, sync_service_->GetUserShare());
+    syncer::WriteNode tab_node(&trans);
+    ASSERT_EQ(syncer::BaseNode::INIT_OK,
+              tab_node.InitByClientTagLookup(syncer::SESSIONS, tab_tag));
+    sync_pb::SessionSpecifics specifics = tab_node.GetSessionSpecifics();
+    sync_pb::SessionTab* tab = specifics.mutable_tab();
+    tab->set_tab_id(1);
+    tab_node.SetSessionSpecifics(specifics);
+  }
+
+  error = model_associator_->DisassociateModels();
+  ASSERT_FALSE(error.IsSet());
+  error = model_associator_->AssociateModels(NULL, NULL);
+  ASSERT_FALSE(error.IsSet());
+}
+
 }  // namespace browser_sync
diff --git a/chrome/browser/sync_file_system/drive_backend/metadata_database.cc b/chrome/browser/sync_file_system/drive_backend/metadata_database.cc
index c0307d4..5219758 100644
--- a/chrome/browser/sync_file_system/drive_backend/metadata_database.cc
+++ b/chrome/browser/sync_file_system/drive_backend/metadata_database.cc
@@ -78,6 +78,46 @@
   return base::FilePath(result).NormalizePathSeparators();
 }
 
+scoped_ptr<FileMetadata> CreateFileMetadataFromChangeResource(
+    const google_apis::ChangeResource& change) {
+  scoped_ptr<FileMetadata> file(new FileMetadata);
+  file->set_file_id(change.file_id());
+
+  FileDetails* details = file->mutable_details();
+  details->set_change_id(change.change_id());
+
+  if (change.is_deleted()) {
+    details->set_deleted(true);
+    return file.Pass();
+  }
+
+  const google_apis::FileResource& file_resource = *change.file();
+  for (ScopedVector<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->set_title(file_resource.title());
+
+  google_apis::DriveEntryKind kind = file_resource.GetKind();
+  if (kind == google_apis::ENTRY_KIND_FILE)
+    details->set_file_kind(FILE_KIND_FILE);
+  else if (kind == google_apis::ENTRY_KIND_FOLDER)
+    details->set_file_kind(FILE_KIND_FOLDER);
+  else
+    details->set_file_kind(FILE_KIND_UNSUPPORTED);
+
+  details->set_md5(file_resource.md5_checksum());
+  details->set_etag(file_resource.etag());
+  details->set_creation_time(file_resource.created_date().ToInternalValue());
+  details->set_modification_time(
+      file_resource.modified_date().ToInternalValue());
+  details->set_deleted(false);
+
+  return file.Pass();
+}
+
 void AdaptLevelDBStatusToSyncStatusCode(const SyncStatusCallback& callback,
                                         const leveldb::Status& status) {
   callback.Run(LevelDBStatusToSyncStatusCode(status));
@@ -115,6 +155,25 @@
   batch->Delete(kFileTrackerKeyPrefix + base::Int64ToString(tracker_id));
 }
 
+void PushChildTrackersToStack(
+    const TrackersByParentAndTitle& trackers_by_parent,
+    int64 parent_tracker_id,
+    std::stack<int64>* stack) {
+  TrackersByParentAndTitle::const_iterator found =
+      trackers_by_parent.find(parent_tracker_id);
+  if (found == trackers_by_parent.end())
+    return;
+
+  for (TrackersByTitle::const_iterator title_itr = found->second.begin();
+       title_itr != found->second.end(); ++title_itr) {
+    const TrackerSet& trackers = title_itr->second;
+    for (TrackerSet::const_iterator tracker_itr = trackers.begin();
+         tracker_itr != trackers.end(); ++tracker_itr) {
+      stack->push((*tracker_itr)->tracker_id());
+    }
+  }
+}
+
 std::string GetTrackerTitle(const FileTracker& tracker) {
   if (tracker.has_synced_details())
     return tracker.synced_details().title();
@@ -391,6 +450,19 @@
   return true;
 }
 
+template <typename Container, typename Key>
+typename Container::mapped_type FindAndEraseItem(Container* container,
+                                                 const Key& key) {
+  typedef typename Container::mapped_type Value;
+  typename Container::iterator found = container->find(key);
+  if (found == container->end())
+    return Value();
+
+  Value result = found->second;
+  container->erase(found);
+  return result;
+}
+
 void RunSoon(const tracked_objects::Location& from_here,
              const base::Closure& closure) {
   base::MessageLoopProxy::current()->PostTask(from_here, closure);
@@ -430,28 +502,153 @@
 void MetadataDatabase::RegisterApp(const std::string& app_id,
                                    const std::string& folder_id,
                                    const SyncStatusCallback& callback) {
-  NOTIMPLEMENTED();
+  if (FindAppRootTracker(app_id, NULL)) {
+    RunSoon(FROM_HERE, base::Bind(callback, SYNC_STATUS_OK));
+    return;
+  }
+
+  TrackerSet trackers;
+  if (!FindTrackersByFileID(folder_id, &trackers) ||
+      trackers.has_active() ||
+      trackers.tracker_set().size() != 1) {
+    util::Log(logging::LOG_WARNING, FROM_HERE,
+              "Failed to register App for %s", app_id.c_str());
+    RunSoon(FROM_HERE, base::Bind(callback, SYNC_STATUS_HAS_CONFLICT));
+    return;
+  }
+
+  FileTracker* tracker = *trackers.tracker_set().begin();
+
+  scoped_ptr<leveldb::WriteBatch> batch(new leveldb::WriteBatch);
+  RegisterTrackerAsAppRoot(app_id, tracker->tracker_id(), batch.get());
+  WriteToDatabase(batch.Pass(), callback);
 }
 
 void MetadataDatabase::DisableApp(const std::string& app_id,
                                   const SyncStatusCallback& callback) {
-  NOTIMPLEMENTED();
+  FileTracker tracker;
+  if (!FindAppRootTracker(app_id, &tracker)) {
+    RunSoon(FROM_HERE, base::Bind(callback, SYNC_DATABASE_ERROR_NOT_FOUND));
+    return;
+  }
+
+  if (!tracker.active()) {
+    RunSoon(FROM_HERE, base::Bind(callback, SYNC_STATUS_OK));
+    return;
+  }
+
+  scoped_ptr<leveldb::WriteBatch> batch(new leveldb::WriteBatch);
+  MakeTrackerInactive(tracker.tracker_id(), batch.get());
+  WriteToDatabase(batch.Pass(), callback);
 }
 
 void MetadataDatabase::EnableApp(const std::string& app_id,
                                  const SyncStatusCallback& callback) {
-  NOTIMPLEMENTED();
+  FileTracker tracker;
+  if (!FindAppRootTracker(app_id, &tracker)) {
+    RunSoon(FROM_HERE, base::Bind(callback, SYNC_DATABASE_ERROR_NOT_FOUND));
+    return;
+  }
+
+  if (tracker.active()) {
+    RunSoon(FROM_HERE, base::Bind(callback, SYNC_STATUS_OK));
+    return;
+  }
+
+  scoped_ptr<leveldb::WriteBatch> batch(new leveldb::WriteBatch);
+  MakeTrackerActive(tracker.tracker_id(), batch.get());
+  WriteToDatabase(batch.Pass(), callback);
 }
 
 void MetadataDatabase::UnregisterApp(const std::string& app_id,
                                      const SyncStatusCallback& callback) {
-  NOTIMPLEMENTED();
+  FileTracker tracker;
+  if (!FindAppRootTracker(app_id, &tracker)) {
+    RunSoon(FROM_HERE, base::Bind(callback, SYNC_STATUS_OK));
+    return;
+  }
+
+  scoped_ptr<leveldb::WriteBatch> batch(new leveldb::WriteBatch);
+  UnregisterTrackerAsAppRoot(app_id, batch.get());
+  WriteToDatabase(batch.Pass(), callback);
+}
+
+bool MetadataDatabase::FindAppRootTracker(const std::string& app_id,
+                                          FileTracker* tracker) const {
+  return FindItem(app_root_by_app_id_, app_id, tracker);
+}
+
+bool MetadataDatabase::FindFileByFileID(const std::string& file_id,
+                                        FileMetadata* file) const {
+  return FindItem(file_by_id_, file_id, file);
+}
+
+bool MetadataDatabase::FindTrackersByFileID(const std::string& file_id,
+                                            TrackerSet* trackers) const {
+  TrackersByFileID::const_iterator found = trackers_by_file_id_.find(file_id);
+  if (found == trackers_by_file_id_.end())
+    return false;
+  if (trackers)
+    *trackers = found->second;
+  return true;
+}
+
+bool MetadataDatabase::FindTrackerByTrackerID(int64 tracker_id,
+                                              FileTracker* tracker) const {
+  return FindItem(tracker_by_id_, tracker_id, tracker);
+}
+
+bool MetadataDatabase::BuildPathForTracker(int64 tracker_id,
+                                           base::FilePath* path) const {
+  FileTracker current;
+  if (!FindTrackerByTrackerID(tracker_id, &current) || !current.active())
+    return false;
+
+  std::vector<base::FilePath> components;
+  while (!current.is_app_root()) {
+    std::string title = GetTrackerTitle(current);
+    if (title.empty())
+      return false;
+    components.push_back(base::FilePath::FromUTF8Unsafe(title));
+    if (!FindTrackerByTrackerID(current.parent_tracker_id(), &current) ||
+        !current.active())
+      return false;
+  }
+
+  if (path)
+    *path = ReverseConcatPathComponents(components);
+
+  return true;
 }
 
 void MetadataDatabase::UpdateByChangeList(
     ScopedVector<google_apis::ChangeResource> changes,
     const SyncStatusCallback& callback) {
-  NOTIMPLEMENTED();
+  scoped_ptr<leveldb::WriteBatch> batch(new leveldb::WriteBatch);
+
+  for (ScopedVector<google_apis::ChangeResource>::const_iterator itr =
+           changes.begin();
+       itr != changes.end();
+       ++itr) {
+    const google_apis::ChangeResource& change = **itr;
+    scoped_ptr<FileMetadata> file(
+        CreateFileMetadataFromChangeResource(change));
+    std::string file_id = file->file_id();
+
+    MarkTrackersDirtyByFileID(file_id, batch.get());
+    if (!file->details().deleted())
+      MaybeAddTrackersForNewFile(*file, batch.get());
+
+    if (FindTrackersByFileID(file_id, NULL)) {
+      PutFileToBatch(*file, batch.get());
+
+      FileMetadata* file_ptr = file.release();
+      std::swap(file_ptr, file_by_id_[file_id]);
+      delete file_ptr;
+    }
+  }
+
+  WriteToDatabase(batch.Pass(), callback);
 }
 
 MetadataDatabase::MetadataDatabase(base::SequencedTaskRunner* task_runner)
@@ -572,6 +769,257 @@
   contents->file_trackers.weak_clear();
 }
 
+void MetadataDatabase::RegisterTrackerAsAppRoot(
+    const std::string& app_id,
+    int64 tracker_id,
+    leveldb::WriteBatch* batch) {
+  FileTracker* tracker = tracker_by_id_[tracker_id];
+  DCHECK(tracker);
+  tracker->set_app_id(app_id);
+  tracker->set_is_app_root(true);
+  app_root_by_app_id_[app_id] = tracker;
+
+  MakeTrackerActive(tracker->tracker_id(), batch);
+}
+
+void MetadataDatabase::UnregisterTrackerAsAppRoot(
+    const std::string& app_id,
+    leveldb::WriteBatch* batch) {
+  FileTracker* tracker = FindAndEraseItem(&app_root_by_app_id_, app_id);
+  tracker->set_app_id(std::string());
+  tracker->set_is_app_root(false);
+
+  // Inactivate the tracker to drop all descendant.
+  // (Note that we set is_app_root to false before calling this.)
+  MakeTrackerInactive(tracker->tracker_id(), batch);
+}
+
+void MetadataDatabase::MakeTrackerActive(int64 tracker_id,
+                                         leveldb::WriteBatch* batch) {
+  FileTracker* tracker = tracker_by_id_[tracker_id];
+  int64 parent_tracker_id = tracker->parent_tracker_id();
+  DCHECK(tracker->has_synced_details());
+  trackers_by_file_id_[tracker->file_id()].Activate(tracker);
+  if (parent_tracker_id) {
+    trackers_by_parent_and_title_[parent_tracker_id][
+        tracker->synced_details().title()].Activate(tracker);
+  }
+  tracker->set_active(true);
+  tracker->set_needs_folder_listing(
+      tracker->synced_details().file_kind() == FILE_KIND_FOLDER);
+  tracker->set_dirty(true);
+  dirty_trackers_.insert(tracker);
+
+  PutTrackerToBatch(*tracker, batch);
+}
+
+void MetadataDatabase::MakeTrackerInactive(int64 tracker_id,
+                                           leveldb::WriteBatch* batch) {
+  FileTracker* tracker = tracker_by_id_[tracker_id];
+  trackers_by_file_id_[tracker->file_id()].Inactivate(tracker);
+
+  std::string title = GetTrackerTitle(*tracker);
+  int64 parent_tracker_id = tracker->parent_tracker_id();
+  if (parent_tracker_id)
+    trackers_by_parent_and_title_[parent_tracker_id][title].Inactivate(tracker);
+  tracker->set_active(false);
+
+  // Keep the folder tree under an app-root, since we keep the local files of
+  // SyncFileSystem.
+  if (!tracker->is_app_root())
+    RemoveAllDescendantTrackers(tracker_id, batch);
+  MarkTrackersDirtyByFileID(tracker->file_id(), batch);
+  if (parent_tracker_id)
+    MarkTrackersDirtyByPath(parent_tracker_id, title, batch);
+  PutTrackerToBatch(*tracker, batch);
+}
+
+void MetadataDatabase::CreateTrackerForParentAndFileID(
+    const FileTracker& parent_tracker,
+    const std::string& file_id,
+    leveldb::WriteBatch* batch) {
+  int64 tracker_id = GetNextTrackerID(batch);
+  scoped_ptr<FileTracker> tracker(new FileTracker);
+  tracker->set_tracker_id(tracker_id);
+  tracker->set_parent_tracker_id(parent_tracker.tracker_id());
+  tracker->set_file_id(file_id);
+  tracker->set_app_id(parent_tracker.app_id());
+  tracker->set_is_app_root(false);
+  tracker->set_dirty(true);
+  tracker->set_active(false);
+  tracker->set_needs_folder_listing(false);
+  PutTrackerToBatch(*tracker, batch);
+
+  trackers_by_file_id_[file_id].Insert(tracker.get());
+  // Note: |trackers_by_parent_and_title_| does not map from
+  // FileMetadata::details but from FileTracker::synced_details, which is filled
+  // on tracker updated phase.  Use empty string as the title since
+  // FileTracker::synced_details is empty here.
+  trackers_by_parent_and_title_[parent_tracker.tracker_id()][std::string()]
+      .Insert(tracker.get());
+  dirty_trackers_.insert(tracker.get());
+  tracker_by_id_[tracker_id] = tracker.release();
+}
+
+void MetadataDatabase::RemoveTrackerIgnoringSiblings(
+    int64 tracker_id,
+    leveldb::WriteBatch* batch) {
+  FileTracker* tracker = FindAndEraseItem(&tracker_by_id_, tracker_id);
+  if (!tracker)
+    return;
+
+  EraseTrackerFromFileIDIndex(tracker, batch);
+  if (tracker->is_app_root())
+    app_root_by_app_id_.erase(tracker->app_id());
+  EraseTrackerFromPathIndex(tracker);
+
+  MarkTrackersDirtyByFileID(tracker->file_id(), batch);
+  // Do not mark the same path trackers as dirty, since the caller is deleting
+  // all its siblings.
+  delete tracker;
+  PutTrackerDeletionToBatch(tracker_id, batch);
+}
+
+void MetadataDatabase::MaybeAddTrackersForNewFile(
+    const FileMetadata& file,
+    leveldb::WriteBatch* batch) {
+  std::set<int64> known_parents;
+  TrackersByFileID::iterator found = trackers_by_file_id_.find(file.file_id());
+  if (found != trackers_by_file_id_.end()) {
+    for (TrackerSet::const_iterator itr = found->second.begin();
+         itr != found->second.end(); ++itr) {
+      int64 parent_tracker_id = (*itr)->parent_tracker_id();
+      if (parent_tracker_id)
+        known_parents.insert(parent_tracker_id);
+    }
+  }
+
+  for (int i = 0; i < file.details().parent_folder_ids_size(); ++i) {
+    std::string parent_folder_id = file.details().parent_folder_ids(i);
+    TrackersByFileID::iterator found =
+        trackers_by_file_id_.find(parent_folder_id);
+    if (found == trackers_by_file_id_.end())
+      continue;
+
+    for (TrackerSet::const_iterator itr = found->second.begin();
+         itr != found->second.end(); ++itr) {
+      FileTracker* parent_tracker = *itr;
+      int64 parent_tracker_id = parent_tracker->tracker_id();
+      if (!parent_tracker->active() && !parent_tracker->is_app_root())
+        continue;
+
+      if (ContainsKey(known_parents, parent_tracker_id))
+        continue;
+
+      CreateTrackerForParentAndFileID(*parent_tracker, file.file_id(), batch);
+    }
+  }
+}
+
+void MetadataDatabase::RemoveAllDescendantTrackers(int64 root_tracker_id,
+                                                   leveldb::WriteBatch* batch) {
+  std::stack<int64> pending_trackers;
+  PushChildTrackersToStack(trackers_by_parent_and_title_,
+                           root_tracker_id, &pending_trackers);
+
+  while (!pending_trackers.empty()) {
+    int64 tracker_id = pending_trackers.top();
+    pending_trackers.pop();
+    PushChildTrackersToStack(trackers_by_parent_and_title_,
+                             tracker_id, &pending_trackers);
+    RemoveTrackerIgnoringSiblings(tracker_id, batch);
+  }
+}
+
+void MetadataDatabase::EraseTrackerFromFileIDIndex(FileTracker* tracker,
+                                                   leveldb::WriteBatch* batch) {
+  TrackersByFileID::iterator found =
+      trackers_by_file_id_.find(tracker->file_id());
+  if (found == trackers_by_file_id_.end())
+    return;
+
+  TrackerSet* trackers = &found->second;
+  trackers->Erase(tracker);
+  if (!trackers->tracker_set().empty())
+    return;
+  trackers_by_file_id_.erase(found);
+  EraseFileFromDatabase(tracker->file_id(), batch);
+}
+
+void MetadataDatabase::EraseFileFromDatabase(const std::string& file_id,
+                                             leveldb::WriteBatch* batch) {
+  FileMetadata* file = FindAndEraseItem(&file_by_id_, file_id);
+  if (!file)
+    return;
+  delete file;
+  PutFileDeletionToBatch(file_id, batch);
+}
+
+void MetadataDatabase::EraseTrackerFromPathIndex(FileTracker* tracker) {
+  TrackersByParentAndTitle::iterator found =
+      trackers_by_parent_and_title_.find(tracker->parent_tracker_id());
+  if (found == trackers_by_parent_and_title_.end())
+    return;
+
+  std::string title = GetTrackerTitle(*tracker);
+  TrackersByTitle* trackers_by_title = &found->second;
+  TrackersByTitle::iterator found_by_title = trackers_by_title->find(title);
+  TrackerSet* conflicting_trackers = &found_by_title->second;
+  conflicting_trackers->Erase(tracker);
+
+  if (conflicting_trackers->tracker_set().empty()) {
+    trackers_by_title->erase(found_by_title);
+    if (trackers_by_title->empty())
+      trackers_by_parent_and_title_.erase(found);
+  }
+}
+
+void MetadataDatabase::MarkTrackerSetDirty(
+    TrackerSet* trackers,
+    leveldb::WriteBatch* batch) {
+  for (TrackerSet::iterator itr = trackers->begin();
+       itr != trackers->end(); ++itr) {
+    FileTracker* tracker = *itr;
+    if (tracker->dirty())
+      continue;
+    tracker->set_dirty(true);
+    PutTrackerToBatch(*tracker, batch);
+    dirty_trackers_.insert(tracker);
+  }
+}
+
+void MetadataDatabase::MarkTrackersDirtyByFileID(
+    const std::string& file_id,
+    leveldb::WriteBatch* batch) {
+  TrackersByFileID::iterator found = trackers_by_file_id_.find(file_id);
+  if (found != trackers_by_file_id_.end())
+    MarkTrackerSetDirty(&found->second, batch);
+}
+
+void MetadataDatabase::MarkTrackersDirtyByPath(int64 parent_tracker_id,
+                                               const std::string& title,
+                                               leveldb::WriteBatch* batch) {
+  TrackersByParentAndTitle::iterator found =
+      trackers_by_parent_and_title_.find(parent_tracker_id);
+  if (found == trackers_by_parent_and_title_.end()) {
+    NOTREACHED() << "parent: " << parent_tracker_id
+                 << ", title: " << title;
+    return;
+  }
+
+  TrackersByTitle::iterator itr = found->second.find(title);
+  if (itr != found->second.end())
+    MarkTrackerSetDirty(&itr->second, batch);
+}
+
+int64 MetadataDatabase::GetNextTrackerID(leveldb::WriteBatch* batch) {
+  int64 tracker_id = service_metadata_->next_tracker_id();
+  service_metadata_->set_next_tracker_id(tracker_id + 1);
+  PutServiceMetadataToBatch(*service_metadata_, batch);
+  DCHECK_GT(tracker_id, 0);
+  return tracker_id;
+}
+
 void MetadataDatabase::WriteToDatabase(scoped_ptr<leveldb::WriteBatch> batch,
                                        const SyncStatusCallback& callback) {
   base::PostTaskAndReplyWithResult(
diff --git a/chrome/browser/sync_file_system/drive_backend/metadata_database.h b/chrome/browser/sync_file_system/drive_backend/metadata_database.h
index d2cb9cd..1be2d1c 100644
--- a/chrome/browser/sync_file_system/drive_backend/metadata_database.h
+++ b/chrome/browser/sync_file_system/drive_backend/metadata_database.h
@@ -42,21 +42,41 @@
 class ServiceMetadata;
 struct DatabaseContents;
 
-// MetadataDatabase instance holds and maintains database and its indexes.  The
-// database holds metadata of the server-side files/folders as
-// DriveFileMetadata instances.
+// MetadataDatabase holds and maintains a LevelDB instance and its indexes,
+// which holds 1)ServiceMetadata, 2)FileMetadata and 3)FileTracker.
+// 1) ServiceMetadata is a singleton in the database which holds information for
+//    the backend.
+// 2) FileMetadata represents a remote-side file and holds latest known
+//    metadata of the remote file.
+// 3) FileTracker represents a synced or to-be-synced file and maintains
+//    the local-side folder tree.
+//
 // The term "file" includes files, folders and other resources on Drive.
 //
+// FileTrackers form a tree structure on the database, which represents the
+// FileSystem trees of SyncFileSystem.  The tree has a FileTracker named
+// sync-root as its root node, and a set of FileTracker named app-root.  An
+// app-root represents a remote folder for an installed Chrome App and holds all
+// synced contents for the App.
+//
+// One FileMetadata is created for each tracked remote file, which is identified
+// by FileID.
+// One FileTracker is created for every different {parent tracker, FileID} pair,
+// excluding non-app-root inactive parent trackers. Multiple trackers may be
+// associated to one FileID when the file has multiple parents. Multiple
+// trackers may have the same {parent tracker, title} pair when the associated
+// remote files have the same title.
+//
 // Files have following state:
 //   - Unknown file
-//     - Is initial state of the files, only file_id and parent_folder_id field
+//     - Has a dirty inactive tracker and empty synced_details.
+//     - Is initial state of a tracker, only file_id and parent_tracker_id field
 //       are known.
-//     - Has empty synced_details, must be active and dirty.
 //   - Folder
 //     - Is either one of sync-root folder, app-root folder or a regular folder.
 //     - Sync-root folder holds app-root folders as its direct children, and
-//       holds entire SyncFileSystem files as its descentants.  Its file_id is
-//       stored in ServiceMetadata.
+//       holds entire SyncFileSystem files as its descentants.  Its tracker
+//       should be stored in ServiceMetadata by its tracker_id.
 //     - App-root folder holds all files for an application as its descendants.
 //   - File
 //   - Unsupported file
@@ -64,16 +84,21 @@
 //       inactive.
 //
 // Invariants:
-//   - Any file in the database must either:
+//   - Any tracker in the database must either:
 //     - be sync-root,
-//     - have an app-root as its parent folder, or
-//     - have an active folder as its parent.
-//   That is, all files must be reachable from sync-root via app-root folders
-//   and active folders.
+//     - have an app-root as its parent tracker, or
+//     - have an active tracker as its parent.
+//   That is, all trackers must be reachable from sync-root via app-root folders
+//   and active trackers.
 //
-//   - Any active folder must either:
-//     - have needs_folder_listing flag and dirty flag, or
-//     - have all children at the stored largest change id.
+//   - Any active tracker must either:
+//     - have |needs_folder_listing| flag and dirty flag, or
+//     - have all children at the stored largest change ID.
+//
+//   - If multiple trackers have the same parent tracker and same title, they
+//     must not have same |file_id|, and at most one of them may be active.
+//   - If multiple trackers have the same |file_id|, at most one of them may be
+//     active.
 //
 class MetadataDatabase {
  public:
@@ -113,14 +138,49 @@
                  const SyncStatusCallback& callback);
 
   // Unregisters the folder as the app-root for |app_id|.  If |app_id| does not
-  // exist, does nothing.  The folder is left as an inactive normal folder.
+  // exist, does nothing.  The folder is left as an inactive regular folder.
+  // Note that the inactivation drops all descendant files since they are no
+  // longer reachable from sync-root via active folder or app-root.
   void UnregisterApp(const std::string& app_id,
                      const SyncStatusCallback& callback);
 
+  // Finds the app-root folder for |app_id|.  Returns true if exists.
+  // Copies the result to |tracker| if it is non-NULL.
+  bool FindAppRootTracker(const std::string& app_id,
+                          FileTracker* tracker) const;
+
+  // Finds the file identified by |file_id|.  Returns true if the file is found.
+  // Copies the metadata identified by |file_id| into |file| if exists and
+  // |file| is non-NULL.
+  bool FindFileByFileID(const std::string& file_id, FileMetadata* file) const;
+
+  // Finds the tracker identified by |tracker_id|.  Returns true if the tracker
+  // is found.
+  // Copies the tracker identified by |tracker_id| into |tracker| if exists and
+  // |tracker| is non-NULL.
+  bool FindTrackerByTrackerID(int64 tracker_id, FileTracker* tracker) const;
+
+  // Finds the trackers tracking |file_id|.  Returns true if the trackers are
+  // found.
+  bool FindTrackersByFileID(const std::string& file_id,
+                            TrackerSet* trackers) const;
+
+  // Finds the set of trackers whose parent's tracker ID is |parent_tracker_id|,
+  // and who has |title| as its title in the synced_details.
+  // Copies the tracker set to |trackers| if it is non-NULL.
+  size_t FindTrackersByParentAndTitle(
+      int64 parent_tracker_id,
+      const std::string& title,
+      TrackerSet* trackers) const;
+
+  // Builds the file path for the given tracker.  Returns true on success.
+  // |path| can be NULL.
+  // The file path is relative to app-root and have a leading path separator.
+  bool BuildPathForTracker(int64 tracker_id, base::FilePath* path) const;
+
   // Updates database by |changes|.
-  // Marks dirty for each changed file if the file has the metadata in the
-  // database.  Adds new metadata to track the file if the file doesn't have
-  // the metadata and its parent folder has the active metadata.
+  // Marks each tracker for modified file as dirty and adds new trackers if
+  // needed.
   void UpdateByChangeList(ScopedVector<google_apis::ChangeResource> changes,
                           const SyncStatusCallback& callback);
 
@@ -145,6 +205,42 @@
   SyncStatusCode InitializeOnTaskRunner(const base::FilePath& database_path);
   void BuildIndexes(DatabaseContents* contents);
 
+  // Database manipulation methods.
+  void RegisterTrackerAsAppRoot(const std::string& app_id,
+                                int64 tracker_id,
+                                leveldb::WriteBatch* batch);
+  void MakeTrackerActive(int64 tracker_id, leveldb::WriteBatch* batch);
+  void MakeTrackerInactive(int64 tracker_id, leveldb::WriteBatch* batch);
+
+  void UnregisterTrackerAsAppRoot(const std::string& app_id,
+                                  leveldb::WriteBatch* batch);
+  void RemoveAllDescendantTrackers(int64 root_tracker_id,
+                                   leveldb::WriteBatch* batch);
+
+  void CreateTrackerForParentAndFileID(const FileTracker& parent_tracker,
+                                       const std::string& file_id,
+                                       leveldb::WriteBatch* batch);
+  void RemoveTrackerIgnoringSiblings(int64 tracker_id,
+                                     leveldb::WriteBatch* batch);
+  void MaybeAddTrackersForNewFile(const FileMetadata& file,
+                                  leveldb::WriteBatch* batch);
+
+  void MarkTrackerSetDirty(TrackerSet* trackers,
+                           leveldb::WriteBatch* batch);
+  void MarkTrackersDirtyByFileID(const std::string& file_id,
+                                 leveldb::WriteBatch* batch);
+  void MarkTrackersDirtyByPath(int64 parent_tracker_id,
+                               const std::string& title,
+                               leveldb::WriteBatch* batch);
+
+  void EraseTrackerFromFileIDIndex(FileTracker* tracker,
+                                   leveldb::WriteBatch* batch);
+  void EraseTrackerFromPathIndex(FileTracker* tracker);
+  void EraseFileFromDatabase(const std::string& file_id,
+                             leveldb::WriteBatch* batch);
+
+  int64 GetNextTrackerID(leveldb::WriteBatch* batch);
+
   void WriteToDatabase(scoped_ptr<leveldb::WriteBatch> batch,
                        const SyncStatusCallback& callback);
 
diff --git a/chrome/browser/sync_file_system/drive_backend/metadata_database.proto b/chrome/browser/sync_file_system/drive_backend/metadata_database.proto
index fbdfa2c..736f357 100644
--- a/chrome/browser/sync_file_system/drive_backend/metadata_database.proto
+++ b/chrome/browser/sync_file_system/drive_backend/metadata_database.proto
@@ -11,9 +11,9 @@
 package sync_file_system.drive_backend;
 
 enum FileKind {
-  KIND_UNSUPPORTED = 0;
-  KIND_FILE = 1;
-  KIND_FOLDER = 2;
+  FILE_KIND_UNSUPPORTED = 0;
+  FILE_KIND_FILE = 1;
+  FILE_KIND_FOLDER = 2;
 }
 
 message ServiceMetadata {
@@ -29,7 +29,7 @@
   repeated string parent_folder_ids = 1;
 
   optional string title = 2;
-  optional FileKind kind = 3;
+  optional FileKind file_kind = 3;
   optional string md5 = 4;
   optional string etag = 5;
 
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 608a180..c748860 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
@@ -23,6 +23,129 @@
 namespace {
 
 const int64 kInitialChangeID = 1234;
+const int64 kSyncRootTrackerID = 100;
+const char kSyncRootFolderID[] = "sync_root_folder_id";
+
+void ExpectEquivalent(const ServiceMetadata* left,
+                      const ServiceMetadata* right) {
+  if (!left) {
+    ASSERT_FALSE(right);
+    return;
+  }
+  ASSERT_TRUE(right);
+
+  EXPECT_EQ(left->largest_change_id(), right->largest_change_id());
+  EXPECT_EQ(left->sync_root_tracker_id(), right->sync_root_tracker_id());
+  EXPECT_EQ(left->next_tracker_id(), right->next_tracker_id());
+}
+
+void ExpectEquivalent(const FileDetails* left, const FileDetails* right) {
+  if (!left) {
+    ASSERT_FALSE(right);
+    return;
+  }
+  ASSERT_TRUE(right);
+
+  std::set<std::string> parents;
+  for (int i = 0; i < left->parent_folder_ids_size(); ++i)
+    EXPECT_TRUE(parents.insert(left->parent_folder_ids(i)).second);
+
+  for (int i = 0; i < right->parent_folder_ids_size(); ++i)
+    EXPECT_EQ(1u, parents.erase(left->parent_folder_ids(i)));
+  EXPECT_TRUE(parents.empty());
+
+  EXPECT_EQ(left->title(), right->title());
+  EXPECT_EQ(left->file_kind(), right->file_kind());
+  EXPECT_EQ(left->md5(), right->md5());
+  EXPECT_EQ(left->etag(), right->etag());
+  EXPECT_EQ(left->creation_time(), right->creation_time());
+  EXPECT_EQ(left->modification_time(), right->modification_time());
+  EXPECT_EQ(left->deleted(), right->deleted());
+  EXPECT_EQ(left->change_id(), right->change_id());
+}
+
+void ExpectEquivalent(const FileMetadata* left, const FileMetadata* right) {
+  if (!left) {
+    ASSERT_FALSE(right);
+    return;
+  }
+  ASSERT_TRUE(right);
+
+  EXPECT_EQ(left->file_id(), right->file_id());
+  ExpectEquivalent(&left->details(), &right->details());
+}
+
+void ExpectEquivalent(const FileTracker* left, const FileTracker* right) {
+  if (!left) {
+    ASSERT_FALSE(right);
+    return;
+  }
+  ASSERT_TRUE(right);
+
+  EXPECT_EQ(left->tracker_id(), right->tracker_id());
+  EXPECT_EQ(left->parent_tracker_id(), right->parent_tracker_id());
+  EXPECT_EQ(left->file_id(), right->file_id());
+  EXPECT_EQ(left->app_id(), right->app_id());
+  EXPECT_EQ(left->is_app_root(), right->is_app_root());
+  ExpectEquivalent(&left->synced_details(), &right->synced_details());
+  EXPECT_EQ(left->dirty(), right->dirty());
+  EXPECT_EQ(left->active(), right->active());
+  EXPECT_EQ(left->needs_folder_listing(), right->needs_folder_listing());
+}
+
+template <typename Container>
+void ExpectEquivalentMaps(const Container& left, const Container& right);
+template <typename Key, typename Value, typename Compare>
+void ExpectEquivalent(const std::map<Key, Value, Compare>& left,
+                      const std::map<Key, Value, Compare>& right) {
+  ExpectEquivalentMaps(left, right);
+}
+
+template <typename Container>
+void ExpectEquivalentSets(const Container& left, const Container& right);
+template <typename Value, typename Compare>
+void ExpectEquivalent(const std::set<Value, Compare>& left,
+                      const std::set<Value, Compare>& right) {
+  return ExpectEquivalentSets(left, right);
+}
+
+void ExpectEquivalent(const TrackerSet& left,
+                      const TrackerSet& right) {
+  {
+    SCOPED_TRACE("Expect equivalent active_tracker");
+    ExpectEquivalent(left.active_tracker(), right.active_tracker());
+  }
+  ExpectEquivalent(left.tracker_set(), right.tracker_set());
+}
+
+template <typename Container>
+void ExpectEquivalentMaps(const Container& left, const Container& right) {
+  ASSERT_EQ(left.size(), right.size());
+
+  typedef typename Container::const_iterator const_iterator;
+  const_iterator left_itr = left.begin();
+  const_iterator right_itr = right.begin();
+  while (left_itr != left.end()) {
+    EXPECT_EQ(left_itr->first, right_itr->first);
+    ExpectEquivalent(left_itr->second, right_itr->second);
+    ++left_itr;
+    ++right_itr;
+  }
+}
+
+template <typename Container>
+void ExpectEquivalentSets(const Container& left, const Container& right) {
+  ASSERT_EQ(left.size(), right.size());
+
+  typedef typename Container::const_iterator const_iterator;
+  const_iterator left_itr = left.begin();
+  const_iterator right_itr = right.begin();
+  while (left_itr != left.end()) {
+    ExpectEquivalent(*left_itr, *right_itr);
+    ++left_itr;
+    ++right_itr;
+  }
+}
 
 void SyncStatusResultCallback(SyncStatusCode* status_out,
                               SyncStatusCode status) {
@@ -45,6 +168,7 @@
  public:
   MetadataDatabaseTest()
       : next_change_id_(kInitialChangeID + 1),
+        next_tracker_id_(kSyncRootTrackerID + 1),
         next_file_id_number_(1),
         next_md5_sequence_number_(1) {}
 
@@ -61,6 +185,15 @@
     return "file_id_" + base::Int64ToString(next_file_id_number_++);
   }
 
+  int64 GetTrackerIDByFileID(const std::string& file_id) {
+    TrackerSet trackers;
+    if (metadata_database_->FindTrackersByFileID(file_id, &trackers)) {
+      EXPECT_FALSE(trackers.empty());
+      return (*trackers.begin())->tracker_id();
+    }
+    return 0;
+  }
+
   SyncStatusCode InitializeMetadataDatabase() {
     SyncStatusCode status = SYNC_STATUS_UNKNOWN;
     MetadataDatabase::Create(base::MessageLoopProxy::current(),
@@ -102,16 +235,225 @@
   void SetUpServiceMetadata(leveldb::DB* db) {
     ServiceMetadata service_metadata;
     service_metadata.set_largest_change_id(kInitialChangeID);
+    service_metadata.set_sync_root_tracker_id(kSyncRootTrackerID);
+    service_metadata.set_next_tracker_id(next_tracker_id_);
     std::string value;
     ASSERT_TRUE(service_metadata.SerializeToString(&value));
     db->Put(leveldb::WriteOptions(), "SERVICE", value);
   }
 
+  FileMetadata CreateSyncRootMetadata() {
+    FileMetadata sync_root;
+    sync_root.set_file_id(kSyncRootFolderID);
+    FileDetails* details = sync_root.mutable_details();
+    details->set_title("Chrome Syncable FileSystem");
+    details->set_file_kind(FILE_KIND_FOLDER);
+    return sync_root;
+  }
+
+  FileMetadata CreateFileMetadata(const FileMetadata& parent,
+                                  const std::string& title) {
+    FileMetadata file;
+    file.set_file_id(GenerateFileID());
+    FileDetails* details = file.mutable_details();
+    details->add_parent_folder_ids(parent.file_id());
+    details->set_title(title);
+    details->set_file_kind(FILE_KIND_FILE);
+    details->set_md5(
+        "md5_value_" + base::Int64ToString(next_md5_sequence_number_++));
+    return file;
+  }
+
+  FileMetadata CreateFolderMetadata(const FileMetadata& parent,
+                                    const std::string& title) {
+    FileMetadata folder;
+    folder.set_file_id(GenerateFileID());
+    FileDetails* details = folder.mutable_details();
+    details->add_parent_folder_ids(parent.file_id());
+    details->set_title(title);
+    details->set_file_kind(FILE_KIND_FOLDER);
+    return folder;
+  }
+
+  FileTracker CreateSyncRootTracker(const FileMetadata& sync_root) {
+    FileTracker sync_root_tracker;
+    sync_root_tracker.set_tracker_id(kSyncRootTrackerID);
+    sync_root_tracker.set_parent_tracker_id(0);
+    sync_root_tracker.set_file_id(sync_root.file_id());
+    sync_root_tracker.set_dirty(false);
+    sync_root_tracker.set_active(true);
+    sync_root_tracker.set_needs_folder_listing(false);
+    *sync_root_tracker.mutable_synced_details() = sync_root.details();
+    return sync_root_tracker;
+  }
+
+  FileTracker CreateTracker(const FileTracker& parent_tracker,
+                            const FileMetadata& file) {
+    FileTracker tracker;
+    tracker.set_tracker_id(next_tracker_id_++);
+    tracker.set_parent_tracker_id(parent_tracker.tracker_id());
+    tracker.set_file_id(file.file_id());
+    tracker.set_app_id(parent_tracker.app_id());
+    tracker.set_is_app_root(false);
+    tracker.set_dirty(false);
+    tracker.set_active(true);
+    tracker.set_needs_folder_listing(false);
+    *tracker.mutable_synced_details() = file.details();
+    return tracker;
+  }
+
+  scoped_ptr<google_apis::ChangeResource> CreateChangeResourceFromMetadata(
+      const FileMetadata& file) {
+    scoped_ptr<google_apis::ChangeResource> change(
+        new google_apis::ChangeResource);
+    change->set_change_id(file.details().change_id());
+    change->set_file_id(file.file_id());
+    change->set_deleted(file.details().deleted());
+    if (change->is_deleted())
+      return change.Pass();
+
+    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());
+    }
+
+    file_resource->set_file_id(file.file_id());
+    file_resource->set_parents(&parents);
+    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");
+    else if (file.details().file_kind() == FILE_KIND_FILE)
+      file_resource->set_mime_type("text/plain");
+    else
+      file_resource->set_mime_type("application/vnd.google-apps.document");
+    file_resource->set_md5_checksum(file.details().md5());
+    file_resource->set_etag(file.details().etag());
+    file_resource->set_created_date(base::Time::FromInternalValue(
+        file.details().creation_time()));
+    file_resource->set_modified_date(base::Time::FromInternalValue(
+        file.details().modification_time()));
+
+    change->set_file(file_resource.Pass());
+    return change.Pass();
+  }
+
+  void ApplyRenameChangeToMetadata(const std::string& new_title,
+                                   FileMetadata* file) {
+    FileDetails* details = file->mutable_details();
+    details->set_title(new_title);
+    details->set_change_id(next_change_id_++);
+  }
+
+  void ApplyReorganizeChangeToMetadata(const std::string& new_parent,
+                                       FileMetadata* file) {
+    FileDetails* details = file->mutable_details();
+    details->clear_parent_folder_ids();
+    details->add_parent_folder_ids(new_parent);
+    details->set_change_id(next_change_id_++);
+  }
+
+  void ApplyContentChangeToMetadata(FileMetadata* file) {
+    FileDetails* details = file->mutable_details();
+    details->set_md5(
+        "md5_value_" + base::Int64ToString(next_md5_sequence_number_++));
+    details->set_change_id(next_change_id_++);
+  }
+
   void PushToChangeList(scoped_ptr<google_apis::ChangeResource> change,
                         ScopedVector<google_apis::ChangeResource>* changes) {
     changes->push_back(change.release());
   }
 
+  leveldb::Status PutFileToDB(leveldb::DB* db, const FileMetadata& file) {
+    std::string key = "FILE: " + file.file_id();
+    std::string value;
+    file.SerializeToString(&value);
+    return db->Put(leveldb::WriteOptions(), key, value);
+  }
+
+  leveldb::Status PutTrackerToDB(leveldb::DB* db,
+                                 const FileTracker& tracker) {
+    std::string key = "TRACKER: " + base::Int64ToString(tracker.tracker_id());
+    std::string value;
+    tracker.SerializeToString(&value);
+    return db->Put(leveldb::WriteOptions(), key, value);
+  }
+
+  void VerifyReloadConsistency() {
+    scoped_ptr<MetadataDatabase> metadata_database_2;
+    ASSERT_EQ(SYNC_STATUS_OK,
+              MetadataDatabase::CreateForTesting(
+                  metadata_database_->db_.Pass(),
+                  &metadata_database_2));
+    metadata_database_->db_ = metadata_database_2->db_.Pass();
+
+    {
+      SCOPED_TRACE("Expect equivalent service_metadata");
+      ExpectEquivalent(metadata_database_->service_metadata_.get(),
+                       metadata_database_2->service_metadata_.get());
+    }
+
+    {
+      SCOPED_TRACE("Expect equivalent file_by_id_ contents.");
+      ExpectEquivalent(metadata_database_->file_by_id_,
+                       metadata_database_2->file_by_id_);
+    }
+
+    {
+      SCOPED_TRACE("Expect equivalent tracker_by_id_ contents.");
+      ExpectEquivalent(metadata_database_->tracker_by_id_,
+                       metadata_database_2->tracker_by_id_);
+    }
+
+    {
+      SCOPED_TRACE("Expect equivalent trackers_by_file_id_ contents.");
+      ExpectEquivalent(metadata_database_->trackers_by_file_id_,
+                       metadata_database_2->trackers_by_file_id_);
+    }
+
+    {
+      SCOPED_TRACE("Expect equivalent app_root_by_app_id_ contents.");
+      ExpectEquivalent(metadata_database_->app_root_by_app_id_,
+                       metadata_database_2->app_root_by_app_id_);
+    }
+
+    {
+      SCOPED_TRACE("Expect equivalent trackers_by_parent_and_title_ contents.");
+      ExpectEquivalent(metadata_database_->trackers_by_parent_and_title_,
+                       metadata_database_2->trackers_by_parent_and_title_);
+    }
+
+    {
+      SCOPED_TRACE("Expect equivalent dirty_trackers_ contents.");
+      ExpectEquivalent(metadata_database_->dirty_trackers_,
+                       metadata_database_2->dirty_trackers_);
+    }
+  }
+
+  void VerifyFile(const FileMetadata& file) {
+    FileMetadata file_in_metadata_database;
+    ASSERT_TRUE(metadata_database()->FindFileByFileID(
+        file.file_id(), &file_in_metadata_database));
+
+    SCOPED_TRACE("Expect equivalent " + file.file_id());
+    ExpectEquivalent(&file, &file_in_metadata_database);
+  }
+
+  void VerifyTracker(const FileTracker& tracker) {
+    FileTracker tracker_in_metadata_database;
+    ASSERT_TRUE(metadata_database()->FindTrackerByTrackerID(
+        tracker.tracker_id(), &tracker_in_metadata_database));
+
+    SCOPED_TRACE("Expect equivalent tracker[" +
+                 base::Int64ToString(tracker.tracker_id()) + "]");
+    ExpectEquivalent(&tracker, &tracker_in_metadata_database);
+  }
+
   SyncStatusCode RegisterApp(const std::string& app_id,
                              const std::string& folder_id) {
     SyncStatusCode status = SYNC_STATUS_UNKNOWN;
@@ -162,6 +504,7 @@
   scoped_ptr<MetadataDatabase> metadata_database_;
 
   int64 next_change_id_;
+  int64 next_tracker_id_;
   int64 next_file_id_number_;
   int64 next_md5_sequence_number_;
 
@@ -174,5 +517,319 @@
   EXPECT_EQ(SYNC_STATUS_OK, InitializeMetadataDatabase());
 }
 
+TEST_F(MetadataDatabaseTest, InitializationTest_SimpleTree) {
+  FileMetadata sync_root(CreateSyncRootMetadata());
+  FileTracker sync_root_tracker(CreateSyncRootTracker(sync_root));
+
+  FileMetadata app_root(
+      CreateFolderMetadata(sync_root, "app_id" /* title */));
+  FileTracker app_root_tracker(
+      CreateTracker(sync_root_tracker, app_root));
+  app_root_tracker.set_app_id(app_root.details().title());
+  app_root_tracker.set_is_app_root(true);
+
+  FileMetadata file(CreateFileMetadata(app_root, "file"));
+  FileTracker file_tracker(CreateTracker(app_root_tracker, file));
+
+  FileMetadata folder(CreateFolderMetadata(app_root, "folder"));
+  FileTracker folder_tracker(CreateTracker(app_root_tracker, folder));
+
+  FileMetadata file_in_folder(
+      CreateFileMetadata(folder, "file_in_folder"));
+  FileTracker file_in_folder_tracker(
+      CreateTracker(folder_tracker, file_in_folder));
+
+  FileMetadata orphaned_file(
+      CreateFileMetadata(sync_root, "orphaned_file"));
+  orphaned_file.mutable_details()->clear_parent_folder_ids();
+  FileTracker orphaned_file_tracker(
+      CreateTracker(sync_root_tracker, orphaned_file));
+  orphaned_file_tracker.set_parent_tracker_id(0);
+
+  {
+    scoped_ptr<leveldb::DB> db = InitializeLevelDB();
+    ASSERT_TRUE(db);
+
+    EXPECT_TRUE(PutFileToDB(db.get(), sync_root).ok());
+    EXPECT_TRUE(PutTrackerToDB(db.get(), sync_root_tracker).ok());
+    EXPECT_TRUE(PutFileToDB(db.get(), app_root).ok());
+    EXPECT_TRUE(PutTrackerToDB(db.get(), app_root_tracker).ok());
+    EXPECT_TRUE(PutFileToDB(db.get(), file).ok());
+    EXPECT_TRUE(PutTrackerToDB(db.get(), file_tracker).ok());
+    EXPECT_TRUE(PutFileToDB(db.get(), folder).ok());
+    EXPECT_TRUE(PutTrackerToDB(db.get(), folder_tracker).ok());
+    EXPECT_TRUE(PutFileToDB(db.get(), file_in_folder).ok());
+    EXPECT_TRUE(PutTrackerToDB(db.get(), file_in_folder_tracker).ok());
+    EXPECT_TRUE(PutFileToDB(db.get(), orphaned_file).ok());
+    EXPECT_TRUE(PutTrackerToDB(db.get(), orphaned_file_tracker).ok());
+  }
+
+  EXPECT_EQ(SYNC_STATUS_OK, InitializeMetadataDatabase());
+
+  VerifyFile(sync_root);
+  VerifyTracker(sync_root_tracker);
+  VerifyFile(app_root);
+  VerifyTracker(app_root_tracker);
+  VerifyFile(file);
+  VerifyTracker(file_tracker);
+  VerifyFile(folder);
+  VerifyTracker(folder_tracker);
+  VerifyFile(file_in_folder);
+  VerifyTracker(file_in_folder_tracker);
+
+  EXPECT_FALSE(metadata_database()->FindFileByFileID(
+      orphaned_file.file_id(), NULL));
+  EXPECT_FALSE(metadata_database()->FindTrackerByTrackerID(
+      orphaned_file_tracker.tracker_id(), NULL));
+}
+
+TEST_F(MetadataDatabaseTest, AppManagementTest) {
+  FileMetadata sync_root(CreateSyncRootMetadata());
+  FileTracker sync_root_tracker(CreateSyncRootTracker(sync_root));
+
+  FileMetadata app_root(CreateFolderMetadata(sync_root, "app_id"));
+  FileTracker app_root_tracker(
+      CreateTracker(sync_root_tracker, app_root));
+  app_root_tracker.set_app_id(app_root.details().title());
+  app_root_tracker.set_is_app_root(true);
+
+  FileMetadata file(CreateFileMetadata(app_root, "file"));
+  FileTracker file_tracker(CreateTracker(app_root_tracker, file));
+
+  FileMetadata folder(CreateFolderMetadata(sync_root, "folder"));
+  FileTracker folder_tracker(CreateTracker(sync_root_tracker, folder));
+  folder_tracker.set_active(false);
+
+  {
+    scoped_ptr<leveldb::DB> db = InitializeLevelDB();
+    ASSERT_TRUE(db);
+
+    EXPECT_TRUE(PutFileToDB(db.get(), sync_root).ok());
+    EXPECT_TRUE(PutTrackerToDB(db.get(), sync_root_tracker).ok());
+    EXPECT_TRUE(PutFileToDB(db.get(), app_root).ok());
+    EXPECT_TRUE(PutTrackerToDB(db.get(), app_root_tracker).ok());
+    EXPECT_TRUE(PutFileToDB(db.get(), file).ok());
+    EXPECT_TRUE(PutTrackerToDB(db.get(), file_tracker).ok());
+    EXPECT_TRUE(PutFileToDB(db.get(), folder).ok());
+    EXPECT_TRUE(PutTrackerToDB(db.get(), folder_tracker).ok());
+  }
+
+  EXPECT_EQ(SYNC_STATUS_OK, InitializeMetadataDatabase());
+  VerifyFile(sync_root);
+  VerifyTracker(sync_root_tracker);
+  VerifyFile(app_root);
+  VerifyTracker(app_root_tracker);
+  VerifyFile(file);
+  VerifyTracker(file_tracker);
+  VerifyFile(folder);
+  VerifyTracker(folder_tracker);
+
+  folder_tracker.set_app_id("foo");
+  folder_tracker.set_is_app_root(true);
+  folder_tracker.set_active(true);
+  folder_tracker.set_dirty(true);
+  folder_tracker.set_needs_folder_listing(true);
+  EXPECT_EQ(SYNC_STATUS_OK, RegisterApp(
+      folder_tracker.app_id(), folder.file_id()));
+  VerifyFile(folder);
+  VerifyTracker(folder_tracker);
+  VerifyReloadConsistency();
+
+  EXPECT_EQ(SYNC_STATUS_OK, DisableApp(folder_tracker.app_id()));
+  folder_tracker.set_active(false);
+  VerifyFile(folder);
+  VerifyTracker(folder_tracker);
+  VerifyReloadConsistency();
+
+  EXPECT_EQ(SYNC_STATUS_OK, EnableApp(folder_tracker.app_id()));
+  folder_tracker.set_active(true);
+  VerifyFile(folder);
+  VerifyTracker(folder_tracker);
+  VerifyReloadConsistency();
+
+  EXPECT_EQ(SYNC_STATUS_OK, UnregisterApp(folder_tracker.app_id()));
+  folder_tracker.set_app_id(std::string());
+  folder_tracker.set_is_app_root(false);
+  folder_tracker.set_active(false);
+  VerifyFile(folder);
+  VerifyTracker(folder_tracker);
+  VerifyReloadConsistency();
+
+  EXPECT_EQ(SYNC_STATUS_OK, UnregisterApp(app_root_tracker.app_id()));
+  app_root_tracker.set_app_id(std::string());
+  app_root_tracker.set_is_app_root(false);
+  app_root_tracker.set_active(false);
+  app_root_tracker.set_dirty(true);
+  VerifyFile(app_root);
+  VerifyTracker(app_root_tracker);
+  EXPECT_FALSE(metadata_database()->FindFileByFileID(file.file_id(), NULL));
+  EXPECT_FALSE(metadata_database()->FindTrackerByTrackerID(
+      file_tracker.tracker_id(), NULL));
+  VerifyReloadConsistency();
+}
+
+TEST_F(MetadataDatabaseTest, BuildPathTest) {
+  FileMetadata sync_root(CreateSyncRootMetadata());
+  FileTracker sync_root_tracker(CreateSyncRootTracker(sync_root));
+
+  FileMetadata app_root(CreateFolderMetadata(sync_root, "app_id"));
+  FileTracker app_root_tracker(
+      CreateTracker(sync_root_tracker, app_root));
+  app_root_tracker.set_app_id(app_root.details().title());
+  app_root_tracker.set_is_app_root(true);
+
+  FileMetadata folder(CreateFolderMetadata(app_root, "folder"));
+  FileTracker folder_tracker(CreateTracker(app_root_tracker, folder));
+
+  FileMetadata file(CreateFolderMetadata(folder, "file"));
+  FileTracker file_tracker(CreateTracker(folder_tracker, file));
+
+  FileMetadata inactive_folder(CreateFolderMetadata(app_root, "folder"));
+  FileTracker inactive_folder_tracker(CreateTracker(app_root_tracker,
+                                                          inactive_folder));
+  inactive_folder_tracker.set_active(false);
+
+  {
+    scoped_ptr<leveldb::DB> db = InitializeLevelDB();
+    ASSERT_TRUE(db);
+
+    EXPECT_TRUE(PutFileToDB(db.get(), sync_root).ok());
+    EXPECT_TRUE(PutTrackerToDB(db.get(), sync_root_tracker).ok());
+    EXPECT_TRUE(PutFileToDB(db.get(), app_root).ok());
+    EXPECT_TRUE(PutTrackerToDB(db.get(), app_root_tracker).ok());
+    EXPECT_TRUE(PutFileToDB(db.get(), folder).ok());
+    EXPECT_TRUE(PutTrackerToDB(db.get(), folder_tracker).ok());
+    EXPECT_TRUE(PutFileToDB(db.get(), file).ok());
+    EXPECT_TRUE(PutTrackerToDB(db.get(), file_tracker).ok());
+  }
+
+  EXPECT_EQ(SYNC_STATUS_OK, InitializeMetadataDatabase());
+
+  base::FilePath path;
+  EXPECT_FALSE(metadata_database()->BuildPathForTracker(
+      sync_root_tracker.tracker_id(), &path));
+  EXPECT_TRUE(metadata_database()->BuildPathForTracker(
+      app_root_tracker.tracker_id(), &path));
+  EXPECT_EQ(base::FilePath(FPL("/")).NormalizePathSeparators(), path);
+  EXPECT_TRUE(metadata_database()->BuildPathForTracker(
+      file_tracker.tracker_id(), &path));
+  EXPECT_EQ(base::FilePath(FPL("/folder/file")).NormalizePathSeparators(),
+            path);
+}
+
+TEST_F(MetadataDatabaseTest, UpdateByChangeListTest) {
+  FileMetadata sync_root(CreateSyncRootMetadata());
+  FileTracker sync_root_tracker(CreateSyncRootTracker(sync_root));
+
+  FileMetadata app_root(CreateFolderMetadata(sync_root, "app_id"));
+  FileTracker app_root_tracker(
+      CreateTracker(sync_root_tracker, app_root));
+
+  FileMetadata disabled_app_root(
+      CreateFolderMetadata(sync_root, "disabled_app"));
+  FileTracker disabled_app_root_tracker(
+      CreateTracker(sync_root_tracker, disabled_app_root));
+
+  FileMetadata file(CreateFileMetadata(app_root, "file"));
+  FileTracker file_tracker(CreateTracker(app_root_tracker, file));
+
+  FileMetadata renamed_file(CreateFileMetadata(app_root, "to be renamed"));
+  FileTracker renamed_file_tracker(
+      CreateTracker(app_root_tracker, renamed_file));
+
+  FileMetadata folder(CreateFolderMetadata(app_root, "folder"));
+  FileTracker folder_tracker(CreateTracker(app_root_tracker, folder));
+
+  FileMetadata reorganized_file(
+      CreateFileMetadata(app_root, "to be reorganized"));
+  FileTracker reorganized_file_tracker(
+      CreateTracker(app_root_tracker, reorganized_file));
+
+  FileMetadata updated_file(CreateFileMetadata(app_root, "to be updated"));
+  FileTracker updated_file_tracker(
+      CreateTracker(app_root_tracker, updated_file));
+
+  FileMetadata noop_file(CreateFileMetadata(app_root, "have noop change"));
+  FileTracker noop_file_tracker(
+      CreateTracker(app_root_tracker, noop_file));
+
+  FileMetadata new_file(CreateFileMetadata(app_root, "to be added later"));
+
+  {
+    scoped_ptr<leveldb::DB> db = InitializeLevelDB();
+    ASSERT_TRUE(db);
+
+    EXPECT_TRUE(PutFileToDB(db.get(), sync_root).ok());
+    EXPECT_TRUE(PutTrackerToDB(db.get(), sync_root_tracker).ok());
+    EXPECT_TRUE(PutFileToDB(db.get(), app_root).ok());
+    EXPECT_TRUE(PutTrackerToDB(db.get(), app_root_tracker).ok());
+    EXPECT_TRUE(PutFileToDB(db.get(), disabled_app_root).ok());
+    EXPECT_TRUE(PutTrackerToDB(db.get(), disabled_app_root_tracker).ok());
+    EXPECT_TRUE(PutFileToDB(db.get(), file).ok());
+    EXPECT_TRUE(PutTrackerToDB(db.get(), file_tracker).ok());
+    EXPECT_TRUE(PutFileToDB(db.get(), renamed_file).ok());
+    EXPECT_TRUE(PutTrackerToDB(db.get(), renamed_file_tracker).ok());
+    EXPECT_TRUE(PutFileToDB(db.get(), folder).ok());
+    EXPECT_TRUE(PutTrackerToDB(db.get(), folder_tracker).ok());
+    EXPECT_TRUE(PutFileToDB(db.get(), reorganized_file).ok());
+    EXPECT_TRUE(PutTrackerToDB(db.get(), reorganized_file_tracker).ok());
+    EXPECT_TRUE(PutFileToDB(db.get(), updated_file).ok());
+    EXPECT_TRUE(PutTrackerToDB(db.get(), updated_file_tracker).ok());
+    EXPECT_TRUE(PutFileToDB(db.get(), noop_file).ok());
+    EXPECT_TRUE(PutTrackerToDB(db.get(), noop_file_tracker).ok());
+  }
+
+  EXPECT_EQ(SYNC_STATUS_OK, InitializeMetadataDatabase());
+
+  ApplyRenameChangeToMetadata("renamed", &renamed_file);
+  ApplyReorganizeChangeToMetadata(folder.file_id(), &reorganized_file);
+  ApplyContentChangeToMetadata(&updated_file);
+
+  ScopedVector<google_apis::ChangeResource> changes;
+  PushToChangeList(CreateChangeResourceFromMetadata(renamed_file), &changes);
+  PushToChangeList(CreateChangeResourceFromMetadata(
+      reorganized_file), &changes);
+  PushToChangeList(CreateChangeResourceFromMetadata(updated_file), &changes);
+  PushToChangeList(CreateChangeResourceFromMetadata(noop_file), &changes);
+  PushToChangeList(CreateChangeResourceFromMetadata(new_file), &changes);
+
+  renamed_file_tracker.set_dirty(true);
+  reorganized_file_tracker.set_dirty(true);
+  updated_file_tracker.set_dirty(true);
+  noop_file_tracker.set_dirty(true);
+
+  EXPECT_EQ(SYNC_STATUS_OK, UpdateByChangeList(changes.Pass()));
+
+  FileTracker new_file_tracker(CreateTracker(app_root_tracker, new_file));
+  new_file_tracker.set_tracker_id(GetTrackerIDByFileID(new_file.file_id()));
+  new_file_tracker.clear_synced_details();
+  new_file_tracker.set_active(false);
+  new_file_tracker.set_dirty(true);
+  EXPECT_NE(0, new_file_tracker.tracker_id());
+
+  VerifyFile(sync_root);
+  VerifyTracker(sync_root_tracker);
+  VerifyFile(app_root);
+  VerifyTracker(app_root_tracker);
+  VerifyFile(disabled_app_root);
+  VerifyTracker(disabled_app_root_tracker);
+  VerifyFile(file);
+  VerifyTracker(file_tracker);
+  VerifyFile(renamed_file);
+  VerifyTracker(renamed_file_tracker);
+  VerifyFile(folder);
+  VerifyTracker(folder_tracker);
+  VerifyFile(reorganized_file);
+  VerifyTracker(reorganized_file_tracker);
+  VerifyFile(updated_file);
+  VerifyTracker(updated_file_tracker);
+  VerifyFile(noop_file);
+  VerifyTracker(noop_file_tracker);
+  VerifyFile(new_file);
+  VerifyTracker(new_file_tracker);
+
+  VerifyReloadConsistency();
+}
+
 }  // namespace drive_backend
 }  // namespace sync_file_system
diff --git a/chrome/browser/sync_file_system/drive_backend/tracker_set.h b/chrome/browser/sync_file_system/drive_backend/tracker_set.h
index 68353a9..1b3f0e9 100644
--- a/chrome/browser/sync_file_system/drive_backend/tracker_set.h
+++ b/chrome/browser/sync_file_system/drive_backend/tracker_set.h
@@ -39,6 +39,7 @@
   iterator end() { return tracker_set_.end(); }
   const_iterator begin() const { return tracker_set_.begin(); }
   const_iterator end() const { return tracker_set_.end(); }
+  bool empty() const { return tracker_set_.empty(); }
 
  private:
   FileTracker* active_tracker_;
diff --git a/chrome/browser/tab_contents/render_view_context_menu.cc b/chrome/browser/tab_contents/render_view_context_menu.cc
index 79e62ee..77b4ff5 100644
--- a/chrome/browser/tab_contents/render_view_context_menu.cc
+++ b/chrome/browser/tab_contents/render_view_context_menu.cc
@@ -30,7 +30,7 @@
 #include "chrome/browser/devtools/devtools_window.h"
 #include "chrome/browser/download/download_service.h"
 #include "chrome/browser/download/download_service_factory.h"
-#include "chrome/browser/download/download_util.h"
+#include "chrome/browser/download/download_stats.h"
 #include "chrome/browser/extensions/extension_host.h"
 #include "chrome/browser/extensions/extension_service.h"
 #include "chrome/browser/extensions/extension_system.h"
@@ -838,7 +838,7 @@
 
   menu_model_.AddItemWithStringId(
       IDC_CONTENT_CONTEXT_COPYLINKLOCATION,
-      params_.link_url.SchemeIs(chrome::kMailToScheme) ?
+      params_.link_url.SchemeIs(content::kMailToScheme) ?
           IDS_CONTENT_CONTEXT_COPYEMAILADDRESS :
           IDS_CONTENT_CONTEXT_COPYLINKLOCATION);
 }
@@ -1566,8 +1566,7 @@
       break;
 
     case IDC_CONTENT_CONTEXT_SAVELINKAS: {
-      download_util::RecordDownloadSource(
-          download_util::INITIATED_BY_CONTEXT_MENU);
+      RecordDownloadSource(DOWNLOAD_INITIATED_BY_CONTEXT_MENU);
       const GURL& referrer =
           params_.frame_url.is_empty() ? params_.page_url : params_.frame_url;
       const GURL& url = params_.link_url;
@@ -1584,8 +1583,7 @@
 
     case IDC_CONTENT_CONTEXT_SAVEAVAS:
     case IDC_CONTENT_CONTEXT_SAVEIMAGEAS: {
-      download_util::RecordDownloadSource(
-          download_util::INITIATED_BY_CONTEXT_MENU);
+      RecordDownloadSource(DOWNLOAD_INITIATED_BY_CONTEXT_MENU);
       const GURL& referrer =
           params_.frame_url.is_empty() ? params_.page_url : params_.frame_url;
       const GURL& url = params_.src_url;
@@ -1980,11 +1978,6 @@
     rvh->NotifyContextMenuClosed(params_.custom_context);
   }
 
-  content::NotificationService::current()->Notify(
-      chrome::NOTIFICATION_RENDER_VIEW_CONTEXT_MENU_CLOSED,
-      content::Source<RenderViewContextMenu>(this),
-      content::NotificationService::NoDetails());
-
   if (!command_executed_) {
     FOR_EACH_OBSERVER(RenderViewContextMenuObserver,
                       observers_,
diff --git a/chrome/browser/tab_contents/tab_util.cc b/chrome/browser/tab_contents/tab_util.cc
index fae1201..ae3100a 100644
--- a/chrome/browser/tab_contents/tab_util.cc
+++ b/chrome/browser/tab_contents/tab_util.cc
@@ -31,9 +31,8 @@
 
 SiteInstance* GetSiteInstanceForNewTab(Profile* profile,
                                        const GURL& url) {
-  // If url is a WebUI or extension, we need to be sure to use the right type
-  // of renderer process up front.  Otherwise, we create a normal SiteInstance
-  // as part of creating the tab.
+  // If |url| is a WebUI or extension, we set the SiteInstance up front so that
+  // we don't end up with an extra process swap on the first navigation.
   ExtensionService* service = profile->GetExtensionService();
   if (ChromeWebUIControllerFactory::GetInstance()->UseWebUIForURL(
           profile, url) ||
@@ -44,7 +43,8 @@
 
   // We used to share the SiteInstance for same-site links opened in new tabs,
   // to leverage the in-memory cache and reduce process creation.  It now
-  // appears that it is more useful to have such links open in a new process.
+  // appears that it is more useful to have such links open in a new process,
+  // so we create new tabs in a new BrowsingInstance.
   return NULL;
 }
 
diff --git a/chrome/browser/themes/theme_properties.h b/chrome/browser/themes/theme_properties.h
index 2eaa1ed..2bea265 100644
--- a/chrome/browser/themes/theme_properties.h
+++ b/chrome/browser/themes/theme_properties.h
@@ -90,6 +90,7 @@
     COLOR_NTP_TEXT_LIGHT,
     COLOR_MANAGED_USER_LABEL,
     COLOR_MANAGED_USER_LABEL_BACKGROUND,
+    COLOR_MANAGED_USER_LABEL_BORDER,
 
 #if defined(OS_MACOSX)
     COLOR_TOOLBAR_BEZEL,
diff --git a/chrome/browser/themes/theme_service.cc b/chrome/browser/themes/theme_service.cc
index 5038dff..fdb0244 100644
--- a/chrome/browser/themes/theme_service.cc
+++ b/chrome/browser/themes/theme_service.cc
@@ -13,6 +13,8 @@
 #include "chrome/browser/chrome_notification_types.h"
 #include "chrome/browser/extensions/extension_service.h"
 #include "chrome/browser/extensions/extension_system.h"
+#include "chrome/browser/managed_mode/managed_user_service.h"
+#include "chrome/browser/managed_mode/managed_user_service_factory.h"
 #include "chrome/browser/managed_mode/managed_user_theme.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/themes/browser_theme_pack.h"
@@ -77,7 +79,8 @@
     : ready_(false),
       rb_(ResourceBundle::GetSharedInstance()),
       profile_(NULL),
-      number_of_infobars_(0) {
+      number_of_infobars_(0),
+      weak_ptr_factory_(this) {
 }
 
 ThemeService::~ThemeService() {
@@ -88,6 +91,9 @@
   DCHECK(CalledOnValidThread());
   profile_ = profile;
 
+  ManagedUserServiceFactory::GetForProfile(profile)->AddInitCallback(base::Bind(
+      &ThemeService::OnManagedUserInitialized, weak_ptr_factory_.GetWeakPtr()));
+
   LoadThemePrefs();
 
   if (!ready_) {
@@ -147,6 +153,11 @@
     case Properties::COLOR_MANAGED_USER_LABEL_BACKGROUND:
       return color_utils::BlendTowardOppositeLuminance(
           GetColor(Properties::COLOR_FRAME), 0x80);
+    case Properties::COLOR_MANAGED_USER_LABEL_BORDER:
+      return color_utils::AlphaBlend(
+          GetColor(Properties::COLOR_MANAGED_USER_LABEL_BACKGROUND),
+          SK_ColorBLACK,
+          230);
   }
 
   return Properties::GetDefaultColor(id);
@@ -455,6 +466,20 @@
   SetCustomDefaultTheme(new ManagedUserTheme);
 }
 
+void ThemeService::OnManagedUserInitialized() {
+  // Currently when creating a supervised user, the ThemeService is initialized
+  // before the boolean flag indicating the profile belongs to a supervised
+  // user gets set. In order to get the custom managed user theme, we get a
+  // callback when ManagedUserService is initialized, which happens some time
+  // after the boolean flag has been set in
+  // ProfileManager::InitProfileUserPrefs() and after the
+  // NOTIFICATION_EXTENSIONS_READY notification is sent.
+  if (theme_supplier_.get() || !IsManagedUser())
+    return;
+
+  SetManagedUserTheme();
+}
+
 void ThemeService::OnInfobarDisplayed() {
   number_of_infobars_++;
 }
diff --git a/chrome/browser/themes/theme_service.h b/chrome/browser/themes/theme_service.h
index b573d2e..117844f 100644
--- a/chrome/browser/themes/theme_service.h
+++ b/chrome/browser/themes/theme_service.h
@@ -13,6 +13,7 @@
 #include "base/compiler_specific.h"
 #include "base/memory/ref_counted.h"
 #include "base/memory/scoped_ptr.h"
+#include "base/memory/weak_ptr.h"
 #include "base/threading/non_thread_safe.h"
 #include "components/browser_context_keyed_service/browser_context_keyed_service.h"
 #include "content/public/browser/notification_observer.h"
@@ -214,6 +215,9 @@
   // managed user profiles.
   void SetManagedUserTheme();
 
+  // Sets the managed user theme if the user has no custom theme yet.
+  void OnManagedUserInitialized();
+
 #if defined(TOOLKIT_GTK)
   // Loads an image and flips it horizontally if |rtl_enabled| is true.
   GdkPixbuf* GetPixbufImpl(int id, bool rtl_enabled) const;
@@ -247,6 +251,8 @@
 
   scoped_ptr<ThemeSyncableService> theme_syncable_service_;
 
+  base::WeakPtrFactory<ThemeService> weak_ptr_factory_;
+
   DISALLOW_COPY_AND_ASSIGN(ThemeService);
 };
 
diff --git a/chrome/browser/themes/theme_service_unittest.cc b/chrome/browser/themes/theme_service_unittest.cc
index 4168f96..6288935 100644
--- a/chrome/browser/themes/theme_service_unittest.cc
+++ b/chrome/browser/themes/theme_service_unittest.cc
@@ -6,19 +6,26 @@
 
 #include "base/json/json_reader.h"
 #include "chrome/browser/extensions/extension_service_unittest.h"
+#include "chrome/browser/managed_mode/managed_user_service.h"
+#include "chrome/browser/managed_mode/managed_user_service_factory.h"
 #include "chrome/browser/themes/custom_theme_supplier.h"
 #include "chrome/browser/themes/theme_service_factory.h"
 #include "chrome/common/extensions/extension.h"
 #include "chrome/common/extensions/extension_manifest_constants.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/gtest/include/gtest/gtest.h"
 
 namespace theme_service_internal {
 
 class ThemeServiceTest : public ExtensionServiceTestBase {
  public:
-  ThemeServiceTest() {}
+  ThemeServiceTest() {
+    manager_.reset(
+        new TestingProfileManager(TestingBrowserProcess::GetGlobal()));
+  }
   virtual ~ThemeServiceTest() {}
 
   scoped_refptr<extensions::Extension> MakeThemeExtension(base::FilePath path) {
@@ -40,11 +47,20 @@
   virtual void SetUp() {
     ExtensionServiceTestBase::SetUp();
     InitializeEmptyExtensionService();
+    bool success = manager_->SetUp();
+    ASSERT_TRUE(success);
   }
 
   const CustomThemeSupplier* get_theme_supplier(ThemeService* theme_service) {
     return theme_service->get_theme_supplier();
   }
+
+  TestingProfileManager* manager() {
+    return manager_.get();
+  }
+
+ private:
+  scoped_ptr<TestingProfileManager> manager_;
 };
 
 // Installs then uninstalls a theme and makes sure that the ThemeService
@@ -103,6 +119,18 @@
             CustomThemeSupplier::MANAGED_USER_THEME);
 }
 
+TEST_F(ThemeServiceTest, ManagedUserThemeNewUser) {
+  TestingProfile* profile = manager()->CreateTestingProfile("mu");
+  // Simulate the current initialization behavior: first the ThemeService is
+  // created, then the supervised user profile is initialized.
+  ThemeService* theme_service =
+      ThemeServiceFactory::GetForProfile(profile);
+  ManagedUserServiceFactory::GetForProfile(profile)->InitForTesting();
+  EXPECT_EQ(get_theme_supplier(theme_service)->get_theme_type(),
+            CustomThemeSupplier::MANAGED_USER_THEME);
+  manager()->DeleteTestingProfile("mu");
+}
+
 #if defined(OS_LINUX) && !defined(OS_CHROMEOS)
 // Checks that managed users don't use the system theme even if it is the
 // default. The system theme is only available on Linux.
diff --git a/chrome/browser/ui/android/autofill/autofill_dialog_controller_android.cc b/chrome/browser/ui/android/autofill/autofill_dialog_controller_android.cc
new file mode 100644
index 0000000..00f5da8
--- /dev/null
+++ b/chrome/browser/ui/android/autofill/autofill_dialog_controller_android.cc
@@ -0,0 +1,488 @@
+// 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/ui/android/autofill/autofill_dialog_controller_android.h"
+
+#include "base/android/jni_android.h"
+#include "base/android/jni_array.h"
+#include "base/android/jni_string.h"
+#include "base/android/scoped_java_ref.h"
+#include "base/bind.h"
+#include "base/logging.h"
+#include "base/prefs/pref_service.h"
+#include "base/strings/utf_string_conversions.h"
+#include "chrome/browser/autofill/personal_data_manager_factory.h"
+#include "chrome/browser/browser_process.h"
+#include "chrome/browser/prefs/scoped_user_pref_update.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/profiles/profile_manager.h"
+#include "chrome/browser/ui/android/autofill/autofill_dialog_result.h"
+#include "chrome/browser/ui/android/window_android_helper.h"
+#include "chrome/browser/ui/autofill/autofill_dialog_common.h"
+#include "chrome/browser/ui/autofill/data_model_wrapper.h"
+#include "chrome/common/pref_names.h"
+#include "chrome/common/url_constants.h"
+#include "components/autofill/content/browser/wallet/full_wallet.h"
+#include "components/autofill/core/browser/autofill_metrics.h"
+#include "components/autofill/core/browser/autofill_profile.h"
+#include "components/autofill/core/browser/autofill_type.h"
+#include "components/autofill/core/browser/credit_card.h"
+#include "components/autofill/core/browser/personal_data_manager.h"
+#include "components/autofill/core/common/form_data.h"
+#include "components/user_prefs/pref_registry_syncable.h"
+#include "content/public/browser/navigation_controller.h"
+#include "content/public/browser/navigation_details.h"
+#include "content/public/browser/navigation_entry.h"
+#include "content/public/browser/web_contents.h"
+#include "grit/generated_resources.h"
+#include "jni/AutofillDialogControllerAndroid_jni.h"
+#include "ui/android/window_android.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/models/combobox_model.h"
+#include "ui/base/models/menu_model.h"
+#include "ui/gfx/android/java_bitmap.h"
+#include "ui/gfx/rect.h"
+#include "url/gurl.h"
+
+namespace autofill {
+
+namespace {
+
+// Keys in kAutofillDialogDefaults pref dictionary (do not change these values).
+const char kLastUsedAccountName[] = "last_used_account_name";
+const char kLastUsedChoiceIsAutofill[] = "last_used_choice_is_autofill";
+const char kLastUsedBillingAddressGuid[] = "last_used_billing";
+const char kLastUsedShippingAddressGuid[] = "last_used_shipping";
+const char kLastUsedCreditCardGuid[] = "last_used_card";
+
+scoped_ptr<DataModelWrapper> CreateWrapper(
+    DialogSection section, wallet::FullWallet* full_wallet) {
+  if (section == SECTION_CC_BILLING) {
+    if (!full_wallet->billing_address())
+      return scoped_ptr<DataModelWrapper>();
+
+    return scoped_ptr<DataModelWrapper>(
+        new FullWalletBillingWrapper(full_wallet));
+  }
+  if (section == SECTION_SHIPPING) {
+    if (!full_wallet->shipping_address())
+      return scoped_ptr<DataModelWrapper>();
+
+    return scoped_ptr<DataModelWrapper>(
+        new FullWalletShippingWrapper(full_wallet));
+  }
+  NOTREACHED();
+  return scoped_ptr<DataModelWrapper>();
+}
+
+void FillOutputForSectionWithComparator(
+    DialogSection section, const DetailInputs& inputs,
+    const InputFieldComparator& compare,
+    FormStructure& form_structure, wallet::FullWallet* full_wallet,
+    const base::string16& email_address) {
+
+  // Email is hidden while using Wallet, special case it.
+  if (section == SECTION_EMAIL) {
+    AutofillProfile profile;
+    profile.SetRawInfo(EMAIL_ADDRESS, email_address);
+    AutofillProfileWrapper profile_wrapper(&profile, 0);
+    profile_wrapper.FillFormStructure(inputs, compare, &form_structure);
+    return;
+  }
+
+  scoped_ptr<DataModelWrapper> wrapper = CreateWrapper(section, full_wallet);
+  if (wrapper)
+    wrapper->FillFormStructure(inputs, compare, &form_structure);
+}
+
+void FillOutputForSection(
+    DialogSection section,
+    FormStructure& form_structure,
+    wallet::FullWallet* full_wallet,
+    const base::string16& email_address) {
+  DetailInputs inputs;
+  common::BuildInputsForSection(section, &inputs);
+
+  FillOutputForSectionWithComparator(
+      section, inputs,
+      base::Bind(common::DetailInputMatchesField, section),
+      form_structure, full_wallet, email_address);
+}
+
+}  // namespace
+
+
+// static
+base::WeakPtr<AutofillDialogController> AutofillDialogControllerAndroid::Create(
+    content::WebContents* contents,
+    const FormData& form_structure,
+    const GURL& source_url,
+    const DialogType dialog_type,
+    const base::Callback<void(const FormStructure*,
+                              const std::string&)>& callback) {
+  // AutofillDialogControllerAndroid owns itself.
+  AutofillDialogControllerAndroid* autofill_dialog_controller =
+      new AutofillDialogControllerAndroid(contents,
+                                          form_structure,
+                                          source_url,
+                                          dialog_type,
+                                          callback);
+  return autofill_dialog_controller->weak_ptr_factory_.GetWeakPtr();
+}
+
+// static
+void AutofillDialogControllerAndroid::RegisterProfilePrefs(
+    user_prefs::PrefRegistrySyncable* registry) {
+  registry->RegisterDictionaryPref(
+      ::prefs::kAutofillDialogDefaults,
+      user_prefs::PrefRegistrySyncable::SYNCABLE_PREF);
+}
+
+// static
+base::WeakPtr<AutofillDialogController>
+AutofillDialogController::Create(
+    content::WebContents* contents,
+    const FormData& form_structure,
+    const GURL& source_url,
+    const DialogType dialog_type,
+    const base::Callback<void(const FormStructure*,
+                              const std::string&)>& callback) {
+  return AutofillDialogControllerAndroid::Create(contents,
+                                                 form_structure,
+                                                 source_url,
+                                                 dialog_type,
+                                                 callback);
+}
+
+// static
+void AutofillDialogController::RegisterProfilePrefs(
+    user_prefs::PrefRegistrySyncable* registry) {
+  AutofillDialogControllerAndroid::RegisterProfilePrefs(registry);
+}
+
+AutofillDialogControllerAndroid::~AutofillDialogControllerAndroid() {
+  JNIEnv* env = base::android::AttachCurrentThread();
+  Java_AutofillDialogControllerAndroid_onDestroy(env, java_object_.obj());
+}
+
+void AutofillDialogControllerAndroid::Show() {
+  dialog_shown_timestamp_ = base::Time::Now();
+
+  content::NavigationEntry* entry = contents_->GetController().GetActiveEntry();
+  const GURL& active_url = entry ? entry->GetURL() : contents_->GetURL();
+  invoked_from_same_origin_ = active_url.GetOrigin() == source_url_.GetOrigin();
+
+  // Log any relevant UI metrics and security exceptions.
+  GetMetricLogger().LogDialogUiEvent(
+      GetDialogType(), AutofillMetrics::DIALOG_UI_SHOWN);
+
+  GetMetricLogger().LogDialogSecurityMetric(
+      GetDialogType(), AutofillMetrics::SECURITY_METRIC_DIALOG_SHOWN);
+
+  if (RequestingCreditCardInfo() && !TransmissionWillBeSecure()) {
+    GetMetricLogger().LogDialogSecurityMetric(
+        GetDialogType(),
+        AutofillMetrics::SECURITY_METRIC_CREDIT_CARD_OVER_HTTP);
+  }
+
+  if (!invoked_from_same_origin_) {
+    GetMetricLogger().LogDialogSecurityMetric(
+        GetDialogType(),
+        AutofillMetrics::SECURITY_METRIC_CROSS_ORIGIN_FRAME);
+  }
+
+  // Determine what field types should be included in the dialog.
+  bool has_types = false;
+  bool has_sections = false;
+  form_structure_.ParseFieldTypesFromAutocompleteAttributes(
+      &has_types, &has_sections);
+
+  // Fail if the author didn't specify autocomplete types.
+  if (!has_types) {
+    callback_.Run(NULL, std::string());
+    delete this;
+    return;
+  }
+
+  bool request_full_billing_address = true;
+  bool request_shipping_address = false;
+  bool request_phone_numbers = false;
+
+  for (size_t i = 0; i < form_structure_.field_count(); ++i) {
+    const ServerFieldType type =
+        form_structure_.field(i)->Type().GetStorableType();
+    if (type == PHONE_HOME_WHOLE_NUMBER || type == PHONE_BILLING_WHOLE_NUMBER) {
+      request_phone_numbers = true;
+    }
+    if (type == NAME_FULL ||
+        type == ADDRESS_HOME_LINE1 || type == ADDRESS_HOME_LINE2 ||
+        type == ADDRESS_HOME_CITY || type == ADDRESS_HOME_STATE ||
+        type == ADDRESS_HOME_ZIP || type == ADDRESS_HOME_COUNTRY ||
+        type == PHONE_HOME_WHOLE_NUMBER) {
+      request_shipping_address = true;
+    }
+    if (type == ADDRESS_BILLING_LINE1 || type == ADDRESS_BILLING_LINE2 ||
+        type == ADDRESS_BILLING_CITY || type == ADDRESS_BILLING_STATE ||
+        type == PHONE_BILLING_WHOLE_NUMBER) {
+      request_full_billing_address = true;
+    }
+  }
+
+  if (request_shipping_address)
+    request_full_billing_address = true;
+
+  const bool incognito_mode = profile_->IsOffTheRecord();
+
+  bool last_used_choice_is_autofill = false;
+  base::string16 last_used_account_name;
+  std::string last_used_billing;
+  std::string last_used_shipping;
+  std::string last_used_credit_card;
+  {
+    const base::DictionaryValue* defaults =
+        profile_->GetPrefs()->GetDictionary(::prefs::kAutofillDialogDefaults);
+    if (defaults) {
+      defaults->GetString(kLastUsedAccountName, &last_used_account_name);
+      defaults->GetBoolean(kLastUsedChoiceIsAutofill,
+                           &last_used_choice_is_autofill);
+      defaults->GetString(kLastUsedBillingAddressGuid, &last_used_billing);
+      defaults->GetString(kLastUsedShippingAddressGuid, &last_used_shipping);
+      defaults->GetString(kLastUsedCreditCardGuid, &last_used_credit_card);
+    } else {
+      DLOG(ERROR) << "Failed to read AutofillDialog preferences";
+    }
+  }
+
+  if (contents_->GetBrowserContext()->IsOffTheRecord())
+    last_used_choice_is_autofill = true;
+
+  JNIEnv* env = base::android::AttachCurrentThread();
+  ScopedJavaLocalRef<jstring> jlast_used_account_name =
+      base::android::ConvertUTF16ToJavaString(
+          env, last_used_account_name);
+  ScopedJavaLocalRef<jstring> jlast_used_billing =
+      base::android::ConvertUTF8ToJavaString(
+          env, last_used_billing);
+  ScopedJavaLocalRef<jstring> jlast_used_shipping =
+      base::android::ConvertUTF8ToJavaString(
+          env, last_used_shipping);
+  ScopedJavaLocalRef<jstring> jlast_used_card =
+      base::android::ConvertUTF8ToJavaString(
+          env, last_used_credit_card);
+  ScopedJavaLocalRef<jstring> jmerchant_domain =
+      base::android::ConvertUTF8ToJavaString(
+          env, source_url_.GetOrigin().spec());
+  java_object_.Reset(Java_AutofillDialogControllerAndroid_create(
+      env,
+      reinterpret_cast<jint>(this),
+      WindowAndroidHelper::FromWebContents(contents_)->
+          GetWindowAndroid()->GetJavaObject().obj(),
+      request_full_billing_address, request_shipping_address,
+      request_phone_numbers, incognito_mode,
+      last_used_choice_is_autofill, jlast_used_account_name.obj(),
+      jlast_used_billing.obj(), jlast_used_shipping.obj(),
+      jlast_used_card.obj(),
+      jmerchant_domain.obj()));
+}
+
+void AutofillDialogControllerAndroid::Hide() {
+  // TODO(aruslan): http://crbug.com/177373 Autocheckout.
+  NOTIMPLEMENTED();
+}
+
+void AutofillDialogControllerAndroid::TabActivated() {}
+
+void AutofillDialogControllerAndroid::AddAutocheckoutStep(
+    AutocheckoutStepType step_type) {
+  // TODO(aruslan): http://crbug.com/177373 Autocheckout.
+  NOTIMPLEMENTED() << " step_type = " << step_type;
+}
+
+void AutofillDialogControllerAndroid::UpdateAutocheckoutStep(
+    AutocheckoutStepType step_type,
+    AutocheckoutStepStatus step_status) {
+  // TODO(aruslan): http://crbug.com/177373 Autocheckout.
+  NOTIMPLEMENTED() << " step_type=" << step_type
+                   << " step_status=" << step_status;
+}
+
+void AutofillDialogControllerAndroid::OnAutocheckoutError() {
+  // TODO(aruslan): http://crbug.com/177373 Autocheckout.
+  NOTIMPLEMENTED();
+  DCHECK_EQ(AUTOCHECKOUT_IN_PROGRESS, autocheckout_state_);
+  GetMetricLogger().LogAutocheckoutDuration(
+      base::Time::Now() - autocheckout_started_timestamp_,
+      AutofillMetrics::AUTOCHECKOUT_FAILED);
+  SetAutocheckoutState(AUTOCHECKOUT_ERROR);
+  autocheckout_started_timestamp_ = base::Time();
+}
+
+void AutofillDialogControllerAndroid::OnAutocheckoutSuccess() {
+  // TODO(aruslan): http://crbug.com/177373 Autocheckout.
+  NOTIMPLEMENTED();
+  DCHECK_EQ(AUTOCHECKOUT_IN_PROGRESS, autocheckout_state_);
+  GetMetricLogger().LogAutocheckoutDuration(
+      base::Time::Now() - autocheckout_started_timestamp_,
+      AutofillMetrics::AUTOCHECKOUT_SUCCEEDED);
+  SetAutocheckoutState(AUTOCHECKOUT_SUCCESS);
+  autocheckout_started_timestamp_ = base::Time();
+}
+
+DialogType AutofillDialogControllerAndroid::GetDialogType() const {
+  return dialog_type_;
+}
+
+// static
+bool AutofillDialogControllerAndroid::
+    RegisterAutofillDialogControllerAndroid(JNIEnv* env) {
+  return RegisterNativesImpl(env);
+}
+
+void AutofillDialogControllerAndroid::DialogCancel(JNIEnv* env,
+                                                   jobject obj) {
+  if (autocheckout_state_ == AUTOCHECKOUT_NOT_STARTED)
+    LogOnCancelMetrics();
+
+  if (autocheckout_state_ == AUTOCHECKOUT_IN_PROGRESS) {
+    GetMetricLogger().LogAutocheckoutDuration(
+        base::Time::Now() - autocheckout_started_timestamp_,
+        AutofillMetrics::AUTOCHECKOUT_CANCELLED);
+  }
+
+  callback_.Run(NULL, std::string());
+}
+
+void AutofillDialogControllerAndroid::DialogContinue(
+    JNIEnv* env,
+    jobject obj,
+    jobject wallet,
+    jboolean jlast_used_choice_is_autofill,
+    jstring jlast_used_account_name,
+    jstring jlast_used_billing,
+    jstring jlast_used_shipping,
+    jstring jlast_used_card) {
+  const string16 email = AutofillDialogResult::GetWalletEmail(env, wallet);
+  const std::string google_transaction_id =
+      AutofillDialogResult::GetWalletGoogleTransactionId(env, wallet);
+
+  const string16 last_used_account_name =
+      base::android::ConvertJavaStringToUTF16(env, jlast_used_account_name);
+  const std::string last_used_billing =
+      base::android::ConvertJavaStringToUTF8(env, jlast_used_billing);
+  const std::string last_used_shipping =
+      base::android::ConvertJavaStringToUTF8(env, jlast_used_shipping);
+  const std::string last_used_card =
+      base::android::ConvertJavaStringToUTF8(env, jlast_used_card);
+
+  scoped_ptr<wallet::FullWallet> full_wallet =
+      AutofillDialogResult::ConvertFromJava(env, wallet);
+  FillOutputForSection(
+      SECTION_EMAIL, form_structure_, full_wallet.get(), email);
+  FillOutputForSection(
+      SECTION_CC_BILLING, form_structure_, full_wallet.get(), email);
+  FillOutputForSection(
+      SECTION_SHIPPING, form_structure_, full_wallet.get(), email);
+
+  {
+    DictionaryPrefUpdate updater(profile_->GetPrefs(),
+                                 ::prefs::kAutofillDialogDefaults);
+    base::DictionaryValue* defaults = updater.Get();
+    if (defaults) {
+      const bool last_used_choice_is_autofill = !!jlast_used_choice_is_autofill;
+      defaults->SetString(kLastUsedAccountName, last_used_account_name);
+      defaults->SetBoolean(kLastUsedChoiceIsAutofill,
+                           last_used_choice_is_autofill);
+      if (!last_used_billing.empty())
+        defaults->SetString(kLastUsedBillingAddressGuid, last_used_billing);
+      if (!last_used_shipping.empty())
+        defaults->SetString(kLastUsedShippingAddressGuid, last_used_shipping);
+      if (!last_used_card.empty())
+        defaults->SetString(kLastUsedCreditCardGuid, last_used_card);
+    } else {
+      LOG(ERROR) << "Failed to save AutofillDialog preferences";
+    }
+  }
+
+  if (GetDialogType() == DIALOG_TYPE_AUTOCHECKOUT) {
+    autocheckout_started_timestamp_ = base::Time::Now();
+    SetAutocheckoutState(AUTOCHECKOUT_IN_PROGRESS);
+  }
+
+  LogOnFinishSubmitMetrics();
+
+  // Callback should be called as late as possible.
+  callback_.Run(&form_structure_, google_transaction_id);
+
+  // This might delete us.
+  if (GetDialogType() == DIALOG_TYPE_REQUEST_AUTOCOMPLETE)
+    Hide();
+}
+
+AutofillDialogControllerAndroid::AutofillDialogControllerAndroid(
+    content::WebContents* contents,
+    const FormData& form_structure,
+    const GURL& source_url,
+    const DialogType dialog_type,
+    const base::Callback<void(const FormStructure*,
+                              const std::string&)>& callback)
+    : profile_(Profile::FromBrowserContext(contents->GetBrowserContext())),
+      contents_(contents),
+      initial_user_state_(AutofillMetrics::DIALOG_USER_STATE_UNKNOWN),
+      dialog_type_(dialog_type),
+      form_structure_(form_structure, std::string()),
+      invoked_from_same_origin_(true),
+      source_url_(source_url),
+      callback_(callback),
+      cares_about_shipping_(true),
+      weak_ptr_factory_(this),
+      autocheckout_state_(AUTOCHECKOUT_NOT_STARTED),
+      was_ui_latency_logged_(false) {
+  DCHECK(!callback_.is_null());
+}
+
+bool AutofillDialogControllerAndroid::RequestingCreditCardInfo() const {
+  DCHECK_GT(form_structure_.field_count(), 0U);
+
+  for (size_t i = 0; i < form_structure_.field_count(); ++i) {
+    AutofillType type = form_structure_.field(i)->Type();
+    if (common::IsCreditCardType(type.GetStorableType()))
+      return true;
+  }
+
+  return false;
+}
+
+bool AutofillDialogControllerAndroid::TransmissionWillBeSecure() const {
+  return source_url_.SchemeIs(chrome::kHttpsScheme);
+}
+
+void AutofillDialogControllerAndroid::SetAutocheckoutState(
+    AutocheckoutState autocheckout_state) {
+  if (autocheckout_state_ == autocheckout_state)
+    return;
+
+  autocheckout_state_ = autocheckout_state;
+}
+
+void AutofillDialogControllerAndroid::LogOnFinishSubmitMetrics() {
+  GetMetricLogger().LogDialogUiDuration(
+      base::Time::Now() - dialog_shown_timestamp_,
+      GetDialogType(),
+      AutofillMetrics::DIALOG_ACCEPTED);
+
+  GetMetricLogger().LogDialogUiEvent(
+      GetDialogType(), AutofillMetrics::DIALOG_UI_ACCEPTED);
+}
+
+void AutofillDialogControllerAndroid::LogOnCancelMetrics() {
+  GetMetricLogger().LogDialogUiDuration(
+      base::Time::Now() - dialog_shown_timestamp_,
+      GetDialogType(),
+      AutofillMetrics::DIALOG_CANCELED);
+
+  GetMetricLogger().LogDialogUiEvent(
+      GetDialogType(), AutofillMetrics::DIALOG_UI_CANCELED);
+}
+
+}  // namespace autofill
diff --git a/chrome/browser/ui/android/autofill/autofill_dialog_controller_android.h b/chrome/browser/ui/android/autofill/autofill_dialog_controller_android.h
new file mode 100644
index 0000000..01a08d6
--- /dev/null
+++ b/chrome/browser/ui/android/autofill/autofill_dialog_controller_android.h
@@ -0,0 +1,144 @@
+// 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_UI_ANDROID_AUTOFILL_AUTOFILL_DIALOG_CONTROLLER_ANDROID_H_
+#define CHROME_BROWSER_UI_ANDROID_AUTOFILL_AUTOFILL_DIALOG_CONTROLLER_ANDROID_H_
+
+#include <jni.h>
+
+#include "base/android/jni_string.h"
+#include "base/android/scoped_java_ref.h"
+#include "base/time/time.h"
+#include "chrome/browser/ui/autofill/autofill_dialog_controller.h"
+#include "chrome/browser/ui/autofill/autofill_dialog_types.h"
+
+class Profile;
+
+namespace user_prefs {
+class PrefRegistrySyncable;
+}
+
+namespace autofill {
+
+// This class defines the form-filling host and JNI glue for the Java-side
+// implementation of the requestAutocomplete dialog.
+class AutofillDialogControllerAndroid : public AutofillDialogController {
+ public:
+  // Creates an instance of the AutofillDialogControllerAndroid.
+  static base::WeakPtr<AutofillDialogController> Create(
+      content::WebContents* contents,
+      const FormData& form_structure,
+      const GURL& source_url,
+      const DialogType dialog_type,
+      const base::Callback<void(const FormStructure*,
+                                const std::string&)>& callback);
+
+  // Registers profile preferences for the AutofillDialogControllerAndroid.
+  static void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry);
+
+  virtual ~AutofillDialogControllerAndroid();
+
+  // AutofillDialogController implementation:
+  virtual void Show() OVERRIDE;
+  virtual void Hide() OVERRIDE;
+  virtual void TabActivated() OVERRIDE;
+  virtual void AddAutocheckoutStep(AutocheckoutStepType step_type) OVERRIDE;
+  virtual void UpdateAutocheckoutStep(
+      AutocheckoutStepType step_type,
+      AutocheckoutStepStatus step_status) OVERRIDE;
+  virtual void OnAutocheckoutError() OVERRIDE;
+  virtual void OnAutocheckoutSuccess() OVERRIDE;
+  virtual DialogType GetDialogType() const OVERRIDE;
+
+  // JNI bindings for Java-side AutofillDialogDelegate:
+  void DialogCancel(JNIEnv* env, jobject obj);
+  void DialogContinue(JNIEnv* env,
+                      jobject obj,
+                      jobject full_wallet,
+                      jboolean last_used_choice_is_autofill,
+                      jstring last_used_account_name,
+                      jstring last_used_billing,
+                      jstring last_used_shipping,
+                      jstring last_used_credit_card);
+
+  // Establishes JNI bindings.
+  static bool RegisterAutofillDialogControllerAndroid(JNIEnv* env);
+
+ private:
+  AutofillDialogControllerAndroid(
+      content::WebContents* contents,
+      const FormData& form_structure,
+      const GURL& source_url,
+      const DialogType dialog_type,
+      const base::Callback<void(const FormStructure*,
+                                const std::string&)>& callback);
+
+  const AutofillMetrics& GetMetricLogger() const {
+    return metric_logger_;
+  }
+
+  // Logs metrics when the dialog is submitted.
+  void LogOnFinishSubmitMetrics();
+
+  // Logs metrics when the dialog is canceled.
+  void LogOnCancelMetrics();
+
+  bool RequestingCreditCardInfo() const;
+  bool TransmissionWillBeSecure() const;
+
+  void SetAutocheckoutState(AutocheckoutState autocheckout_state);
+
+  // The |profile| for |contents_|.
+  Profile* const profile_;
+
+  // The WebContents where the Autocomplete/Checkout action originated.
+  content::WebContents* const contents_;
+
+  // For logging UMA metrics.
+  const AutofillMetrics metric_logger_;
+  base::Time dialog_shown_timestamp_;
+  AutofillMetrics::DialogInitialUserStateMetric initial_user_state_;
+
+  // The time that Autocheckout started running. Reset on error. While this is
+  // a valid time, |AutocheckoutIsRunning()| will return true.
+  base::Time autocheckout_started_timestamp_;
+
+  // Whether this is an Autocheckout or a requestAutocomplete dialog.
+  const DialogType dialog_type_;
+
+  FormStructure form_structure_;
+
+  // Whether the URL visible to the user when this dialog was requested to be
+  // invoked is the same as |source_url_|.
+  bool invoked_from_same_origin_;
+
+  // The URL of the invoking site.
+  GURL source_url_;
+
+  // The callback via which we return the collected data and, if Online Wallet
+  // was used, the Google transaction id.
+  base::Callback<void(const FormStructure*, const std::string&)> callback_;
+
+  // Whether |form_structure_| has asked for any details that would indicate
+  // we should show a shipping section.
+  bool cares_about_shipping_;
+
+  base::WeakPtrFactory<AutofillDialogControllerAndroid>
+      weak_ptr_factory_;
+
+  // The current state of the Autocheckout flow.
+  AutocheckoutState autocheckout_state_;
+
+  // Whether the latency to display to the UI was logged to UMA yet.
+  bool was_ui_latency_logged_;
+
+  // The corresponding java object.
+  base::android::ScopedJavaGlobalRef<jobject> java_object_;
+
+  DISALLOW_COPY_AND_ASSIGN(AutofillDialogControllerAndroid);
+};
+
+}  // namespace autofill
+
+#endif  // CHROME_BROWSER_UI_ANDROID_AUTOFILL_AUTOFILL_DIALOG_CONTROLLER_ANDROID_H_
diff --git a/chrome/browser/ui/android/autofill/autofill_dialog_result.cc b/chrome/browser/ui/android/autofill/autofill_dialog_result.cc
new file mode 100644
index 0000000..7c223a1
--- /dev/null
+++ b/chrome/browser/ui/android/autofill/autofill_dialog_result.cc
@@ -0,0 +1,138 @@
+// 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/ui/android/autofill/autofill_dialog_result.h"
+
+#include "base/android/jni_android.h"
+#include "base/android/jni_array.h"
+#include "base/android/jni_string.h"
+#include "base/android/scoped_java_ref.h"
+#include "base/bind.h"
+#include "base/logging.h"
+#include "base/strings/utf_string_conversions.h"
+#include "chrome/browser/ui/autofill/data_model_wrapper.h"
+#include "components/autofill/content/browser/wallet/full_wallet.h"
+#include "components/autofill/core/browser/credit_card.h"
+#include "components/autofill/core/common/form_data.h"
+#include "jni/AutofillDialogResult_jni.h"
+#include "ui/base/l10n/l10n_util.h"
+
+namespace autofill {
+
+namespace {
+
+std::string ConvertNullOrJavaStringToUTF8(JNIEnv* env, jstring str) {
+  return str ? base::android::ConvertJavaStringToUTF8(env, str) : std::string();
+}
+
+base::string16 ConvertNullOrJavaStringToUTF16(JNIEnv* env, jstring str) {
+  return str ? base::android::ConvertJavaStringToUTF16(env, str)
+             : base::string16();
+}
+
+#define FETCH_JFIELD(env, jobj, cls, getter) \
+    (Java_##cls##_get##getter((env), (jobj)))
+
+#define FETCH_JSTRING(utf, env, jobj, cls, getter) \
+    (ConvertNullOrJavaStringTo##utf( \
+        (env), FETCH_JFIELD((env), (jobj), cls, getter).obj()))
+
+scoped_ptr<wallet::Address> ParseJavaWalletAddress(
+    JNIEnv* env, jobject address) {
+  if (!address)
+    return scoped_ptr<wallet::Address>();
+
+  const base::string16 recipient_name =
+      FETCH_JSTRING(UTF16, env, address, ResultAddress, Name);
+  const base::string16 address_line_1 =
+      FETCH_JSTRING(UTF16, env, address, ResultAddress, Address1);
+  const base::string16 address_line_2 =
+      FETCH_JSTRING(UTF16, env, address, ResultAddress, Address2);
+  const base::string16 locality_name =
+      FETCH_JSTRING(UTF16, env, address, ResultAddress, City);
+  const base::string16 administrative_area_name =
+      FETCH_JSTRING(UTF16, env, address, ResultAddress, State);
+  const base::string16 postal_code_number =
+      FETCH_JSTRING(UTF16, env, address, ResultAddress, PostalCode);
+  const base::string16 phone_number =
+      FETCH_JSTRING(UTF16, env, address, ResultAddress, PhoneNumber);
+  const std::string country_name_code =
+      FETCH_JSTRING(UTF8, env, address, ResultAddress, CountryCode);
+  DCHECK(!country_name_code.empty());
+
+  return scoped_ptr<wallet::Address>(new wallet::Address(
+      country_name_code,
+      recipient_name,
+      address_line_1,
+      address_line_2,
+      locality_name,
+      administrative_area_name,
+      postal_code_number,
+      phone_number,
+      std::string()));
+}
+
+scoped_ptr<wallet::FullWallet> ParseJavaWallet(JNIEnv* env, jobject wallet) {
+  const ScopedJavaLocalRef<jobject> billing_address(
+      FETCH_JFIELD(env, wallet, ResultWallet, BillingAddress));
+  const ScopedJavaLocalRef<jobject> shipping_address(
+      FETCH_JFIELD(env, wallet, ResultWallet, ShippingAddress));
+  const ScopedJavaLocalRef<jobject> card(
+      FETCH_JFIELD(env, wallet, ResultWallet, Card));
+
+  const int expiration_month =
+      FETCH_JFIELD(env, card.obj(), ResultCard, ExpirationMonth);
+  const int expiration_year =
+      FETCH_JFIELD(env, card.obj(), ResultCard, ExpirationYear);
+  const std::string pan =
+      FETCH_JSTRING(UTF8, env, card.obj(), ResultCard, Pan);
+  const std::string cvn =
+      FETCH_JSTRING(UTF8, env, card.obj(), ResultCard, Cvn);
+
+  return wallet::FullWallet::CreateFullWalletFromClearText(
+      expiration_month,
+      expiration_year,
+      pan,
+      cvn,
+      ParseJavaWalletAddress(env, billing_address.obj()),
+      ParseJavaWalletAddress(env, shipping_address.obj()));
+}
+
+base::string16 ParseWalletEmail(JNIEnv* env, jobject wallet) {
+  return FETCH_JSTRING(UTF16, env, wallet, ResultWallet, Email);
+}
+
+std::string ParseGoogleTransactionId(JNIEnv* env, jobject wallet) {
+  return FETCH_JSTRING(UTF8, env, wallet, ResultWallet, GoogleTransactionId);
+}
+
+#undef FETCH_JSTRING
+#undef FETCH_FIELD
+
+}  // namespace
+
+// static
+scoped_ptr<wallet::FullWallet> AutofillDialogResult::ConvertFromJava(
+    JNIEnv* env, jobject wallet) {
+  return ParseJavaWallet(env, wallet);
+}
+
+// static
+base::string16 AutofillDialogResult::GetWalletEmail(
+    JNIEnv* env, jobject wallet) {
+  return ParseWalletEmail(env, wallet);
+}
+
+// static
+std::string AutofillDialogResult::GetWalletGoogleTransactionId(
+    JNIEnv* env, jobject wallet) {
+  return ParseGoogleTransactionId(env, wallet);
+}
+
+// static
+bool AutofillDialogResult::RegisterAutofillDialogResult(JNIEnv* env) {
+  return RegisterNativesImpl(env);
+}
+
+}  // namespace autofill
diff --git a/chrome/browser/ui/android/autofill/autofill_dialog_result.h b/chrome/browser/ui/android/autofill/autofill_dialog_result.h
new file mode 100644
index 0000000..2fe26a9
--- /dev/null
+++ b/chrome/browser/ui/android/autofill/autofill_dialog_result.h
@@ -0,0 +1,49 @@
+// 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_UI_ANDROID_AUTOFILL_AUTOFILL_DIALOG_RESULT_H_
+#define CHROME_BROWSER_UI_ANDROID_AUTOFILL_AUTOFILL_DIALOG_RESULT_H_
+
+#include <jni.h>
+#include <string>
+
+#include "base/memory/scoped_ptr.h"
+#include "base/strings/string16.h"
+
+namespace autofill {
+namespace wallet {
+class FullWallet;
+}
+}
+
+namespace autofill {
+
+// A result of the non-cancelled Java-side AutofillDialog invocation.
+// Passed to the AutofillDialogControllerAndroid in dialogContinue.
+class AutofillDialogResult {
+ public:
+  // Converts the requested information to wallet::FullWallet.
+  // The dialog stores the requested information in the same format
+  // regardless if the information was obtained from Autofill or Google Wallet.
+  static scoped_ptr<wallet::FullWallet> ConvertFromJava(
+      JNIEnv* env, jobject wallet);
+
+  // Returns the email address to be associated with this request,
+  // or an empty string.
+  static base::string16 GetWalletEmail(JNIEnv* env, jobject wallet);
+
+  // Returns the Google Transaction ID to be associated with this request,
+  // or an empty string.
+  static std::string GetWalletGoogleTransactionId(JNIEnv* env, jobject wallet);
+
+  // Establishes JNI bindings.
+  static bool RegisterAutofillDialogResult(JNIEnv* env);
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(AutofillDialogResult);
+};
+
+}  // namespace autofill
+
+#endif  // CHROME_BROWSER_UI_ANDROID_AUTOFILL_AUTOFILL_DIALOG_RESULT_H_
diff --git a/chrome/browser/ui/app_list/app_list_service.cc b/chrome/browser/ui/app_list/app_list_service.cc
index 8120aae..5a5f933 100644
--- a/chrome/browser/ui/app_list/app_list_service.cc
+++ b/chrome/browser/ui/app_list/app_list_service.cc
@@ -47,11 +47,12 @@
     else
       UMA_HISTOGRAM_LONG_TIMES("Startup.ShowAppListWarmStart", elapsed);
   } else {
-    // base::CurrentProcessInfo::CreationTime() is only defined on win/mac.
-#if defined(OS_WIN) || defined(OS_MACOSX)
+    // base::CurrentProcessInfo::CreationTime() is only defined on some
+    // platforms.
+#if defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_LINUX)
     UMA_HISTOGRAM_LONG_TIMES(
         "Startup.ShowAppListColdStart",
-        base::Time::Now() - *base::CurrentProcessInfo::CreationTime());
+        base::Time::Now() - base::CurrentProcessInfo::CreationTime());
 #endif
   }
 }
diff --git a/chrome/browser/ui/app_list/app_list_service.h b/chrome/browser/ui/app_list/app_list_service.h
index edac211..441fdc1 100644
--- a/chrome/browser/ui/app_list/app_list_service.h
+++ b/chrome/browser/ui/app_list/app_list_service.h
@@ -48,6 +48,9 @@
   // current browser process.
   virtual void Show() = 0;
 
+  // Create the app list UI, and maintain its state, but do not show it.
+  virtual void CreateForProfile(Profile* requested_profile) = 0;
+
   // Show the app list for the given profile. If it differs from the profile the
   // app list is currently showing, repopulate the app list and save the new
   // profile to local prefs as the default app list profile.
diff --git a/chrome/browser/ui/app_list/app_list_service_disabled.cc b/chrome/browser/ui/app_list/app_list_service_disabled.cc
index 6c1ec63..b3c879d 100644
--- a/chrome/browser/ui/app_list/app_list_service_disabled.cc
+++ b/chrome/browser/ui/app_list/app_list_service_disabled.cc
@@ -31,6 +31,7 @@
   virtual void SetProfilePath(const base::FilePath& profile_path) OVERRIDE {}
 
   virtual void Show() OVERRIDE {}
+  virtual void CreateForProfile(Profile* profile) OVERRIDE {}
   virtual void ShowForProfile(Profile* profile) OVERRIDE {}
   virtual void DismissAppList() OVERRIDE {}
 
diff --git a/chrome/browser/ui/app_list/app_list_service_impl.cc b/chrome/browser/ui/app_list/app_list_service_impl.cc
index 8054e87..102809c 100644
--- a/chrome/browser/ui/app_list/app_list_service_impl.cc
+++ b/chrome/browser/ui/app_list/app_list_service_impl.cc
@@ -69,6 +69,11 @@
   }
 }
 
+bool HasAppListEnabledPreference() {
+  PrefService* local_state = g_browser_process->local_state();
+  return local_state->GetBoolean(apps::prefs::kAppLauncherHasBeenEnabled);
+}
+
 void SetAppListEnabledPreference(bool enabled) {
   PrefService* local_state = g_browser_process->local_state();
   local_state->SetBoolean(apps::prefs::kAppLauncherHasBeenEnabled, enabled);
@@ -184,8 +189,11 @@
 }
 
 void AppListServiceImpl::EnableAppList(Profile* initial_profile) {
-  SetAppListEnabledPreference(true);
   SetProfilePath(initial_profile->GetPath());
+  if (HasAppListEnabledPreference())
+    return;
+
+  SetAppListEnabledPreference(true);
   CreateShortcut();
 }
 
diff --git a/chrome/browser/ui/app_list/app_list_service_mac.mm b/chrome/browser/ui/app_list/app_list_service_mac.mm
index 56b9db4..bc34424 100644
--- a/chrome/browser/ui/app_list/app_list_service_mac.mm
+++ b/chrome/browser/ui/app_list/app_list_service_mac.mm
@@ -59,11 +59,11 @@
                      LeakySingletonTraits<AppListServiceMac> >::get();
   }
 
-  void CreateAppList(Profile* profile);
   void ShowWindowNearDock();
 
   // AppListService overrides:
   virtual void Init(Profile* initial_profile) OVERRIDE;
+  virtual void CreateForProfile(Profile* requested_profile) OVERRIDE;
   virtual void ShowForProfile(Profile* requested_profile) OVERRIDE;
   virtual void DismissAppList() OVERRIDE;
   virtual bool IsAppListVisible() const OVERRIDE;
@@ -241,7 +241,7 @@
 
 bool AppListControllerDelegateCocoa::CanDoCreateShortcutsFlow(
     bool is_platform_app) {
-  return is_platform_app && apps::IsAppShimsEnabled();
+  return false;
 }
 
 void AppListControllerDelegateCocoa::DoCreateShortcutsFlow(
@@ -268,22 +268,6 @@
       profile, extension, NEW_FOREGROUND_TAB));
 }
 
-void AppListServiceMac::CreateAppList(Profile* requested_profile) {
-  if (profile() == requested_profile)
-    return;
-
-  // The Objective C objects might be released at some unknown point in the
-  // future, so explicitly clear references to C++ objects.
-  [[window_controller_ appListViewController]
-      setDelegate:scoped_ptr<app_list::AppListViewDelegate>()];
-
-  SetProfile(requested_profile);
-  scoped_ptr<app_list::AppListViewDelegate> delegate(
-      new AppListViewDelegate(new AppListControllerDelegateCocoa(), profile()));
-  window_controller_.reset([[AppListWindowController alloc] init]);
-  [[window_controller_ appListViewController] setDelegate:delegate.Pass()];
-}
-
 void AppListServiceMac::Init(Profile* initial_profile) {
   // On Mac, Init() is called multiple times for a process: any time there is no
   // browser window open and a new window is opened, and during process startup
@@ -311,6 +295,22 @@
                                         AppListServiceMac::GetInstance());
 }
 
+void AppListServiceMac::CreateForProfile(Profile* requested_profile) {
+  if (profile() == requested_profile)
+    return;
+
+  // The Objective C objects might be released at some unknown point in the
+  // future, so explicitly clear references to C++ objects.
+  [[window_controller_ appListViewController]
+      setDelegate:scoped_ptr<app_list::AppListViewDelegate>()];
+
+  SetProfile(requested_profile);
+  scoped_ptr<app_list::AppListViewDelegate> delegate(
+      new AppListViewDelegate(new AppListControllerDelegateCocoa(), profile()));
+  window_controller_.reset([[AppListWindowController alloc] init]);
+  [[window_controller_ appListViewController] setDelegate:delegate.Pass()];
+}
+
 void AppListServiceMac::ShowForProfile(Profile* requested_profile) {
   InvalidatePendingProfileLoads();
 
@@ -322,7 +322,7 @@
   SetProfilePath(requested_profile->GetPath());
 
   DismissAppList();
-  CreateAppList(requested_profile);
+  CreateForProfile(requested_profile);
   ShowWindowNearDock();
 }
 
diff --git a/chrome/browser/ui/app_list/apps_model_builder_unittest.cc b/chrome/browser/ui/app_list/apps_model_builder_unittest.cc
index 3781da0..4dca6ee 100644
--- a/chrome/browser/ui/app_list/apps_model_builder_unittest.cc
+++ b/chrome/browser/ui/app_list/apps_model_builder_unittest.cc
@@ -9,6 +9,7 @@
 #include "base/files/file_path.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/prefs/pref_service.h"
+#include "base/run_loop.h"
 #include "base/values.h"
 #include "chrome/browser/extensions/extension_function_test_utils.h"
 #include "chrome/browser/extensions/extension_service_unittest.h"
@@ -160,7 +161,7 @@
   EXPECT_EQ(std::string("Packaged App 1,Hosted App"),
             GetModelContent(model.get()));
 
-  loop_.RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
 }
 
 TEST_F(AppsModelBuilderTest, UninstallTerminatedApp) {
@@ -180,7 +181,7 @@
   EXPECT_EQ(std::string("Packaged App 1,Hosted App"),
             GetModelContent(model.get()));
 
-  loop_.RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
 }
 
 TEST_F(AppsModelBuilderTest, OrdinalPrefsChange) {
diff --git a/chrome/browser/ui/app_list/search/app_result.cc b/chrome/browser/ui/app_list/search/app_result.cc
index 3877c74..4cd6328 100644
--- a/chrome/browser/ui/app_list/search/app_result.cc
+++ b/chrome/browser/ui/app_list/search/app_result.cc
@@ -6,6 +6,8 @@
 
 #include "chrome/browser/extensions/extension_service.h"
 #include "chrome/browser/extensions/extension_system_factory.h"
+#include "chrome/browser/extensions/install_tracker.h"
+#include "chrome/browser/extensions/install_tracker_factory.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/app_list/app_context_menu.h"
 #include "chrome/browser/ui/app_list/app_list_controller_delegate.h"
@@ -24,7 +26,8 @@
                      AppListControllerDelegate* controller)
     : profile_(profile),
       app_id_(app_id),
-      controller_(controller) {
+      controller_(controller),
+      install_tracker_(NULL) {
   set_id(extensions::Extension::GetBaseURLFromExtensionId(app_id_).spec());
 
   const extensions::Extension* extension =
@@ -42,8 +45,12 @@
       extensions::IconsInfo::GetDefaultAppIcon(),
       this));
   SetIcon(icon_->image_skia());
+  StartObservingInstall();
 }
-AppResult::~AppResult() {}
+
+AppResult::~AppResult() {
+  StopObservingInstall();
+}
 
 void AppResult::UpdateFromMatch(const TokenizedString& title,
                                 const TokenizedStringMatch& match) {
@@ -97,8 +104,21 @@
   return context_menu_->GetMenuModel();
 }
 
-void AppResult::OnExtensionIconImageChanged(
-    extensions::IconImage* image) {
+void AppResult::StartObservingInstall() {
+  DCHECK(!install_tracker_);
+
+  install_tracker_ = extensions::InstallTrackerFactory::GetForProfile(profile_);
+  install_tracker_->AddObserver(this);
+}
+
+void AppResult::StopObservingInstall() {
+  if (install_tracker_)
+    install_tracker_->RemoveObserver(this);
+
+  install_tracker_ = NULL;
+}
+
+void AppResult::OnExtensionIconImageChanged(extensions::IconImage* image) {
   DCHECK_EQ(icon_.get(), image);
   SetIcon(icon_->image_skia());
 }
@@ -107,4 +127,34 @@
   Open(event_flags);
 }
 
+void AppResult::OnBeginExtensionInstall(const std::string& extension_id,
+                                        const std::string& extension_name,
+                                        const gfx::ImageSkia& installing_icon,
+                                        bool is_app,
+                                        bool is_platform_app) {}
+
+void AppResult::OnDownloadProgress(const std::string& extension_id,
+                                   int percent_downloaded) {}
+
+void AppResult::OnInstallFailure(const std::string& extension_id) {}
+
+void AppResult::OnExtensionInstalled(const extensions::Extension* extension) {}
+
+void AppResult::OnExtensionLoaded(const extensions::Extension* extension) {}
+
+void AppResult::OnExtensionUnloaded(const extensions::Extension* extension) {}
+
+void AppResult::OnExtensionUninstalled(const extensions::Extension* extension) {
+  if (extension->id() != app_id_)
+    return;
+
+  NotifyItemUninstalled();
+}
+
+void AppResult::OnAppsReordered() {}
+
+void AppResult::OnAppInstalledToAppList(const std::string& extension_id) {}
+
+void AppResult::OnShutdown() { StopObservingInstall(); }
+
 }  // namespace app_list
diff --git a/chrome/browser/ui/app_list/search/app_result.h b/chrome/browser/ui/app_list/search/app_result.h
index f270058..bb46181 100644
--- a/chrome/browser/ui/app_list/search/app_result.h
+++ b/chrome/browser/ui/app_list/search/app_result.h
@@ -9,12 +9,17 @@
 
 #include "base/memory/scoped_ptr.h"
 #include "chrome/browser/extensions/extension_icon_image.h"
+#include "chrome/browser/extensions/install_observer.h"
 #include "chrome/browser/ui/app_list/app_context_menu_delegate.h"
 #include "chrome/browser/ui/app_list/search/chrome_search_result.h"
 
 class AppListControllerDelegate;
 class Profile;
 
+namespace extensions {
+class InstallTracker;
+}
+
 namespace app_list {
 
 class AppContextMenu;
@@ -23,7 +28,8 @@
 
 class AppResult : public ChromeSearchResult,
                   public extensions::IconImage::Observer,
-                  public AppContextMenuDelegate {
+                  public AppContextMenuDelegate,
+                  public extensions::InstallObserver {
  public:
   AppResult(Profile* profile,
             const std::string& app_id,
@@ -41,6 +47,9 @@
   virtual ChromeSearchResultType GetType() OVERRIDE;
 
  private:
+  void StartObservingInstall();
+  void StopObservingInstall();
+
   // extensions::IconImage::Observer overrides:
   virtual void OnExtensionIconImageChanged(
       extensions::IconImage* image) OVERRIDE;
@@ -48,6 +57,28 @@
   // AppContextMenuDelegate overrides:
   virtual void ExecuteLaunchCommand(int event_flags) OVERRIDE;
 
+  // extensions::InstallObserver overrides:
+  virtual void OnBeginExtensionInstall(const std::string& extension_id,
+                                       const std::string& extension_name,
+                                       const gfx::ImageSkia& installing_icon,
+                                       bool is_app,
+                                       bool is_platform_app) OVERRIDE;
+  virtual void OnDownloadProgress(const std::string& extension_id,
+                                  int percent_downloaded) OVERRIDE;
+  virtual void OnInstallFailure(const std::string& extension_id) OVERRIDE;
+  virtual void OnExtensionInstalled(
+      const extensions::Extension* extension) OVERRIDE;
+  virtual void OnExtensionLoaded(
+      const extensions::Extension* extension) OVERRIDE;
+  virtual void OnExtensionUnloaded(
+      const extensions::Extension* extension) OVERRIDE;
+  virtual void OnExtensionUninstalled(
+      const extensions::Extension* extension) OVERRIDE;
+  virtual void OnAppsReordered() OVERRIDE;
+  virtual void OnAppInstalledToAppList(
+      const std::string& extension_id) OVERRIDE;
+  virtual void OnShutdown() OVERRIDE;
+
   Profile* profile_;
   const std::string app_id_;
   AppListControllerDelegate* controller_;
@@ -56,6 +87,8 @@
   scoped_ptr<extensions::IconImage> icon_;
   scoped_ptr<AppContextMenu> context_menu_;
 
+  extensions::InstallTracker* install_tracker_;  // Not owned.
+
   DISALLOW_COPY_AND_ASSIGN(AppResult);
 };
 
diff --git a/chrome/browser/ui/app_list/search/app_search_provider_unittest.cc b/chrome/browser/ui/app_list/search/app_search_provider_unittest.cc
index 4e0d064..f487c67 100644
--- a/chrome/browser/ui/app_list/search/app_search_provider_unittest.cc
+++ b/chrome/browser/ui/app_list/search/app_search_provider_unittest.cc
@@ -6,6 +6,7 @@
 
 #include "base/basictypes.h"
 #include "base/memory/scoped_ptr.h"
+#include "base/run_loop.h"
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/browser/extensions/extension_service_unittest.h"
 #include "chrome/browser/ui/app_list/search/app_search_provider.h"
@@ -104,7 +105,7 @@
   EXPECT_EQ("", RunQuery("pa1"));
 
   // Let uninstall code to clean up.
-  loop_.RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
 }
 
 }  // namespace test
diff --git a/chrome/browser/ui/apps/OWNERS b/chrome/browser/ui/apps/OWNERS
index 8391787..34cff5f 100644
--- a/chrome/browser/ui/apps/OWNERS
+++ b/chrome/browser/ui/apps/OWNERS
@@ -3,4 +3,5 @@
 benwells@chromium.org
 koz@chromium.org
 miket@chromium.org
+scheib@chromium.org
 tapted@chromium.org
diff --git a/chrome/browser/ui/ash/app_list/app_list_service_ash.cc b/chrome/browser/ui/ash/app_list/app_list_service_ash.cc
index cf10ee6..1e9d69f 100644
--- a/chrome/browser/ui/ash/app_list/app_list_service_ash.cc
+++ b/chrome/browser/ui/ash/app_list/app_list_service_ash.cc
@@ -28,6 +28,7 @@
   // AppListService overrides:
   virtual base::FilePath GetProfilePath(
       const base::FilePath& user_data_dir) OVERRIDE;
+  virtual void CreateForProfile(Profile* default_profile) OVERRIDE;
   virtual void ShowForProfile(Profile* default_profile) OVERRIDE;
   virtual bool IsAppListVisible() const OVERRIDE;
   virtual void DismissAppList() OVERRIDE;
@@ -42,6 +43,8 @@
   return ChromeLauncherController::instance()->profile()->GetPath();
 }
 
+void AppListServiceAsh::CreateForProfile(Profile* default_profile) {}
+
 void AppListServiceAsh::ShowForProfile(Profile* default_profile) {
   // This may not work correctly if the profile passed in is different from the
   // one the ash Shell is currently using.
diff --git a/chrome/browser/ui/ash/chrome_shell_delegate.cc b/chrome/browser/ui/ash/chrome_shell_delegate.cc
index 1d0d4f6..2a22df0 100644
--- a/chrome/browser/ui/ash/chrome_shell_delegate.cc
+++ b/chrome/browser/ui/ash/chrome_shell_delegate.cc
@@ -6,6 +6,7 @@
 
 #include "apps/native_app_window.h"
 #include "apps/shell_window.h"
+#include "apps/shell_window_registry.h"
 #include "ash/ash_switches.h"
 #include "ash/host/root_window_host_factory.h"
 #include "ash/launcher/launcher_types.h"
@@ -21,7 +22,6 @@
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/browser/app_mode/app_mode_utils.h"
 #include "chrome/browser/chrome_notification_types.h"
-#include "chrome/browser/extensions/shell_window_registry.h"
 #include "chrome/browser/lifetime/application_lifetime.h"
 #include "chrome/browser/profiles/profile_manager.h"
 #include "chrome/browser/sessions/tab_restore_service.h"
@@ -187,7 +187,7 @@
   }
 
   // |window| may belong to a shell window.
-  apps::ShellWindow* shell_window = extensions::ShellWindowRegistry::
+  apps::ShellWindow* shell_window = apps::ShellWindowRegistry::
       GetShellWindowForNativeWindowAnyProfile(window);
   if (shell_window) {
     if (is_fullscreen)
diff --git a/chrome/browser/ui/ash/chrome_shell_delegate_chromeos.cc b/chrome/browser/ui/ash/chrome_shell_delegate_chromeos.cc
index d8cb05b..e8194fa 100644
--- a/chrome/browser/ui/ash/chrome_shell_delegate_chromeos.cc
+++ b/chrome/browser/ui/ash/chrome_shell_delegate_chromeos.cc
@@ -5,6 +5,7 @@
 #include "chrome/browser/ui/ash/chrome_shell_delegate.h"
 
 #include "apps/native_app_window.h"
+#include "apps/shell_window_registry.h"
 #include "ash/keyboard_overlay/keyboard_overlay_view.h"
 #include "ash/wm/window_util.h"
 #include "base/command_line.h"
@@ -20,7 +21,6 @@
 #include "chrome/browser/chromeos/system/ash_system_tray_delegate.h"
 #include "chrome/browser/extensions/api/terminal/terminal_extension_helper.h"
 #include "chrome/browser/extensions/extension_service.h"
-#include "chrome/browser/extensions/shell_window_registry.h"
 #include "chrome/browser/profiles/profile_manager.h"
 #include "chrome/browser/speech/tts_controller.h"
 #include "chrome/browser/ui/ash/caps_lock_delegate_chromeos.h"
@@ -45,7 +45,7 @@
 
 bool ChromeShellDelegate::IsFirstRunAfterBoot() const {
   return CommandLine::ForCurrentProcess()->HasSwitch(
-      chromeos::switches::kFirstBoot);
+      chromeos::switches::kFirstExecAfterBoot);
 }
 
 void ChromeShellDelegate::PreInit() {
@@ -70,9 +70,9 @@
     }
   } else {
     Profile* const profile = ProfileManager::GetDefaultProfileOrOffTheRecord();
-    const extensions::ShellWindowRegistry* const registry =
-        extensions::ShellWindowRegistry::Get(profile);
-    const extensions::ShellWindowRegistry::ShellWindowList list =
+    const apps::ShellWindowRegistry* const registry =
+        apps::ShellWindowRegistry::Get(profile);
+    const apps::ShellWindowRegistry::ShellWindowList list =
         registry->GetShellWindowsForApp(kFileBrowserDomain);
     if (list.empty()) {
       // Open the new window.
diff --git a/chrome/browser/ui/ash/launcher/browser_shortcut_launcher_item_controller.cc b/chrome/browser/ui/ash/launcher/browser_shortcut_launcher_item_controller.cc
index 11bdcca..61a3e59 100644
--- a/chrome/browser/ui/ash/launcher/browser_shortcut_launcher_item_controller.cc
+++ b/chrome/browser/ui/ash/launcher/browser_shortcut_launcher_item_controller.cc
@@ -45,6 +45,10 @@
       profile_(profile) {
 }
 
+BrowserShortcutLauncherItemController::
+    ~BrowserShortcutLauncherItemController() {
+}
+
 string16 BrowserShortcutLauncherItemController::GetTitle() {
   return l10n_util::GetStringUTF16(IDS_PRODUCT_NAME);
 }
diff --git a/chrome/browser/ui/ash/launcher/browser_shortcut_launcher_item_controller.h b/chrome/browser/ui/ash/launcher/browser_shortcut_launcher_item_controller.h
index 7d30b8e..4454b71 100644
--- a/chrome/browser/ui/ash/launcher/browser_shortcut_launcher_item_controller.h
+++ b/chrome/browser/ui/ash/launcher/browser_shortcut_launcher_item_controller.h
@@ -23,9 +23,10 @@
 class BrowserShortcutLauncherItemController : public LauncherItemController {
  public:
   BrowserShortcutLauncherItemController(
-      ChromeLauncherControllerPerApp* controller, Profile* profile);
+      ChromeLauncherControllerPerApp* controller,
+      Profile* profile);
 
-  virtual ~BrowserShortcutLauncherItemController() {}
+  virtual ~BrowserShortcutLauncherItemController();
 
   // LauncherItemController overrides:
   virtual string16 GetTitle() OVERRIDE;
diff --git a/chrome/browser/ui/ash/launcher/chrome_launcher_controller_browsertest.cc b/chrome/browser/ui/ash/launcher/chrome_launcher_controller_browsertest.cc
index 1cae4cc..801538a 100644
--- a/chrome/browser/ui/ash/launcher/chrome_launcher_controller_browsertest.cc
+++ b/chrome/browser/ui/ash/launcher/chrome_launcher_controller_browsertest.cc
@@ -6,6 +6,7 @@
 
 #include "apps/native_app_window.h"
 #include "apps/shell_window.h"
+#include "apps/shell_window_registry.h"
 #include "ash/ash_switches.h"
 #include "ash/launcher/launcher.h"
 #include "ash/launcher/launcher_model.h"
@@ -25,7 +26,6 @@
 #include "chrome/browser/extensions/extension_system.h"
 #include "chrome/browser/extensions/extension_test_message_listener.h"
 #include "chrome/browser/extensions/platform_app_browsertest_util.h"
-#include "chrome/browser/extensions/shell_window_registry.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_commands.h"
diff --git a/chrome/browser/ui/ash/launcher/chrome_launcher_controller_per_app_browsertest.cc b/chrome/browser/ui/ash/launcher/chrome_launcher_controller_per_app_browsertest.cc
index 8c0cfba..248b19a 100644
--- a/chrome/browser/ui/ash/launcher/chrome_launcher_controller_per_app_browsertest.cc
+++ b/chrome/browser/ui/ash/launcher/chrome_launcher_controller_per_app_browsertest.cc
@@ -6,6 +6,7 @@
 
 #include "apps/native_app_window.h"
 #include "apps/shell_window.h"
+#include "apps/shell_window_registry.h"
 #include "ash/ash_switches.h"
 #include "ash/display/display_controller.h"
 #include "ash/launcher/launcher.h"
@@ -26,7 +27,6 @@
 #include "chrome/browser/extensions/extension_system.h"
 #include "chrome/browser/extensions/extension_test_message_listener.h"
 #include "chrome/browser/extensions/platform_app_browsertest_util.h"
-#include "chrome/browser/extensions/shell_window_registry.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/app_list/app_list_service.h"
 #include "chrome/browser/ui/ash/launcher/browser_shortcut_launcher_item_controller.h"
@@ -72,16 +72,16 @@
 };
 
 class TestShellWindowRegistryObserver
-    : public extensions::ShellWindowRegistry::Observer {
+    : public apps::ShellWindowRegistry::Observer {
  public:
   explicit TestShellWindowRegistryObserver(Profile* profile)
       : profile_(profile),
         icon_updates_(0) {
-    extensions::ShellWindowRegistry::Get(profile_)->AddObserver(this);
+    apps::ShellWindowRegistry::Get(profile_)->AddObserver(this);
   }
 
   virtual ~TestShellWindowRegistryObserver() {
-    extensions::ShellWindowRegistry::Get(profile_)->RemoveObserver(this);
+    apps::ShellWindowRegistry::Get(profile_)->RemoveObserver(this);
   }
 
   // Overridden from ShellWindowRegistry::Observer:
diff --git a/chrome/browser/ui/ash/launcher/shell_window_launcher_controller.cc b/chrome/browser/ui/ash/launcher/shell_window_launcher_controller.cc
index 779a8f9..618397c 100644
--- a/chrome/browser/ui/ash/launcher/shell_window_launcher_controller.cc
+++ b/chrome/browser/ui/ash/launcher/shell_window_launcher_controller.cc
@@ -28,7 +28,7 @@
 ShellWindowLauncherController::ShellWindowLauncherController(
     ChromeLauncherController* owner)
     : owner_(owner),
-      registry_(extensions::ShellWindowRegistry::Get(owner->profile())),
+      registry_(apps::ShellWindowRegistry::Get(owner->profile())),
       activation_client_(NULL) {
   registry_->AddObserver(this);
   if (ash::Shell::HasInstance()) {
diff --git a/chrome/browser/ui/ash/launcher/shell_window_launcher_controller.h b/chrome/browser/ui/ash/launcher/shell_window_launcher_controller.h
index c47c357..3669f72 100644
--- a/chrome/browser/ui/ash/launcher/shell_window_launcher_controller.h
+++ b/chrome/browser/ui/ash/launcher/shell_window_launcher_controller.h
@@ -9,7 +9,7 @@
 #include <map>
 #include <string>
 
-#include "chrome/browser/extensions/shell_window_registry.h"
+#include "apps/shell_window_registry.h"
 #include "ui/aura/client/activation_change_observer.h"
 #include "ui/aura/window_observer.h"
 
@@ -34,7 +34,7 @@
 // aura window manager. It handles adding and removing launcher items from
 // ChromeLauncherController.
 class ShellWindowLauncherController
-    : public extensions::ShellWindowRegistry::Observer,
+    : public apps::ShellWindowRegistry::Observer,
       public aura::WindowObserver,
       public aura::client::ActivationChangeObserver {
  public:
@@ -68,7 +68,7 @@
   ShellWindowLauncherItemController* ControllerForWindow(aura::Window* window);
 
   ChromeLauncherController* owner_;
-  extensions::ShellWindowRegistry* registry_;  // Unowned convenience pointer
+  apps::ShellWindowRegistry* registry_;  // Unowned convenience pointer
   aura::client::ActivationClient* activation_client_;
 
   // Map of app launcher id to controller.
diff --git a/chrome/browser/ui/ash/screenshot_taker.cc b/chrome/browser/ui/ash/screenshot_taker.cc
index 548e93f..f1764fb 100644
--- a/chrome/browser/ui/ash/screenshot_taker.cc
+++ b/chrome/browser/ui/ash/screenshot_taker.cc
@@ -39,6 +39,7 @@
 #include "chrome/browser/chromeos/login/user_manager.h"
 #include "chrome/browser/notifications/desktop_notification_service.h"
 #include "chrome/browser/notifications/desktop_notification_service_factory.h"
+#include "chromeos/login/login_state.h"
 #endif
 
 namespace {
@@ -352,6 +353,12 @@
     const base::FilePath& screenshot_path) {
   DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
 #if defined(OS_CHROMEOS)
+  // Do not show a notification that a screenshot was taken while no user is
+  // logged in, since it is confusing for the user to get a message about it
+  // after he logs in (crbug.com/235217).
+  if (!chromeos::LoginState::Get()->IsUserLoggedIn())
+    return;
+
   // TODO(sschmitz): make this work for Windows.
   DesktopNotificationService* const service =
       DesktopNotificationServiceFactory::GetForProfile(GetProfile());
diff --git a/chrome/browser/ui/ash/screenshot_taker_unittest.cc b/chrome/browser/ui/ash/screenshot_taker_unittest.cc
index a35339a..f27b97a 100644
--- a/chrome/browser/ui/ash/screenshot_taker_unittest.cc
+++ b/chrome/browser/ui/ash/screenshot_taker_unittest.cc
@@ -22,6 +22,10 @@
 #include "ui/aura/root_window.h"
 #include "ui/message_center/message_center_switches.h"
 
+#if defined(OS_CHROMEOS)
+#include "chromeos/login/login_state.h"
+#endif
+
 namespace ash {
 namespace test {
 
@@ -94,6 +98,12 @@
 };
 
 TEST_F(ScreenshotTakerTest, TakeScreenshot) {
+#if defined(OS_CHROMEOS)
+  // Note that within the test framework the LoginState object will always
+  // claim that the user did log in.
+  ASSERT_FALSE(chromeos::LoginState::IsInitialized());
+  chromeos::LoginState::Initialize();
+#endif
   scoped_ptr<TestingProfileManager> profile_manager(
       new TestingProfileManager(TestingBrowserProcess::GetGlobal()));
   ASSERT_TRUE(profile_manager->SetUp());
@@ -127,6 +137,10 @@
 
   if (ScreenshotTakerObserver::SCREENSHOT_SUCCESS == screenshot_result_)
     EXPECT_TRUE(base::PathExists(screenshot_path_));
+
+#if defined(OS_CHROMEOS)
+  chromeos::LoginState::Shutdown();
+#endif
 }
 
 }  // namespace test
diff --git a/chrome/browser/ui/auto_login_prompter.cc b/chrome/browser/ui/auto_login_prompter.cc
index f77cbb1..9d9bff0 100644
--- a/chrome/browser/ui/auto_login_prompter.cc
+++ b/chrome/browser/ui/auto_login_prompter.cc
@@ -11,12 +11,10 @@
 #include "chrome/browser/google/google_url_tracker.h"
 #include "chrome/browser/infobars/infobar_service.h"
 #include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/signin/profile_oauth2_token_service.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/signin/token_service.h"
-#include "chrome/browser/signin/token_service_factory.h"
-#include "chrome/browser/sync/profile_sync_service.h"
-#include "chrome/browser/sync/profile_sync_service_factory.h"
 #include "chrome/browser/tab_contents/tab_util.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/common/pref_names.h"
@@ -32,14 +30,10 @@
 namespace {
 
 bool FetchUsernameThroughSigninManager(Profile* profile, std::string* output) {
-  // In an incognito window, there may not be a profile sync service and/or
-  // signin manager.
-  if (!ProfileSyncServiceFactory::GetInstance()->HasProfileSyncService(
-      profile)) {
-    return false;
-  }
-
-  if (!TokenServiceFactory::GetForProfile(profile)->AreCredentialsValid())
+  // In an incognito window these services are not available.
+  ProfileOAuth2TokenService* token_service =
+      ProfileOAuth2TokenServiceFactory::GetForProfile(profile);
+  if (!token_service || !token_service->RefreshTokenIsAvailable())
     return false;
 
   SigninManagerBase* signin_manager =
diff --git a/chrome/browser/ui/autofill/OWNERS b/chrome/browser/ui/autofill/OWNERS
index b05d196..8c68959 100644
--- a/chrome/browser/ui/autofill/OWNERS
+++ b/chrome/browser/ui/autofill/OWNERS
@@ -3,6 +3,7 @@
 
 per-file autofill_dialog*=dbeam@chromium.org
 per-file data_model*=dbeam@chromium.org
+per-file *credit_card_bubble*=dbeam@chromium.org
 
 # Temporary owner, for refactoring changes only.
 joi@chromium.org
diff --git a/chrome/browser/ui/autofill/autofill_credit_card_bubble.cc b/chrome/browser/ui/autofill/autofill_credit_card_bubble.cc
deleted file mode 100644
index 133de0a..0000000
--- a/chrome/browser/ui/autofill/autofill_credit_card_bubble.cc
+++ /dev/null
@@ -1,23 +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/ui/autofill/autofill_credit_card_bubble.h"
-
-namespace autofill {
-
-// static
-const int AutofillCreditCardBubble::kContentWidth = 300;
-
-AutofillCreditCardBubble::~AutofillCreditCardBubble() {}
-
-#if !defined(TOOLKIT_VIEWS)
-// static
-base::WeakPtr<AutofillCreditCardBubble> AutofillCreditCardBubble::Create(
-    const base::WeakPtr<AutofillCreditCardBubbleController>& controller) {
-  // TODO(dbeam): make a bubble on all applicable platforms.
-  return base::WeakPtr<AutofillCreditCardBubble>();
-}
-#endif
-
-}  // namespace autofill
diff --git a/chrome/browser/ui/autofill/autofill_credit_card_bubble.h b/chrome/browser/ui/autofill/autofill_credit_card_bubble.h
deleted file mode 100644
index 2ef632a..0000000
--- a/chrome/browser/ui/autofill/autofill_credit_card_bubble.h
+++ /dev/null
@@ -1,49 +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_UI_AUTOFILL_AUTOFILL_CREDIT_CARD_BUBBLE_H_
-#define CHROME_BROWSER_UI_AUTOFILL_AUTOFILL_CREDIT_CARD_BUBBLE_H_
-
-#include "base/memory/weak_ptr.h"
-
-namespace autofill {
-
-class AutofillCreditCardBubbleController;
-
-////////////////////////////////////////////////////////////////////////////////
-//
-// AutofillCreditCardBubble
-//
-//  An interface to be implemented on each platform to show a bubble after the
-//  Autofill dialog is sucessfully submitted. Shows anchored to an icon that
-//  looks like a credit card or the Google Wallet logo in the omnibox. Hidden
-//  when focus is lost.
-//
-////////////////////////////////////////////////////////////////////////////////
-class AutofillCreditCardBubble {
- public:
-  // The preferred size of the bubble's contents.
-  static const int kContentWidth;
-
-  virtual ~AutofillCreditCardBubble();
-
-  // Visually reveals the dialog bubble.
-  virtual void Show() = 0;
-
-  // Hides the bubble from view.
-  virtual void Hide() = 0;
-
-  // Returns whether the bubble is currently in the process of hiding itself.
-  virtual bool IsHiding() const = 0;
-
-  // Creates a bubble view that's operated by |controller| and owned by the
-  // platform's widget or view management framework. |controller| is invalid
-  // while the bubble is closing.
-  static base::WeakPtr<AutofillCreditCardBubble> Create(
-      const base::WeakPtr<AutofillCreditCardBubbleController>& controller);
-};
-
-}  // namespace autofill
-
-#endif  // CHROME_BROWSER_UI_AUTOFILL_AUTOFILL_CREDIT_CARD_BUBBLE_H_
diff --git a/chrome/browser/ui/autofill/autofill_credit_card_bubble_controller.cc b/chrome/browser/ui/autofill/autofill_credit_card_bubble_controller.cc
deleted file mode 100644
index 5d79a69..0000000
--- a/chrome/browser/ui/autofill/autofill_credit_card_bubble_controller.cc
+++ /dev/null
@@ -1,335 +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/ui/autofill/autofill_credit_card_bubble_controller.h"
-
-#include <climits>
-#include <string>
-
-#include "base/prefs/pref_service.h"
-#include "base/strings/string_split.h"
-#include "base/strings/utf_string_conversions.h"
-#include "chrome/browser/browser_process.h"
-#include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/ui/autofill/autofill_credit_card_bubble.h"
-#include "chrome/browser/ui/autofill/tab_autofill_manager_delegate.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/omnibox/location_bar.h"
-#include "chrome/browser/ui/tabs/tab_strip_model.h"
-#include "chrome/common/pref_names.h"
-#include "components/user_prefs/pref_registry_syncable.h"
-#include "content/public/browser/navigation_details.h"
-#include "content/public/browser/navigation_entry.h"
-#include "content/public/browser/web_contents.h"
-#include "grit/generated_resources.h"
-#include "grit/theme_resources.h"
-#include "grit/webkit_resources.h"
-#include "ui/base/l10n/l10n_util.h"
-#include "ui/base/range/range.h"
-#include "ui/base/resource/resource_bundle.h"
-#include "ui/gfx/image/image.h"
-
-DEFINE_WEB_CONTENTS_USER_DATA_KEY(autofill::AutofillCreditCardBubbleController);
-
-namespace autofill {
-
-namespace {
-
-// TODO(dbeam): add back a sensible limit once it's decided or remove
-// kMaxGeneratedCardTimesToShow if this behavior is finalized.
-static const int kMaxGeneratedCardTimesToShow = INT_MAX;
-static const base::char16 kRangeSeparator = '|';
-static const char kWalletGeneratedCardLearnMoreLink[] =
-    "http://support.google.com/wallet/bin/answer.py?hl=en&answer=2740044";
-
-AutofillCreditCardBubbleController* GetOrCreate(content::WebContents* wc) {
-  AutofillCreditCardBubbleController::CreateForWebContents(wc);
-  return AutofillCreditCardBubbleController::FromWebContents(wc);
-}
-
-}  // namespace
-
-AutofillCreditCardBubbleController::AutofillCreditCardBubbleController(
-    content::WebContents* web_contents)
-    : WebContentsObserver(web_contents),
-      web_contents_(web_contents),
-      should_show_anchor_(true),
-      weak_ptr_factory_(this) {}
-
-AutofillCreditCardBubbleController::~AutofillCreditCardBubbleController() {
-  // In the case that the tab is closed, the controller can be deleted while the
-  // bubble is showing. Always calling |Hide()| ensures the bubble is closed.
-  Hide();
-}
-
-// static
-void AutofillCreditCardBubbleController::RegisterUserPrefs(
-    user_prefs::PrefRegistrySyncable* registry) {
-  registry->RegisterIntegerPref(
-      ::prefs::kAutofillGeneratedCardBubbleTimesShown,
-      0,
-      user_prefs::PrefRegistrySyncable::SYNCABLE_PREF);
-}
-
-// static
-void AutofillCreditCardBubbleController::ShowGeneratedCardUI(
-    content::WebContents* contents,
-    const base::string16& fronting_card_name,
-    const base::string16& backing_card_name) {
-  GetOrCreate(contents)->ShowAsGeneratedCardBubble(fronting_card_name,
-                                                   backing_card_name);
-}
-
-// static
-void AutofillCreditCardBubbleController::ShowNewCardSavedBubble(
-    content::WebContents* contents,
-    const base::string16& new_card_name) {
-  GetOrCreate(contents)->ShowAsNewCardSavedBubble(new_card_name);
-}
-
-void AutofillCreditCardBubbleController::DidNavigateMainFrame(
-    const content::LoadCommittedDetails& details,
-    const content::FrameNavigateParams& params) {
-  if (details.entry &&
-      !content::PageTransitionIsRedirect(details.entry->GetTransitionType())) {
-    should_show_anchor_ = false;
-    UpdateAnchor();
-    web_contents()->RemoveUserData(UserDataKey());
-    // |this| is now deleted.
-  }
-}
-
-bool AutofillCreditCardBubbleController::IsHiding() const {
-  return bubble_ && bubble_->IsHiding();
-}
-
-gfx::Image AutofillCreditCardBubbleController::AnchorIcon() const {
-  if (!should_show_anchor_)
-    return gfx::Image();
-
-  return ui::ResourceBundle::GetSharedInstance().GetImageNamed(
-      IsGeneratedCardBubble() ? IDR_WALLET_ICON : IDR_AUTOFILL_CC_GENERIC);
-}
-
-base::string16 AutofillCreditCardBubbleController::BubbleTitle() const {
-  return !IsGeneratedCardBubble() ?
-      ASCIIToUTF16("Lorem ipsum, savum cardum") :
-      l10n_util::GetStringUTF16(
-          IDS_AUTOFILL_CREDIT_CARD_BUBBLE_GENERATED_TITLE);
-}
-
-base::string16 AutofillCreditCardBubbleController::BubbleText() const {
-  DCHECK(IsSetUp());
-  return bubble_text_;
-}
-
-const std::vector<ui::Range>& AutofillCreditCardBubbleController::
-    BubbleTextRanges() const {
-  DCHECK(IsSetUp());
-  return bubble_text_ranges_;
-}
-
-base::string16 AutofillCreditCardBubbleController::LinkText() const {
-  return l10n_util::GetStringUTF16(
-      IsGeneratedCardBubble() ? IDS_LEARN_MORE :
-                                IDS_AUTOFILL_CREDIT_CARD_BUBBLE_MANAGE_CARDS);
-}
-
-void AutofillCreditCardBubbleController::OnAnchorClicked() {
-  Show(true);
-}
-
-void AutofillCreditCardBubbleController::OnLinkClicked() {
-  if (IsGeneratedCardBubble()) {
-#if !defined(OS_ANDROID)
-    // Open a new tab to the Online Wallet help link.
-    chrome::NavigateParams params(
-        chrome::FindBrowserWithWebContents(web_contents()),
-        GURL(kWalletGeneratedCardLearnMoreLink),
-        content::PAGE_TRANSITION_AUTO_BOOKMARK);
-    params.disposition = NEW_FOREGROUND_TAB;
-    chrome::Navigate(&params);
-#else
-  // TODO(dbeam): implement.
-#endif
-  } else {
-    TabAutofillManagerDelegate::FromWebContents(web_contents())->
-        ShowAutofillSettings();
-  }
-  Hide();
-}
-
-base::WeakPtr<AutofillCreditCardBubbleController>
-    AutofillCreditCardBubbleController::GetWeakPtr() {
-  return weak_ptr_factory_.GetWeakPtr();
-}
-
-base::WeakPtr<AutofillCreditCardBubble> AutofillCreditCardBubbleController::
-    CreateBubble() {
-  return AutofillCreditCardBubble::Create(GetWeakPtr());
-}
-
-base::WeakPtr<AutofillCreditCardBubble> AutofillCreditCardBubbleController::
-    bubble() {
-  return bubble_;
-}
-
-bool AutofillCreditCardBubbleController::CanShow() const {
-#if !defined(OS_ANDROID)
-  Browser* browser = chrome::FindBrowserWithWebContents(web_contents());
-  return web_contents() == browser->tab_strip_model()->GetActiveWebContents();
-#else
-  return true;
-#endif
-}
-
-bool AutofillCreditCardBubbleController::ShouldDisplayBubbleInitially() const {
-  Profile* profile = Profile::FromBrowserContext(
-      web_contents_->GetBrowserContext());
-  int times_shown = profile->GetPrefs()->GetInteger(
-      ::prefs::kAutofillGeneratedCardBubbleTimesShown);
-  return times_shown < kMaxGeneratedCardTimesToShow;
-}
-
-void AutofillCreditCardBubbleController::ShowAsGeneratedCardBubble(
-    const base::string16& fronting_card_name,
-    const base::string16& backing_card_name) {
-  Reset();
-
-  DCHECK(!fronting_card_name.empty());
-  DCHECK(!backing_card_name.empty());
-  fronting_card_name_ = fronting_card_name;
-  backing_card_name_ = backing_card_name;
-
-  SetUp();
-
-  if (ShouldDisplayBubbleInitially())
-    Show(false);
-}
-
-void AutofillCreditCardBubbleController::ShowAsNewCardSavedBubble(
-    const base::string16& new_card_name) {
-  Reset();
-
-  DCHECK(!new_card_name.empty());
-  new_card_name_ = new_card_name;
-
-  SetUp();
-  Show(false);
-}
-
-void AutofillCreditCardBubbleController::Reset() {
-  Hide();
-
-  // Clear any generated state or stored |ShowAs*()| arguments.
-  fronting_card_name_.clear();
-  backing_card_name_.clear();
-  new_card_name_.clear();
-  bubble_text_.clear();
-  bubble_text_ranges_.clear();
-
-  DCHECK(!IsSetUp());
-}
-
-void AutofillCreditCardBubbleController::SetUp() {
-  base::string16 full_text;
-  if (IsGeneratedCardBubble()) {
-    full_text = l10n_util::GetStringFUTF16(
-        IDS_AUTOFILL_CREDIT_CARD_BUBBLE_GENERATED_TEXT,
-        fronting_card_name_,
-        backing_card_name_);
-  } else {
-    full_text = ReplaceStringPlaceholders(
-        ASCIIToUTF16("Lorem ipsum, savum cardem |$1|. Replacem before launch."),
-        new_card_name_,
-        NULL);
-  }
-
-  // Split the full text on '|' to highlight certain parts. For example, "sly"
-  // and "jumped" would be bolded in "The |sly| fox |jumped| over the lazy dog".
-  std::vector<base::string16> pieces;
-  base::SplitStringDontTrim(full_text, kRangeSeparator, &pieces);
-
-  while (!pieces.empty()) {
-    base::string16 piece = pieces.front();
-
-    // Every second piece should be bolded. Because |base::SplitString*()|
-    // leaves an empty "" even if '|' is the first character, this is guaranteed
-    // to work for "|highlighting| starts here". Ignore empty pieces because
-    // there's nothing to highlight.
-    if (!piece.empty() && pieces.size() % 2 == 0) {
-      const size_t start = bubble_text_.size();
-      bubble_text_ranges_.push_back(ui::Range(start, start + piece.size()));
-    }
-
-    // Append the piece whether it's bolded or not and move on to the next one.
-    bubble_text_.append(piece);
-    pieces.erase(pieces.begin(), pieces.begin() + 1);
-  }
-
-  UpdateAnchor();
-  DCHECK(IsSetUp());
-}
-
-bool AutofillCreditCardBubbleController::IsSetUp() const {
-  // Because |bubble_text_| should never be empty after |SetUp()|, and all
-  // translations should have some text highlighting (i.e. "some |pipes|"),
-  // if there is text there should be text ranges as well. Sanity check this.
-  DCHECK_EQ(bubble_text_.empty(), bubble_text_ranges_.empty());
-  return !bubble_text_.empty();
-}
-
-bool AutofillCreditCardBubbleController::IsGeneratedCardBubble() const {
-  // Do a quick sanity check to ensure that the bubble isn't partially set up as
-  // the other type (i.e. a fronting card and a new card doesn't make sense).
-  DCHECK_EQ(fronting_card_name_.empty(), backing_card_name_.empty());
-  DCHECK_NE(backing_card_name_.empty(), new_card_name_.empty());
-  return !fronting_card_name_.empty();
-}
-
-void AutofillCreditCardBubbleController::Show(bool was_anchor_click) {
-  if (!CanShow())
-    return;
-
-  bubble_ = CreateBubble();
-  if (!bubble_) {
-    // TODO(dbeam): Make a bubble on all applicable platforms.
-    return;
-  }
-
-  bubble_->Show();
-
-  if (IsGeneratedCardBubble() && !was_anchor_click) {
-    // If the bubble was an automatically created "you generated a card" bubble,
-    // count it as a show. If the user clicked the omnibox icon, don't count it.
-    PrefService* prefs = Profile::FromBrowserContext(
-        web_contents()->GetBrowserContext())->GetPrefs();
-    prefs->SetInteger(::prefs::kAutofillGeneratedCardBubbleTimesShown,
-        prefs->GetInteger(::prefs::kAutofillGeneratedCardBubbleTimesShown) + 1);
-  }
-}
-
-void AutofillCreditCardBubbleController::UpdateAnchor() {
-#if !defined(OS_ANDROID)
-  Browser* browser = chrome::FindBrowserWithWebContents(web_contents());
-  if (browser && browser->window() && browser->window()->GetLocationBar())
-    browser->window()->GetLocationBar()->UpdateAutofillCreditCardView();
-#else
-  // TODO(dbeam): implement.
-#endif
-}
-
-void AutofillCreditCardBubbleController::Hide() {
-  // Sever |bubble_|'s reference to the controller and hide (if it exists).
-  weak_ptr_factory_.InvalidateWeakPtrs();
-
-  if (bubble_ && !bubble_->IsHiding())
-    bubble_->Hide();
-
-  DCHECK(!bubble_ || bubble_->IsHiding());
-}
-
-}  // namespace autofill
diff --git a/chrome/browser/ui/autofill/autofill_credit_card_bubble_controller.h b/chrome/browser/ui/autofill/autofill_credit_card_bubble_controller.h
deleted file mode 100644
index dfe5b55..0000000
--- a/chrome/browser/ui/autofill/autofill_credit_card_bubble_controller.h
+++ /dev/null
@@ -1,195 +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_UI_AUTOFILL_AUTOFILL_CREDIT_CARD_BUBBLE_CONTROLLER_H_
-#define CHROME_BROWSER_UI_AUTOFILL_AUTOFILL_CREDIT_CARD_BUBBLE_CONTROLLER_H_
-
-#include <vector>
-
-#include "base/basictypes.h"
-#include "base/compiler_specific.h"
-#include "base/memory/weak_ptr.h"
-#include "base/strings/string16.h"
-#include "content/public/browser/web_contents_observer.h"
-#include "content/public/browser/web_contents_user_data.h"
-
-class Profile;
-
-namespace content {
-class WebContents;
-}
-
-namespace gfx {
-class Image;
-}
-
-namespace ui {
-class Range;
-}
-
-namespace user_prefs {
-class PrefRegistrySyncable;
-}
-
-namespace autofill {
-
-class AutofillCreditCardBubble;
-
-////////////////////////////////////////////////////////////////////////////////
-//
-// AutofillCreditCardBubbleController
-//
-//  A class to show a bubble after successfully submitting the Autofill dialog.
-//  The bubble is shown when a new credit card is saved locally or to explain
-//  generated Online Wallet cards to the user. This class does not own the shown
-//  bubble, but only has a weak reference to it (it is often owned by the native
-//  platform's ui toolkit).
-//
-////////////////////////////////////////////////////////////////////////////////
-class AutofillCreditCardBubbleController
-    : public content::WebContentsObserver,
-      public content::WebContentsUserData<AutofillCreditCardBubbleController> {
- public:
-  virtual ~AutofillCreditCardBubbleController();
-
-  // Registers preferences this class cares about.
-  static void RegisterUserPrefs(user_prefs::PrefRegistrySyncable* registry);
-
-  // Shows a clickable icon in the omnibox that informs the user about generated
-  // (fronting) cards and how they are used to bill their original (backing)
-  // card. Additionally, if |ShouldDisplayBubbleInitially()| is true, the bubble
-  // will be shown initially (doesn't require being clicked).
-  static void ShowGeneratedCardUI(content::WebContents* contents,
-                                  const base::string16& backing_card_name,
-                                  const base::string16& fronting_card_name);
-
-  // Show a bubble and clickable omnibox icon notifying the user that new credit
-  // card data has been saved. This bubble always shows initially.
-  static void ShowNewCardSavedBubble(content::WebContents* contents,
-                                     const base::string16& new_card_name);
-
-  // content::WebContentsObserver implementation.
-  virtual void DidNavigateMainFrame(
-      const content::LoadCommittedDetails& details,
-      const content::FrameNavigateParams& params) OVERRIDE;
-
-  // Returns whether |bubble_| is currently in the process of hiding.
-  bool IsHiding() const;
-
-  // The image that should be shown as an icon in the omnibox.
-  gfx::Image AnchorIcon() const;
-
-  // The title of the bubble. May be empty.
-  base::string16 BubbleTitle() const;
-
-  // The main text of the bubble.
-  base::string16 BubbleText() const;
-
-  // Ranges of text styles in the bubble's main content.
-  const std::vector<ui::Range>& BubbleTextRanges() const;
-
-  // The text of the link shown at the bubble of the bubble.
-  base::string16 LinkText() const;
-
-  // Called when the anchor for this bubble is clicked. Shows a new bubble.
-  void OnAnchorClicked();
-
-  // Called when the link at the bottom of the bubble is clicked. Opens and
-  // navigates a new tab to an informational page and hides the bubble.
-  void OnLinkClicked();
-
-  // The web contents that successfully submitted the Autofill dialog (causing
-  // this bubble to show).
-  content::WebContents* web_contents() { return web_contents_; }
-  const content::WebContents* web_contents() const { return web_contents_; }
-
- protected:
-  // Creates a bubble connected to |web_contents|. Its content will be based on
-  // which |ShowAs*()| method is called.
-  explicit AutofillCreditCardBubbleController(content::WebContents* contents);
-
-  // Returns a base::WeakPtr that references |this|. Exposed for testing.
-  base::WeakPtr<AutofillCreditCardBubbleController> GetWeakPtr();
-
-  // Creates and returns an Autofill credit card bubble. Exposed for testing.
-  virtual base::WeakPtr<AutofillCreditCardBubble> CreateBubble();
-
-  // Returns a weak reference to |bubble_|. May be invalid/NULL.
-  virtual base::WeakPtr<AutofillCreditCardBubble> bubble();
-
-  // Returns whether the bubble can currently show itself.
-  virtual bool CanShow() const;
-
-  // Whether the generated card bubble should be shown initially when showing
-  // the anchor icon. This does not affect whether the generated card's icon
-  // will show in the omnibox.
-  bool ShouldDisplayBubbleInitially() const;
-
-  // Show a bubble to educate the user about generated (fronting) cards and how
-  // they are used to bill their original (backing) card. Exposed for testing.
-  virtual void ShowAsGeneratedCardBubble(
-      const base::string16& backing_card_name,
-      const base::string16& fronting_card_name);
-
-  // Shows a bubble notifying the user that new credit card data has been saved.
-  // Exposed for testing.
-  virtual void ShowAsNewCardSavedBubble(const base::string16& new_card_name);
-
- private:
-  friend class content::WebContentsUserData<AutofillCreditCardBubbleController>;
-
-  // Nukes the state of this controller and hides |bubble_| (if it exists).
-  void Reset();
-
-  // Generates the correct bubble text and text highlighting ranges for the
-  // types of bubble being shown. Must be called before showing the bubble.
-  void SetUp();
-
-  // Returns whether the controller has been setup as a certain type of bubble.
-  bool IsSetUp() const;
-
-  // Returns whether the bubble is an educational bubble about generated cards.
-  bool IsGeneratedCardBubble() const;
-
-  // Hides any existing bubbles and creates and shows a new one. Called in
-  // response to successful Autofill dialog submission or anchor click.
-  void Show(bool was_anchor_click);
-
-  // Updates the omnibox icon that |bubble_| will be anchored to.
-  void UpdateAnchor();
-
-  // Hides |bubble_| (if it exists and isn't already hiding).
-  void Hide();
-
-  // The web contents associated with this bubble.
-  content::WebContents* const web_contents_;
-
-  // The newly saved credit card.
-  base::string16 new_card_name_;
-
-  // The generated credit card number and associated backing card.
-  base::string16 fronting_card_name_;
-  base::string16 backing_card_name_;
-
-  // Bubble contents text and text ranges generated in |SetUp()|.
-  base::string16 bubble_text_;
-  std::vector<ui::Range> bubble_text_ranges_;
-
-  // A bubble view that's created by calling either |Show*()| method; owned by
-  // the native widget/hierarchy, not this class (though this class must outlive
-  // |bubble_|). NULL in many cases.
-  base::WeakPtr<AutofillCreditCardBubble> bubble_;
-
-  // Whether the anchor should currently be showing.
-  bool should_show_anchor_;
-
-  // A weak pointer factory for |Create()|.
-  base::WeakPtrFactory<AutofillCreditCardBubbleController> weak_ptr_factory_;
-
-  DISALLOW_COPY_AND_ASSIGN(AutofillCreditCardBubbleController);
-};
-
-}  // namespace autofill
-
-#endif  // CHROME_BROWSER_UI_AUTOFILL_AUTOFILL_CREDIT_CARD_BUBBLE_CONTROLLER_H_
diff --git a/chrome/browser/ui/autofill/autofill_credit_card_bubble_controller_unittest.cc b/chrome/browser/ui/autofill/autofill_credit_card_bubble_controller_unittest.cc
deleted file mode 100644
index 63efafe..0000000
--- a/chrome/browser/ui/autofill/autofill_credit_card_bubble_controller_unittest.cc
+++ /dev/null
@@ -1,244 +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/basictypes.h"
-#include "base/compiler_specific.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/prefs/pref_service.h"
-#include "base/strings/string16.h"
-#include "base/strings/utf_string_conversions.h"
-#include "chrome/browser/ui/autofill/autofill_credit_card_bubble_controller.h"
-#include "chrome/browser/ui/autofill/test_autofill_credit_card_bubble.h"
-#include "chrome/common/pref_names.h"
-#include "chrome/test/base/testing_profile.h"
-#include "content/public/browser/web_contents.h"
-#include "content/public/common/page_transition_types.h"
-#include "content/public/test/test_browser_thread_bundle.h"
-#include "content/public/test/web_contents_tester.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "ui/base/range/range.h"
-
-#if defined(OS_WIN)
-#include "ui/base/win/scoped_ole_initializer.h"
-#endif
-
-namespace autofill {
-
-namespace {
-
-base::string16 BackingCard() {
-  return ASCIIToUTF16("Visa - 1111");
-}
-base::string16 FrontingCard() {
-  return ASCIIToUTF16("Mastercard - 4444");
-}
-base::string16 NewCard() {
-  return ASCIIToUTF16("Discover - 7777");
-}
-
-base::string16 RangeOfString(const base::string16& string,
-                             const ui::Range& range) {
-  return string.substr(range.start(), range.end() - range.start());
-}
-
-class TestAutofillCreditCardBubbleController
-    : public AutofillCreditCardBubbleController {
- public:
-  explicit TestAutofillCreditCardBubbleController(
-      content::WebContents* contents)
-      : AutofillCreditCardBubbleController(contents) {
-    contents->SetUserData(UserDataKey(), this);
-  }
-
-  virtual ~TestAutofillCreditCardBubbleController() {}
-
-  bool IsInstalled() const {
-    return web_contents()->GetUserData(UserDataKey()) == this;
-  }
-
-  TestAutofillCreditCardBubble* GetTestingBubble() {
-    return static_cast<TestAutofillCreditCardBubble*>(
-        AutofillCreditCardBubbleController::bubble().get());
-  }
-
- protected:
-  virtual base::WeakPtr<AutofillCreditCardBubble> CreateBubble() OVERRIDE {
-    return TestAutofillCreditCardBubble::Create(GetWeakPtr());
-  }
-
-  virtual bool CanShow() const OVERRIDE {
-    return true;
-  }
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(TestAutofillCreditCardBubbleController);
-};
-
-class AutofillCreditCardBubbleControllerTest : public testing::Test {
- public:
-  AutofillCreditCardBubbleControllerTest()
-      : test_web_contents_(
-            content::WebContentsTester::CreateTestWebContents(
-                profile(), NULL)) {}
-
-  virtual void SetUp() OVERRIDE {
-    // Attaches immediately to |test_web_contents_| so a test version will exist
-    // before a non-test version can be created.
-    new TestAutofillCreditCardBubbleController(test_web_contents_.get());
-    ASSERT_TRUE(controller()->IsInstalled());
-  }
-
- protected:
-  TestAutofillCreditCardBubbleController* controller() {
-    return static_cast<TestAutofillCreditCardBubbleController*>(
-        TestAutofillCreditCardBubbleController::FromWebContents(
-            test_web_contents_.get()));
-  }
-
-  int GeneratedCardBubbleTimesShown() {
-    return profile()->GetPrefs()->GetInteger(
-        ::prefs::kAutofillGeneratedCardBubbleTimesShown);
-  }
-
-  Profile* profile() { return &profile_; }
-
-  content::WebContentsTester* test_web_contents() {
-    return content::WebContentsTester::For(test_web_contents_.get());
-  }
-
-  void ShowGeneratedCardUI() {
-    ASSERT_TRUE(controller()->IsInstalled());
-    TestAutofillCreditCardBubbleController::ShowGeneratedCardUI(
-        test_web_contents_.get(), BackingCard(), FrontingCard());
-  }
-
-  void ShowNewCardSavedBubble() {
-    ASSERT_TRUE(controller()->IsInstalled());
-    TestAutofillCreditCardBubbleController::ShowNewCardSavedBubble(
-        test_web_contents_.get(), NewCard());
-  }
-
-  void Navigate() {
-    NavigateWithTransition(content::PAGE_TRANSITION_LINK);
-  }
-
-  void Redirect() {
-    NavigateWithTransition(content::PAGE_TRANSITION_CLIENT_REDIRECT);
-  }
-
- private:
-  void NavigateWithTransition(content::PageTransition trans) {
-    test_web_contents()->TestDidNavigate(
-        test_web_contents_->GetRenderViewHost(), 1, GURL("about:blank"), trans);
-  }
-
-  content::TestBrowserThreadBundle thread_bundle_;
-#if defined(OS_WIN)
-  // Without this there will be drag and drop failures. http://crbug.com/227221
-  ui::ScopedOleInitializer ole_initializer_;
-#endif
-  TestingProfile profile_;
-  scoped_ptr<content::WebContents> test_web_contents_;
-};
-
-}  // namespace
-
-TEST_F(AutofillCreditCardBubbleControllerTest, GeneratedCardBubbleTimesShown) {
-  ASSERT_EQ(0, GeneratedCardBubbleTimesShown());
-
-  // Ensure that showing the generated card UI bumps the persistent count.
-  ShowGeneratedCardUI();
-  EXPECT_EQ(1, GeneratedCardBubbleTimesShown());
-  EXPECT_TRUE(controller()->GetTestingBubble()->showing());
-
-  ShowGeneratedCardUI();
-  ShowGeneratedCardUI();
-  EXPECT_EQ(3, GeneratedCardBubbleTimesShown());
-  EXPECT_TRUE(controller()->GetTestingBubble()->showing());
-}
-
-TEST_F(AutofillCreditCardBubbleControllerTest, BubbleText) {
-  // Ensure that while showing the generated card UI that the bubble's text
-  // contains "Visa - 1111" and "Mastercard - 4444".
-  ShowGeneratedCardUI();
-  base::string16 generated_text = controller()->BubbleText();
-  EXPECT_NE(base::string16::npos, generated_text.find(BackingCard()));
-  EXPECT_NE(base::string16::npos, generated_text.find(FrontingCard()));
-  EXPECT_EQ(base::string16::npos, generated_text.find(NewCard()));
-
-  // Ensure that while showing the new card bubble that "Discover - 7777" is in
-  // the bubble text.
-  ShowNewCardSavedBubble();
-  base::string16 new_text = controller()->BubbleText();
-  EXPECT_NE(new_text, generated_text);
-  EXPECT_EQ(base::string16::npos, new_text.find(BackingCard()));
-  EXPECT_EQ(base::string16::npos, new_text.find(FrontingCard()));
-  EXPECT_NE(base::string16::npos, new_text.find(NewCard()));
-
-  // Make sure that |bubble_text_| is regenerated the same way in |Setup()|.
-  ShowGeneratedCardUI();
-  EXPECT_EQ(generated_text, controller()->BubbleText());
-
-  ShowNewCardSavedBubble();
-  EXPECT_EQ(new_text, controller()->BubbleText());
-}
-
-TEST_F(AutofillCreditCardBubbleControllerTest, BubbleTextRanges) {
-  // Check that the highlighted ranges in the bubble's text are correct.
-  ShowGeneratedCardUI();
-  base::string16 text = controller()->BubbleText();
-  std::vector<ui::Range> ranges = controller()->BubbleTextRanges();
-
-  ASSERT_EQ(2U, ranges.size());
-  EXPECT_EQ(BackingCard(), RangeOfString(text, ranges[0]));
-  EXPECT_EQ(FrontingCard(), RangeOfString(text, ranges[1]));
-
-  ShowNewCardSavedBubble();
-  text = controller()->BubbleText();
-  ranges = controller()->BubbleTextRanges();
-
-  ASSERT_EQ(1U, ranges.size());
-  EXPECT_EQ(NewCard(), RangeOfString(text, ranges[0]));
-}
-
-TEST_F(AutofillCreditCardBubbleControllerTest, HideOnNavigate) {
-  // When a user navigates away from a page (or refreshes) normally, the bubbles
-  // should be hidden.
-  EXPECT_FALSE(controller()->GetTestingBubble());
-  ShowGeneratedCardUI();
-  EXPECT_TRUE(controller()->GetTestingBubble()->showing());
-
-  Navigate();
-  EXPECT_FALSE(controller());
-
-  SetUp();
-
-  EXPECT_FALSE(controller()->GetTestingBubble());
-  ShowNewCardSavedBubble();
-  EXPECT_TRUE(controller()->GetTestingBubble()->showing());
-
-  Navigate();
-  EXPECT_FALSE(controller());
-}
-
-TEST_F(AutofillCreditCardBubbleControllerTest, StayOnRedirect) {
-  // If a page redirects right after submitting, the bubble should remain.
-  EXPECT_FALSE(controller()->GetTestingBubble());
-  ShowGeneratedCardUI();
-  EXPECT_TRUE(controller()->GetTestingBubble()->showing());
-
-  Redirect();
-  EXPECT_TRUE(controller()->GetTestingBubble()->showing());
-
-  SetUp();
-
-  EXPECT_FALSE(controller()->GetTestingBubble());
-  ShowNewCardSavedBubble();
-  EXPECT_TRUE(controller()->GetTestingBubble()->showing());
-
-  Redirect();
-  EXPECT_TRUE(controller()->GetTestingBubble()->showing());
-}
-
-}  // namespace autofill
diff --git a/chrome/browser/ui/autofill/autofill_dialog_common.cc b/chrome/browser/ui/autofill/autofill_dialog_common.cc
new file mode 100644
index 0000000..4cb8cd3
--- /dev/null
+++ b/chrome/browser/ui/autofill/autofill_dialog_common.cc
@@ -0,0 +1,224 @@
+// 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/ui/autofill/autofill_dialog_common.h"
+
+#include "components/autofill/core/browser/autofill_field.h"
+#include "components/autofill/core/browser/autofill_type.h"
+#include "grit/chromium_strings.h"
+#include "grit/component_strings.h"
+#include "grit/generated_resources.h"
+#include "grit/theme_resources.h"
+#include "grit/webkit_resources.h"
+
+namespace autofill {
+namespace common {
+
+// Returns true if |input| should be shown when |field_type| has been requested.
+bool InputTypeMatchesFieldType(const DetailInput& input,
+                               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();
+  if (server_type == CREDIT_CARD_EXP_4_DIGIT_YEAR ||
+      server_type == CREDIT_CARD_EXP_2_DIGIT_YEAR ||
+      server_type == CREDIT_CARD_EXP_DATE_4_DIGIT_YEAR ||
+      server_type == CREDIT_CARD_EXP_DATE_2_DIGIT_YEAR ||
+      server_type == CREDIT_CARD_EXP_MONTH) {
+    return input.type == CREDIT_CARD_EXP_4_DIGIT_YEAR ||
+           input.type == CREDIT_CARD_EXP_MONTH;
+  }
+
+  if (server_type == CREDIT_CARD_TYPE)
+    return input.type == CREDIT_CARD_NUMBER;
+
+  // Check the groups to distinguish billing types from shipping ones.
+  AutofillType input_type = AutofillType(input.type);
+  return input_type.GetStorableType() == server_type &&
+         input_type.group() == field_type.group();
+}
+
+// Returns true if |input| in the given |section| should be used for a
+// site-requested |field|.
+bool DetailInputMatchesField(DialogSection section,
+                             const DetailInput& input,
+                             const AutofillField& field) {
+  AutofillType field_type = field.Type();
+
+  // The credit card name is filled from the billing section's data.
+  if (field_type.GetStorableType() == CREDIT_CARD_NAME &&
+      (section == SECTION_BILLING || section == SECTION_CC_BILLING)) {
+    return input.type == NAME_BILLING_FULL;
+  }
+
+  return InputTypeMatchesFieldType(input, 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) {
+  for (size_t i = 0; i < template_size; ++i) {
+    const DetailInput* input = &input_template[i];
+    inputs->push_back(*input);
+  }
+}
+
+// Constructs |inputs| from template data for a given |dialog_section|.
+void BuildInputsForSection(DialogSection dialog_section,
+                           DetailInputs* inputs) {
+  const DetailInput kEmailInputs[] = {
+    { 1, EMAIL_ADDRESS, IDS_AUTOFILL_DIALOG_PLACEHOLDER_EMAIL },
+  };
+
+  const DetailInput kCCInputs[] = {
+    { 2, CREDIT_CARD_NUMBER, IDS_AUTOFILL_DIALOG_PLACEHOLDER_CARD_NUMBER },
+    { 3, CREDIT_CARD_EXP_MONTH, IDS_AUTOFILL_DIALOG_PLACEHOLDER_EXPIRY_MONTH },
+    { 3, CREDIT_CARD_EXP_4_DIGIT_YEAR,
+      IDS_AUTOFILL_DIALOG_PLACEHOLDER_EXPIRY_YEAR },
+    { 3, CREDIT_CARD_VERIFICATION_CODE, IDS_AUTOFILL_DIALOG_PLACEHOLDER_CVC,
+      1.5 },
+  };
+
+  const DetailInput kBillingInputs[] = {
+    { 4, NAME_BILLING_FULL, IDS_AUTOFILL_DIALOG_PLACEHOLDER_CARDHOLDER_NAME },
+    { 5, ADDRESS_BILLING_LINE1,
+      IDS_AUTOFILL_DIALOG_PLACEHOLDER_ADDRESS_LINE_1 },
+    { 6, ADDRESS_BILLING_LINE2,
+      IDS_AUTOFILL_DIALOG_PLACEHOLDER_ADDRESS_LINE_2 },
+    { 7, ADDRESS_BILLING_CITY,
+      IDS_AUTOFILL_DIALOG_PLACEHOLDER_LOCALITY },
+    // TODO(estade): state placeholder should depend on locale.
+    { 8, ADDRESS_BILLING_STATE, IDS_AUTOFILL_FIELD_LABEL_STATE },
+    { 8, ADDRESS_BILLING_ZIP,
+      IDS_AUTOFILL_DIALOG_PLACEHOLDER_POSTAL_CODE },
+    // We don't allow the user to change the country: http://crbug.com/247518
+    { -1, ADDRESS_BILLING_COUNTRY, 0 },
+    { 10, PHONE_BILLING_WHOLE_NUMBER,
+      IDS_AUTOFILL_DIALOG_PLACEHOLDER_PHONE_NUMBER },
+  };
+
+  const DetailInput kShippingInputs[] = {
+    { 11, NAME_FULL, IDS_AUTOFILL_DIALOG_PLACEHOLDER_ADDRESSEE_NAME },
+    { 12, ADDRESS_HOME_LINE1, IDS_AUTOFILL_DIALOG_PLACEHOLDER_ADDRESS_LINE_1 },
+    { 13, ADDRESS_HOME_LINE2, IDS_AUTOFILL_DIALOG_PLACEHOLDER_ADDRESS_LINE_2 },
+    { 14, ADDRESS_HOME_CITY, IDS_AUTOFILL_DIALOG_PLACEHOLDER_LOCALITY },
+    { 15, ADDRESS_HOME_STATE, IDS_AUTOFILL_FIELD_LABEL_STATE },
+    { 15, ADDRESS_HOME_ZIP, IDS_AUTOFILL_DIALOG_PLACEHOLDER_POSTAL_CODE },
+    { -1, ADDRESS_HOME_COUNTRY, 0 },
+    { 17, PHONE_HOME_WHOLE_NUMBER,
+      IDS_AUTOFILL_DIALOG_PLACEHOLDER_PHONE_NUMBER },
+  };
+
+  switch (dialog_section) {
+    case SECTION_EMAIL:
+      BuildInputs(kEmailInputs,
+                  arraysize(kEmailInputs),
+                  inputs);
+      break;
+
+    case SECTION_CC:
+      BuildInputs(kCCInputs,
+                  arraysize(kCCInputs),
+                  inputs);
+      break;
+
+    case SECTION_BILLING:
+      BuildInputs(kBillingInputs,
+                  arraysize(kBillingInputs),
+                  inputs);
+      break;
+
+    case SECTION_CC_BILLING:
+      BuildInputs(kCCInputs,
+                  arraysize(kCCInputs),
+                  inputs);
+      BuildInputs(kBillingInputs,
+                  arraysize(kBillingInputs),
+                  inputs);
+      break;
+
+    case SECTION_SHIPPING:
+      BuildInputs(kShippingInputs,
+                  arraysize(kShippingInputs),
+                  inputs);
+      break;
+  }
+}
+
+AutofillMetrics::DialogUiEvent DialogSectionToUiEditEvent(
+    DialogSection section) {
+  switch (section) {
+    case SECTION_EMAIL:
+      return AutofillMetrics::DIALOG_UI_EMAIL_EDIT_UI_SHOWN;
+
+    case SECTION_BILLING:
+      return AutofillMetrics::DIALOG_UI_BILLING_EDIT_UI_SHOWN;
+
+    case SECTION_CC_BILLING:
+      return AutofillMetrics::DIALOG_UI_CC_BILLING_EDIT_UI_SHOWN;
+
+    case SECTION_SHIPPING:
+      return AutofillMetrics::DIALOG_UI_SHIPPING_EDIT_UI_SHOWN;
+
+    case SECTION_CC:
+      return AutofillMetrics::DIALOG_UI_CC_EDIT_UI_SHOWN;
+  }
+
+  NOTREACHED();
+  return AutofillMetrics::NUM_DIALOG_UI_EVENTS;
+}
+
+AutofillMetrics::DialogUiEvent DialogSectionToUiItemAddedEvent(
+    DialogSection section) {
+  switch (section) {
+    case SECTION_EMAIL:
+      return AutofillMetrics::DIALOG_UI_EMAIL_ITEM_ADDED;
+
+    case SECTION_BILLING:
+      return AutofillMetrics::DIALOG_UI_BILLING_ITEM_ADDED;
+
+    case SECTION_CC_BILLING:
+      return AutofillMetrics::DIALOG_UI_CC_BILLING_ITEM_ADDED;
+
+    case SECTION_SHIPPING:
+      return AutofillMetrics::DIALOG_UI_SHIPPING_ITEM_ADDED;
+
+    case SECTION_CC:
+      return AutofillMetrics::DIALOG_UI_CC_ITEM_ADDED;
+  }
+
+  NOTREACHED();
+  return AutofillMetrics::NUM_DIALOG_UI_EVENTS;
+}
+
+AutofillMetrics::DialogUiEvent DialogSectionToUiSelectionChangedEvent(
+    DialogSection section) {
+  switch (section) {
+    case SECTION_EMAIL:
+      return AutofillMetrics::DIALOG_UI_EMAIL_SELECTED_SUGGESTION_CHANGED;
+
+    case SECTION_BILLING:
+      return AutofillMetrics::DIALOG_UI_BILLING_SELECTED_SUGGESTION_CHANGED;
+
+    case SECTION_CC_BILLING:
+      return AutofillMetrics::DIALOG_UI_CC_BILLING_SELECTED_SUGGESTION_CHANGED;
+
+    case SECTION_SHIPPING:
+      return AutofillMetrics::DIALOG_UI_SHIPPING_SELECTED_SUGGESTION_CHANGED;
+
+    case SECTION_CC:
+      return AutofillMetrics::DIALOG_UI_CC_SELECTED_SUGGESTION_CHANGED;
+  }
+
+  NOTREACHED();
+  return AutofillMetrics::NUM_DIALOG_UI_EVENTS;
+}
+
+}  // namespace common
+}  // namespace autofill
diff --git a/chrome/browser/ui/autofill/autofill_dialog_common.h b/chrome/browser/ui/autofill/autofill_dialog_common.h
new file mode 100644
index 0000000..be5261e
--- /dev/null
+++ b/chrome/browser/ui/autofill/autofill_dialog_common.h
@@ -0,0 +1,57 @@
+// 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_UI_AUTOFILL_AUTOFILL_DIALOG_COMMON_H_
+#define CHROME_BROWSER_UI_AUTOFILL_AUTOFILL_DIALOG_COMMON_H_
+
+#include "chrome/browser/ui/autofill/autofill_dialog_types.h"
+#include "components/autofill/core/browser/autofill_type.h"
+#include "components/autofill/core/browser/field_types.h"
+
+namespace autofill {
+class AutofillProfile;
+}
+
+namespace wallet {
+class Address;
+}
+
+namespace autofill {
+namespace common {
+
+// Returns true if |input| should be shown when |field_type| has been requested.
+bool InputTypeMatchesFieldType(const DetailInput& input,
+                               const AutofillType& field_type);
+
+// Returns true if |input| in the given |section| should be used for a
+// site-requested |field|.
+bool DetailInputMatchesField(DialogSection section,
+                             const DetailInput& input,
+                             const AutofillField& field);
+
+// Returns true if the |type| belongs to the CREDIT_CARD field type group.
+bool IsCreditCardType(ServerFieldType type);
+
+// Constructs |inputs| from template data for a given |dialog_section|.
+void BuildInputsForSection(DialogSection dialog_section, DetailInputs* inputs);
+
+// Returns the AutofillMetrics::DIALOG_UI_*_EDIT_UI_SHOWN metric corresponding
+// to the |section|.
+AutofillMetrics::DialogUiEvent DialogSectionToUiEditEvent(
+    DialogSection section);
+
+// Returns the AutofillMetrics::DIALOG_UI_*_ITEM_ADDED metric corresponding
+// to the |section|.
+AutofillMetrics::DialogUiEvent DialogSectionToUiItemAddedEvent(
+    DialogSection section);
+
+// Returns the AutofillMetrics::DIALOG_UI_*_ITEM_ADDED metric corresponding
+// to the |section|.
+AutofillMetrics::DialogUiEvent DialogSectionToUiSelectionChangedEvent(
+    DialogSection section);
+
+}  // namespace common
+}  // namespace autofill
+
+#endif  // CHROME_BROWSER_UI_AUTOFILL_AUTOFILL_DIALOG_COMMON_H_
diff --git a/chrome/browser/ui/autofill/autofill_dialog_controller.cc b/chrome/browser/ui/autofill/autofill_dialog_controller.cc
new file mode 100644
index 0000000..69a03a8
--- /dev/null
+++ b/chrome/browser/ui/autofill/autofill_dialog_controller.cc
@@ -0,0 +1,30 @@
+// 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/ui/autofill/autofill_dialog_controller.h"
+
+namespace autofill {
+
+AutofillDialogController::~AutofillDialogController() {}
+
+#if !defined(ENABLE_AUTOFILL_DIALOG)
+// static
+base::WeakPtr<AutofillDialogController>
+AutofillDialogController::Create(
+    content::WebContents* contents,
+    const FormData& form_structure,
+    const GURL& source_url,
+    const DialogType dialog_type,
+    const base::Callback<void(const FormStructure*,
+                              const std::string&)>& callback) {
+  NOTIMPLEMENTED();
+  return base::WeakPtr<AutofillDialogController>();
+}
+
+// static
+void AutofillDialogController::RegisterProfilePrefs(
+    user_prefs::PrefRegistrySyncable* registry) {}
+#endif  //  !defined(ENABLE_AUTOFILL_DIALOG)
+
+}  // namespace autofill
diff --git a/chrome/browser/ui/autofill/autofill_dialog_controller.h b/chrome/browser/ui/autofill/autofill_dialog_controller.h
new file mode 100644
index 0000000..819f654
--- /dev/null
+++ b/chrome/browser/ui/autofill/autofill_dialog_controller.h
@@ -0,0 +1,76 @@
+// 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_UI_AUTOFILL_AUTOFILL_DIALOG_CONTROLLER_H_
+#define CHROME_BROWSER_UI_AUTOFILL_AUTOFILL_DIALOG_CONTROLLER_H_
+
+#include <string>
+
+#include "base/callback.h"
+#include "base/memory/weak_ptr.h"
+#include "base/strings/string16.h"
+#include "chrome/browser/ui/autofill/autofill_dialog_types.h"
+#include "components/autofill/content/browser/autocheckout_steps.h"
+#include "components/autofill/core/browser/form_structure.h"
+
+class GURL;
+
+namespace content {
+class WebContents;
+}
+
+namespace user_prefs {
+class PrefRegistrySyncable;
+}
+
+namespace autofill {
+
+// This class defines the interface to the controller for TabAutofillManager.
+class AutofillDialogController {
+ public:
+  virtual ~AutofillDialogController();
+
+  // Creates the AutofillDialogController.
+  static base::WeakPtr<AutofillDialogController> Create(
+      content::WebContents* contents,
+      const FormData& form_structure,
+      const GURL& source_url,
+      const DialogType dialog_type,
+      const base::Callback<void(const FormStructure*,
+                                const std::string&)>& callback);
+
+  // Registers profile preferences.
+  static void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry);
+
+  // Shows the Autofill dialog.
+  virtual void Show() = 0;
+
+  // Hides the Autofill dialog.
+  virtual void Hide() = 0;
+
+  // Called when the tab hosting this dialog is activated by a user gesture.
+  // Used to trigger a refresh of the user's Wallet data.
+  virtual void TabActivated() = 0;
+
+  // Adds a step in the flow to the Autocheckout UI.
+  virtual void AddAutocheckoutStep(AutocheckoutStepType step_type) = 0;
+
+  // Updates the status of a step in the Autocheckout UI.
+  virtual void UpdateAutocheckoutStep(
+      AutocheckoutStepType step_type,
+      AutocheckoutStepStatus step_status) = 0;
+
+  // Called when there is an error in an active Autocheckout flow.
+  virtual void OnAutocheckoutError() = 0;
+
+  // Called when an Autocheckout flow completes successfully.
+  virtual void OnAutocheckoutSuccess() = 0;
+
+  // Returns the dialog type.
+  virtual DialogType GetDialogType() const = 0;
+};
+
+}  // namespace autofill
+
+#endif  // CHROME_BROWSER_UI_AUTOFILL_AUTOFILL_DIALOG_CONTROLLER_H_
diff --git a/chrome/browser/ui/autofill/autofill_dialog_controller_browsertest.cc b/chrome/browser/ui/autofill/autofill_dialog_controller_browsertest.cc
index 6aa1712..92a893d 100644
--- a/chrome/browser/ui/autofill/autofill_dialog_controller_browsertest.cc
+++ b/chrome/browser/ui/autofill/autofill_dialog_controller_browsertest.cc
@@ -140,7 +140,7 @@
         section, inputs, validation_type);
   }
 
-  // Saving to Chrome is tested in AutofillDialogController unit tests.
+  // Saving to Chrome is tested in AutofillDialogControllerImpl unit tests.
   // TODO(estade): test that the view defaults to saving to Chrome.
   virtual bool ShouldOfferToSaveInChrome() const OVERRIDE {
     return false;
@@ -301,7 +301,8 @@
     ExpectDomMessage("clicked");
 
     AutofillDialogControllerImpl* controller =
-        delegate->GetDialogControllerForTesting();
+        static_cast<AutofillDialogControllerImpl*>(
+            delegate->GetDialogControllerForTesting());
     DCHECK(controller);
     return controller;
   }
@@ -562,8 +563,17 @@
 
 // Tests that changing the value of a CC expiration date combobox works as
 // expected when Autofill is used to fill text inputs.
+//
+// Flaky on Win7, WinXP, and Win Aura.  http://crbug.com/270314.
+// TODO(groby): Enable this test on mac once AutofillDialogCocoa handles
+// comboboxes for GetTextContentsForInput. http://crbug.com/270205
+#if defined(OS_MACOSX) || defined(OS_WIN)
+#define MAYBE_FillComboboxFromAutofill DISABLED_FillComboboxFromAutofill
+#else
+#define MAYBE_FillComboboxFromAutofill FillComboboxFromAutofill
+#endif
 IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest,
-                       FillComboboxFromAutofill) {
+                       MAYBE_FillComboboxFromAutofill) {
   InitializeControllerOfType(DIALOG_TYPE_REQUEST_AUTOCOMPLETE);
 
   CreditCard card1;
@@ -793,7 +803,13 @@
       controller()->GetTestableView()->SubmitForTesting());
 }
 
-IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest, PreservedSections) {
+// Flaky on Win7, WinXP, and Win Aura.  http://crbug.com/270314.
+#if defined(OS_WIN)
+#define MAYBE_PreservedSections DISABLED_PreservedSections
+#else
+#define MAYBE_PreservedSections PreservedSections
+#endif
+IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest, MAYBE_PreservedSections) {
   InitializeControllerOfType(DIALOG_TYPE_REQUEST_AUTOCOMPLETE);
   controller()->set_use_validation(true);
 
diff --git a/chrome/browser/ui/autofill/autofill_dialog_controller_impl.cc b/chrome/browser/ui/autofill/autofill_dialog_controller_impl.cc
index 3a42603..0ac504d 100644
--- a/chrome/browser/ui/autofill/autofill_dialog_controller_impl.cc
+++ b/chrome/browser/ui/autofill/autofill_dialog_controller_impl.cc
@@ -10,6 +10,7 @@
 
 #include "apps/native_app_window.h"
 #include "apps/shell_window.h"
+#include "apps/shell_window_registry.h"
 #include "base/base64.h"
 #include "base/bind.h"
 #include "base/i18n/rtl.h"
@@ -22,12 +23,15 @@
 #include "base/time/time.h"
 #include "chrome/browser/autofill/personal_data_manager_factory.h"
 #include "chrome/browser/browser_process.h"
-#include "chrome/browser/extensions/shell_window_registry.h"
 #include "chrome/browser/prefs/scoped_user_pref_update.h"
 #include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/ui/autofill/autofill_credit_card_bubble_controller.h"
+#include "chrome/browser/ui/autofill/autofill_dialog_common.h"
 #include "chrome/browser/ui/autofill/autofill_dialog_view.h"
 #include "chrome/browser/ui/autofill/data_model_wrapper.h"
+#if !defined(OS_ANDROID)
+#include "chrome/browser/ui/autofill/generated_credit_card_bubble_controller.h"
+#include "chrome/browser/ui/autofill/new_credit_card_bubble_controller.h"
+#endif
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_finder.h"
 #include "chrome/browser/ui/browser_navigator.h"
@@ -110,50 +114,6 @@
          card_type == autofill::kDiscoverCard;
 }
 
-// Returns true if |input| should be shown when |field_type| has been requested.
-bool InputTypeMatchesFieldType(const DetailInput& input,
-                               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();
-  if (server_type == CREDIT_CARD_EXP_4_DIGIT_YEAR ||
-      server_type == CREDIT_CARD_EXP_2_DIGIT_YEAR ||
-      server_type == CREDIT_CARD_EXP_DATE_4_DIGIT_YEAR ||
-      server_type == CREDIT_CARD_EXP_DATE_2_DIGIT_YEAR ||
-      server_type == CREDIT_CARD_EXP_MONTH) {
-    return input.type == CREDIT_CARD_EXP_4_DIGIT_YEAR ||
-           input.type == CREDIT_CARD_EXP_MONTH;
-  }
-
-  if (server_type == CREDIT_CARD_TYPE)
-    return input.type == CREDIT_CARD_NUMBER;
-
-  // Check the groups to distinguish billing types from shipping ones.
-  AutofillType input_type = AutofillType(input.type);
-  return input_type.GetStorableType() == server_type &&
-         input_type.group() == field_type.group();
-}
-
-// Returns true if |input| in the given |section| should be used for a
-// site-requested |field|.
-bool DetailInputMatchesField(DialogSection section,
-                             const DetailInput& input,
-                             const AutofillField& field) {
-  AutofillType field_type = field.Type();
-
-  // The credit card name is filled from the billing section's data.
-  if (field_type.GetStorableType() == CREDIT_CARD_NAME &&
-      (section == SECTION_BILLING || section == SECTION_CC_BILLING)) {
-    return input.type == NAME_BILLING_FULL;
-  }
-
-  return InputTypeMatchesFieldType(input, field_type);
-}
-
-bool IsCreditCardType(ServerFieldType type) {
-  return AutofillType(type).group() == CREDIT_CARD;
-}
-
 // Returns true if |input| should be used to fill a site-requested |field| which
 // is notated with a "shipping" tag, for use when the user has decided to use
 // the billing address as the shipping address.
@@ -165,17 +125,7 @@
       AutofillType::GetEquivalentBillingFieldType(
           field.Type().GetStorableType());
 
-  return InputTypeMatchesFieldType(input, AutofillType(field_type));
-}
-
-// Constructs |inputs| from template data.
-void BuildInputs(const DetailInput* input_template,
-                 size_t template_size,
-                 DetailInputs* inputs) {
-  for (size_t i = 0; i < template_size; ++i) {
-    const DetailInput* input = &input_template[i];
-    inputs->push_back(*input);
-  }
+  return common::InputTypeMatchesFieldType(input, AutofillType(field_type));
 }
 
 // Initializes |form_group| from user-entered data.
@@ -225,7 +175,7 @@
       if (card && it->first->type == NAME_FULL)
         card->SetRawInfo(CREDIT_CARD_NAME, trimmed);
 
-      if (IsCreditCardType(it->first->type)) {
+      if (common::IsCreditCardType(it->first->type)) {
         if (card)
           card->SetRawInfo(it->first->type, trimmed);
       } else if (profile) {
@@ -247,7 +197,7 @@
   gfx::NativeWindow native_window =
       web_contents->GetView()->GetTopLevelNativeWindow();
   apps::ShellWindow* shell_window =
-      extensions::ShellWindowRegistry::
+      apps::ShellWindowRegistry::
           GetShellWindowForNativeWindowAnyProfile(native_window);
   return shell_window->GetBaseWindow();
 }
@@ -385,6 +335,14 @@
     case wallet::WalletClient::BUYER_ACCOUNT_ERROR:
       return l10n_util::GetStringUTF16(IDS_AUTOFILL_WALLET_BUYER_ACCOUNT_ERROR);
 
+    case wallet::WalletClient::BUYER_LEGAL_ADDRESS_NOT_SUPPORTED:
+      return l10n_util::GetStringUTF16(
+          IDS_AUTOFILL_WALLET_BUYER_COUNTRY_NOT_SUPPORTED);
+
+    case wallet::WalletClient::UNSUPPORTED_MERCHANT:
+      return l10n_util::GetStringUTF16(
+          IDS_AUTOFILL_WALLET_UNSUPPORTED_MERCHANT);
+
     case wallet::WalletClient::BAD_REQUEST:
       return l10n_util::GetStringFUTF16(
           IDS_AUTOFILL_WALLET_UPGRADE_CHROME_ERROR,
@@ -395,6 +353,10 @@
           IDS_AUTOFILL_WALLET_UPGRADE_CHROME_ERROR,
           ASCIIToUTF16("42"));
 
+    case wallet::WalletClient::UNVERIFIED_KNOW_YOUR_CUSTOMER_STATUS:
+      return l10n_util::GetStringUTF16(
+          IDS_AUTOFILL_WALLET_UNVERIFIED_KNOW_YOUR_CUSTOMER_STATUS);
+
     case wallet::WalletClient::UNSUPPORTED_API_VERSION:
       return l10n_util::GetStringFUTF16(
           IDS_AUTOFILL_WALLET_UPGRADE_CHROME_ERROR,
@@ -432,7 +394,6 @@
   gfx::Canvas canvas(card->size(), ui::SCALE_FACTOR_100P, false);
   canvas.DrawImageInt(*card, 0, 0);
 
-#if !defined(OS_ANDROID)
   gfx::Rect display_rect(gfx::Point(), card->size());
   display_rect.Inset(14, 0, 14, 0);
   // TODO(estade): fallback font for systems that don't have Helvetica?
@@ -446,7 +407,6 @@
       helvetica,
       SK_ColorWHITE,
       display_rect, 0, 0, shadows);
-#endif
 
   gfx::ImageSkia skia(canvas.ExtractImageRep());
   return gfx::Image(skia);
@@ -470,7 +430,6 @@
   }
 }
 
-#if !defined(OS_ANDROID)
 // static
 base::WeakPtr<AutofillDialogControllerImpl>
     AutofillDialogControllerImpl::Create(
@@ -489,7 +448,6 @@
                                        callback);
   return autofill_dialog_controller->weak_ptr_factory_.GetWeakPtr();
 }
-#endif  // !defined(OS_ANDROID)
 
 // static
 void AutofillDialogControllerImpl::RegisterProfilePrefs(
@@ -511,6 +469,27 @@
       user_prefs::PrefRegistrySyncable::SYNCABLE_PREF);
 }
 
+// static
+base::WeakPtr<AutofillDialogController> AutofillDialogController::Create(
+    content::WebContents* contents,
+    const FormData& form_structure,
+    const GURL& source_url,
+    const DialogType dialog_type,
+    const base::Callback<void(const FormStructure*,
+                              const std::string&)>& callback) {
+  return AutofillDialogControllerImpl::Create(contents,
+                                              form_structure,
+                                              source_url,
+                                              dialog_type,
+                                              callback);
+}
+
+// static
+void AutofillDialogController::RegisterProfilePrefs(
+    user_prefs::PrefRegistrySyncable* registry) {
+  AutofillDialogControllerImpl::RegisterProfilePrefs(registry);
+}
+
 void AutofillDialogControllerImpl::Show() {
   dialog_shown_timestamp_ = base::Time::Now();
 
@@ -551,70 +530,16 @@
     return;
   }
 
-  const DetailInput kEmailInputs[] = {
-    { 1, EMAIL_ADDRESS, IDS_AUTOFILL_DIALOG_PLACEHOLDER_EMAIL },
-  };
-
-  const DetailInput kCCInputs[] = {
-    { 2, CREDIT_CARD_NUMBER, IDS_AUTOFILL_DIALOG_PLACEHOLDER_CARD_NUMBER },
-    { 3, CREDIT_CARD_EXP_MONTH },
-    { 3, CREDIT_CARD_EXP_4_DIGIT_YEAR },
-    { 3, CREDIT_CARD_VERIFICATION_CODE, IDS_AUTOFILL_DIALOG_PLACEHOLDER_CVC,
-      1.5 },
-  };
-
-  const DetailInput kBillingInputs[] = {
-    { 4, NAME_BILLING_FULL, IDS_AUTOFILL_DIALOG_PLACEHOLDER_CARDHOLDER_NAME },
-    { 5, ADDRESS_BILLING_LINE1,
-      IDS_AUTOFILL_DIALOG_PLACEHOLDER_ADDRESS_LINE_1 },
-    { 6, ADDRESS_BILLING_LINE2,
-      IDS_AUTOFILL_DIALOG_PLACEHOLDER_ADDRESS_LINE_2 },
-    { 7, ADDRESS_BILLING_CITY,
-      IDS_AUTOFILL_DIALOG_PLACEHOLDER_LOCALITY },
-    // TODO(estade): state placeholder should depend on locale.
-    { 8, ADDRESS_BILLING_STATE, IDS_AUTOFILL_FIELD_LABEL_STATE },
-    { 8, ADDRESS_BILLING_ZIP,
-      IDS_AUTOFILL_DIALOG_PLACEHOLDER_POSTAL_CODE },
-    // We don't allow the user to change the country: http://crbug.com/247518
-    { -1, ADDRESS_BILLING_COUNTRY, 0 },
-    { 10, PHONE_BILLING_WHOLE_NUMBER,
-      IDS_AUTOFILL_DIALOG_PLACEHOLDER_PHONE_NUMBER },
-  };
-
-  const DetailInput kShippingInputs[] = {
-    { 11, NAME_FULL, IDS_AUTOFILL_DIALOG_PLACEHOLDER_ADDRESSEE_NAME },
-    { 12, ADDRESS_HOME_LINE1, IDS_AUTOFILL_DIALOG_PLACEHOLDER_ADDRESS_LINE_1 },
-    { 13, ADDRESS_HOME_LINE2, IDS_AUTOFILL_DIALOG_PLACEHOLDER_ADDRESS_LINE_2 },
-    { 14, ADDRESS_HOME_CITY, IDS_AUTOFILL_DIALOG_PLACEHOLDER_LOCALITY },
-    { 15, ADDRESS_HOME_STATE, IDS_AUTOFILL_FIELD_LABEL_STATE },
-    { 15, ADDRESS_HOME_ZIP, IDS_AUTOFILL_DIALOG_PLACEHOLDER_POSTAL_CODE },
-    { -1, ADDRESS_HOME_COUNTRY, 0 },
-    { 17, PHONE_HOME_WHOLE_NUMBER,
-      IDS_AUTOFILL_DIALOG_PLACEHOLDER_PHONE_NUMBER },
-  };
-
-  BuildInputs(kEmailInputs,
-              arraysize(kEmailInputs),
-              &requested_email_fields_);
-
-  BuildInputs(kCCInputs,
-              arraysize(kCCInputs),
-              &requested_cc_fields_);
-
-  BuildInputs(kBillingInputs,
-              arraysize(kBillingInputs),
-              &requested_billing_fields_);
-
-  BuildInputs(kCCInputs,
-              arraysize(kCCInputs),
-              &requested_cc_billing_fields_);
-  BuildInputs(kBillingInputs,
-              arraysize(kBillingInputs),
-              &requested_cc_billing_fields_);
-
-  BuildInputs(kShippingInputs,
-              arraysize(kShippingInputs),
-              &requested_shipping_fields_);
+  common::BuildInputsForSection(SECTION_EMAIL,
+                                &requested_email_fields_);
+  common::BuildInputsForSection(SECTION_CC,
+                                &requested_cc_fields_);
+  common::BuildInputsForSection(SECTION_BILLING,
+                                &requested_billing_fields_);
+  common::BuildInputsForSection(SECTION_CC_BILLING,
+                                &requested_cc_billing_fields_);
+  common::BuildInputsForSection(SECTION_SHIPPING,
+                                &requested_shipping_fields_);
 
   // Test whether we need to show the shipping section. If filling that section
   // would be a no-op, don't show it.
@@ -622,7 +547,7 @@
   EmptyDataModelWrapper empty_wrapper;
   cares_about_shipping_ = empty_wrapper.FillFormStructure(
       inputs,
-      base::Bind(DetailInputMatchesField, SECTION_SHIPPING),
+      base::Bind(common::DetailInputMatchesField, SECTION_SHIPPING),
       &form_structure_);
 
   SuggestionsUpdated();
@@ -788,9 +713,8 @@
 }
 
 string16 AutofillDialogControllerImpl::AccountChooserText() const {
-  // TODO(aruslan): this should be l10n "Not using Google Wallet".
   if (!account_chooser_model_.WalletIsSelected())
-    return l10n_util::GetStringUTF16(IDS_AUTOFILL_DIALOG_PAY_WITHOUT_WALLET);
+    return l10n_util::GetStringUTF16(IDS_AUTOFILL_DIALOG_PAYING_WITHOUT_WALLET);
 
   if (SignedInState() == SIGNED_IN)
     return account_chooser_model_.active_wallet_account_name();
@@ -802,14 +726,15 @@
 string16 AutofillDialogControllerImpl::SignInLinkText() const {
   return l10n_util::GetStringUTF16(
       signin_registrar_.IsEmpty() ? IDS_AUTOFILL_DIALOG_SIGN_IN :
-                                    IDS_AUTOFILL_DIALOG_PAY_WITHOUT_WALLET);
+                                    IDS_AUTOFILL_DIALOG_CANCEL_SIGN_IN);
 }
 
 bool AutofillDialogControllerImpl::ShouldOfferToSaveInChrome() const {
   return !IsPayingWithWallet() &&
       !profile_->IsOffTheRecord() &&
       IsManuallyEditingAnySection() &&
-      ShouldShowDetailArea();
+      ShouldShowDetailArea() &&
+      !ShouldShowSpinner();
 }
 
 int AutofillDialogControllerImpl::GetDialogButtons() const {
@@ -853,10 +778,7 @@
 
   state.strings.push_back(DialogOverlayString());
   DialogOverlayString& string = state.strings.back();
-#if !defined(OS_ANDROID)
-  // gfx::Font isn't implemented on Android; DeriveFont() causes a null deref.
   string.font = rb.GetFont(ui::ResourceBundle::BaseFont).DeriveFont(4);
-#endif
 
   // First-run, post-submit, Wallet expository page.
   if (full_wallet_ && full_wallet_->required_actions().empty()) {
@@ -1102,13 +1024,13 @@
   }
 }
 
-bool AutofillDialogControllerImpl::InputWasEdited(const DetailInput& input,
+bool AutofillDialogControllerImpl::InputWasEdited(ServerFieldType type,
                                                   const base::string16& value) {
   if (value.empty())
     return false;
 
-  // If this is a combobox at the default value, don't preserve.
-  ui::ComboboxModel* model = ComboboxModelForAutofillType(input.type);
+  // If this is a combobox at the default value, don't preserve it.
+  ui::ComboboxModel* model = ComboboxModelForAutofillType(type);
   if (model && model->GetItemAt(model->GetDefaultIndex()) == value)
     return false;
 
@@ -1131,7 +1053,7 @@
     // Remove fields that are empty, at their default values, or invalid.
     for (DetailOutputMap::iterator it = outputs.begin(); it != outputs.end();
          ++it) {
-      if (InputWasEdited(*it->first, it->second) &&
+      if (InputWasEdited(it->first->type, it->second) &&
           InputValidityMessage(section, it->first->type, it->second).empty()) {
         snapshot.insert(std::make_pair(it->first, it->second));
       }
@@ -1156,7 +1078,7 @@
     wrapper.FillInputs(inputs);
 
     for (size_t i = 0; i < inputs->size(); ++i) {
-      if (InputWasEdited((*inputs)[i], (*inputs)[i].initial_value)) {
+      if (InputWasEdited((*inputs)[i].type, (*inputs)[i].initial_value)) {
         SuggestionsMenuModelForSection(section)->SetCheckedItem(kAddNewItemKey);
         break;
       }
@@ -1507,7 +1429,7 @@
   UpdateSection(section);
 
   GetMetricLogger().LogDialogUiEvent(
-      GetDialogType(), DialogSectionToUiEditEvent(section));
+      GetDialogType(), common::DialogSectionToUiEditEvent(section));
 }
 
 void AutofillDialogControllerImpl::EditCancelledForSection(
@@ -1602,7 +1524,17 @@
     }
 
     case CREDIT_CARD_EXP_MONTH:
+      if (!InputWasEdited(CREDIT_CARD_EXP_MONTH, value)) {
+        return l10n_util::GetStringUTF16(
+            IDS_AUTOFILL_DIALOG_VALIDATION_MISSING_VALUE);
+      }
+      break;
+
     case CREDIT_CARD_EXP_4_DIGIT_YEAR:
+      if (!InputWasEdited(CREDIT_CARD_EXP_4_DIGIT_YEAR, value)) {
+        return l10n_util::GetStringUTF16(
+            IDS_AUTOFILL_DIALOG_VALIDATION_MISSING_VALUE);
+      }
       break;
 
     case CREDIT_CARD_VERIFICATION_CODE:
@@ -1672,11 +1604,16 @@
   std::map<ServerFieldType, string16> field_values;
   for (DetailOutputMap::const_iterator iter = inputs.begin();
        iter != inputs.end(); ++iter) {
-    // Skip empty fields in edit mode.
-    if (validation_type == VALIDATE_EDIT && iter->second.empty())
-      continue;
-
     const ServerFieldType type = iter->first->type;
+
+    // Skip empty/unchanged fields in edit mode. Ignore country code as it
+    // always has a value.
+    if (validation_type == VALIDATE_EDIT &&
+        !InputWasEdited(type, iter->second) &&
+        ComboboxModelForAutofillType(type) != &country_combobox_model_) {
+      continue;
+    }
+
     string16 message = InputValidityMessage(section, type, iter->second);
     if (!message.empty())
       invalid_messages[type] = message;
@@ -1688,6 +1625,10 @@
   // never supposed to have 2-digit years, so not checked).
   if (field_values.count(CREDIT_CARD_EXP_4_DIGIT_YEAR) &&
       field_values.count(CREDIT_CARD_EXP_MONTH) &&
+      InputWasEdited(CREDIT_CARD_EXP_4_DIGIT_YEAR,
+                     field_values[CREDIT_CARD_EXP_4_DIGIT_YEAR]) &&
+      InputWasEdited(CREDIT_CARD_EXP_MONTH,
+                     field_values[CREDIT_CARD_EXP_MONTH]) &&
       !IsCreditCardExpirationValid(field_values[CREDIT_CARD_EXP_4_DIGIT_YEAR],
                                    field_values[CREDIT_CARD_EXP_MONTH])) {
     // The dialog shows the same error message for the month and year fields.
@@ -1761,7 +1702,7 @@
   }
 
   std::vector<string16> popup_values, popup_labels, popup_icons;
-  if (IsCreditCardType(input->type)) {
+  if (common::IsCreditCardType(input->type)) {
     GetManager()->GetCreditCardSuggestions(AutofillType(input->type),
                                            field_contents,
                                            &popup_values,
@@ -2063,7 +2004,7 @@
   const PersonalDataManager::GUIDPair& pair = popup_guids_[identifier];
 
   scoped_ptr<DataModelWrapper> wrapper;
-  if (IsCreditCardType(input_showing_popup_->type)) {
+  if (common::IsCreditCardType(input_showing_popup_->type)) {
     wrapper.reset(new AutofillCreditCardWrapper(
         GetManager()->GetCreditCardByGUID(pair.first)));
   } else {
@@ -2338,7 +2279,7 @@
 
   for (size_t i = 0; i < form_structure_.field_count(); ++i) {
     AutofillType type = form_structure_.field(i)->Type();
-    if (IsCreditCardType(type.GetStorableType()))
+    if (common::IsCreditCardType(type.GetStorableType()))
       return true;
   }
 
@@ -2349,6 +2290,16 @@
   return source_url_.SchemeIs(chrome::kHttpsScheme);
 }
 
+void AutofillDialogControllerImpl::ShowNewCreditCardBubble(
+    scoped_ptr<CreditCard> new_card,
+    scoped_ptr<AutofillProfile> billing_profile) {
+#if !defined(OS_ANDROID)
+  NewCreditCardBubbleController::Show(profile(),
+                                      new_card.Pass(),
+                                      billing_profile.Pass());
+#endif
+}
+
 AutofillDialogControllerImpl::AutofillDialogControllerImpl(
     content::WebContents* contents,
     const FormData& form_structure,
@@ -2416,9 +2367,7 @@
   DCHECK(success);
 
   gfx::Rect window_bounds;
-#if !defined(OS_ANDROID)
   window_bounds = GetBaseWindowForWebContents(web_contents())->GetBounds();
-#endif
 
   PrefService* user_prefs = profile_->GetPrefs();
   std::string charset = user_prefs->GetString(::prefs::kDefaultCharset);
@@ -2448,14 +2397,12 @@
 }
 
 void AutofillDialogControllerImpl::OpenTabWithUrl(const GURL& url) {
-#if !defined(OS_ANDROID)
   chrome::NavigateParams params(
       chrome::FindBrowserWithWebContents(web_contents()),
       url,
       content::PAGE_TRANSITION_AUTO_BOOKMARK);
   params.disposition = NEW_FOREGROUND_TAB;
   chrome::Navigate(&params);
-#endif
 }
 
 bool AutofillDialogControllerImpl::IsEditingExistingData(
@@ -2782,7 +2729,7 @@
 
 void AutofillDialogControllerImpl::FillOutputForSection(DialogSection section) {
   FillOutputForSectionWithComparator(
-      section, base::Bind(DetailInputMatchesField, section));
+      section, base::Bind(common::DetailInputMatchesField, section));
 }
 
 bool AutofillDialogControllerImpl::FormStructureCaresAboutSection(
@@ -3384,10 +3331,10 @@
   AutofillMetrics::DialogUiEvent dialog_ui_event;
   if (model.GetItemKeyForCheckedItem() == kAddNewItemKey) {
     // Selected to add a new item.
-    dialog_ui_event = DialogSectionToUiItemAddedEvent(section);
+    dialog_ui_event = common::DialogSectionToUiItemAddedEvent(section);
   } else if (IsASuggestionItemKey(model.GetItemKeyForCheckedItem())) {
     // Selected an existing item.
-    dialog_ui_event = DialogSectionToUiSelectionChangedEvent(section);
+    dialog_ui_event = common::DialogSectionToUiSelectionChangedEvent(section);
   } else {
     // TODO(estade): add logging for "Manage items" or "Use billing for
     // shipping"?
@@ -3463,8 +3410,28 @@
     return;
 
   if (newly_saved_card_) {
-    AutofillCreditCardBubbleController::ShowNewCardSavedBubble(
-        web_contents(), newly_saved_card_->TypeAndLastFourDigits());
+    scoped_ptr<AutofillProfile> billing_profile;
+    if (IsManuallyEditingSection(SECTION_BILLING)) {
+      // Scrape the view as the user's entering or updating information.
+      DetailOutputMap outputs;
+      view_->GetUserInput(SECTION_BILLING, &outputs);
+      billing_profile.reset(new AutofillProfile);
+      FillFormGroupFromOutputs(outputs, billing_profile.get());
+    } else {
+      // Just snag the currently suggested profile.
+      std::string item_key = SuggestionsMenuModelForSection(SECTION_BILLING)->
+          GetItemKeyForCheckedItem();
+      AutofillProfile* profile = GetManager()->GetProfileByGUID(item_key);
+      billing_profile.reset(new AutofillProfile(*profile));
+    }
+
+    // The bubble also needs the associated email address.
+    billing_profile->SetRawInfo(
+        EMAIL_ADDRESS,
+        GetValueFromSection(SECTION_EMAIL, EMAIL_ADDRESS));
+
+    ShowNewCreditCardBubble(newly_saved_card_.Pass(),
+                            billing_profile.Pass());
     return;
   }
 
@@ -3487,8 +3454,12 @@
     GetBillingInfoFromOutputs(output, &card, NULL, NULL);
     backing_last_four = card.TypeAndLastFourDigits();
   }
-  AutofillCreditCardBubbleController::ShowGeneratedCardUI(
-      web_contents(), backing_last_four, full_wallet_->TypeAndLastFourDigits());
+#if !defined(OS_ANDROID)
+  GeneratedCreditCardBubbleController::Show(
+      web_contents(),
+      backing_last_four,
+      full_wallet_->TypeAndLastFourDigits());
+#endif
 }
 
 }  // namespace autofill
diff --git a/chrome/browser/ui/autofill/autofill_dialog_controller_impl.h b/chrome/browser/ui/autofill/autofill_dialog_controller_impl.h
index 6aa4ae1..6a98284 100644
--- a/chrome/browser/ui/autofill/autofill_dialog_controller_impl.h
+++ b/chrome/browser/ui/autofill/autofill_dialog_controller_impl.h
@@ -14,6 +14,7 @@
 #include "base/strings/string16.h"
 #include "base/time/time.h"
 #include "chrome/browser/ui/autofill/account_chooser_model.h"
+#include "chrome/browser/ui/autofill/autofill_dialog_controller.h"
 #include "chrome/browser/ui/autofill/autofill_dialog_models.h"
 #include "chrome/browser/ui/autofill/autofill_dialog_types.h"
 #include "chrome/browser/ui/autofill/autofill_dialog_view_delegate.h"
@@ -68,6 +69,7 @@
 // This class drives the dialog that appears when a site uses the imperative
 // autocomplete API to fill out a form.
 class AutofillDialogControllerImpl : public AutofillDialogViewDelegate,
+                                     public AutofillDialogController,
                                      public AutofillPopupDelegate,
                                      public content::NotificationObserver,
                                      public content::WebContentsObserver,
@@ -89,25 +91,16 @@
 
   static void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry);
 
-  void Show();
-  void Hide();
-
-  // Called when the tab hosting this dialog is activated by a user gesture.
-  // Used to trigger a refresh of the user's Wallet data.
-  void TabActivated();
-
-  // Adds a step in the flow to the Autocheckout UI.
-  void AddAutocheckoutStep(AutocheckoutStepType step_type);
-
-  // Updates the status of a step in the Autocheckout UI.
-  void UpdateAutocheckoutStep(AutocheckoutStepType step_type,
-                              AutocheckoutStepStatus step_status);
-
-  // Called when there is an error in an active Autocheckout flow.
-  void OnAutocheckoutError();
-
-  // Called when an Autocheckout flow completes successfully.
-  void OnAutocheckoutSuccess();
+  // AutofillDialogController implementation.
+  virtual void Show() OVERRIDE;
+  virtual void Hide() OVERRIDE;
+  virtual void TabActivated() OVERRIDE;
+  virtual void AddAutocheckoutStep(AutocheckoutStepType step_type) OVERRIDE;
+  virtual void UpdateAutocheckoutStep(
+      AutocheckoutStepType step_type,
+      AutocheckoutStepStatus step_status) OVERRIDE;
+  virtual void OnAutocheckoutError() OVERRIDE;
+  virtual void OnAutocheckoutSuccess() OVERRIDE;
 
   // Returns |view_| as a testable version of itself (if |view_| exists and
   // actually implements |AutofillDialogView::GetTestableView()|).
@@ -294,6 +287,12 @@
 
   AutocheckoutState autocheckout_state() const { return autocheckout_state_; }
 
+  // Shows a new credit card saved bubble and passes ownership of |new_card| and
+  // |billing_profile| to the bubble. Exposed for testing.
+  virtual void ShowNewCreditCardBubble(
+      scoped_ptr<CreditCard> new_card,
+      scoped_ptr<AutofillProfile> billing_profile);
+
  private:
   // Whether or not the current request wants credit info back.
   bool RequestingCreditCardInfo() const;
@@ -333,7 +332,7 @@
   void ShowEditUiIfBadSuggestion(DialogSection section);
 
   // Whether the |value| of |input| should be preserved on account change.
-  bool InputWasEdited(const DetailInput& input,
+  bool InputWasEdited(ServerFieldType type,
                       const base::string16& value);
 
   // Takes a snapshot of the newly inputted user data in |view_| (if it exists).
diff --git a/chrome/browser/ui/autofill/autofill_dialog_controller_unittest.cc b/chrome/browser/ui/autofill/autofill_dialog_controller_unittest.cc
index 7d16140..7a616b8 100644
--- a/chrome/browser/ui/autofill/autofill_dialog_controller_unittest.cc
+++ b/chrome/browser/ui/autofill/autofill_dialog_controller_unittest.cc
@@ -14,10 +14,11 @@
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/tuple.h"
-#include "chrome/browser/ui/autofill/autofill_credit_card_bubble_controller.h"
 #include "chrome/browser/ui/autofill/autofill_dialog_controller_impl.h"
 #include "chrome/browser/ui/autofill/autofill_dialog_view.h"
-#include "chrome/browser/ui/autofill/test_autofill_credit_card_bubble.h"
+#include "chrome/browser/ui/autofill/generated_credit_card_bubble_controller.h"
+#include "chrome/browser/ui/autofill/mock_new_credit_card_bubble_controller.h"
+#include "chrome/browser/ui/autofill/test_generated_credit_card_bubble_view.h"
 #include "chrome/common/pref_names.h"
 #include "chrome/common/render_messages.h"
 #include "chrome/test/base/chrome_render_view_host_test_harness.h"
@@ -193,7 +194,8 @@
       const AutofillMetrics& metric_logger,
       const DialogType dialog_type,
       const base::Callback<void(const FormStructure*,
-                                const std::string&)>& callback)
+                                const std::string&)>& callback,
+      MockNewCreditCardBubbleController* mock_new_card_bubble_controller)
       : AutofillDialogControllerImpl(contents,
                                      form_structure,
                                      source_url,
@@ -203,7 +205,9 @@
         mock_wallet_client_(
             Profile::FromBrowserContext(contents->GetBrowserContext())->
                 GetRequestContext(), this),
-        dialog_type_(dialog_type) {}
+        dialog_type_(dialog_type),
+        mock_new_card_bubble_controller_(mock_new_card_bubble_controller) {}
+
   virtual ~TestAutofillDialogController() {}
 
   virtual AutofillDialogView* CreateView() OVERRIDE {
@@ -265,6 +269,13 @@
     return true;
   }
 
+  virtual void ShowNewCreditCardBubble(
+      scoped_ptr<CreditCard> new_card,
+      scoped_ptr<AutofillProfile> billing_profile) OVERRIDE {
+    mock_new_card_bubble_controller_->Show(new_card.Pass(),
+                                           billing_profile.Pass());
+  }
+
  private:
   // To specify our own metric logger.
   virtual const AutofillMetrics& GetMetricLogger() const OVERRIDE {
@@ -276,31 +287,29 @@
   testing::NiceMock<wallet::MockWalletClient> mock_wallet_client_;
   GURL open_tab_url_;
   DialogType dialog_type_;
+  MockNewCreditCardBubbleController* mock_new_card_bubble_controller_;
 
   DISALLOW_COPY_AND_ASSIGN(TestAutofillDialogController);
 };
 
-class TestAutofillCreditCardBubbleController :
-    public AutofillCreditCardBubbleController {
+class TestGeneratedCreditCardBubbleController :
+    public GeneratedCreditCardBubbleController {
  public:
-  explicit TestAutofillCreditCardBubbleController(
+  explicit TestGeneratedCreditCardBubbleController(
       content::WebContents* contents)
-      : AutofillCreditCardBubbleController(contents) {
+      : GeneratedCreditCardBubbleController(contents) {
     contents->SetUserData(UserDataKey(), this);
     CHECK_EQ(contents->GetUserData(UserDataKey()), this);
   }
 
-  virtual ~TestAutofillCreditCardBubbleController() {}
+  virtual ~TestGeneratedCreditCardBubbleController() {}
 
-  MOCK_METHOD2(ShowAsGeneratedCardBubble,
-               void(const base::string16& backing_card_name,
-                    const base::string16& fronting_card_name));
-  MOCK_METHOD1(ShowAsNewCardSavedBubble,
-               void(const base::string16& newly_saved_card_name));
+  MOCK_METHOD2(SetupAndShow, void(const base::string16& backing_card_name,
+                                  const base::string16& fronting_card_name));
 
  protected:
-  virtual base::WeakPtr<AutofillCreditCardBubble> CreateBubble() OVERRIDE {
-    return TestAutofillCreditCardBubble::Create(GetWeakPtr());
+  virtual base::WeakPtr<GeneratedCreditCardBubbleView> CreateBubble() OVERRIDE {
+    return TestGeneratedCreditCardBubbleView::Create(GetWeakPtr());
   }
 
   virtual bool CanShow() const OVERRIDE {
@@ -308,7 +317,7 @@
   }
 
  private:
-  DISALLOW_COPY_AND_ASSIGN(TestAutofillCreditCardBubbleController);
+  DISALLOW_COPY_AND_ASSIGN(TestGeneratedCreditCardBubbleController);
 };
 
 class AutofillDialogControllerTest : public ChromeRenderViewHostTestHarness {
@@ -318,16 +327,7 @@
   // testing::Test implementation:
   virtual void SetUp() OVERRIDE {
     ChromeRenderViewHostTestHarness::SetUp();
-
-    test_bubble_controller_ =
-        new testing::NiceMock<TestAutofillCreditCardBubbleController>(
-            web_contents());
-
-    // Don't get stuck on the first run wallet interstitial.
-    profile()->GetPrefs()->SetBoolean(::prefs::kAutofillDialogHasPaidWithWallet,
-                                      true);
-
-    SetUpControllerWithFormData(DefaultFormData());
+    Reset();
   }
 
   virtual void TearDown() OVERRIDE {
@@ -340,9 +340,11 @@
     if (controller_)
       controller_->ViewClosed();
 
-    test_bubble_controller_ =
-        new testing::NiceMock<TestAutofillCreditCardBubbleController>(
+    test_generated_bubble_controller_ =
+        new testing::NiceMock<TestGeneratedCreditCardBubbleController>(
             web_contents());
+    mock_new_card_bubble_controller_.reset(
+        new MockNewCreditCardBubbleController);
 
     // Don't get stuck on the first run wallet interstitial.
     profile()->GetPrefs()->SetBoolean(::prefs::kAutofillDialogHasPaidWithWallet,
@@ -374,7 +376,8 @@
         GURL(),
         metric_logger_,
         DIALOG_TYPE_REQUEST_AUTOCOMPLETE,
-        callback))->AsWeakPtr();
+        callback,
+        mock_new_card_bubble_controller_.get()))->AsWeakPtr();
     controller_->Init(profile());
     controller_->Show();
     controller_->OnUserNameFetchSuccess(kFakeEmail);
@@ -461,8 +464,12 @@
 
   const FormStructure* form_structure() { return form_structure_; }
 
-  TestAutofillCreditCardBubbleController* test_bubble_controller() {
-    return test_bubble_controller_;
+  TestGeneratedCreditCardBubbleController* test_generated_bubble_controller() {
+    return test_generated_bubble_controller_;
+  }
+
+  const MockNewCreditCardBubbleController* mock_new_card_bubble_controller() {
+    return mock_new_card_bubble_controller_.get();
   }
 
  private:
@@ -489,7 +496,11 @@
 
   // Used to monitor if the Autofill credit card bubble is shown. Owned by
   // |web_contents()|.
-  TestAutofillCreditCardBubbleController* test_bubble_controller_;
+  TestGeneratedCreditCardBubbleController* test_generated_bubble_controller_;
+
+  // Used to record when new card bubbles would show. Created in |Reset()|.
+  scoped_ptr<MockNewCreditCardBubbleController>
+      mock_new_card_bubble_controller_;
 };
 
 }  // namespace
@@ -1488,10 +1499,12 @@
 TEST_F(AutofillDialogControllerTest, EditAutofillProfile) {
   SwitchToAutofill();
 
-  EXPECT_CALL(*controller()->GetView(), ModelChanged()).Times(1);
+  EXPECT_CALL(*controller()->GetView(), ModelChanged()).Times(2);
 
   AutofillProfile full_profile(test::GetVerifiedProfile());
+  CreditCard credit_card(test::GetVerifiedCreditCard());
   controller()->GetTestingManager()->AddTestingProfile(&full_profile);
+  controller()->GetTestingManager()->AddTestingCreditCard(&credit_card);
   controller()->EditClickedForSection(SECTION_SHIPPING);
 
   DetailOutputMap outputs;
@@ -1521,6 +1534,7 @@
 
 // Tests that adding an autofill profile and then submitting works.
 TEST_F(AutofillDialogControllerTest, AddAutofillProfile) {
+  SwitchToAutofill();
   EXPECT_CALL(*controller()->GetView(), ModelChanged()).Times(2);
 
   AutofillProfile full_profile(test::GetVerifiedProfile());
@@ -1567,10 +1581,13 @@
 // Makes sure that a newly added email address gets added to an existing profile
 // (as opposed to creating its own profile). http://crbug.com/240926
 TEST_F(AutofillDialogControllerTest, AddEmail) {
-  EXPECT_CALL(*controller()->GetView(), ModelChanged()).Times(1);
+  SwitchToAutofill();
+  EXPECT_CALL(*controller()->GetView(), ModelChanged()).Times(2);
 
   AutofillProfile full_profile(test::GetVerifiedProfile());
+  CreditCard credit_card(test::GetVerifiedCreditCard());
   controller()->GetTestingManager()->AddTestingProfile(&full_profile);
+  controller()->GetTestingManager()->AddTestingCreditCard(&credit_card);
 
   ui::MenuModel* model = controller()->MenuModelForSection(SECTION_EMAIL);
   ASSERT_TRUE(model);
@@ -2078,6 +2095,7 @@
 }
 
 TEST_F(AutofillDialogControllerTest, SaveDetailsInChrome) {
+  SwitchToAutofill();
   EXPECT_CALL(*controller()->GetView(), ModelChanged()).Times(2);
 
   AutofillProfile full_profile(test::GetVerifiedProfile());
@@ -2392,27 +2410,25 @@
   EXPECT_FALSE(ReadSetVisuallyDeemphasizedIpc());
 }
 
-
 TEST_F(AutofillDialogControllerTest, NewCardBubbleShown) {
-  EXPECT_CALL(*test_bubble_controller(),
-              ShowAsNewCardSavedBubble(ASCIIToUTF16("Visa - 1111"))).Times(1);
-  EXPECT_CALL(*test_bubble_controller(),
-              ShowAsGeneratedCardBubble(_, _)).Times(0);
+  EXPECT_CALL(*test_generated_bubble_controller(), SetupAndShow(_, _)).Times(0);
 
   SwitchToAutofill();
   FillCreditCardInputs();
   controller()->OnAccept();
   controller()->ViewClosed();
+
+  EXPECT_EQ(1, mock_new_card_bubble_controller()->bubbles_shown());
 }
 
 TEST_F(AutofillDialogControllerTest, GeneratedCardBubbleShown) {
-  EXPECT_CALL(*test_bubble_controller(),
-              ShowAsGeneratedCardBubble(_, _)).Times(1);
-  EXPECT_CALL(*test_bubble_controller(), ShowAsNewCardSavedBubble(_)).Times(0);
+  EXPECT_CALL(*test_generated_bubble_controller(), SetupAndShow(_, _)).Times(1);
 
   SubmitWithWalletItems(CompleteAndValidWalletItems());
   controller()->OnDidGetFullWallet(wallet::GetTestFullWallet());
   controller()->ViewClosed();
+
+  EXPECT_EQ(0, mock_new_card_bubble_controller()->bubbles_shown());
 }
 
 TEST_F(AutofillDialogControllerTest, ReloadWalletItemsOnActivation) {
@@ -2488,15 +2504,15 @@
 }
 
 TEST_F(AutofillDialogControllerTest, GeneratedCardBubbleNotShown) {
-  EXPECT_CALL(*test_bubble_controller(),
-              ShowAsGeneratedCardBubble(_, _)).Times(0);
-  EXPECT_CALL(*test_bubble_controller(), ShowAsNewCardSavedBubble(_)).Times(0);
+  EXPECT_CALL(*test_generated_bubble_controller(), SetupAndShow(_, _)).Times(0);
 
   SubmitWithWalletItems(CompleteAndValidWalletItems());
   controller()->set_dialog_type(DIALOG_TYPE_AUTOCHECKOUT);
   controller()->OnDidGetFullWallet(wallet::GetTestFullWallet());
   controller()->OnAutocheckoutError();
   controller()->ViewClosed();
+
+  EXPECT_EQ(0, mock_new_card_bubble_controller()->bubbles_shown());
 }
 
 }  // namespace autofill
diff --git a/chrome/browser/ui/autofill/autofill_dialog_models.cc b/chrome/browser/ui/autofill/autofill_dialog_models.cc
index f5c7849..297896e 100644
--- a/chrome/browser/ui/autofill/autofill_dialog_models.cc
+++ b/chrome/browser/ui/autofill/autofill_dialog_models.cc
@@ -155,7 +155,9 @@
 }
 
 string16 MonthComboboxModel::GetItemAt(int index) {
-  return index == 0 ? string16() : FormatMonth(index);
+  return index == 0 ?
+      l10n_util::GetStringUTF16(IDS_AUTOFILL_DIALOG_PLACEHOLDER_EXPIRY_MONTH) :
+      FormatMonth(index);
 }
 
 // YearComboboxModel -----------------------------------------------------------
@@ -175,10 +177,12 @@
 }
 
 string16 YearComboboxModel::GetItemAt(int index) {
-  if (index == 0)
-    return string16();
+  if (index == 0) {
+    return l10n_util::GetStringUTF16(
+        IDS_AUTOFILL_DIALOG_PLACEHOLDER_EXPIRY_YEAR);
+  }
 
   return base::IntToString16(this_year_ + index - 1);
 }
 
-}  // autofill
+}  // namespace autofill
diff --git a/chrome/browser/ui/autofill/autofill_dialog_types.cc b/chrome/browser/ui/autofill/autofill_dialog_types.cc
index a10aa43..e326419 100644
--- a/chrome/browser/ui/autofill/autofill_dialog_types.cc
+++ b/chrome/browser/ui/autofill/autofill_dialog_types.cc
@@ -247,73 +247,4 @@
 DialogOverlayState::DialogOverlayState() {}
 DialogOverlayState::~DialogOverlayState() {}
 
-AutofillMetrics::DialogUiEvent DialogSectionToUiEditEvent(
-    DialogSection section) {
-  switch (section) {
-    case SECTION_EMAIL:
-      return AutofillMetrics::DIALOG_UI_EMAIL_EDIT_UI_SHOWN;
-
-    case SECTION_BILLING:
-      return AutofillMetrics::DIALOG_UI_BILLING_EDIT_UI_SHOWN;
-
-    case SECTION_CC_BILLING:
-      return AutofillMetrics::DIALOG_UI_CC_BILLING_EDIT_UI_SHOWN;
-
-    case SECTION_SHIPPING:
-      return AutofillMetrics::DIALOG_UI_SHIPPING_EDIT_UI_SHOWN;
-
-    case SECTION_CC:
-      return AutofillMetrics::DIALOG_UI_CC_EDIT_UI_SHOWN;
-  }
-
-  NOTREACHED();
-  return AutofillMetrics::NUM_DIALOG_UI_EVENTS;
-}
-
-AutofillMetrics::DialogUiEvent DialogSectionToUiItemAddedEvent(
-    DialogSection section) {
-  switch (section) {
-    case SECTION_EMAIL:
-      return AutofillMetrics::DIALOG_UI_EMAIL_ITEM_ADDED;
-
-    case SECTION_BILLING:
-      return AutofillMetrics::DIALOG_UI_BILLING_ITEM_ADDED;
-
-    case SECTION_CC_BILLING:
-      return AutofillMetrics::DIALOG_UI_CC_BILLING_ITEM_ADDED;
-
-    case SECTION_SHIPPING:
-      return AutofillMetrics::DIALOG_UI_SHIPPING_ITEM_ADDED;
-
-    case SECTION_CC:
-      return AutofillMetrics::DIALOG_UI_CC_ITEM_ADDED;
-  }
-
-  NOTREACHED();
-  return AutofillMetrics::NUM_DIALOG_UI_EVENTS;
-}
-
-AutofillMetrics::DialogUiEvent DialogSectionToUiSelectionChangedEvent(
-    DialogSection section) {
-  switch (section) {
-    case SECTION_EMAIL:
-      return AutofillMetrics::DIALOG_UI_EMAIL_SELECTED_SUGGESTION_CHANGED;
-
-    case SECTION_BILLING:
-      return AutofillMetrics::DIALOG_UI_BILLING_SELECTED_SUGGESTION_CHANGED;
-
-    case SECTION_CC_BILLING:
-      return AutofillMetrics::DIALOG_UI_CC_BILLING_SELECTED_SUGGESTION_CHANGED;
-
-    case SECTION_SHIPPING:
-      return AutofillMetrics::DIALOG_UI_SHIPPING_SELECTED_SUGGESTION_CHANGED;
-
-    case SECTION_CC:
-      return AutofillMetrics::DIALOG_UI_CC_SELECTED_SUGGESTION_CHANGED;
-  }
-
-  NOTREACHED();
-  return AutofillMetrics::NUM_DIALOG_UI_EVENTS;
-}
-
 }  // namespace autofill
diff --git a/chrome/browser/ui/autofill/autofill_dialog_types.h b/chrome/browser/ui/autofill/autofill_dialog_types.h
index c31b0d7..d40d90a 100644
--- a/chrome/browser/ui/autofill/autofill_dialog_types.h
+++ b/chrome/browser/ui/autofill/autofill_dialog_types.h
@@ -236,21 +236,6 @@
 
 typedef std::map<ServerFieldType, string16> ValidityData;
 
-// Returns the AutofillMetrics::DIALOG_UI_*_EDIT_UI_SHOWN metric corresponding
-// to the |section|.
-AutofillMetrics::DialogUiEvent DialogSectionToUiEditEvent(
-    DialogSection section);
-
-// Returns the AutofillMetrics::DIALOG_UI_*_ITEM_ADDED metric corresponding
-// to the |section|.
-AutofillMetrics::DialogUiEvent DialogSectionToUiItemAddedEvent(
-    DialogSection section);
-
-// Returns the AutofillMetrics::DIALOG_UI_*_ITEM_ADDED metric corresponding
-// to the |section|.
-AutofillMetrics::DialogUiEvent DialogSectionToUiSelectionChangedEvent(
-    DialogSection section);
-
 }  // namespace autofill
 
 #endif  // CHROME_BROWSER_UI_AUTOFILL_AUTOFILL_DIALOG_TYPES_H_
diff --git a/chrome/browser/ui/autofill/autofill_dialog_view.cc b/chrome/browser/ui/autofill/autofill_dialog_view.cc
index 4267180..10024d2 100644
--- a/chrome/browser/ui/autofill/autofill_dialog_view.cc
+++ b/chrome/browser/ui/autofill/autofill_dialog_view.cc
@@ -12,7 +12,7 @@
 
 AutofillDialogView::~AutofillDialogView() {}
 
-#if defined(TOOLKIT_GTK) || defined(OS_ANDROID)
+#if defined(TOOLKIT_GTK)
 // TODO(estade): implement the dialog on GTK. See http://crbug.com/157275.
 AutofillDialogView* AutofillDialogView::Create(
     AutofillDialogViewDelegate* delegate) {
diff --git a/chrome/browser/ui/autofill/generated_credit_card_bubble_controller.cc b/chrome/browser/ui/autofill/generated_credit_card_bubble_controller.cc
new file mode 100644
index 0000000..1c8a170
--- /dev/null
+++ b/chrome/browser/ui/autofill/generated_credit_card_bubble_controller.cc
@@ -0,0 +1,258 @@
+// 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/ui/autofill/generated_credit_card_bubble_controller.h"
+
+#include <climits>
+
+#include "base/logging.h"
+#include "base/prefs/pref_service.h"
+#include "base/strings/string_split.h"
+#include "base/strings/utf_string_conversions.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/ui/autofill/generated_credit_card_bubble_view.h"
+#include "chrome/browser/ui/autofill/tab_autofill_manager_delegate.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/omnibox/location_bar.h"
+#include "chrome/browser/ui/tabs/tab_strip_model.h"
+#include "chrome/common/pref_names.h"
+#include "components/user_prefs/pref_registry_syncable.h"
+#include "content/public/browser/navigation_details.h"
+#include "content/public/browser/navigation_entry.h"
+#include "content/public/browser/web_contents.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"
+
+DEFINE_WEB_CONTENTS_USER_DATA_KEY(
+    autofill::GeneratedCreditCardBubbleController);
+
+namespace autofill {
+
+namespace {
+
+static const int kMaxGeneratedCardTimesToShow = INT_MAX;
+static const base::char16 kRangeSeparator = '|';
+static const char kWalletGeneratedCardLearnMoreLink[] =
+    "http://support.google.com/wallet/bin/answer.py?hl=en&answer=2740044";
+
+GeneratedCreditCardBubbleController* GetOrCreate(content::WebContents* wc) {
+  GeneratedCreditCardBubbleController::CreateForWebContents(wc);
+  return GeneratedCreditCardBubbleController::FromWebContents(wc);
+}
+
+}  // namespace
+
+bool TextRange::operator==(const TextRange& other) const {
+  return other.range == range && other.is_link == is_link;
+}
+
+GeneratedCreditCardBubbleController::GeneratedCreditCardBubbleController(
+    content::WebContents* web_contents)
+    : WebContentsObserver(web_contents),
+      web_contents_(web_contents),
+      title_text_(l10n_util::GetStringUTF16(
+          IDS_AUTOFILL_GENERATED_CREDIT_CARD_BUBBLE_TITLE)),
+      should_show_anchor_(true),
+      weak_ptr_factory_(this) {}
+
+GeneratedCreditCardBubbleController::~GeneratedCreditCardBubbleController() {
+  // In the case that the tab is closed, the controller can be deleted while
+  // bubble is showing. Always calling |Hide()| ensures that the bubble closes.
+  Hide();
+}
+
+// static
+void GeneratedCreditCardBubbleController::RegisterUserPrefs(
+    user_prefs::PrefRegistrySyncable* registry) {
+  registry->RegisterIntegerPref(
+      ::prefs::kAutofillGeneratedCardBubbleTimesShown,
+      0,
+      user_prefs::PrefRegistrySyncable::SYNCABLE_PREF);
+}
+
+// static
+void GeneratedCreditCardBubbleController::Show(
+    content::WebContents* contents,
+    const base::string16& fronting_card_name,
+    const base::string16& backing_card_name) {
+  GetOrCreate(contents)->SetupAndShow(fronting_card_name, backing_card_name);
+}
+
+void GeneratedCreditCardBubbleController::DidNavigateMainFrame(
+    const content::LoadCommittedDetails& details,
+    const content::FrameNavigateParams& params) {
+  if (details.entry &&
+      !content::PageTransitionIsRedirect(details.entry->GetTransitionType())) {
+    should_show_anchor_ = false;
+    UpdateAnchor();
+    web_contents()->RemoveUserData(UserDataKey());
+    // |this| is now deleted.
+  }
+}
+
+bool GeneratedCreditCardBubbleController::IsHiding() const {
+  return bubble_ && bubble_->IsHiding();
+}
+
+gfx::Image GeneratedCreditCardBubbleController::AnchorIcon() const {
+  if (!should_show_anchor_)
+    return gfx::Image();
+  return ui::ResourceBundle::GetSharedInstance().GetImageNamed(IDR_WALLET_ICON);
+}
+
+const base::string16& GeneratedCreditCardBubbleController::TitleText() const {
+  return title_text_;
+}
+
+const base::string16& GeneratedCreditCardBubbleController::ContentsText()
+    const {
+  return contents_text_;
+}
+
+const std::vector<TextRange>& GeneratedCreditCardBubbleController::
+    ContentsTextRanges() const {
+  return contents_text_ranges_;
+}
+
+void GeneratedCreditCardBubbleController::OnAnchorClicked() {
+  Show(true);
+}
+
+void GeneratedCreditCardBubbleController::OnLinkClicked() {
+  // Open a new tab to the Online Wallet help link.
+  chrome::NavigateParams params(
+      chrome::FindBrowserWithWebContents(web_contents()),
+      GURL(kWalletGeneratedCardLearnMoreLink),
+      content::PAGE_TRANSITION_AUTO_BOOKMARK);
+  params.disposition = NEW_FOREGROUND_TAB;
+  chrome::Navigate(&params);
+
+  Hide();
+}
+
+base::WeakPtr<GeneratedCreditCardBubbleController>
+    GeneratedCreditCardBubbleController::GetWeakPtr() {
+  return weak_ptr_factory_.GetWeakPtr();
+}
+
+base::WeakPtr<GeneratedCreditCardBubbleView>
+    GeneratedCreditCardBubbleController::CreateBubble() {
+  return GeneratedCreditCardBubbleView::Create(GetWeakPtr());
+}
+
+base::WeakPtr<GeneratedCreditCardBubbleView>
+    GeneratedCreditCardBubbleController::bubble() {
+  return bubble_;
+}
+
+bool GeneratedCreditCardBubbleController::CanShow() const {
+  Browser* browser = chrome::FindBrowserWithWebContents(web_contents());
+  return web_contents() == browser->tab_strip_model()->GetActiveWebContents();
+}
+
+bool GeneratedCreditCardBubbleController::ShouldDisplayBubbleInitially() const {
+  Profile* profile = Profile::FromBrowserContext(
+      web_contents_->GetBrowserContext());
+  int times_shown = profile->GetPrefs()->GetInteger(
+      ::prefs::kAutofillGeneratedCardBubbleTimesShown);
+  return times_shown < kMaxGeneratedCardTimesToShow;
+}
+
+void GeneratedCreditCardBubbleController::SetupAndShow(
+    const base::string16& fronting_card_name,
+    const base::string16& backing_card_name) {
+  DCHECK(!fronting_card_name.empty());
+  DCHECK(!backing_card_name.empty());
+
+  fronting_card_name_ = fronting_card_name;
+  backing_card_name_ = backing_card_name;
+
+  // Clear any generated state or from the last |SetupAndShow()| call.
+  contents_text_.clear();
+  contents_text_ranges_.clear();
+
+  base::string16 to_split = l10n_util::GetStringFUTF16(
+      IDS_AUTOFILL_GENERATED_CREDIT_CARD_BUBBLE_CONTENTS,
+      fronting_card_name_,
+      backing_card_name_);
+
+  // Split the full text on '|' to highlight certain parts. For example, "sly"
+  // and "jumped" would be bolded in "The |sly| fox |jumped| over the lazy dog".
+  std::vector<base::string16> pieces;
+  base::SplitStringDontTrim(to_split, kRangeSeparator, &pieces);
+
+  while (!pieces.empty()) {
+    base::string16 piece = pieces.front();
+
+    // Every second piece should be bolded. Because |base::SplitString*()|
+    // leaves an empty "" even if '|' is the first character, this is guaranteed
+    // to work for "|highlighting| starts here". Ignore empty pieces because
+    // there's nothing to highlight.
+    if (!piece.empty() && pieces.size() % 2 == 0) {
+      const size_t start = contents_text_.size();
+      TextRange bold_text;
+      bold_text.range = ui::Range(start, start + piece.size());
+      bold_text.is_link = false;
+      contents_text_ranges_.push_back(bold_text);
+    }
+
+    // Append the piece whether it's bolded or not and move on to the next one.
+    contents_text_.append(piece);
+    pieces.erase(pieces.begin(), pieces.begin() + 1);
+  }
+
+  // Add a "Learn more" link at the end of the header text if it's a generated
+  // card bubble.
+  base::string16 learn_more = l10n_util::GetStringUTF16(IDS_LEARN_MORE);
+  contents_text_.append(ASCIIToUTF16(" ") + learn_more);
+  const size_t header_size = contents_text_.size();
+  TextRange end_link;
+  end_link.range = ui::Range(header_size - learn_more.size(), header_size);
+  end_link.is_link = true;
+  contents_text_ranges_.push_back(end_link);
+
+  UpdateAnchor();
+
+  if (ShouldDisplayBubbleInitially())
+    Show(false);
+}
+
+void GeneratedCreditCardBubbleController::Show(bool was_anchor_click) {
+  if (!CanShow())
+    return;
+
+  bubble_ = CreateBubble();
+  if (!bubble_) {
+    // TODO(dbeam): Make a bubble on all applicable platforms.
+    return;
+  }
+
+  bubble_->Show();
+
+  if (!was_anchor_click) {
+    // If the bubble was an automatically created "you generated a card" bubble,
+    // count it as a show. If the user clicked the omnibox icon, don't count it.
+    PrefService* prefs = Profile::FromBrowserContext(
+        web_contents()->GetBrowserContext())->GetPrefs();
+    prefs->SetInteger(::prefs::kAutofillGeneratedCardBubbleTimesShown,
+        prefs->GetInteger(::prefs::kAutofillGeneratedCardBubbleTimesShown) + 1);
+  }
+}
+
+void GeneratedCreditCardBubbleController::UpdateAnchor() {
+  Browser* browser = chrome::FindBrowserWithWebContents(web_contents());
+  if (browser && browser->window() && browser->window()->GetLocationBar())
+    browser->window()->GetLocationBar()->UpdateGeneratedCreditCardView();
+}
+
+void GeneratedCreditCardBubbleController::Hide() {
+  if (bubble_ && !bubble_->IsHiding())
+    bubble_->Hide();
+}
+
+}  // namespace autofill
diff --git a/chrome/browser/ui/autofill/generated_credit_card_bubble_controller.h b/chrome/browser/ui/autofill/generated_credit_card_bubble_controller.h
new file mode 100644
index 0000000..0f6f638
--- /dev/null
+++ b/chrome/browser/ui/autofill/generated_credit_card_bubble_controller.h
@@ -0,0 +1,169 @@
+// 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_UI_AUTOFILL_GENERATED_CREDIT_CARD_BUBBLE_CONTROLLER_H_
+#define CHROME_BROWSER_UI_AUTOFILL_GENERATED_CREDIT_CARD_BUBBLE_CONTROLLER_H_
+
+#include <vector>
+
+#include "base/basictypes.h"
+#include "base/compiler_specific.h"
+#include "base/memory/weak_ptr.h"
+#include "base/strings/string16.h"
+#include "content/public/browser/web_contents_observer.h"
+#include "content/public/browser/web_contents_user_data.h"
+#include "ui/base/range/range.h"
+#include "ui/gfx/image/image.h"
+
+namespace content {
+class WebContents;
+}
+
+namespace user_prefs {
+class PrefRegistrySyncable;
+}
+
+namespace autofill {
+
+class GeneratedCreditCardBubbleView;
+
+// A simple struct of text highlighting range information. If |is_link| is true
+// this portion of the text should be clickable (and trigger |OnLinkClicked()|).
+// If |is_link| is false, the text denoted by |range| should be bolded.
+struct TextRange {
+  // The range of text this TextRange applies to (start and end).
+  ui::Range range;
+  // Whether this text range should be styled like a link (e.g. clickable).
+  bool is_link;
+  // An equality operator for testing.
+  bool operator==(const TextRange& other) const;
+};
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// GeneratedCreditCardBubbleController
+//
+//  A class to control showing and hiding a bubble after a credit card is
+//  generated.
+//
+////////////////////////////////////////////////////////////////////////////////
+class GeneratedCreditCardBubbleController
+    : public content::WebContentsObserver,
+      public content::WebContentsUserData<GeneratedCreditCardBubbleController> {
+ public:
+  virtual ~GeneratedCreditCardBubbleController();
+
+  // Registers preferences this class cares about.
+  static void RegisterUserPrefs(user_prefs::PrefRegistrySyncable* registry);
+
+  // Show a bubble to educate the user about generated (fronting) cards and how
+  // they are used to bill their original (backing) card.
+  static void Show(content::WebContents* contents,
+                   const base::string16& backing_card_name,
+                   const base::string16& fronting_card_name);
+
+  // content::WebContentsObserver:
+  virtual void DidNavigateMainFrame(
+      const content::LoadCommittedDetails& details,
+      const content::FrameNavigateParams& params) OVERRIDE;
+
+  // Returns whether |bubble_| is currently in the process of hiding.
+  bool IsHiding() const;
+
+  // Returns the image that should be shown as an icon in the omnibox.
+  gfx::Image AnchorIcon() const;
+
+  // The title of the bubble.
+  const base::string16& TitleText() const;
+
+  // Text in the contents of the bubble.
+  const base::string16& ContentsText() const;
+
+  // Ranges of text styles in the bubble's main content.
+  const std::vector<TextRange>& ContentsTextRanges() const;
+
+  // Called when the anchor for this bubble is clicked. Shows a new bubble.
+  void OnAnchorClicked();
+
+  // Called when the link at the bottom of the bubble is clicked. Opens and
+  // navigates a new tab to an informational page and hides the bubble.
+  void OnLinkClicked();
+
+  // The web contents that successfully submitted the Autofill dialog (causing
+  // this bubble to show).
+  content::WebContents* web_contents() { return web_contents_; }
+  const content::WebContents* web_contents() const { return web_contents_; }
+
+ protected:
+  // Creates a bubble connected to |web_contents|.
+  explicit GeneratedCreditCardBubbleController(content::WebContents* contents);
+
+  // Returns a base::WeakPtr that references |this|. Exposed for testing.
+  base::WeakPtr<GeneratedCreditCardBubbleController> GetWeakPtr();
+
+  // Creates and returns an Autofill credit card bubble. Exposed for testing.
+  virtual base::WeakPtr<GeneratedCreditCardBubbleView> CreateBubble();
+
+  // Returns a weak reference to |bubble_|. May be invalid/NULL.
+  virtual base::WeakPtr<GeneratedCreditCardBubbleView> bubble();
+
+  // Returns whether the bubble can currently show itself.
+  virtual bool CanShow() const;
+
+  // Whether the generated card bubble should be shown initially when showing
+  // the anchor icon. This does not affect whether the generated card's icon
+  // will show in the omnibox.
+  bool ShouldDisplayBubbleInitially() const;
+
+  // Generates the correct bubble text and text highlighting ranges and shows a
+  // bubble to educate the user about generated (fronting) cards and how they
+  // are used to bill their original (backing) card. Exposed for testing.
+  virtual void SetupAndShow(const base::string16& backing_card_name,
+                            const base::string16& fronting_card_name);
+
+ private:
+  friend class
+      content::WebContentsUserData<GeneratedCreditCardBubbleController>;
+
+  // An internal helper to show the bubble.
+  void Show(bool was_anchor_click);
+
+  // Updates the omnibox icon that |bubble_| is anchored to.
+  void UpdateAnchor();
+
+  // Hides |bubble_| (if it exists and isn't already hiding).
+  void Hide();
+
+  // The web contents associated with this bubble.
+  content::WebContents* const web_contents_;
+
+  // The generated credit card number and associated backing card.
+  base::string16 fronting_card_name_;
+  base::string16 backing_card_name_;
+
+  // The title text of the bubble.
+  const base::string16 title_text_;
+
+  // Strings and ranges generated based on |backing_card_name_| and
+  // |fronting_card_name_|.
+  base::string16 contents_text_;
+  std::vector<TextRange> contents_text_ranges_;
+
+  // A bubble view that's created by calling either |Show*()| method; owned by
+  // the native widget/hierarchy, not this class (though this class must outlive
+  // |bubble_|). NULL in many cases.
+  base::WeakPtr<GeneratedCreditCardBubbleView> bubble_;
+
+  // Whether the anchor should currently be showing.
+  bool should_show_anchor_;
+
+  // A weak pointer factory for |Create()|.
+  base::WeakPtrFactory<GeneratedCreditCardBubbleController> weak_ptr_factory_;
+
+  DISALLOW_COPY_AND_ASSIGN(GeneratedCreditCardBubbleController);
+};
+
+}  // namespace autofill
+
+#endif  // CHROME_BROWSER_UI_AUTOFILL_GENERATED_CREDIT_CARD_BUBBLE_CONTROLLER_H_
diff --git a/chrome/browser/ui/autofill/generated_credit_card_bubble_controller_unittest.cc b/chrome/browser/ui/autofill/generated_credit_card_bubble_controller_unittest.cc
new file mode 100644
index 0000000..206f354
--- /dev/null
+++ b/chrome/browser/ui/autofill/generated_credit_card_bubble_controller_unittest.cc
@@ -0,0 +1,214 @@
+// 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/basictypes.h"
+#include "base/compiler_specific.h"
+#include "base/logging.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/prefs/pref_service.h"
+#include "base/strings/string16.h"
+#include "base/strings/utf_string_conversions.h"
+#include "chrome/browser/ui/autofill/generated_credit_card_bubble_controller.h"
+#include "chrome/browser/ui/autofill/test_generated_credit_card_bubble_view.h"
+#include "chrome/common/pref_names.h"
+#include "chrome/test/base/testing_profile.h"
+#include "components/autofill/core/browser/autofill_common_test.h"
+#include "content/public/browser/web_contents.h"
+#include "content/public/common/page_transition_types.h"
+#include "content/public/test/test_browser_thread_bundle.h"
+#include "content/public/test/web_contents_tester.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/base/range/range.h"
+
+#if defined(OS_WIN)
+#include "ui/base/win/scoped_ole_initializer.h"
+#endif
+
+namespace autofill {
+
+namespace {
+
+base::string16 BackingCard() {
+  return ASCIIToUTF16("Visa - 1111");
+}
+
+base::string16 FrontingCard() {
+  return ASCIIToUTF16("Mastercard - 4444");
+}
+
+base::string16 RangeOfString(const base::string16& string,
+                             const ui::Range& range) {
+  return string.substr(range.start(), range.end() - range.start());
+}
+
+class TestGeneratedCreditCardBubbleController
+    : public GeneratedCreditCardBubbleController {
+ public:
+  explicit TestGeneratedCreditCardBubbleController(
+      content::WebContents* contents)
+      : GeneratedCreditCardBubbleController(contents) {
+    contents->SetUserData(UserDataKey(), this);
+  }
+
+  virtual ~TestGeneratedCreditCardBubbleController() {}
+
+  bool IsInstalled() const {
+    return web_contents()->GetUserData(UserDataKey()) == this;
+  }
+
+  TestGeneratedCreditCardBubbleView* GetTestingBubble() {
+    return static_cast<TestGeneratedCreditCardBubbleView*>(
+        GeneratedCreditCardBubbleController::bubble().get());
+  }
+
+ protected:
+  virtual base::WeakPtr<GeneratedCreditCardBubbleView> CreateBubble() OVERRIDE {
+    return TestGeneratedCreditCardBubbleView::Create(GetWeakPtr());
+  }
+
+  virtual bool CanShow() const OVERRIDE {
+    return true;
+  }
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(TestGeneratedCreditCardBubbleController);
+};
+
+class GeneratedCreditCardBubbleControllerTest : public testing::Test {
+ public:
+  GeneratedCreditCardBubbleControllerTest()
+      : test_web_contents_(
+            content::WebContentsTester::CreateTestWebContents(
+                &profile_, NULL)) {}
+
+  virtual void SetUp() OVERRIDE {
+    // Attaches immediately to |test_web_contents_| so a test version will exist
+    // before a non-test version can be created.
+    new TestGeneratedCreditCardBubbleController(test_web_contents_.get());
+    ASSERT_TRUE(controller()->IsInstalled());
+  }
+
+ protected:
+  TestGeneratedCreditCardBubbleController* controller() {
+    return static_cast<TestGeneratedCreditCardBubbleController*>(
+        TestGeneratedCreditCardBubbleController::FromWebContents(
+            test_web_contents_.get()));
+  }
+
+  int GeneratedCardBubbleTimesShown() {
+    return profile_.GetPrefs()->GetInteger(
+        ::prefs::kAutofillGeneratedCardBubbleTimesShown);
+  }
+
+  void Show() {
+    ASSERT_TRUE(controller()->IsInstalled());
+    TestGeneratedCreditCardBubbleController::Show(test_web_contents_.get(),
+                                                  BackingCard(),
+                                                  FrontingCard());
+  }
+
+  void Navigate() {
+    NavigateWithTransition(content::PAGE_TRANSITION_LINK);
+  }
+
+  void Redirect() {
+    NavigateWithTransition(content::PAGE_TRANSITION_CLIENT_REDIRECT);
+  }
+
+ private:
+  void NavigateWithTransition(content::PageTransition trans) {
+    content::WebContentsTester::For(test_web_contents_.get())->TestDidNavigate(
+        test_web_contents_->GetRenderViewHost(), 1, GURL("about:blank"), trans);
+  }
+
+  content::TestBrowserThreadBundle thread_bundle_;
+#if defined(OS_WIN)
+  // Without this there will be drag and drop failures. http://crbug.com/227221
+  ui::ScopedOleInitializer ole_initializer_;
+#endif
+  TestingProfile profile_;
+  scoped_ptr<content::WebContents> test_web_contents_;
+};
+
+}  // namespace
+
+TEST_F(GeneratedCreditCardBubbleControllerTest, GeneratedCardBubbleTimesShown) {
+  ASSERT_EQ(0, GeneratedCardBubbleTimesShown());
+
+  // Ensure that showing the generated card UI bumps the persistent count.
+  Show();
+  EXPECT_EQ(1, GeneratedCardBubbleTimesShown());
+  EXPECT_TRUE(controller()->GetTestingBubble()->showing());
+
+  Show();
+  Show();
+  EXPECT_EQ(3, GeneratedCardBubbleTimesShown());
+  EXPECT_TRUE(controller()->GetTestingBubble()->showing());
+}
+
+TEST_F(GeneratedCreditCardBubbleControllerTest, TitleText) {
+  Show();
+  EXPECT_FALSE(controller()->TitleText().empty());
+}
+
+TEST_F(GeneratedCreditCardBubbleControllerTest, ContentsText) {
+  // Ensure that while showing the generated card UI that the bubble's text
+  // contains "Visa - 1111" and "Mastercard - 4444".
+  Show();
+  base::string16 contents_text = controller()->ContentsText();
+  EXPECT_NE(base::string16::npos, contents_text.find(BackingCard()));
+  EXPECT_NE(base::string16::npos, contents_text.find(FrontingCard()));
+
+  // Make sure that |bubble_text_| is regenerated the same way in |Setup()|.
+  Show();
+  EXPECT_EQ(contents_text, controller()->ContentsText());
+}
+
+TEST_F(GeneratedCreditCardBubbleControllerTest, ContentsTextRanges) {
+  // Check that the highlighted ranges in the bubble's text are correct.
+  Show();
+  const base::string16& contents_text = controller()->ContentsText();
+  const std::vector<TextRange>& ranges = controller()->ContentsTextRanges();
+
+  ASSERT_EQ(3U, ranges.size());
+
+  EXPECT_EQ(BackingCard(), RangeOfString(contents_text, ranges[0].range));
+  EXPECT_FALSE(ranges[0].is_link);
+
+  EXPECT_EQ(FrontingCard(), RangeOfString(contents_text, ranges[1].range));
+  EXPECT_FALSE(ranges[1].is_link);
+
+  EXPECT_TRUE(ranges[2].is_link);
+
+  Show();
+  EXPECT_EQ(ranges, controller()->ContentsTextRanges());
+}
+
+TEST_F(GeneratedCreditCardBubbleControllerTest, AnchorIcon) {
+  Show();
+  EXPECT_FALSE(controller()->AnchorIcon().IsEmpty());
+}
+
+TEST_F(GeneratedCreditCardBubbleControllerTest, HideOnNavigate) {
+  // When a user navigates away from a page (or refreshes) normally, the bubble
+  // should be hidden.
+  EXPECT_FALSE(controller()->GetTestingBubble());
+  Show();
+  EXPECT_TRUE(controller()->GetTestingBubble()->showing());
+
+  Navigate();
+  EXPECT_FALSE(controller());
+}
+
+TEST_F(GeneratedCreditCardBubbleControllerTest, StayOnRedirect) {
+  // If a page redirects right after submitting, the bubble should remain.
+  EXPECT_FALSE(controller()->GetTestingBubble());
+  Show();
+  EXPECT_TRUE(controller()->GetTestingBubble()->showing());
+
+  Redirect();
+  EXPECT_TRUE(controller()->GetTestingBubble()->showing());
+}
+
+}  // namespace autofill
diff --git a/chrome/browser/ui/autofill/generated_credit_card_bubble_view.cc b/chrome/browser/ui/autofill/generated_credit_card_bubble_view.cc
new file mode 100644
index 0000000..9044a1e
--- /dev/null
+++ b/chrome/browser/ui/autofill/generated_credit_card_bubble_view.cc
@@ -0,0 +1,24 @@
+// 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/ui/autofill/generated_credit_card_bubble_view.h"
+
+namespace autofill {
+
+// static
+const int GeneratedCreditCardBubbleView::kContentsWidth = 350;
+
+GeneratedCreditCardBubbleView::~GeneratedCreditCardBubbleView() {}
+
+#if !defined(TOOLKIT_VIEWS)
+// static
+base::WeakPtr<GeneratedCreditCardBubbleView>
+    GeneratedCreditCardBubbleView::Create(
+        const base::WeakPtr<GeneratedCreditCardBubbleController>& controller) {
+  // TODO(dbeam): make a bubble on all applicable platforms.
+  return base::WeakPtr<GeneratedCreditCardBubbleView>();
+}
+#endif
+
+}  // namespace autofill
diff --git a/chrome/browser/ui/autofill/generated_credit_card_bubble_view.h b/chrome/browser/ui/autofill/generated_credit_card_bubble_view.h
new file mode 100644
index 0000000..565495f
--- /dev/null
+++ b/chrome/browser/ui/autofill/generated_credit_card_bubble_view.h
@@ -0,0 +1,41 @@
+// 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_UI_AUTOFILL_GENERATED_CREDIT_CARD_BUBBLE_VIEW_H_
+#define CHROME_BROWSER_UI_AUTOFILL_GENERATED_CREDIT_CARD_BUBBLE_VIEW_H_
+
+#include "base/memory/weak_ptr.h"
+
+namespace autofill {
+
+class GeneratedCreditCardBubbleController;
+
+// A cross-platform interface for a bubble shown to educate users after a credit
+// card number is generated. Anchored to an omnibox icon and shown either on
+// creation or when the anchor is clicked. Hidden when focus is lost.
+class GeneratedCreditCardBubbleView {
+ public:
+  // The preferred size of the bubble's contents.
+  static const int kContentsWidth;
+
+  virtual ~GeneratedCreditCardBubbleView();
+
+  // Visually reveals the bubble.
+  virtual void Show() = 0;
+
+  // Hides the bubble from view.
+  virtual void Hide() = 0;
+
+  // Returns whether the bubble is currently in the process of hiding itself.
+  virtual bool IsHiding() const = 0;
+
+  // Creates a bubble that's operated by |controller| and owns itself.
+  // |controller| may be invalid while the bubble is closing.
+  static base::WeakPtr<GeneratedCreditCardBubbleView> Create(
+      const base::WeakPtr<GeneratedCreditCardBubbleController>& controller);
+};
+
+}  // namespace autofill
+
+#endif  // CHROME_BROWSER_UI_AUTOFILL_GENERATED_CREDIT_CARD_BUBBLE_VIEW_H_
diff --git a/chrome/browser/ui/autofill/mock_new_credit_card_bubble_controller.cc b/chrome/browser/ui/autofill/mock_new_credit_card_bubble_controller.cc
new file mode 100644
index 0000000..e2dfa87
--- /dev/null
+++ b/chrome/browser/ui/autofill/mock_new_credit_card_bubble_controller.cc
@@ -0,0 +1,30 @@
+// 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/ui/autofill/mock_new_credit_card_bubble_controller.h"
+
+#include "base/logging.h"
+#include "components/autofill/core/browser/autofill_profile.h"
+#include "components/autofill/core/browser/credit_card.h"
+
+namespace autofill {
+
+MockNewCreditCardBubbleController::MockNewCreditCardBubbleController()
+    : bubbles_shown_(0) {}
+
+MockNewCreditCardBubbleController::~MockNewCreditCardBubbleController() {}
+
+void MockNewCreditCardBubbleController::Show(
+    scoped_ptr<CreditCard> new_card,
+    scoped_ptr<AutofillProfile> billing_profile) {
+  CHECK(new_card);
+  CHECK(billing_profile);
+
+  new_card_ = new_card.Pass();
+  billing_profile_ = billing_profile.Pass();
+
+  ++bubbles_shown_;
+}
+
+}  // namespace autofill
diff --git a/chrome/browser/ui/autofill/mock_new_credit_card_bubble_controller.h b/chrome/browser/ui/autofill/mock_new_credit_card_bubble_controller.h
new file mode 100644
index 0000000..c3b7d9e
--- /dev/null
+++ b/chrome/browser/ui/autofill/mock_new_credit_card_bubble_controller.h
@@ -0,0 +1,44 @@
+// 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_UI_AUTOFILL_MOCK_NEW_CREDIT_CARD_BUBBLE_CONTROLLER_H_
+#define CHROME_BROWSER_UI_AUTOFILL_MOCK_NEW_CREDIT_CARD_BUBBLE_CONTROLLER_H_
+
+#include "base/basictypes.h"
+#include "base/memory/scoped_ptr.h"
+
+namespace autofill {
+
+class AutofillProfile;
+class CreditCard;
+
+class MockNewCreditCardBubbleController {
+ public:
+  MockNewCreditCardBubbleController();
+
+  ~MockNewCreditCardBubbleController();
+
+  void Show(scoped_ptr<CreditCard> new_card,
+            scoped_ptr<AutofillProfile> billing_profile);
+
+  const CreditCard* new_card() const { return new_card_.get(); }
+
+  const AutofillProfile* billing_profile() const {
+    return billing_profile_.get();
+  }
+
+  int bubbles_shown() const { return bubbles_shown_; }
+
+ private:
+  scoped_ptr<CreditCard> new_card_;
+  scoped_ptr<AutofillProfile> billing_profile_;
+
+  int bubbles_shown_;
+
+  DISALLOW_COPY_AND_ASSIGN(MockNewCreditCardBubbleController);
+};
+
+}  // namespace autofill
+
+#endif  // CHROME_BROWSER_UI_AUTOFILL_MOCK_NEW_CREDIT_CARD_BUBBLE_CONTROLLER_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
new file mode 100644
index 0000000..2fb5db3
--- /dev/null
+++ b/chrome/browser/ui/autofill/new_credit_card_bubble_controller.cc
@@ -0,0 +1,132 @@
+// 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/ui/autofill/new_credit_card_bubble_controller.h"
+
+#include <string>
+
+#include "base/logging.h"
+#include "base/strings/utf_string_conversions.h"
+#include "chrome/browser/browser_process.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/ui/autofill/data_model_wrapper.h"
+#include "chrome/browser/ui/autofill/new_credit_card_bubble_view.h"
+#include "chrome/browser/ui/browser_finder.h"
+#include "chrome/browser/ui/chrome_pages.h"
+#include "chrome/browser/ui/host_desktop.h"
+#include "chrome/common/url_constants.h"
+#include "components/autofill/core/browser/autofill_profile.h"
+#include "components/autofill/core/browser/credit_card.h"
+#include "grit/chromium_strings.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"
+
+namespace autofill {
+
+namespace {
+
+static const int kMaxGeneratedCardTimesToShow = 5;
+static const char kWalletGeneratedCardLearnMoreLink[] =
+    "http://support.google.com/wallet/bin/answer.py?hl=en&answer=2740044";
+
+}  // namespace
+
+CreditCardDescription::CreditCardDescription() {}
+CreditCardDescription::~CreditCardDescription() {}
+
+NewCreditCardBubbleController::~NewCreditCardBubbleController() {
+  Hide();
+}
+
+// static
+void NewCreditCardBubbleController::Show(
+    Profile* profile,
+    scoped_ptr<CreditCard> new_card,
+    scoped_ptr<AutofillProfile> billing_profile) {
+  (new NewCreditCardBubbleController(profile))->SetupAndShow(
+      new_card.Pass(),
+      billing_profile.Pass());
+}
+
+const base::string16& NewCreditCardBubbleController::TitleText() const {
+  return title_text_;
+}
+
+const CreditCardDescription& NewCreditCardBubbleController::CardDescription()
+    const {
+  return card_desc_;
+}
+
+const base::string16& NewCreditCardBubbleController::LinkText() const {
+  return link_text_;
+}
+
+void NewCreditCardBubbleController::OnBubbleDestroyed() {
+  delete this;
+}
+
+void NewCreditCardBubbleController::OnLinkClicked() {
+  Browser* browser = chrome::FindTabbedBrowser(profile_, false,
+                                               chrome::GetActiveDesktop());
+  if (browser)
+    chrome::ShowSettingsSubPage(browser, chrome::kAutofillSubPage);
+
+  Hide();
+}
+
+NewCreditCardBubbleController::NewCreditCardBubbleController(Profile* profile)
+    : profile_(profile),
+      title_text_(l10n_util::GetStringUTF16(
+          IDS_AUTOFILL_NEW_CREDIT_CARD_BUBBLE_TITLE)),
+      link_text_(l10n_util::GetStringUTF16(
+          IDS_AUTOFILL_NEW_CREDIT_CARD_BUBBLE_LINK)),
+      weak_ptr_factory_(this) {}
+
+base::WeakPtr<NewCreditCardBubbleView> NewCreditCardBubbleController::
+    CreateBubble() {
+  return NewCreditCardBubbleView::Create(this);
+}
+
+base::WeakPtr<NewCreditCardBubbleView> NewCreditCardBubbleController::
+    bubble() {
+  return bubble_;
+}
+
+void NewCreditCardBubbleController::SetupAndShow(
+    scoped_ptr<CreditCard> new_card,
+    scoped_ptr<AutofillProfile> billing_profile) {
+  DCHECK(new_card);
+  DCHECK(billing_profile);
+
+  new_card_ = new_card.Pass();
+  billing_profile_ = billing_profile.Pass();
+
+  const base::string16 card_number =
+      new_card_->GetRawInfo(CREDIT_CARD_NUMBER);
+  ui::ResourceBundle& rb = ResourceBundle::GetSharedInstance();
+  card_desc_.icon = rb.GetImageNamed(
+      CreditCard::IconResourceId(CreditCard::GetCreditCardType(card_number)));
+  card_desc_.name = new_card_->TypeAndLastFourDigits();
+
+  AutofillProfileWrapper wrapper(billing_profile_.get(), 0);
+  card_desc_.description = wrapper.GetDisplayText();
+
+  bubble_ = CreateBubble();
+  if (!bubble_) {
+    // TODO(dbeam): Make a bubble on all applicable platforms.
+    delete this;
+    return;
+  }
+
+  bubble_->Show();
+}
+
+void NewCreditCardBubbleController::Hide() {
+  if (bubble_)
+    bubble_->Hide();
+}
+
+}  // namespace autofill
diff --git a/chrome/browser/ui/autofill/new_credit_card_bubble_controller.h b/chrome/browser/ui/autofill/new_credit_card_bubble_controller.h
new file mode 100644
index 0000000..2b7f6d9
--- /dev/null
+++ b/chrome/browser/ui/autofill/new_credit_card_bubble_controller.h
@@ -0,0 +1,132 @@
+// 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_UI_AUTOFILL_NEW_CREDIT_CARD_BUBBLE_CONTROLLER_H_
+#define CHROME_BROWSER_UI_AUTOFILL_NEW_CREDIT_CARD_BUBBLE_CONTROLLER_H_
+
+#include "base/basictypes.h"
+#include "base/compiler_specific.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/memory/weak_ptr.h"
+#include "base/strings/string16.h"
+#include "ui/gfx/image/image.h"
+
+class Profile;
+
+namespace autofill {
+
+class NewCreditCardBubbleView;
+class AutofillProfile;
+class CreditCard;
+
+// A simple wrapper that contains descriptive information about a credit card
+// that should be shown in the content of the bubble.
+struct CreditCardDescription {
+ CreditCardDescription();
+ ~CreditCardDescription();
+ // The icon of the credit card issuer (i.e. Visa, Mastercard).
+ gfx::Image icon;
+ // The display name of the card. Shown next to the icon.
+ base::string16 name;
+ // A longer description of the card being shown in the bubble.
+ base::string16 description;
+};
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// NewCreditCardBubbleController
+//
+//  A class to control showing/hiding a bubble after saved a new card in Chrome.
+//  Here's a visual reference to what this bubble looks like:
+//
+//  @----------------------------------------@
+//  |  Bubble title text                     |
+//  |                                        |
+//  |  [ Card icon ] Card name               |
+//  |  Card description that will probably   |
+//  |  also span multiple lines.             |
+//  |                                        |
+//  |  Learn more link                       |
+//  @----------------------------------------@
+//
+////////////////////////////////////////////////////////////////////////////////
+class NewCreditCardBubbleController {
+ public:
+  virtual ~NewCreditCardBubbleController();
+
+  // Show a bubble informing the user that new credit card data has been saved.
+  // This bubble points to the settings menu. Ownership of |new_card|
+  // and |billing_profile| are transferred by this call.
+  static void Show(Profile* profile,
+                   scoped_ptr<CreditCard> new_card,
+                   scoped_ptr<AutofillProfile> billing_profile);
+
+  // The bubble's title text.
+  const base::string16& TitleText() const;
+
+  // A card description to show in the bubble.
+  const CreditCardDescription& CardDescription() const;
+
+  // The text of the link shown at the bubble of the bubble.
+  const base::string16& LinkText() const;
+
+  // Called when |bubble_| is destroyed.
+  void OnBubbleDestroyed();
+
+  // Called when the link at the bottom of the bubble is clicked.
+  void OnLinkClicked();
+
+  // Returns the profile this bubble is associated with.
+  Profile* profile() { return profile_; }
+
+ protected:
+  // Create a bubble attached to |profile|.
+  explicit NewCreditCardBubbleController(Profile* profile);
+
+  // Creates and returns an Autofill credit card bubble. Exposed for testing.
+  virtual base::WeakPtr<NewCreditCardBubbleView> CreateBubble();
+
+  // Returns a weak reference to |bubble_|. May be invalid/NULL.
+  virtual base::WeakPtr<NewCreditCardBubbleView> bubble();
+
+  // Show a bubble notifying the user that new credit card data has been saved.
+  // Exposed for testing.
+  virtual void SetupAndShow(scoped_ptr<CreditCard> new_card,
+                            scoped_ptr<AutofillProfile> billing_profile);
+
+ private:
+  // Hides |bubble_| if it exists.
+  void Hide();
+
+  // The profile this bubble is associated with.
+  Profile* const profile_;
+
+  // The newly saved credit card and assocated billing information.
+  scoped_ptr<CreditCard> new_card_;
+  scoped_ptr<AutofillProfile> billing_profile_;
+
+  // The title text of the bubble.
+  const base::string16 title_text_;
+
+  // The bubble's link text.
+  const base::string16 link_text_;
+
+  // Strings and descriptions that are generated based on |new_card_| and
+  // |billing_profile_|.
+  struct CreditCardDescription card_desc_;
+
+  // A bubble view that's created by calling either |Show*()| method; owned by
+  // the native widget/hierarchy, not this class (though this class must outlive
+  // |bubble_|). NULL in many cases.
+  base::WeakPtr<NewCreditCardBubbleView> bubble_;
+
+  // A weak pointer factory for |Create()|.
+  base::WeakPtrFactory<NewCreditCardBubbleController> weak_ptr_factory_;
+
+  DISALLOW_COPY_AND_ASSIGN(NewCreditCardBubbleController);
+};
+
+}  // namespace autofill
+
+#endif  // CHROME_BROWSER_UI_AUTOFILL_NEW_CREDIT_CARD_BUBBLE_CONTROLLER_H_
diff --git a/chrome/browser/ui/autofill/new_credit_card_bubble_view.cc b/chrome/browser/ui/autofill/new_credit_card_bubble_view.cc
new file mode 100644
index 0000000..2b86d4e
--- /dev/null
+++ b/chrome/browser/ui/autofill/new_credit_card_bubble_view.cc
@@ -0,0 +1,23 @@
+// 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/ui/autofill/new_credit_card_bubble_view.h"
+
+namespace autofill {
+
+NewCreditCardBubbleView::~NewCreditCardBubbleView() {}
+
+// static
+const int NewCreditCardBubbleView::kContentsWidth = 400;
+
+#if !defined(TOOLKIT_VIEWS)
+// static
+base::WeakPtr<NewCreditCardBubbleView> NewCreditCardBubbleView::Create(
+    NewCreditCardBubbleController* controller) {
+  // TODO(dbeam): make a bubble on all applicable platforms.
+  return base::WeakPtr<NewCreditCardBubbleView>();
+}
+#endif
+
+}  // namespace autofill
diff --git a/chrome/browser/ui/autofill/new_credit_card_bubble_view.h b/chrome/browser/ui/autofill/new_credit_card_bubble_view.h
new file mode 100644
index 0000000..e6ef8f8
--- /dev/null
+++ b/chrome/browser/ui/autofill/new_credit_card_bubble_view.h
@@ -0,0 +1,38 @@
+// 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_UI_AUTOFILL_NEW_CREDIT_CARD_BUBBLE_VIEW_H_
+#define CHROME_BROWSER_UI_AUTOFILL_NEW_CREDIT_CARD_BUBBLE_VIEW_H_
+
+#include "base/memory/weak_ptr.h"
+
+namespace autofill {
+
+class NewCreditCardBubbleController;
+
+// A cross-platform interface for a bubble that is shown when a new credit card
+// is saved. Points at the settings menu in the toolbar and hides when
+// activation is lost.
+class NewCreditCardBubbleView {
+ public:
+  // The preferred width of the bubble's contents.
+  static const int kContentsWidth;
+
+  virtual ~NewCreditCardBubbleView();
+
+  // Visually reveals the bubble.
+  virtual void Show() = 0;
+
+  // Hides the bubble from view.
+  virtual void Hide() = 0;
+
+  // Creates a bubble that's operated by |controller| and owns itself.
+  // |controller| may be invalid while the bubble is closing.
+  static base::WeakPtr<NewCreditCardBubbleView> Create(
+      NewCreditCardBubbleController* controller);
+};
+
+}  // namespace autofill
+
+#endif  // CHROME_BROWSER_UI_AUTOFILL_NEW_CREDIT_CARD_BUBBLE_VIEW_H_
diff --git a/chrome/browser/ui/autofill/tab_autofill_manager_delegate.cc b/chrome/browser/ui/autofill/tab_autofill_manager_delegate.cc
index cf4ab39..4b50949 100644
--- a/chrome/browser/ui/autofill/tab_autofill_manager_delegate.cc
+++ b/chrome/browser/ui/autofill/tab_autofill_manager_delegate.cc
@@ -13,7 +13,7 @@
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/autofill/autocheckout_bubble.h"
 #include "chrome/browser/ui/autofill/autocheckout_bubble_controller.h"
-#include "chrome/browser/ui/autofill/autofill_dialog_controller_impl.h"
+#include "chrome/browser/ui/autofill/autofill_dialog_controller.h"
 #include "chrome/browser/ui/autofill/autofill_popup_controller_impl.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_finder.h"
@@ -150,19 +150,19 @@
     DialogType dialog_type,
     const base::Callback<void(const FormStructure*,
                               const std::string&)>& callback) {
-#if defined(ENABLE_AUTOFILL_DIALOG)
   HideRequestAutocompleteDialog();
 
-  dialog_controller_ = AutofillDialogControllerImpl::Create(web_contents_,
-                                                            form,
-                                                            source_url,
-                                                            dialog_type,
-                                                            callback);
-  dialog_controller_->Show();
-#else
-  callback.Run(NULL, std::string());
-  NOTIMPLEMENTED();
-#endif  // #if !defined(ENABLE_AUTOFILL_DIALOG)
+  dialog_controller_ = AutofillDialogController::Create(web_contents_,
+                                                        form,
+                                                        source_url,
+                                                        dialog_type,
+                                                        callback);
+  if (dialog_controller_) {
+    dialog_controller_->Show();
+  } else {
+    callback.Run(NULL, std::string());
+    NOTIMPLEMENTED();
+  }
 }
 
 void TabAutofillManagerDelegate::ShowAutofillPopup(
@@ -246,7 +246,7 @@
   bool was_redirect = details.entry &&
       content::PageTransitionIsRedirect(details.entry->GetTransitionType());
 
-  if (dialog_controller_->dialog_type() == DIALOG_TYPE_REQUEST_AUTOCOMPLETE ||
+  if (dialog_controller_->GetDialogType() == DIALOG_TYPE_REQUEST_AUTOCOMPLETE ||
       (!was_redirect && !preserve_dialog)) {
     HideRequestAutocompleteDialog();
   }
diff --git a/chrome/browser/ui/autofill/tab_autofill_manager_delegate.h b/chrome/browser/ui/autofill/tab_autofill_manager_delegate.h
index 40588b5..21d9a61 100644
--- a/chrome/browser/ui/autofill/tab_autofill_manager_delegate.h
+++ b/chrome/browser/ui/autofill/tab_autofill_manager_delegate.h
@@ -25,7 +25,7 @@
 namespace autofill {
 
 class AutocheckoutBubble;
-class AutofillDialogControllerImpl;
+class AutofillDialogController;
 class AutofillPopupControllerImpl;
 struct FormData;
 
@@ -92,7 +92,7 @@
   virtual void WasShown() OVERRIDE;
 
   // Exposed for testing.
-  AutofillDialogControllerImpl* GetDialogControllerForTesting() {
+  AutofillDialogController* GetDialogControllerForTesting() {
     return dialog_controller_.get();
   }
 
@@ -101,7 +101,7 @@
   friend class content::WebContentsUserData<TabAutofillManagerDelegate>;
 
   content::WebContents* const web_contents_;
-  base::WeakPtr<AutofillDialogControllerImpl> dialog_controller_;
+  base::WeakPtr<AutofillDialogController> dialog_controller_;
   base::WeakPtr<AutocheckoutBubble> autocheckout_bubble_;
   base::WeakPtr<AutofillPopupControllerImpl> popup_controller_;
 
diff --git a/chrome/browser/ui/autofill/test_autofill_credit_card_bubble.cc b/chrome/browser/ui/autofill/test_autofill_credit_card_bubble.cc
deleted file mode 100644
index 237b969..0000000
--- a/chrome/browser/ui/autofill/test_autofill_credit_card_bubble.cc
+++ /dev/null
@@ -1,40 +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/ui/autofill/test_autofill_credit_card_bubble.h"
-
-namespace autofill {
-
-// static
-base::WeakPtr<TestAutofillCreditCardBubble>
-    TestAutofillCreditCardBubble::Create(
-        const base::WeakPtr<AutofillCreditCardBubbleController>& controller) {
-  return (new TestAutofillCreditCardBubble(controller))->GetWeakPtr();
-}
-
-TestAutofillCreditCardBubble::~TestAutofillCreditCardBubble() {}
-
-void TestAutofillCreditCardBubble::Show() {
-  showing_ = true;
-}
-
-void TestAutofillCreditCardBubble::Hide() {
-  delete this;
-}
-
-bool TestAutofillCreditCardBubble::IsHiding() const {
-  return !showing_;
-}
-
-base::WeakPtr<TestAutofillCreditCardBubble>
-    TestAutofillCreditCardBubble::GetWeakPtr() {
-  return weak_ptr_factory_.GetWeakPtr();
-}
-
-TestAutofillCreditCardBubble::TestAutofillCreditCardBubble(
-    const base::WeakPtr<AutofillCreditCardBubbleController>& controller)
-    : showing_(false),
-      weak_ptr_factory_(this) {}
-
-}  // namespace autofill
diff --git a/chrome/browser/ui/autofill/test_autofill_credit_card_bubble.h b/chrome/browser/ui/autofill/test_autofill_credit_card_bubble.h
deleted file mode 100644
index 4eef7b7..0000000
--- a/chrome/browser/ui/autofill/test_autofill_credit_card_bubble.h
+++ /dev/null
@@ -1,53 +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_UI_AUTOFILL_TEST_AUTOFILL_CREDIT_CARD_BUBBLE_H_
-#define CHROME_BROWSER_UI_AUTOFILL_TEST_AUTOFILL_CREDIT_CARD_BUBBLE_H_
-
-#include "base/basictypes.h"
-#include "base/compiler_specific.h"
-#include "base/memory/weak_ptr.h"
-#include "chrome/browser/ui/autofill/autofill_credit_card_bubble.h"
-
-namespace autofill {
-
-////////////////////////////////////////////////////////////////////////////////
-//
-// TestAutofillCreditCardBubble
-//
-//  A cross-platform, headless bubble that doesn't conflict with other top-level
-//  widgets/windows.
-////////////////////////////////////////////////////////////////////////////////
-class TestAutofillCreditCardBubble : public AutofillCreditCardBubble {
- public:
-  // Creates a bubble and returns a weak reference to it.
-  static base::WeakPtr<TestAutofillCreditCardBubble> Create(
-      const base::WeakPtr<AutofillCreditCardBubbleController>& controller);
-
-  virtual ~TestAutofillCreditCardBubble();
-
-  // AutofillCreditCardBubble:
-  virtual void Show() OVERRIDE;
-  virtual void Hide() OVERRIDE;
-  virtual bool IsHiding() const OVERRIDE;
-
-  base::WeakPtr<TestAutofillCreditCardBubble> GetWeakPtr();
-
-  bool showing() const { return showing_; }
-
- private:
-  explicit TestAutofillCreditCardBubble(
-      const base::WeakPtr<AutofillCreditCardBubbleController>& controller);
-
-  // Whether the bubble is currently showing or not.
-  bool showing_;
-
-  base::WeakPtrFactory<TestAutofillCreditCardBubble> weak_ptr_factory_;
-
-  DISALLOW_COPY_AND_ASSIGN(TestAutofillCreditCardBubble);
-};
-
-}  // namespace autofill
-
-#endif  // CHROME_BROWSER_UI_AUTOFILL_TEST_AUTOFILL_CREDIT_CARD_BUBBLE_H_
diff --git a/chrome/browser/ui/autofill/test_generated_credit_card_bubble_view.cc b/chrome/browser/ui/autofill/test_generated_credit_card_bubble_view.cc
new file mode 100644
index 0000000..dd19c63
--- /dev/null
+++ b/chrome/browser/ui/autofill/test_generated_credit_card_bubble_view.cc
@@ -0,0 +1,43 @@
+// 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/ui/autofill/test_generated_credit_card_bubble_view.h"
+
+#include "chrome/browser/ui/autofill/generated_credit_card_bubble_controller.h"
+
+namespace autofill {
+
+// static
+base::WeakPtr<TestGeneratedCreditCardBubbleView>
+    TestGeneratedCreditCardBubbleView::Create(
+        const base::WeakPtr<GeneratedCreditCardBubbleController>& controller) {
+  return (new TestGeneratedCreditCardBubbleView(controller))->GetWeakPtr();
+}
+
+TestGeneratedCreditCardBubbleView::~TestGeneratedCreditCardBubbleView() {}
+
+void TestGeneratedCreditCardBubbleView::Show() {
+  showing_ = true;
+}
+
+void TestGeneratedCreditCardBubbleView::Hide() {
+  delete this;
+}
+
+bool TestGeneratedCreditCardBubbleView::IsHiding() const {
+  return !showing_;
+}
+
+base::WeakPtr<TestGeneratedCreditCardBubbleView>
+    TestGeneratedCreditCardBubbleView::GetWeakPtr() {
+  return weak_ptr_factory_.GetWeakPtr();
+}
+
+TestGeneratedCreditCardBubbleView::TestGeneratedCreditCardBubbleView(
+    const base::WeakPtr<GeneratedCreditCardBubbleController>& controller)
+    : controller_(controller),
+      showing_(false),
+      weak_ptr_factory_(this) {}
+
+}  // namespace autofill
diff --git a/chrome/browser/ui/autofill/test_generated_credit_card_bubble_view.h b/chrome/browser/ui/autofill/test_generated_credit_card_bubble_view.h
new file mode 100644
index 0000000..5892ff0
--- /dev/null
+++ b/chrome/browser/ui/autofill/test_generated_credit_card_bubble_view.h
@@ -0,0 +1,57 @@
+// 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_UI_AUTOFILL_TEST_GENERATED_CREDIT_CARD_BUBBLE_VIEW_H_
+#define CHROME_BROWSER_UI_AUTOFILL_TEST_GENERATED_CREDIT_CARD_BUBBLE_VIEW_H_
+
+#include "base/basictypes.h"
+#include "base/compiler_specific.h"
+#include "base/memory/weak_ptr.h"
+#include "chrome/browser/ui/autofill/generated_credit_card_bubble_view.h"
+
+namespace autofill {
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// TestGeneratedCreditCardBubbleView
+//
+//  A cross-platform, headless bubble that doesn't conflict with other top-level
+//  widgets/windows.
+//
+////////////////////////////////////////////////////////////////////////////////
+class TestGeneratedCreditCardBubbleView : public GeneratedCreditCardBubbleView {
+ public:
+  // Creates a bubble and returns a weak reference to it.
+  static base::WeakPtr<TestGeneratedCreditCardBubbleView> Create(
+      const base::WeakPtr<GeneratedCreditCardBubbleController>& controller);
+
+  virtual ~TestGeneratedCreditCardBubbleView();
+
+  // GeneratedCreditCardBubbleView:
+  virtual void Show() OVERRIDE;
+  virtual void Hide() OVERRIDE;
+  virtual bool IsHiding() const OVERRIDE;
+
+  base::WeakPtr<TestGeneratedCreditCardBubbleView> GetWeakPtr();
+
+  bool showing() const { return showing_; }
+
+ private:
+  explicit TestGeneratedCreditCardBubbleView(
+      const base::WeakPtr<GeneratedCreditCardBubbleController>& controller);
+
+  // A weak reference to the controller that operates this bubble.
+  base::WeakPtr<GeneratedCreditCardBubbleController> controller_;
+
+  // Whether the bubble is currently showing or not.
+  bool showing_;
+
+  base::WeakPtrFactory<TestGeneratedCreditCardBubbleView> weak_ptr_factory_;
+
+  DISALLOW_COPY_AND_ASSIGN(TestGeneratedCreditCardBubbleView);
+};
+
+}  // namespace autofill
+
+#endif  // CHROME_BROWSER_UI_AUTOFILL_TEST_GENERATED_CREDIT_CARD_BUBBLE_VIEW_H_
diff --git a/chrome/browser/ui/browser.cc b/chrome/browser/ui/browser.cc
index 54251d0..1424f7e 100644
--- a/chrome/browser/ui/browser.cc
+++ b/chrome/browser/ui/browser.cc
@@ -747,6 +747,13 @@
     UpdateToolbar(false);
 }
 
+void Browser::OnWebContentsInstantSupportDisabled(
+    const content::WebContents* web_contents) {
+  DCHECK(web_contents);
+  if (tab_strip_model_->GetActiveWebContents() == web_contents)
+    UpdateToolbar(false);
+}
+
 ///////////////////////////////////////////////////////////////////////////////
 // Browser, Assorted browser commands:
 
@@ -1211,25 +1218,24 @@
     return;
   window_has_shown_ = true;
 
-// CurrentProcessInfo::CreationTime() is currently only implemented on Mac and
-// Windows.
-#if defined(OS_MACOSX) || defined(OS_WIN)
+// CurrentProcessInfo::CreationTime() is missing on some platforms.
+#if defined(OS_MACOSX) || defined(OS_WIN) || defined(OS_LINUX)
   // Measure the latency from startup till the first browser window becomes
   // visible.
   static bool is_first_browser_window = true;
   if (is_first_browser_window &&
       !startup_metric_utils::WasNonBrowserUIDisplayed()) {
     is_first_browser_window = false;
-    const base::Time* process_creation_time =
+    const base::Time process_creation_time =
         base::CurrentProcessInfo::CreationTime();
 
-    if (process_creation_time) {
+    if (!process_creation_time.is_null()) {
       UMA_HISTOGRAM_LONG_TIMES(
           "Startup.BrowserWindowDisplay",
-          base::Time::Now() - *process_creation_time);
+          base::Time::Now() - process_creation_time);
     }
   }
-#endif  // defined(OS_MACOSX) || defined(OS_WIN)
+#endif  // defined(OS_MACOSX) || defined(OS_WIN) || defined(OS_LINUX)
 
   // Nothing to do for non-tabbed windows.
   if (!is_type_tabbed())
diff --git a/chrome/browser/ui/browser.h b/chrome/browser/ui/browser.h
index 2093f48..22e7fb0 100644
--- a/chrome/browser/ui/browser.h
+++ b/chrome/browser/ui/browser.h
@@ -320,7 +320,7 @@
   DownloadClosePreventionType OkToCloseWithInProgressDownloads(
       int* num_downloads_blocking) const;
 
-  // Tab adding/showing functions /////////////////////////////////////////////
+  // External state change handling ////////////////////////////////////////////
 
   // Invoked when the fullscreen state of the window changes.
   // BrowserWindow::EnterFullscreen invokes this after the window has become
@@ -330,6 +330,11 @@
   // Invoked when visible SSL state (as defined by SSLStatus) changes.
   void VisibleSSLStateChanged(content::WebContents* web_contents);
 
+  // Invoked when the |web_contents| no longer supports Instant. Refreshes the
+  // omnibox so it no longer shows search terms.
+  void OnWebContentsInstantSupportDisabled(
+      const content::WebContents* web_contents);
+
   // Assorted browser commands ////////////////////////////////////////////////
 
   // NOTE: Within each of the following sections, the IDs are ordered roughly by
diff --git a/chrome/browser/ui/browser_instant_controller.cc b/chrome/browser/ui/browser_instant_controller.cc
index 650da0d..2e6c12d 100644
--- a/chrome/browser/ui/browser_instant_controller.cc
+++ b/chrome/browser/ui/browser_instant_controller.cc
@@ -18,6 +18,7 @@
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_window.h"
 #include "chrome/browser/ui/omnibox/location_bar.h"
+#include "chrome/browser/ui/omnibox/omnibox_popup_model.h"
 #include "chrome/browser/ui/omnibox/omnibox_view.h"
 #include "chrome/browser/ui/search/instant_ntp.h"
 #include "chrome/browser/ui/search/search_model.h"
@@ -30,6 +31,7 @@
 #include "content/public/browser/render_process_host.h"
 #include "content/public/browser/user_metrics.h"
 #include "content/public/browser/web_contents.h"
+#include "content/public/browser/web_contents_view.h"
 
 using content::UserMetricsAction;
 
@@ -151,18 +153,42 @@
                                                       index);
 }
 
-void BrowserInstantController::FocusOmnibox(bool caret_visibility) {
+void BrowserInstantController::FocusOmnibox(OmniboxFocusState state) {
   OmniboxView* omnibox_view = browser_->window()->GetLocationBar()->
       GetLocationEntry();
-  omnibox_view->SetFocus();
-  omnibox_view->model()->SetCaretVisibility(caret_visibility);
-  if (!caret_visibility) {
-    // If the user clicked on the fakebox, any text already in the omnibox
-    // should get cleared when they start typing. Selecting all the existing
-    // text is a convenient way to accomplish this. It also gives a slight
-    // visual cue to users who really understand selection state about what will
-    // happen if they start typing.
-    omnibox_view->SelectAll(false);
+
+  // Do not add a default case in the switch block for the following reasons:
+  // (1) Explicitly handle the new states. If new states are added in the
+  // OmniboxFocusState, the compiler will warn the developer to handle the new
+  // states.
+  // (2) An attacker may control the renderer and sends the browser process a
+  // malformed IPC. This function responds to the invalid |state| values by
+  // doing nothing instead of crashing the browser process (intentional no-op).
+  switch (state) {
+    case OMNIBOX_FOCUS_VISIBLE:
+      omnibox_view->SetFocus();
+      omnibox_view->model()->SetCaretVisibility(true);
+      break;
+    case OMNIBOX_FOCUS_INVISIBLE:
+      omnibox_view->SetFocus();
+      omnibox_view->model()->SetCaretVisibility(false);
+      // If the user clicked on the fakebox, any text already in the omnibox
+      // should get cleared when they start typing. Selecting all the existing
+      // text is a convenient way to accomplish this. It also gives a slight
+      // visual cue to users who really understand selection state about what
+      // will happen if they start typing.
+      omnibox_view->SelectAll(false);
+      break;
+    case OMNIBOX_FOCUS_NONE:
+      // Remove focus only if the popup is closed. This will prevent someone
+      // from changing the omnibox value and closing the popup without user
+      // interaction.
+      if (!omnibox_view->model()->popup_model()->IsOpen()) {
+        content::WebContents* contents = GetActiveWebContents();
+        if (contents)
+          contents->GetView()->Focus();
+      }
+      break;
   }
 }
 
@@ -189,6 +215,27 @@
                                            false));
 }
 
+void BrowserInstantController::PasteIntoOmnibox(const string16& text) {
+  OmniboxView* omnibox_view = browser_->window()->GetLocationBar()->
+      GetLocationEntry();
+  // The first case is for right click to paste, where the text is retrieved
+  // from the clipboard already sanitized. The second case is needed to handle
+  // drag-and-drop value and it has to be sanitazed before setting it into the
+  // omnibox.
+  string16 text_to_paste = text.empty() ?
+      omnibox_view->GetClipboardText() :
+      omnibox_view->SanitizeTextForPaste(text);
+
+  if (!text_to_paste.empty()) {
+    if (!omnibox_view->model()->has_focus())
+      omnibox_view->SetFocus();
+    omnibox_view->OnBeforePossibleChange();
+    omnibox_view->model()->on_paste();
+    omnibox_view->SetUserText(text_to_paste);
+    omnibox_view->OnAfterPossibleChange();
+  }
+}
+
 void BrowserInstantController::SetOmniboxBounds(const gfx::Rect& bounds) {
   instant_.SetOmniboxBounds(bounds);
 }
diff --git a/chrome/browser/ui/browser_instant_controller.h b/chrome/browser/ui/browser_instant_controller.h
index 0d99aaa..8ddcb48 100644
--- a/chrome/browser/ui/browser_instant_controller.h
+++ b/chrome/browser/ui/browser_instant_controller.h
@@ -55,9 +55,8 @@
   // this BrowserInstantController.
   InstantController* instant() { return &instant_; }
 
-  // Invoked by |instant_| to give the omnibox focus, with the option of making
-  // the caret invisible.
-  void FocusOmnibox(bool caret_visibility);
+  // Invoked by |instant_| to change the omnibox focus.
+  void FocusOmnibox(OmniboxFocusState state);
 
   // Invoked by |instant_| to get the currently active tab.
   content::WebContents* GetActiveWebContents() const;
@@ -73,6 +72,11 @@
                content::PageTransition transition,
                WindowOpenDisposition disposition);
 
+  // Invoked by |instant_| to paste the |text| (or clipboard content if text is
+  // empty) into the omnibox. It will set focus to the omnibox if the omnibox is
+  // not focused.
+  void PasteIntoOmnibox(const string16& text);
+
   // Sets the stored omnibox bounds.
   void SetOmniboxBounds(const gfx::Rect& bounds);
 
diff --git a/chrome/browser/ui/chrome_pages.cc b/chrome/browser/ui/chrome_pages.cc
index a9caa99..34d9b6b 100644
--- a/chrome/browser/ui/chrome_pages.cc
+++ b/chrome/browser/ui/chrome_pages.cc
@@ -147,6 +147,12 @@
   ShowSingletonTab(browser, GURL(kChromeUIPolicyURL));
 }
 
+void ShowSlow(Browser* browser) {
+#if defined(OS_CHROMEOS)
+  ShowSingletonTab(browser, GURL(kChromeUISlowURL));
+#endif
+}
+
 void ShowSettings(Browser* browser) {
   content::RecordAction(UserMetricsAction("ShowOptions"));
   ShowSettingsSubPage(browser, std::string());
diff --git a/chrome/browser/ui/chrome_pages.h b/chrome/browser/ui/chrome_pages.h
index d4174fa..792fb6d 100644
--- a/chrome/browser/ui/chrome_pages.h
+++ b/chrome/browser/ui/chrome_pages.h
@@ -45,6 +45,7 @@
 
 void ShowHelp(Browser* browser, HelpSource source);
 void ShowPolicy(Browser* browser);
+void ShowSlow(Browser* browser);
 
 // Various things that open in a settings UI.
 void ShowSettings(Browser* browser);
diff --git a/chrome/browser/ui/cocoa/OWNERS b/chrome/browser/ui/cocoa/OWNERS
index 1ced4d8..75b56c8 100644
--- a/chrome/browser/ui/cocoa/OWNERS
+++ b/chrome/browser/ui/cocoa/OWNERS
@@ -1,6 +1,5 @@
 asvitkine@chromium.org
 avi@chromium.org
-isherman@chromium.org
 jeremy@chromium.org
 mark@chromium.org
 rohitrao@chromium.org
diff --git a/chrome/browser/ui/cocoa/autofill/OWNERS b/chrome/browser/ui/cocoa/autofill/OWNERS
new file mode 100644
index 0000000..c539e57
--- /dev/null
+++ b/chrome/browser/ui/cocoa/autofill/OWNERS
@@ -0,0 +1,2 @@
+groby@chromium.org
+isherman@chromium.org
diff --git a/chrome/browser/ui/cocoa/autofill/autofill_section_container_unittest.mm b/chrome/browser/ui/cocoa/autofill/autofill_section_container_unittest.mm
index a9aea29..6b79aa2 100644
--- a/chrome/browser/ui/cocoa/autofill/autofill_section_container_unittest.mm
+++ b/chrome/browser/ui/cocoa/autofill/autofill_section_container_unittest.mm
@@ -78,27 +78,38 @@
   using namespace testing;
 
   const DetailInput kTestInputs[] = {
-    { 2, CREDIT_CARD_EXP_MONTH }
+    { 2, CREDIT_CARD_EXP_MONTH },
+    { 3, CREDIT_CARD_EXP_4_DIGIT_YEAR }
   };
 
   DetailInputs inputs;
   inputs.push_back(kTestInputs[0]);
+  inputs.push_back(kTestInputs[1]);
 
-  autofill::MonthComboboxModel comboModel;
+  autofill::MonthComboboxModel monthComboModel;
+  autofill::YearComboboxModel yearComboModel;
   EXPECT_CALL(delegate_, RequestedFieldsForSection(section_))
       .WillOnce(ReturnRef(inputs));
   EXPECT_CALL(delegate_, ComboboxModelForAutofillType(CREDIT_CARD_EXP_MONTH))
-      .WillRepeatedly(Return(&comboModel));
+      .WillRepeatedly(Return(&monthComboModel));
+  EXPECT_CALL(
+    delegate_, ComboboxModelForAutofillType(CREDIT_CARD_EXP_4_DIGIT_YEAR))
+      .WillRepeatedly(Return(&yearComboModel));
   ResetContainer();
 
   NSPopUpButton* popup = base::mac::ObjCCastStrict<NSPopUpButton>(
       [container_ getField:CREDIT_CARD_EXP_MONTH]);
   EXPECT_EQ(13, [popup numberOfItems]);
-  EXPECT_NSEQ(@"", [popup itemTitleAtIndex:0]);
+  EXPECT_NSEQ(@"Month", [popup itemTitleAtIndex:0]);
   EXPECT_NSEQ(@"01", [popup itemTitleAtIndex:1]);
   EXPECT_NSEQ(@"02", [popup itemTitleAtIndex:2]);
   EXPECT_NSEQ(@"03", [popup itemTitleAtIndex:3]);
   EXPECT_NSEQ(@"12", [popup itemTitleAtIndex:12]);
+
+  NSPopUpButton* yearPopup = base::mac::ObjCCastStrict<NSPopUpButton>(
+      [container_ getField:CREDIT_CARD_EXP_4_DIGIT_YEAR]);
+  EXPECT_EQ(11, [yearPopup numberOfItems]);
+  EXPECT_NSEQ(@"Year", [yearPopup itemTitleAtIndex:0]);
 };
 
 TEST_F(AutofillSectionContainerTest, OutputMatchesDefinition) {
diff --git a/chrome/browser/ui/cocoa/browser/avatar_button_controller.h b/chrome/browser/ui/cocoa/browser/avatar_button_controller.h
index f61ccad..54b9849 100644
--- a/chrome/browser/ui/cocoa/browser/avatar_button_controller.h
+++ b/chrome/browser/ui/cocoa/browser/avatar_button_controller.h
@@ -10,6 +10,7 @@
 #import "base/mac/scoped_nsobject.h"
 #include "base/memory/scoped_ptr.h"
 
+@class AvatarLabelButton;
 @class AvatarMenuBubbleController;
 class Browser;
 
@@ -17,10 +18,6 @@
 class Observer;
 }
 
-namespace ui {
-class ThemeProvider;
-}
-
 // This view controller manages the button/image that sits in the top of the
 // window frame when using multi-profiles. It shows the current profile's
 // avatar, or, when in Incognito, the spy dude. With multi-profiles, clicking
@@ -38,8 +35,8 @@
   // The avatar button.
   base::scoped_nsobject<NSButton> button_;
 
-  // The managed user avatar label. Only used for managed user profiles.
-  base::scoped_nsobject<NSButton> labelButton_;
+  // The managed user avatar label button. Only used for managed user profiles.
+  base::scoped_nsobject<AvatarLabelButton> labelButton_;
 }
 
 // The avatar button view.
diff --git a/chrome/browser/ui/cocoa/browser/avatar_button_controller.mm b/chrome/browser/ui/cocoa/browser/avatar_button_controller.mm
index 471b64d..6c37962 100644
--- a/chrome/browser/ui/cocoa/browser/avatar_button_controller.mm
+++ b/chrome/browser/ui/cocoa/browser/avatar_button_controller.mm
@@ -14,11 +14,10 @@
 #include "chrome/browser/profiles/profile_info_util.h"
 #include "chrome/browser/profiles/profile_manager.h"
 #include "chrome/browser/profiles/profile_metrics.h"
-#include "chrome/browser/themes/theme_properties.h"
-#include "chrome/browser/themes/theme_service.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_commands.h"
 #include "chrome/browser/ui/browser_window.h"
+#import "chrome/browser/ui/cocoa/browser/avatar_label_button.h"
 #import "chrome/browser/ui/cocoa/browser/avatar_menu_bubble_controller.h"
 #import "chrome/browser/ui/cocoa/browser_window_controller.h"
 #include "content/public/browser/notification_service.h"
@@ -31,9 +30,21 @@
 
 namespace {
 
-// Space between the avatar icon and the managed user avatar label.
+// Space between the avatar icon and the avatar menu bubble.
+const CGFloat kMenuYOffsetAdjust = 1.0;
+
+// Space between the avatar label and the left edge of the container containing
+// the label and the icon.
 const CGFloat kAvatarSpacing = 4;
 
+// Space between the bottom of the avatar icon and the bottom of the avatar
+// label.
+const CGFloat kAvatarLabelBottomSpacing = 3;
+
+// Space between the right edge of the avatar label and the right edge of the
+// avatar icon.
+const CGFloat kAvatarLabelRightSpacing = 2;
+
 }  // namespace
 
 @interface AvatarButtonController (Private)
@@ -83,12 +94,6 @@
 
 }  // namespace AvatarButtonControllerInternal
 
-namespace {
-
-const CGFloat kMenuYOffsetAdjust = 1.0;
-
-}  // namespace
-
 ////////////////////////////////////////////////////////////////////////////////
 
 @implementation AvatarButtonController
@@ -136,8 +141,6 @@
         l10n_util::GetNSString(IDS_PROFILES_BUBBLE_ACCESSIBLE_DESCRIPTION)
                            forAttribute:NSAccessibilityDescriptionAttribute];
 
-    [[self view] addSubview:button_];
-
     Profile* profile = browser_->profile();
     if (profile->IsOffTheRecord()) {
       ResourceBundle& bundle = ResourceBundle::GetSharedInstance();
@@ -152,32 +155,26 @@
       // Managed users cannot enter incognito mode, so we only need to check
       // it in this code path.
       if (profile->IsManaged()) {
-        labelButton_.reset([[NSButton alloc] initWithFrame:NSZeroRect]);
-        [labelButton_ setButtonType:NSMomentaryLightButton];
-        [labelButton_ setBezelStyle:NSRecessedBezelStyle];
-        [labelButton_ setTitle:
-            l10n_util::GetNSString(IDS_MANAGED_USER_AVATAR_LABEL)];
-        [labelButton_ setShowsBorderOnlyWhileMouseInside:YES];
-
+        // Initialize the avatar label button.
+        CGFloat extraWidth =
+            profiles::kAvatarIconWidth + kAvatarLabelRightSpacing;
+        NSRect frame = NSMakeRect(
+            kAvatarSpacing, kAvatarLabelBottomSpacing, extraWidth, 0);
+        labelButton_.reset([[AvatarLabelButton alloc] initWithFrame:frame]);
         [labelButton_ setTarget:self];
         [labelButton_ setAction:@selector(buttonClicked:)];
-
-        [labelButton_ sizeToFit];
-        [labelButton_ setFrameOrigin:
-            NSMakePoint(kAvatarSpacing,
-                        (profiles::kAvatarIconHeight -
-                             NSHeight([labelButton_ frame])) / 2)];
         [[self view] addSubview:labelButton_];
 
-        // Reposition the avatar button and resize the container.
-        CGFloat avatarButtonXOffset =
-            NSWidth([labelButton_ frame]) + 2 * kAvatarSpacing;
+        // Resize the container and reposition the avatar button.
+        NSSize textSize = [[labelButton_ cell] labelTextSize];
         [container setFrameSize:
-            NSMakeSize(avatarButtonXOffset + NSWidth([button_ frame]),
+            NSMakeSize([labelButton_ frame].size.width + kAvatarSpacing,
                        profiles::kAvatarIconHeight)];
-        [button_ setFrameOrigin:NSMakePoint(avatarButtonXOffset, 0)];
+        [button_
+            setFrameOrigin:NSMakePoint(kAvatarSpacing + textSize.width, 0)];
       }
     }
+    [[self view] addSubview:button_];
   }
   return self;
 }
@@ -241,7 +238,7 @@
 
 - (IBAction)buttonClicked:(id)sender {
   DCHECK(sender == button_.get() || sender == labelButton_.get());
-  [self showAvatarBubble:sender];
+  [self showAvatarBubble:button_];
 }
 
 - (void)bubbleWillClose:(NSNotification*)notif {
@@ -282,7 +279,7 @@
 
   [destination unlockFocus];
 
-  return [destination.release() autorelease];
+  return destination.autorelease();
 }
 
 // Updates the avatar information from the profile cache.
diff --git a/chrome/browser/ui/cocoa/browser/avatar_label_button.h b/chrome/browser/ui/cocoa/browser/avatar_label_button.h
new file mode 100644
index 0000000..6244c27
--- /dev/null
+++ b/chrome/browser/ui/cocoa/browser/avatar_label_button.h
@@ -0,0 +1,24 @@
+// 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_UI_COCOA_AVATAR_LABEL_BUTTON_H_
+#define CHROME_BROWSER_UI_COCOA_AVATAR_LABEL_BUTTON_H_
+
+#import <Cocoa/Cocoa.h>
+
+#import "base/mac/scoped_nsobject.h"
+#import "chrome/browser/ui/cocoa/nine_part_button_cell.h"
+
+@interface AvatarLabelButton : NSButton
+@end
+
+// Draws the button cell for the avatar label.
+@interface AvatarLabelButtonCell : NinePartButtonCell
+
+// Returns the size of the label text (including boundaries).
+- (NSSize)labelTextSize;
+
+@end
+
+#endif  // CHROME_BROWSER_UI_COCOA_AVATAR_LABEL_BUTTON_H_
diff --git a/chrome/browser/ui/cocoa/browser/avatar_label_button.mm b/chrome/browser/ui/cocoa/browser/avatar_label_button.mm
new file mode 100644
index 0000000..a37d011
--- /dev/null
+++ b/chrome/browser/ui/cocoa/browser/avatar_label_button.mm
@@ -0,0 +1,144 @@
+// 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.
+
+#import "chrome/browser/ui/cocoa/browser/avatar_label_button.h"
+
+#include "chrome/browser/themes/theme_properties.h"
+#include "chrome/browser/ui/cocoa/themed_window.h"
+#include "grit/generated_resources.h"
+#include "grit/theme_resources.h"
+#include "ui/base/l10n/l10n_util_mac.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/base/theme_provider.h"
+
+namespace {
+
+// Space between the left edge of the label background and the left edge of the
+// label text.
+const CGFloat kLabelTextLeftSpacing = 10;
+
+// Space between the right edge of the label text and the avatar icon.
+const CGFloat kLabelTextRightSpacing = 4;
+
+// Space between the top edge of the label background and the top edge of the
+// label text.
+const CGFloat kLabelTextTopSpacing = 3;
+
+// Space between the bottom edge of the label background and the bottom edge of
+// the label text.
+const CGFloat kLabelTextBottomSpacing = 4;
+
+}  // namespace
+
+@implementation AvatarLabelButton
+
+- (id)initWithFrame:(NSRect)frameRect {
+  if ((self = [super initWithFrame:frameRect])) {
+    // Increase the frame by the size of the label to be displayed.
+    NSSize textSize = [[self cell] labelTextSize];
+    frameRect.size = NSMakeSize(frameRect.size.width + textSize.width,
+                                frameRect.size.height + textSize.height);
+    [self setFrame:frameRect];
+  }
+  return self;
+}
+
++ (Class)cellClass {
+  return [AvatarLabelButtonCell class];
+}
+
+@end
+
+@implementation AvatarLabelButtonCell
+
+- (id)init {
+  const int resourceIds[9] = {
+    IDR_MANAGED_USER_LABEL_TOP_LEFT, IDR_MANAGED_USER_LABEL_TOP,
+    IDR_MANAGED_USER_LABEL_TOP_RIGHT, IDR_MANAGED_USER_LABEL_LEFT,
+    IDR_MANAGED_USER_LABEL_CENTER, IDR_MANAGED_USER_LABEL_RIGHT,
+    IDR_MANAGED_USER_LABEL_BOTTOM_LEFT, IDR_MANAGED_USER_LABEL_BOTTOM,
+    IDR_MANAGED_USER_LABEL_BOTTOM_RIGHT
+  };
+  if ((self = [super initWithResourceIds:resourceIds])) {
+    NSString* title = l10n_util::GetNSString(IDS_MANAGED_USER_AVATAR_LABEL);
+    [self accessibilitySetOverrideValue:title
+                           forAttribute:NSAccessibilityTitleAttribute];
+    [self setTitle:title];
+    [self setFont:[NSFont labelFontOfSize:12.0]];
+  }
+  return self;
+}
+
+- (NSSize)labelTextSize {
+  NSSize size = [[self attributedTitle] size];
+  size.width += kLabelTextLeftSpacing + kLabelTextRightSpacing;
+  size.height += kLabelTextTopSpacing + kLabelTextBottomSpacing;
+  return size;
+}
+
+- (NSRect)titleRectForBounds:(NSRect)theRect {
+  theRect.origin = NSMakePoint(kLabelTextLeftSpacing, kLabelTextBottomSpacing);
+  theRect.size = [[self attributedTitle] size];
+  return theRect;
+}
+
+- (NSRect)drawTitle:(NSAttributedString*)title
+          withFrame:(NSRect)frame
+             inView:(NSView*)controlView {
+  base::scoped_nsobject<NSMutableAttributedString> themedTitle(
+      [[NSMutableAttributedString alloc] initWithAttributedString:title]);
+  ui::ThemeProvider* themeProvider = [[controlView window] themeProvider];
+  if (themeProvider) {
+    NSColor* textColor = themeProvider->GetNSColor(
+        ThemeProperties::COLOR_MANAGED_USER_LABEL);
+    [themedTitle addAttribute:NSForegroundColorAttributeName
+                        value:textColor
+                        range:NSMakeRange(0, title.length)];
+  }
+  [themedTitle drawInRect:frame];
+  return frame;
+}
+
+- (void)drawInteriorWithFrame:(NSRect)cellFrame inView:(NSView*)controlView {
+  ui::ThemeProvider* themeProvider = [[controlView window] themeProvider];
+  if (themeProvider) {
+    // Draw the label button background using the color provided by
+    // |themeProvider|. First paint the border.
+    NSColor* borderColor = themeProvider->GetNSColor(
+        ThemeProperties::COLOR_MANAGED_USER_LABEL_BORDER);
+    if ([self isHighlighted]) {
+      borderColor = [borderColor blendedColorWithFraction:0.5
+                                                  ofColor:[NSColor blackColor]];
+    }
+    NSSize frameSize = cellFrame.size;
+    NSRect backgroundRect;
+    backgroundRect.origin = NSMakePoint(1, 1);
+    backgroundRect.size = NSMakeSize(frameSize.width - 2, frameSize.height - 2);
+    NSBezierPath* path =
+        [NSBezierPath bezierPathWithRoundedRect:backgroundRect
+                                        xRadius:2.0
+                                        yRadius:2.0];
+    [borderColor set];
+    [path fill];
+
+    // Now paint the background.
+    NSColor* backgroundColor = themeProvider->GetNSColor(
+        ThemeProperties::COLOR_MANAGED_USER_LABEL_BACKGROUND);
+    if ([self isHighlighted]) {
+      backgroundColor =
+          [backgroundColor blendedColorWithFraction:0.5
+                                            ofColor:[NSColor blackColor]];
+    }
+    backgroundRect.origin = NSMakePoint(2, 2);
+    backgroundRect.size = NSMakeSize(frameSize.width - 4, frameSize.height - 4);
+    path = [NSBezierPath bezierPathWithRoundedRect:backgroundRect
+                                           xRadius:2.0
+                                           yRadius:2.0];
+    [backgroundColor set];
+    [path fill];
+  }
+  [super drawInteriorWithFrame:cellFrame inView:controlView];
+}
+
+@end
diff --git a/chrome/browser/ui/cocoa/browser/avatar_label_button_unittest.mm b/chrome/browser/ui/cocoa/browser/avatar_label_button_unittest.mm
new file mode 100644
index 0000000..c080fb3
--- /dev/null
+++ b/chrome/browser/ui/cocoa/browser/avatar_label_button_unittest.mm
@@ -0,0 +1,32 @@
+// 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.
+
+#import <Cocoa/Cocoa.h>
+
+#include "base/mac/scoped_nsobject.h"
+#import "chrome/browser/ui/cocoa/browser/avatar_label_button.h"
+#import "chrome/browser/ui/cocoa/cocoa_test_helper.h"
+#include "grit/theme_resources.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+class AvatarLabelButtonTest : public CocoaTest {
+ public:
+  AvatarLabelButtonTest() {
+    NSRect content_frame = [[test_window() contentView] frame];
+    button_.reset([[AvatarLabelButton alloc] initWithFrame:content_frame]);
+    [[test_window() contentView] addSubview:button_];
+  }
+
+ protected:
+  base::scoped_nsobject<AvatarLabelButton> button_;
+};
+
+TEST_VIEW(AvatarLabelButtonTest, button_)
+
+TEST_F(AvatarLabelButtonTest, TestHighlight) {
+  EXPECT_FALSE([[button_ cell] isHighlighted]);
+  [button_ display];
+  [[button_ cell] setHighlighted:YES];
+  [button_ display];
+}
diff --git a/chrome/browser/ui/cocoa/content_settings/content_setting_bubble_cocoa.mm b/chrome/browser/ui/cocoa/content_settings/content_setting_bubble_cocoa.mm
index 74d1890..7900efe 100644
--- a/chrome/browser/ui/cocoa/content_settings/content_setting_bubble_cocoa.mm
+++ b/chrome/browser/ui/cocoa/content_settings/content_setting_bubble_cocoa.mm
@@ -70,6 +70,18 @@
 // The minimum width of the media menu buttons.
 const CGFloat kMinMediaMenuButtonWidth = 100;
 
+// Height of each of the labels in the MIDI bubble.
+const int kMIDISysExLabelHeight = 14;
+
+// Height of the "Clear" button in the MIDI bubble.
+const int kMIDISysExClearButtonHeight = 17;
+
+// General padding between elements in the MIDI bubble.
+const int kMIDISysExPadding = 8;
+
+// Padding between host names in the MIDI bubble.
+const int kMIDISysExHostPadding = 4;
+
 void SetControlSize(NSControl* control, NSControlSize controlSize) {
   CGFloat fontSize = [NSFont systemFontSizeForControlSize:controlSize];
   NSCell* cell = [control cell];
@@ -171,11 +183,13 @@
 - (void)initializePopupList;
 - (void)initializeGeoLists;
 - (void)initializeMediaMenus;
+- (void)initializeMIDISysExLists;
 - (void)sizeToFitLoadButton;
 - (void)initManageDoneButtons;
 - (void)removeInfoButton;
 - (void)popupLinkClicked:(id)sender;
 - (void)clearGeolocationForCurrentHost:(id)sender;
+- (void)clearMIDISysExForCurrentHost:(id)sender;
 @end
 
 @implementation ContentSettingBubbleController
@@ -221,6 +235,8 @@
       nibPath = @"ContentBlockedMedia"; break;
     case CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS:
       nibPath = @"ContentBlockedDownloads"; break;
+    case CONTENT_SETTINGS_TYPE_MIDI_SYSEX:
+      nibPath = @"ContentBlockedMIDISysEx"; break;
     // These content types have no bubble:
     case CONTENT_SETTINGS_TYPE_DEFAULT:
     case CONTENT_SETTINGS_TYPE_NOTIFICATIONS:
@@ -229,7 +245,6 @@
     case CONTENT_SETTINGS_TYPE_MOUSELOCK:
     case CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC:
     case CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA:
-    case CONTENT_SETTINGS_TYPE_MIDI_SYSEX:
     case CONTENT_SETTINGS_NUM_TYPES:
       NOTREACHED();
   }
@@ -449,14 +464,10 @@
     frame.origin.y = NSMaxY([control frame]) + kGeoPadding;
   }
 
-  typedef
-      std::vector<ContentSettingBubbleModel::DomainList>::const_reverse_iterator
-      GeolocationGroupIterator;
-  for (GeolocationGroupIterator i = content.domain_lists.rbegin();
+  for (auto i = content.domain_lists.rbegin();
        i != content.domain_lists.rend(); ++i) {
     // Add all hosts in the current domain list.
-    for (std::set<std::string>::const_reverse_iterator j = i->hosts.rbegin();
-         j != i->hosts.rend(); ++j) {
+    for (auto j = i->hosts.rbegin(); j != i->hosts.rend(); ++j) {
       NSTextField* title = LabelWithFrame(base::SysUTF8ToNSString(*j), frame);
       SetControlSize(title, NSSmallControlSize);
       [contentsContainer_ addSubview:title];
@@ -579,6 +590,88 @@
   }
 }
 
+- (void)initializeMIDISysExLists {
+  const ContentSettingBubbleModel::BubbleContent& content =
+      contentSettingBubbleModel_->bubble_content();
+  NSRect containerFrame = [contentsContainer_ frame];
+  NSRect frame =
+      NSMakeRect(0, 0, NSWidth(containerFrame), kMIDISysExLabelHeight);
+
+  // "Clear" button / text field.
+  if (!content.custom_link.empty()) {
+    base::scoped_nsobject<NSControl> control;
+    if (content.custom_link_enabled) {
+      NSRect buttonFrame = NSMakeRect(0, 0,
+                                      NSWidth(containerFrame),
+                                      kMIDISysExClearButtonHeight);
+      NSButton* button = [[NSButton alloc] initWithFrame:buttonFrame];
+      control.reset(button);
+      [button setTitle:base::SysUTF8ToNSString(content.custom_link)];
+      [button setTarget:self];
+      [button setAction:@selector(clearMIDISysExForCurrentHost:)];
+      [button setBezelStyle:NSRoundRectBezelStyle];
+      SetControlSize(button, NSSmallControlSize);
+      [button sizeToFit];
+    } else {
+      // Add the notification that settings will be cleared on next reload.
+      control.reset([LabelWithFrame(
+          base::SysUTF8ToNSString(content.custom_link), frame) retain]);
+      SetControlSize(control.get(), NSSmallControlSize);
+    }
+
+    // If the new control is wider than the container, widen the window.
+    CGFloat controlWidth = NSWidth([control frame]);
+    if (controlWidth > NSWidth(containerFrame)) {
+      NSRect windowFrame = [[self window] frame];
+      windowFrame.size.width += controlWidth - NSWidth(containerFrame);
+      [[self window] setFrame:windowFrame display:NO];
+      // Fetch the updated sizes.
+      containerFrame = [contentsContainer_ frame];
+      frame = NSMakeRect(0, 0, NSWidth(containerFrame), kMIDISysExLabelHeight);
+    }
+
+    DCHECK(control);
+    [contentsContainer_ addSubview:control];
+    frame.origin.y = NSMaxY([control frame]) + kMIDISysExPadding;
+  }
+
+  for (auto i = content.domain_lists.rbegin();
+       i != content.domain_lists.rend(); ++i) {
+    // Add all hosts in the current domain list.
+    for (auto j = i->hosts.rbegin(); j != i->hosts.rend(); ++j) {
+      NSTextField* title = LabelWithFrame(base::SysUTF8ToNSString(*j), frame);
+      SetControlSize(title, NSSmallControlSize);
+      [contentsContainer_ addSubview:title];
+
+      frame.origin.y = NSMaxY(frame) + kMIDISysExHostPadding +
+          [GTMUILocalizerAndLayoutTweaker sizeToFitFixedWidthTextField:title];
+    }
+    if (!i->hosts.empty())
+      frame.origin.y += kMIDISysExPadding - kMIDISysExHostPadding;
+
+    // Add the domain list's title.
+    NSTextField* title =
+        LabelWithFrame(base::SysUTF8ToNSString(i->title), frame);
+    SetControlSize(title, NSSmallControlSize);
+    [contentsContainer_ addSubview:title];
+
+    frame.origin.y = NSMaxY(frame) + kMIDISysExPadding +
+        [GTMUILocalizerAndLayoutTweaker sizeToFitFixedWidthTextField:title];
+  }
+
+  CGFloat containerHeight = frame.origin.y;
+  // Undo last padding.
+  if (!content.domain_lists.empty())
+    containerHeight -= kMIDISysExPadding;
+
+  // Resize container to fit its subviews, and window to fit the container.
+  NSRect windowFrame = [[self window] frame];
+  windowFrame.size.height += containerHeight - NSHeight(containerFrame);
+  [[self window] setFrame:windowFrame display:NO];
+  containerFrame.size.height = containerHeight;
+  [contentsContainer_ setFrame:containerFrame];
+}
+
 - (void)sizeToFitLoadButton {
   const ContentSettingBubbleModel::BubbleContent& content =
       contentSettingBubbleModel_->bubble_content();
@@ -640,6 +733,8 @@
     [self initializeGeoLists];
   if (type == CONTENT_SETTINGS_TYPE_MEDIASTREAM)
     [self initializeMediaMenus];
+  if (type == CONTENT_SETTINGS_TYPE_MIDI_SYSEX)
+    [self initializeMIDISysExLists];
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -661,6 +756,11 @@
   [self close];
 }
 
+- (void)clearMIDISysExForCurrentHost:(id)sender {
+  contentSettingBubbleModel_->OnCustomLinkClicked();
+  [self close];
+}
+
 - (IBAction)showMoreInfo:(id)sender {
   contentSettingBubbleModel_->OnCustomLinkClicked();
   [self close];
diff --git a/chrome/browser/ui/cocoa/dev_tools_controller.h b/chrome/browser/ui/cocoa/dev_tools_controller.h
index cfb12c6..8684e9c 100644
--- a/chrome/browser/ui/cocoa/dev_tools_controller.h
+++ b/chrome/browser/ui/cocoa/dev_tools_controller.h
@@ -10,6 +10,7 @@
 #include "base/mac/scoped_nsobject.h"
 #include "chrome/browser/devtools/devtools_window.h"
 
+@class FocusTracker;
 @class GraySplitView;
 class Profile;
 
@@ -30,6 +31,8 @@
   // Docked devtools window instance. NULL when current tab is not inspected
   // or is inspected with undocked version of DevToolsWindow.
   DevToolsWindow* devToolsWindow_;
+
+  base::scoped_nsobject<FocusTracker> focusTracker_;
 }
 
 - (id)init;
diff --git a/chrome/browser/ui/cocoa/dev_tools_controller.mm b/chrome/browser/ui/cocoa/dev_tools_controller.mm
index d9e5b77..4c90907 100644
--- a/chrome/browser/ui/cocoa/dev_tools_controller.mm
+++ b/chrome/browser/ui/cocoa/dev_tools_controller.mm
@@ -15,6 +15,7 @@
 #include "chrome/common/pref_names.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/browser/web_contents_view.h"
+#include "ui/base/cocoa/focus_tracker.h"
 
 using content::WebContents;
 
@@ -119,6 +120,8 @@
   NSArray* subviews = [splitView_ subviews];
   DCHECK_EQ([subviews count], 1u);
   WebContents* devToolsContents = devToolsWindow_->web_contents();
+  focusTracker_.reset(
+      [[FocusTracker alloc] initWithWindow:[splitView_ window]]);
 
   // |devToolsView| is a TabContentsViewCocoa object, whose ViewID was
   // set to VIEW_ID_TAB_CONTAINER initially, so we need to change it to
@@ -138,6 +141,8 @@
   NSView* oldDevToolsContentsView = [subviews objectAtIndex:1];
   [oldDevToolsContentsView removeFromSuperview];
   [splitView_ adjustSubviews];
+  [focusTracker_ restoreFocusInWindow:[splitView_ window]];
+  focusTracker_.reset();
 }
 
 - (void)updateDevToolsSplitPosition {
diff --git a/chrome/browser/ui/cocoa/download/download_shelf_controller.mm b/chrome/browser/ui/cocoa/download/download_shelf_controller.mm
index be8355b..687da1b 100644
--- a/chrome/browser/ui/cocoa/download/download_shelf_controller.mm
+++ b/chrome/browser/ui/cocoa/download/download_shelf_controller.mm
@@ -7,7 +7,7 @@
 #include "base/mac/bundle_locations.h"
 #include "base/mac/mac_util.h"
 #include "base/strings/sys_string_conversions.h"
-#include "chrome/browser/download/download_util.h"
+#include "chrome/browser/download/download_stats.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/themes/theme_service.h"
 #include "chrome/browser/themes/theme_service_factory.h"
@@ -243,7 +243,7 @@
       if (item->GetState() == DownloadItem::IN_PROGRESS)
         ++numInProgress;
     }
-    download_util::RecordShelfClose(
+    RecordDownloadShelfClose(
         [downloadItemControllers_ count], numInProgress, !isUserAction);
   }
 
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 d682305..44d3ac0 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
@@ -63,7 +63,7 @@
   virtual void UpdatePageActions() OVERRIDE;
   virtual void InvalidatePageActions() OVERRIDE;
   virtual void UpdateOpenPDFInReaderPrompt() OVERRIDE;
-  virtual void UpdateAutofillCreditCardView() OVERRIDE;
+  virtual void UpdateGeneratedCreditCardView() OVERRIDE;
   virtual void SaveStateToContents(content::WebContents* contents) OVERRIDE;
   virtual void Revert() OVERRIDE;
   virtual const OmniboxView* GetLocationEntry() const OVERRIDE;
@@ -153,7 +153,6 @@
   virtual string16 GetTitle() const OVERRIDE;
   virtual InstantController* GetInstant() OVERRIDE;
   virtual content::WebContents* GetWebContents() const OVERRIDE;
-  virtual gfx::Rect GetOmniboxBounds() const OVERRIDE;
 
   NSImage* GetKeywordImage(const string16& keyword);
 
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 ec510a6..b28c4aa 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
@@ -218,7 +218,7 @@
   // Not implemented on Mac.
 }
 
-void LocationBarViewMac::UpdateAutofillCreditCardView() {
+void LocationBarViewMac::UpdateGeneratedCreditCardView() {
   // TODO(dbeam): encourage groby@ to implement via prodding or chocolate.
   NOTIMPLEMENTED();
 }
@@ -357,10 +357,6 @@
   return browser_->tab_strip_model()->GetActiveWebContents();
 }
 
-gfx::Rect LocationBarViewMac::GetOmniboxBounds() const {
-  return gfx::Rect(NSRectToCGRect([field_ frame]));
-}
-
 PageActionDecoration* LocationBarViewMac::GetPageActionDecoration(
     ExtensionAction* page_action) {
   DCHECK(page_action);
diff --git a/chrome/browser/ui/cocoa/nine_part_button_cell.h b/chrome/browser/ui/cocoa/nine_part_button_cell.h
new file mode 100644
index 0000000..493c698
--- /dev/null
+++ b/chrome/browser/ui/cocoa/nine_part_button_cell.h
@@ -0,0 +1,31 @@
+// 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_UI_COCOA_NINE_PART_BUTTON_CELL_H_
+#define CHROME_BROWSER_UI_COCOA_NINE_PART_BUTTON_CELL_H_
+
+#import <Cocoa/Cocoa.h>
+
+#import "base/mac/scoped_nsobject.h"
+
+// Handles painting of a button using images from a ResourceBundle. The
+// constructor expects an array of 9 image resource ids. The images
+// corresponding to the resource ids are assigned to a 3 by 3 grid in row major
+// order, i.e.
+//  _________________
+// |_id0_|_id1_|_id2_|
+// |_id3_|_id4_|_id5_|
+// |_id6_|_id7_|_id8_|
+@interface NinePartButtonCell : NSButtonCell {
+ @private
+  base::scoped_nsobject<NSMutableArray> images_;
+}
+
+// Loads the images from the ResourceBundle using the provided image resource
+// ids and sets the image of the cell.
+- (id)initWithResourceIds:(const int[9])ids;
+
+@end  // @interface NinePartButtonCell
+
+#endif  // CHROME_BROWSER_UI_COCOA_NINE_PART_BUTTON_CELL_H_
diff --git a/chrome/browser/ui/cocoa/nine_part_button_cell.mm b/chrome/browser/ui/cocoa/nine_part_button_cell.mm
new file mode 100644
index 0000000..e156232
--- /dev/null
+++ b/chrome/browser/ui/cocoa/nine_part_button_cell.mm
@@ -0,0 +1,125 @@
+// 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.
+
+#import "chrome/browser/ui/cocoa/nine_part_button_cell.h"
+
+#include <algorithm>
+
+#include "ui/base/resource/resource_bundle.h"
+
+@implementation NinePartButtonCell
+
+- (id)initWithResourceIds:(const int[9])ids {
+  if ((self = [super initImageCell:nil])) {
+    images_.reset([[NSMutableArray alloc] initWithCapacity:9]);
+    ResourceBundle& rb = ResourceBundle::GetSharedInstance();
+    for (NSInteger i = 0; i < 9; ++i)
+      [images_ addObject:rb.GetNativeImageNamed(ids[i]).ToNSImage()];
+    [self setBezeled:YES];
+    [self setBezelStyle:NSSmallSquareBezelStyle];
+  }
+  return self;
+}
+
+- (void)drawBezelWithFrame:(NSRect)frame inView:(NSView*)controlView {
+  NSSize targetSize = frame.size;
+
+  // Retrieve the sizes of the images (except the size of the center image,
+  // which will be scaled anyway).
+  NSSize topLeft = [[images_ objectAtIndex:0] size];
+  NSSize top = [[images_ objectAtIndex:1] size];
+  NSSize topRight = [[images_ objectAtIndex:2] size];
+  NSSize left = [[images_ objectAtIndex:3] size];
+  NSSize right = [[images_ objectAtIndex:5] size];
+  NSSize bottomLeft = [[images_ objectAtIndex:6] size];
+  NSSize bottom = [[images_ objectAtIndex:7] size];
+  NSSize bottomRight = [[images_ objectAtIndex:8] size];
+
+  // Determine the minimum width of images on the left side.
+  CGFloat minLeftWidth =
+      std::min(topLeft.width, std::min(left.width, bottomLeft.width));
+  // Determine the minimum width of images on the right side.
+  CGFloat minRightWidth =
+      std::min(topRight.width, std::min(right.width, bottomRight.width));
+  // Determine the minimum height of images on the top side.
+  CGFloat minTopHeight =
+      std::min(topLeft.height, std::min(top.height, topRight.height));
+  // Determine the minimum height of images on the bottom side.
+  CGFloat minBottomHeight =
+      std::min(bottomLeft.height, std::min(bottom.height, bottomRight.height));
+
+  // Now paint the center image and extend it in all directions to the edges of
+  // images with the smallest height/width.
+  NSSize centerSize =
+      NSMakeSize(targetSize.width - minLeftWidth - minRightWidth,
+                 targetSize.height - minTopHeight - minBottomHeight);
+  NSRect centerRect = NSMakeRect(
+      minLeftWidth, minBottomHeight, centerSize.width, centerSize.height);
+  [[images_ objectAtIndex:4] drawInRect:centerRect
+                               fromRect:NSZeroRect
+                              operation:NSCompositeSourceOver
+                               fraction:1.0];
+
+  // Paint the corner images next.
+  NSRect topLeftRect = NSMakeRect(
+      0, targetSize.height - topLeft.height, topLeft.width, topLeft.height);
+  [[images_ objectAtIndex:0] drawInRect:topLeftRect
+                               fromRect:NSZeroRect
+                              operation:NSCompositeSourceOver
+                               fraction:1.0];
+  NSRect topRightRect = NSMakeRect(targetSize.width - topRight.width,
+                                   targetSize.height - topRight.height,
+                                   topRight.width,
+                                   topRight.height);
+  [[images_ objectAtIndex:2] drawInRect:topRightRect
+                               fromRect:NSZeroRect
+                              operation:NSCompositeSourceOver
+                               fraction:1.0];
+  NSRect bottomLeftRect = NSMakeRect(
+      0, 0, bottomLeft.width, bottomLeft.height);
+  [[images_ objectAtIndex:6] drawInRect:bottomLeftRect
+                               fromRect:NSZeroRect
+                              operation:NSCompositeSourceOver
+                               fraction:1.0];
+  NSRect bottomRightRect = NSMakeRect(targetSize.width - bottomRight.width,
+                                      0,
+                                      bottomRight.width,
+                                      bottomRight.height);
+  [[images_ objectAtIndex:8] drawInRect:bottomRightRect
+                               fromRect:NSZeroRect
+                              operation:NSCompositeSourceOver
+                               fraction:1.0];
+
+  // Now paint the remaining images.
+  NSRect topRect = NSMakeRect(minLeftWidth,
+                              targetSize.height - top.height,
+                              centerSize.width,
+                              top.height);
+  [[images_ objectAtIndex:1] drawInRect:topRect
+                               fromRect:NSZeroRect
+                              operation:NSCompositeSourceOver
+                               fraction:1.0];
+  NSRect leftRect =
+      NSMakeRect(0, minBottomHeight, left.width, centerSize.height);
+  [[images_ objectAtIndex:3] drawInRect:leftRect
+                               fromRect:NSZeroRect
+                              operation:NSCompositeSourceOver
+                               fraction:1.0];
+  NSRect rightRect = NSMakeRect(targetSize.width - minRightWidth,
+                                minBottomHeight,
+                                right.width,
+                                centerSize.height);
+  [[images_ objectAtIndex:5] drawInRect:rightRect
+                               fromRect:NSZeroRect
+                              operation:NSCompositeSourceOver
+                               fraction:1.0];
+  NSRect bottomRect =
+      NSMakeRect(minLeftWidth, 0, centerSize.width, bottom.height);
+  [[images_ objectAtIndex:7] drawInRect:bottomRect
+                               fromRect:NSZeroRect
+                              operation:NSCompositeSourceOver
+                               fraction:1.0];
+}
+
+@end
diff --git a/chrome/browser/ui/cocoa/nine_part_button_cell_unittest.mm b/chrome/browser/ui/cocoa/nine_part_button_cell_unittest.mm
new file mode 100644
index 0000000..e44da40
--- /dev/null
+++ b/chrome/browser/ui/cocoa/nine_part_button_cell_unittest.mm
@@ -0,0 +1,35 @@
+// 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.
+
+#import <Cocoa/Cocoa.h>
+
+#include "base/mac/scoped_nsobject.h"
+#import "chrome/browser/ui/cocoa/cocoa_test_helper.h"
+#import "chrome/browser/ui/cocoa/nine_part_button_cell.h"
+#include "grit/theme_resources.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+class NinePartButtonCellTest : public CocoaTest {
+ public:
+  NinePartButtonCellTest() {
+    const int resourceIds[9] = {
+      IDR_MANAGED_USER_LABEL_TOP_LEFT, IDR_MANAGED_USER_LABEL_TOP,
+      IDR_MANAGED_USER_LABEL_TOP_RIGHT, IDR_MANAGED_USER_LABEL_LEFT,
+      IDR_MANAGED_USER_LABEL_CENTER, IDR_MANAGED_USER_LABEL_RIGHT,
+      IDR_MANAGED_USER_LABEL_BOTTOM_LEFT, IDR_MANAGED_USER_LABEL_BOTTOM,
+      IDR_MANAGED_USER_LABEL_BOTTOM_RIGHT
+    };
+    NSRect content_frame = [[test_window() contentView] frame];
+    button_.reset([[NSButton alloc] initWithFrame:content_frame]);
+    base::scoped_nsobject<NinePartButtonCell> cell(
+        [[NinePartButtonCell alloc] initWithResourceIds:resourceIds]);
+    [button_ setCell:cell.get()];
+    [[test_window() contentView] addSubview:button_];
+  }
+
+ protected:
+  base::scoped_nsobject<NSButton> button_;
+};
+
+TEST_VIEW(NinePartButtonCellTest, button_)
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 e011276..cac4fc7 100644
--- a/chrome/browser/ui/cocoa/omnibox/omnibox_popup_view_mac.mm
+++ b/chrome/browser/ui/cocoa/omnibox/omnibox_popup_view_mac.mm
@@ -16,7 +16,6 @@
 #include "chrome/browser/ui/cocoa/omnibox/omnibox_view_mac.h"
 #include "chrome/browser/ui/omnibox/omnibox_edit_model.h"
 #include "chrome/browser/ui/omnibox/omnibox_popup_model.h"
-#include "chrome/browser/ui/omnibox/omnibox_popup_non_view.h"
 #include "chrome/common/autocomplete_match_type.h"
 #include "grit/theme_resources.h"
 #include "skia/ext/skia_utils_mac.h"
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 de9f42a..0749f66 100644
--- a/chrome/browser/ui/cocoa/omnibox/omnibox_view_mac_unittest.mm
+++ b/chrome/browser/ui/cocoa/omnibox/omnibox_view_mac_unittest.mm
@@ -13,7 +13,6 @@
 #include "chrome/browser/ui/toolbar/toolbar_model_impl.h"
 #include "testing/platform_test.h"
 #include "ui/gfx/image/image.h"
-#include "ui/gfx/rect.h"
 
 namespace {
 
@@ -98,7 +97,6 @@
   virtual content::WebContents* GetWebContents() const OVERRIDE {
     return NULL;
   }
-  virtual gfx::Rect GetOmniboxBounds() const OVERRIDE { return gfx::Rect(); }
 
  private:
   DISALLOW_COPY_AND_ASSIGN(TestingOmniboxEditController);
diff --git a/chrome/browser/ui/content_settings/content_setting_bubble_model.cc b/chrome/browser/ui/content_settings/content_setting_bubble_model.cc
index 63e06d9..98d0091 100644
--- a/chrome/browser/ui/content_settings/content_setting_bubble_model.cc
+++ b/chrome/browser/ui/content_settings/content_setting_bubble_model.cc
@@ -163,6 +163,7 @@
     {CONTENT_SETTINGS_TYPE_MEDIASTREAM, IDS_MEDIASTREAM_BUBBLE_MANAGE_LINK},
     {CONTENT_SETTINGS_TYPE_PPAPI_BROKER, IDS_PPAPI_BROKER_BUBBLE_MANAGE_LINK},
     {CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS, IDS_BLOCKED_DOWNLOADS_LINK},
+    {CONTENT_SETTINGS_TYPE_MIDI_SYSEX, IDS_MIDI_SYSEX_BUBBLE_MANAGE_LINK},
   };
   set_manage_link(l10n_util::GetStringUTF8(
       GetIdForContentType(kLinkIDs, arraysize(kLinkIDs), content_type())));
@@ -1162,6 +1163,93 @@
   }
 }
 
+// TODO(toyoshim): Should share as many code with geolocation as possible.
+class ContentSettingMIDISysExBubbleModel
+    : public ContentSettingTitleAndLinkModel {
+ public:
+  ContentSettingMIDISysExBubbleModel(Delegate* delegate,
+                                     WebContents* web_contents,
+                                     Profile* profile,
+                                     ContentSettingsType content_type);
+  virtual ~ContentSettingMIDISysExBubbleModel() {}
+
+ private:
+  void MaybeAddDomainList(const std::set<std::string>& hosts, int title_id);
+  void SetDomainsAndCustomLink();
+  virtual void OnCustomLinkClicked() OVERRIDE;
+};
+
+ContentSettingMIDISysExBubbleModel::ContentSettingMIDISysExBubbleModel(
+    Delegate* delegate,
+    WebContents* web_contents,
+    Profile* profile,
+    ContentSettingsType content_type)
+    : ContentSettingTitleAndLinkModel(
+        delegate, web_contents, profile, content_type) {
+  DCHECK_EQ(CONTENT_SETTINGS_TYPE_MIDI_SYSEX, content_type);
+  SetDomainsAndCustomLink();
+}
+
+void ContentSettingMIDISysExBubbleModel::MaybeAddDomainList(
+    const std::set<std::string>& hosts, int title_id) {
+  if (!hosts.empty()) {
+    DomainList domain_list;
+    domain_list.title = l10n_util::GetStringUTF8(title_id);
+    domain_list.hosts = hosts;
+    add_domain_list(domain_list);
+  }
+}
+
+void ContentSettingMIDISysExBubbleModel::SetDomainsAndCustomLink() {
+  TabSpecificContentSettings* content_settings =
+      TabSpecificContentSettings::FromWebContents(web_contents());
+  const ContentSettingsUsagesState& usages_state =
+      content_settings->midi_usages_state();
+  ContentSettingsUsagesState::FormattedHostsPerState formatted_hosts_per_state;
+  unsigned int tab_state_flags = 0;
+  usages_state.GetDetailedInfo(&formatted_hosts_per_state, &tab_state_flags);
+  // Divide the tab's current MIDI sysex users into sets according to their
+  // permission state.
+  MaybeAddDomainList(formatted_hosts_per_state[CONTENT_SETTING_ALLOW],
+                     IDS_MIDI_SYSEX_BUBBLE_ALLOWED);
+
+  MaybeAddDomainList(formatted_hosts_per_state[CONTENT_SETTING_BLOCK],
+                     IDS_MIDI_SYSEX_BUBBLE_DENIED);
+
+  if (tab_state_flags & ContentSettingsUsagesState::TABSTATE_HAS_EXCEPTION) {
+    set_custom_link(l10n_util::GetStringUTF8(
+        IDS_MIDI_SYSEX_BUBBLE_CLEAR_LINK));
+    set_custom_link_enabled(true);
+  } else if (tab_state_flags &
+             ContentSettingsUsagesState::TABSTATE_HAS_CHANGED) {
+    set_custom_link(l10n_util::GetStringUTF8(
+        IDS_MIDI_SYSEX_BUBBLE_REQUIRE_RELOAD_TO_CLEAR));
+  }
+}
+
+void ContentSettingMIDISysExBubbleModel::OnCustomLinkClicked() {
+  if (!web_contents())
+    return;
+  // Reset this embedder's entry to default for each of the requesting
+  // origins currently on the page.
+  TabSpecificContentSettings* content_settings =
+      TabSpecificContentSettings::FromWebContents(web_contents());
+  const ContentSettingsUsagesState::StateMap& state_map =
+      content_settings->midi_usages_state().state_map();
+  HostContentSettingsMap* settings_map =
+      profile()->GetHostContentSettingsMap();
+
+  for (ContentSettingsUsagesState::StateMap::const_iterator it =
+       state_map.begin(); it != state_map.end(); ++it) {
+    settings_map->SetContentSetting(
+        ContentSettingsPattern::FromURLNoWildcard(it->first),
+        ContentSettingsPattern::Wildcard(),
+        CONTENT_SETTINGS_TYPE_MIDI_SYSEX,
+        std::string(),
+        CONTENT_SETTING_DEFAULT);
+  }
+}
+
 // static
 ContentSettingBubbleModel*
     ContentSettingBubbleModel::CreateContentSettingBubbleModel(
@@ -1199,6 +1287,10 @@
     return new ContentSettingRPHBubbleModel(delegate, web_contents, profile,
                                             registry, content_type);
   }
+  if (content_type == CONTENT_SETTINGS_TYPE_MIDI_SYSEX) {
+    return new ContentSettingMIDISysExBubbleModel(delegate, web_contents,
+                                                  profile, content_type);
+  }
   return new ContentSettingSingleRadioGroup(delegate, web_contents, profile,
                                             content_type);
 }
diff --git a/chrome/browser/ui/content_settings/content_setting_image_model.cc b/chrome/browser/ui/content_settings/content_setting_image_model.cc
index c49163b..9e564a2 100644
--- a/chrome/browser/ui/content_settings/content_setting_image_model.cc
+++ b/chrome/browser/ui/content_settings/content_setting_image_model.cc
@@ -52,6 +52,13 @@
   virtual void UpdateFromWebContents(WebContents* web_contents) OVERRIDE;
 };
 
+class ContentSettingMIDISysExImageModel : public ContentSettingImageModel {
+ public:
+  ContentSettingMIDISysExImageModel();
+
+  virtual void UpdateFromWebContents(WebContents* web_contents) OVERRIDE;
+};
+
 namespace {
 
 struct ContentSettingsTypeIdEntry {
@@ -297,6 +304,36 @@
   set_visible(false);
 }
 
+ContentSettingMIDISysExImageModel::ContentSettingMIDISysExImageModel()
+    : ContentSettingImageModel(CONTENT_SETTINGS_TYPE_MIDI_SYSEX) {
+}
+
+void ContentSettingMIDISysExImageModel::UpdateFromWebContents(
+    WebContents* web_contents) {
+  set_visible(false);
+  if (!web_contents)
+    return;
+  TabSpecificContentSettings* content_settings =
+      TabSpecificContentSettings::FromWebContents(web_contents);
+  if (!content_settings)
+    return;
+  const ContentSettingsUsagesState& usages_state =
+      content_settings->midi_usages_state();
+  if (usages_state.state_map().empty())
+    return;
+  set_visible(true);
+
+  // If any embedded site has access the allowed icon takes priority over the
+  // blocked icon.
+  unsigned int state_flags = 0;
+  usages_state.GetDetailedInfo(NULL, &state_flags);
+  bool allowed =
+      !!(state_flags & ContentSettingsUsagesState::TABSTATE_HAS_ANY_ALLOWED);
+  set_icon(allowed ? IDR_ALLOWED_MIDI_SYSEX : IDR_BLOCKED_MIDI_SYSEX);
+  set_tooltip(l10n_util::GetStringUTF8(allowed ?
+      IDS_MIDI_SYSEX_ALLOWED_TOOLTIP : IDS_MIDI_SYSEX_BLOCKED_TOOLTIP));
+}
+
 ContentSettingImageModel::ContentSettingImageModel(
     ContentSettingsType content_settings_type)
     : content_settings_type_(content_settings_type),
@@ -320,6 +357,8 @@
     case CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC:
     case CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA:
       return new ContentSettingMediaImageModel(content_settings_type);
+    case CONTENT_SETTINGS_TYPE_MIDI_SYSEX:
+      return new ContentSettingMIDISysExImageModel();
     default:
       return new ContentSettingBlockedImageModel(content_settings_type);
   }
diff --git a/chrome/browser/ui/extensions/application_launch.cc b/chrome/browser/ui/extensions/application_launch.cc
index 02112d1..cec680a 100644
--- a/chrome/browser/ui/extensions/application_launch.cc
+++ b/chrome/browser/ui/extensions/application_launch.cc
@@ -20,7 +20,6 @@
 #include "chrome/browser/ui/browser_finder.h"
 #include "chrome/browser/ui/browser_tabstrip.h"
 #include "chrome/browser/ui/browser_window.h"
-#include "chrome/browser/ui/extensions/app_metro_infobar_delegate_win.h"
 #include "chrome/browser/ui/host_desktop.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
 #include "chrome/browser/web_applications/web_app.h"
@@ -343,17 +342,6 @@
   UMA_HISTOGRAM_ENUMERATION("Extensions.AppLaunchContainer", container, 100);
 
   if (extension->is_platform_app()) {
-#if defined(OS_WIN)
-    // On Windows 8's single window Metro mode we can not launch platform apps.
-    // Offer to switch Chrome to desktop mode.
-    if (win8::IsSingleWindowMetroMode()) {
-      AppMetroInfoBarDelegateWin::Create(
-          profile, AppMetroInfoBarDelegateWin::LAUNCH_PACKAGED_APP,
-          extension->id());
-      return NULL;
-    }
-#endif
-
     apps::LaunchPlatformAppWithCommandLine(
         profile, extension, params.command_line, params.current_directory);
     return NULL;
diff --git a/chrome/browser/ui/extensions/apps_metro_handler_win.cc b/chrome/browser/ui/extensions/apps_metro_handler_win.cc
index 0f253b2..f59f675 100644
--- a/chrome/browser/ui/extensions/apps_metro_handler_win.cc
+++ b/chrome/browser/ui/extensions/apps_metro_handler_win.cc
@@ -5,7 +5,7 @@
 #include "chrome/browser/ui/extensions/apps_metro_handler_win.h"
 
 #include "apps/shell_window.h"
-#include "chrome/browser/extensions/shell_window_registry.h"
+#include "apps/shell_window_registry.h"
 #include "chrome/browser/ui/simple_message_box.h"
 #include "grit/chromium_strings.h"
 #include "grit/generated_resources.h"
@@ -14,7 +14,7 @@
 namespace chrome {
 
 bool VerifySwitchToMetroForApps(gfx::NativeWindow parent_window) {
-  if (!extensions::ShellWindowRegistry::IsShellWindowRegisteredInAnyProfile(
+  if (!apps::ShellWindowRegistry::IsShellWindowRegisteredInAnyProfile(
           apps::ShellWindow::WINDOW_TYPE_DEFAULT)) {
     return true;
   }
diff --git a/chrome/browser/ui/extensions/extension_enable_flow.cc b/chrome/browser/ui/extensions/extension_enable_flow.cc
index c1d59a6..b1ec1a9 100644
--- a/chrome/browser/ui/extensions/extension_enable_flow.cc
+++ b/chrome/browser/ui/extensions/extension_enable_flow.cc
@@ -4,10 +4,13 @@
 
 #include "chrome/browser/ui/extensions/extension_enable_flow.h"
 
+#include "chrome/browser/chrome_notification_types.h"
 #include "chrome/browser/extensions/extension_service.h"
 #include "chrome/browser/extensions/extension_system.h"
 #include "chrome/browser/ui/browser_finder.h"
 #include "chrome/browser/ui/extensions/extension_enable_flow_delegate.h"
+#include "content/public/browser/notification_details.h"
+#include "content/public/browser/notification_source.h"
 
 using extensions::Extension;
 
@@ -48,10 +51,30 @@
     // the user clicked on it.
     if (!extension)
       return;
-    // If the app was terminated, reload it first. (This reallocates the
-    // Extension object.)
+    // If the app was terminated, reload it first.
     service->ReloadExtension(extension_id_);
+
+    // ReloadExtension reallocates the Extension object.
     extension = service->GetExtensionById(extension_id_, true);
+
+    // |extension| could be NULL for asynchronous load, such as the case of
+    // an unpacked extension. Wait for the load to continue the flow.
+    if (!extension) {
+      StartObserving();
+      return;
+    }
+  }
+
+  CheckPermissionAndMaybePromptUser();
+}
+
+void ExtensionEnableFlow::CheckPermissionAndMaybePromptUser() {
+  ExtensionService* service =
+      extensions::ExtensionSystem::Get(profile_)->extension_service();
+  const Extension* extension = service->GetExtensionById(extension_id_, true);
+  if (!extension) {
+    delegate_->ExtensionEnableFlowAborted(false);  // |delegate_| may delete us.
+    return;
   }
 
   extensions::ExtensionPrefs* extension_prefs = service->extension_prefs();
@@ -74,6 +97,53 @@
       new ExtensionInstallPrompt(profile_, parent_window_, this));
 }
 
+void ExtensionEnableFlow::StartObserving() {
+  registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_LOADED,
+                 content::Source<Profile>(profile_));
+  registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_LOAD_ERROR,
+                 content::Source<Profile>(profile_));
+  registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_UNINSTALLED,
+                 content::Source<Profile>(profile_));
+}
+
+void ExtensionEnableFlow::StopObserving() {
+  registrar_.RemoveAll();
+}
+
+void ExtensionEnableFlow::Observe(int type,
+                                  const content::NotificationSource& source,
+                                  const content::NotificationDetails& details) {
+  switch (type) {
+    case chrome::NOTIFICATION_EXTENSION_LOADED: {
+      const Extension* extension =
+          content::Details<const Extension>(details).ptr();
+      if (extension->id() == extension_id_) {
+        StopObserving();
+        CheckPermissionAndMaybePromptUser();
+      }
+
+      break;
+    }
+    case chrome::NOTIFICATION_EXTENSION_LOAD_ERROR: {
+      StopObserving();
+      delegate_->ExtensionEnableFlowAborted(false);
+      break;
+    }
+    case chrome::NOTIFICATION_EXTENSION_UNINSTALLED: {
+      const Extension* extension =
+          content::Details<const Extension>(details).ptr();
+      if (extension->id() == extension_id_) {
+        StopObserving();
+        delegate_->ExtensionEnableFlowAborted(false);
+      }
+
+      break;
+    }
+    default:
+      NOTREACHED();
+  }
+}
+
 void ExtensionEnableFlow::InstallUIProceed() {
   ExtensionService* service =
       extensions::ExtensionSystem::Get(profile_)->extension_service();
diff --git a/chrome/browser/ui/extensions/extension_enable_flow.h b/chrome/browser/ui/extensions/extension_enable_flow.h
index 1581e56..4a1548c 100644
--- a/chrome/browser/ui/extensions/extension_enable_flow.h
+++ b/chrome/browser/ui/extensions/extension_enable_flow.h
@@ -10,6 +10,8 @@
 #include "base/basictypes.h"
 #include "base/compiler_specific.h"
 #include "chrome/browser/extensions/extension_install_prompt.h"
+#include "content/public/browser/notification_observer.h"
+#include "content/public/browser/notification_registrar.h"
 #include "content/public/browser/page_navigator.h"
 
 class ExtensionEnableFlowDelegate;
@@ -27,7 +29,8 @@
 // shown to user. The extension is enabled when user acknowledges it or the
 // flow is aborted when user declines it.
 class ExtensionEnableFlow : public ExtensionInstallPrompt::Delegate,
-                            public content::PageNavigator {
+                            public content::PageNavigator,
+                            public content::NotificationObserver {
  public:
   ExtensionEnableFlow(Profile* profile,
                       const std::string& extension_id,
@@ -45,15 +48,30 @@
   const std::string& extension_id() const { return extension_id_; }
 
  private:
-  // Runs the enable flow. Currently, it checks if there is permission
-  // escalation while the extension is disabled/terminated. If no, enables the
-  // extension and notify |delegate_| synchronously. Otherwise, creates an
-  // ExtensionInstallPrompt and asks user to confirm.
+  // Runs the enable flow. It starts by checking if the extension is loaded.
+  // If not, it tries to reload it. If the load is asynchronous, wait for the
+  // load to finish before continuing the flow. Otherwise, calls
+  // CheckPermissionAndMaybePromptUser finish the flow.
   void Run();
 
+  // Checks if there is permission escalation while the extension is
+  // disabled/terminated. If no, enables the extension and notify |delegate_|
+  // synchronously. Otherwise, creates an ExtensionInstallPrompt and asks user
+  // to confirm.
+  void CheckPermissionAndMaybePromptUser();
+
   // Creates an ExtensionInstallPrompt in |prompt_|.
   void CreatePrompt();
 
+  // Starts/stops observing extension load notifications.
+  void StartObserving();
+  void StopObserving();
+
+  // content::NotificationObserver overrides:
+  virtual void Observe(int type,
+                       const content::NotificationSource& source,
+                       const content::NotificationDetails& details) OVERRIDE;
+
   // ExtensionInstallPrompt::Delegate overrides:
   virtual void InstallUIProceed() OVERRIDE;
   virtual void InstallUIAbort(bool user_initiated) OVERRIDE;
@@ -75,6 +93,7 @@
   gfx::NativeWindow parent_window_;
 
   scoped_ptr<ExtensionInstallPrompt> prompt_;
+  content::NotificationRegistrar registrar_;
 
   DISALLOW_COPY_AND_ASSIGN(ExtensionEnableFlow);
 };
diff --git a/chrome/browser/ui/find_bar/find_match_rects_details.cc b/chrome/browser/ui/find_bar/find_match_rects_details.cc
deleted file mode 100644
index 7e8e9da..0000000
--- a/chrome/browser/ui/find_bar/find_match_rects_details.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 "chrome/browser/ui/find_bar/find_match_rects_details.h"
-
-FindMatchRectsDetails::FindMatchRectsDetails()
-    : version_(-1) {
-}
-
-FindMatchRectsDetails::FindMatchRectsDetails(
-    int version,
-    const std::vector<gfx::RectF>& rects,
-    const gfx::RectF& active_rect)
-    : version_(version),
-      rects_(rects),
-      active_rect_(active_rect) {
-}
-
-FindMatchRectsDetails::~FindMatchRectsDetails() {
-}
diff --git a/chrome/browser/ui/find_bar/find_match_rects_details.h b/chrome/browser/ui/find_bar/find_match_rects_details.h
deleted file mode 100644
index 98c0380..0000000
--- a/chrome/browser/ui/find_bar/find_match_rects_details.h
+++ /dev/null
@@ -1,41 +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_UI_FIND_BAR_FIND_MATCH_RECTS_DETAILS_H_
-#define CHROME_BROWSER_UI_FIND_BAR_FIND_MATCH_RECTS_DETAILS_H_
-
-#include <vector>
-
-#include "base/basictypes.h"
-#include "ui/gfx/rect_f.h"
-
-// Holds the result details of a RequestFindMatchRects reply.
-class FindMatchRectsDetails {
- public:
-  FindMatchRectsDetails();
-
-  FindMatchRectsDetails(int version,
-                        const std::vector<gfx::RectF>& rects,
-                        const gfx::RectF& active_rect);
-
-  ~FindMatchRectsDetails();
-
-  int version() const { return version_; }
-
-  const std::vector<gfx::RectF>& rects() const { return rects_; }
-
-  const gfx::RectF& active_rect() const { return active_rect_; }
-
- private:
-  // The version of the rects in this structure.
-  int version_;
-
-  // The rects of the find matches in find-in-page coordinates.
-  std::vector<gfx::RectF> rects_;
-
-  // The rect of the active find match in find-in-page coordinates.
-  gfx::RectF active_rect_;
-};
-
-#endif  // CHROME_BROWSER_UI_FIND_BAR_FIND_MATCH_RECTS_DETAILS_H_
diff --git a/chrome/browser/ui/gesture_prefs_observer_factory_aura.cc b/chrome/browser/ui/gesture_prefs_observer_factory_aura.cc
index 82895ff..4e73dcc 100644
--- a/chrome/browser/ui/gesture_prefs_observer_factory_aura.cc
+++ b/chrome/browser/ui/gesture_prefs_observer_factory_aura.cc
@@ -151,6 +151,31 @@
   // Clear for migration.
   prefs->ClearPref(kTouchScreenFlingAccelerationAdjustment);
 
+  // TODO(mohsen): Remove following code in M32. By then, gesture prefs will
+  // have been cleared for majority of the users: crbug.com/269292.
+  // Do a one-time wipe of all gesture preferences.
+  if (!prefs->GetBoolean(prefs::kGestureConfigIsTrustworthy)) {
+    for (size_t i = 0; i < arraysize(kPrefsToObserve); ++i)
+      prefs->ClearPref(kPrefsToObserve[i]);
+
+    const std::vector<OverscrollPref>& overscroll_prefs = GetOverscrollPrefs();
+    for (size_t i = 0; i < overscroll_prefs.size(); ++i)
+      prefs->ClearPref(overscroll_prefs[i].pref_name);
+
+    for (size_t i = 0; i < arraysize(kFlingTouchpadPrefs); ++i)
+      prefs->ClearPref(kFlingTouchpadPrefs[i]);
+
+    for (size_t i = 0; i < arraysize(kFlingTouchscreenPrefs); ++i)
+      prefs->ClearPref(kFlingTouchscreenPrefs[i]);
+
+#if defined(USE_ASH)
+    for (size_t i = 0; i < arraysize(kImmersiveModePrefs); ++i)
+      prefs->ClearPref(kImmersiveModePrefs[i]);
+#endif  // USE_ASH
+
+    prefs->SetBoolean(prefs::kGestureConfigIsTrustworthy, true);
+  }
+
   registrar_.Init(prefs);
   registrar_.RemoveAll();
   base::Closure callback = base::Bind(&GesturePrefsObserver::Update,
@@ -481,6 +506,12 @@
   RegisterOverscrollPrefs(registry);
   RegisterFlingCurveParameters(registry);
   RegisterImmersiveModePrefs(registry);
+
+  // Register pref for a one-time wipe of all gesture preferences.
+  registry->RegisterBooleanPref(
+      prefs::kGestureConfigIsTrustworthy,
+      false,
+      user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
 }
 
 bool
diff --git a/chrome/browser/ui/gtk/download/download_shelf_gtk.cc b/chrome/browser/ui/gtk/download/download_shelf_gtk.cc
index 638fb10..a799604 100644
--- a/chrome/browser/ui/gtk/download/download_shelf_gtk.cc
+++ b/chrome/browser/ui/gtk/download/download_shelf_gtk.cc
@@ -9,7 +9,7 @@
 #include "base/bind.h"
 #include "chrome/browser/chrome_notification_types.h"
 #include "chrome/browser/download/download_item_model.h"
-#include "chrome/browser/download/download_util.h"
+#include "chrome/browser/download/download_stats.h"
 #include "chrome/browser/themes/theme_properties.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/chrome_pages.h"
@@ -209,7 +209,7 @@
     if (download_items_[i]->download()->GetState() == DownloadItem::IN_PROGRESS)
       ++num_in_progress;
   }
-  download_util::RecordShelfClose(
+  RecordDownloadShelfClose(
       download_items_.size(), num_in_progress, reason == AUTOMATIC);
   SetCloseOnMouseOut(false);
 }
diff --git a/chrome/browser/ui/gtk/gtk_theme_service.cc b/chrome/browser/ui/gtk/gtk_theme_service.cc
index 76befd6..97e0ec5 100644
--- a/chrome/browser/ui/gtk/gtk_theme_service.cc
+++ b/chrome/browser/ui/gtk/gtk_theme_service.cc
@@ -17,6 +17,7 @@
 #include "base/stl_util.h"
 #include "chrome/browser/chrome_notification_types.h"
 #include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/themes/custom_theme_supplier.h"
 #include "chrome/browser/themes/theme_properties.h"
 #include "chrome/browser/themes/theme_service_factory.h"
 #include "chrome/browser/ui/browser.h"
@@ -347,6 +348,7 @@
 
 void GtkThemeService::SetTheme(const extensions::Extension* extension) {
   profile()->GetPrefs()->SetBoolean(prefs::kUsesSystemTheme, false);
+  use_gtk_ = false;
   LoadDefaultValues();
   ThemeService::SetTheme(extension);
 }
@@ -370,6 +372,14 @@
   return !use_gtk_ && ThemeService::UsingDefaultTheme();
 }
 
+void GtkThemeService::SetCustomDefaultTheme(
+    scoped_refptr<CustomThemeSupplier> theme_supplier) {
+  profile()->GetPrefs()->SetBoolean(prefs::kUsesSystemTheme, false);
+  use_gtk_ = false;
+  LoadDefaultValues();
+  ThemeService::SetCustomDefaultTheme(theme_supplier);
+}
+
 bool GtkThemeService::ShouldInitWithNativeTheme() const {
   return profile()->GetPrefs()->GetBoolean(prefs::kUsesSystemTheme);
 }
diff --git a/chrome/browser/ui/gtk/gtk_theme_service.h b/chrome/browser/ui/gtk/gtk_theme_service.h
index 18a840e..fbb487b 100644
--- a/chrome/browser/ui/gtk/gtk_theme_service.h
+++ b/chrome/browser/ui/gtk/gtk_theme_service.h
@@ -18,6 +18,7 @@
 #include "ui/base/gtk/owned_widget_gtk.h"
 #include "ui/gfx/color_utils.h"
 
+class CustomThemeSupplier;
 class Profile;
 
 namespace content {
@@ -79,6 +80,8 @@
   virtual void SetNativeTheme() OVERRIDE;
   virtual bool UsingDefaultTheme() const OVERRIDE;
   virtual bool UsingNativeTheme() const OVERRIDE;
+  virtual void SetCustomDefaultTheme(
+      scoped_refptr<CustomThemeSupplier> theme_supplier) OVERRIDE;
   virtual bool ShouldInitWithNativeTheme() const OVERRIDE;
 
   // Creates a GtkChromeButton instance, registered with this theme provider,
diff --git a/chrome/browser/ui/gtk/location_bar_view_gtk.cc b/chrome/browser/ui/gtk/location_bar_view_gtk.cc
index 8f8b8b0..95693c2 100644
--- a/chrome/browser/ui/gtk/location_bar_view_gtk.cc
+++ b/chrome/browser/ui/gtk/location_bar_view_gtk.cc
@@ -92,7 +92,6 @@
 #include "ui/gfx/font.h"
 #include "ui/gfx/gtk_util.h"
 #include "ui/gfx/image/image.h"
-#include "ui/gfx/rect.h"
 
 using content::NavigationEntry;
 using content::OpenURLParams;
@@ -618,12 +617,6 @@
   return browser_->tab_strip_model()->GetActiveWebContents();
 }
 
-gfx::Rect LocationBarViewGtk::GetOmniboxBounds() const {
-  GtkAllocation hbox_allocation;
-  gtk_widget_get_allocation(hbox_.get(), &hbox_allocation);
-  return AllocationToRect(hbox_allocation);
-}
-
 void LocationBarViewGtk::SetPreviewEnabledPageAction(
     ExtensionAction* page_action,
     bool preview_enabled) {
@@ -949,7 +942,7 @@
   // Not implemented on Gtk.
 }
 
-void LocationBarViewGtk::UpdateAutofillCreditCardView() {
+void LocationBarViewGtk::UpdateGeneratedCreditCardView() {
   NOTIMPLEMENTED();
 }
 
diff --git a/chrome/browser/ui/gtk/location_bar_view_gtk.h b/chrome/browser/ui/gtk/location_bar_view_gtk.h
index c886f32..b8dc178 100644
--- a/chrome/browser/ui/gtk/location_bar_view_gtk.h
+++ b/chrome/browser/ui/gtk/location_bar_view_gtk.h
@@ -122,7 +122,6 @@
   virtual string16 GetTitle() const OVERRIDE;
   virtual InstantController* GetInstant() OVERRIDE;
   virtual content::WebContents* GetWebContents() const OVERRIDE;
-  virtual gfx::Rect GetOmniboxBounds() const OVERRIDE;
 
   // LocationBar:
   virtual void ShowFirstRunBubble() OVERRIDE;
@@ -136,7 +135,7 @@
   virtual void UpdatePageActions() OVERRIDE;
   virtual void InvalidatePageActions() OVERRIDE;
   virtual void UpdateOpenPDFInReaderPrompt() OVERRIDE;
-  virtual void UpdateAutofillCreditCardView() OVERRIDE;
+  virtual void UpdateGeneratedCreditCardView() OVERRIDE;
   virtual void SaveStateToContents(content::WebContents* contents) OVERRIDE;
   virtual void Revert() OVERRIDE;
   virtual const OmniboxView* GetLocationEntry() const OVERRIDE;
diff --git a/chrome/browser/ui/gtk/menu_gtk.cc b/chrome/browser/ui/gtk/menu_gtk.cc
index 27fff39..bbed502 100644
--- a/chrome/browser/ui/gtk/menu_gtk.cc
+++ b/chrome/browser/ui/gtk/menu_gtk.cc
@@ -322,7 +322,7 @@
 GtkWidget* MenuGtk::AppendMenuItemWithLabel(int command_id,
                                             const std::string& label) {
   std::string converted_label = ui::ConvertAcceleratorsFromWindowsStyle(label);
-  GtkWidget* menu_item = BuildMenuItemWithLabel(label, command_id);
+  GtkWidget* menu_item = BuildMenuItemWithLabel(converted_label, command_id);
   return AppendMenuItem(command_id, menu_item);
 }
 
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 b3e429c..a77871a 100644
--- a/chrome/browser/ui/gtk/omnibox/omnibox_view_gtk_unittest.cc
+++ b/chrome/browser/ui/gtk/omnibox/omnibox_view_gtk_unittest.cc
@@ -16,7 +16,6 @@
 #include "testing/platform_test.h"
 #include "ui/base/gtk/gtk_hig_constants.h"
 #include "ui/gfx/image/image.h"
-#include "ui/gfx/rect.h"
 
 namespace {
 class OmniboxEditControllerMock : public OmniboxEditController {
@@ -34,7 +33,6 @@
   MOCK_CONST_METHOD0(GetTitle, string16());
   MOCK_METHOD0(GetInstant, InstantController*());
   MOCK_CONST_METHOD0(GetWebContents, content::WebContents*());
-  MOCK_CONST_METHOD0(GetOmniboxBounds, gfx::Rect());
 
   virtual ~OmniboxEditControllerMock() {}
 };
diff --git a/chrome/browser/ui/omnibox/location_bar.h b/chrome/browser/ui/omnibox/location_bar.h
index 6a759b1..3a4fc68 100644
--- a/chrome/browser/ui/omnibox/location_bar.h
+++ b/chrome/browser/ui/omnibox/location_bar.h
@@ -64,10 +64,10 @@
   // Updates the state of the button to open a PDF in Adobe Reader.
   virtual void UpdateOpenPDFInReaderPrompt() = 0;
 
-  // Updates the Autofill credit card view. This views serves as an anchor for
-  // the Autofill credit card bubble, which might show on successful run of the
-  // Autofill dialog.
-  virtual void UpdateAutofillCreditCardView() = 0;
+  // Updates the generated credit card view. This view serves as an anchor for
+  // the generated credit card bubble, which can show on successful generation
+  // of a new credit card number.
+  virtual void UpdateGeneratedCreditCardView() = 0;
 
   // Saves the state of the location bar to the specified WebContents, so that
   // it can be restored later. (Done when switching tabs).
diff --git a/chrome/browser/ui/omnibox/omnibox_controller.cc b/chrome/browser/ui/omnibox/omnibox_controller.cc
index 31ae5e5..a15dd14 100644
--- a/chrome/browser/ui/omnibox/omnibox_controller.cc
+++ b/chrome/browser/ui/omnibox/omnibox_controller.cc
@@ -43,16 +43,10 @@
     AutocompleteInput::PageClassification current_page_classification,
     bool prevent_inline_autocomplete,
     bool prefer_keyword,
-    bool allow_exact_keyword_match,
-    int omnibox_start_margin) const {
+    bool allow_exact_keyword_match) const {
   ClearPopupKeywordMode();
   popup_->SetHoveredLine(OmniboxPopupModel::kNoMatch);
 
-  if (chrome::IsInstantExtendedAPIEnabled()) {
-    autocomplete_controller_->search_provider()->
-        SetOmniboxStartMargin(omnibox_start_margin);
-  }
-
   // We don't explicitly clear OmniboxPopupModel::manually_selected_match, as
   // Start ends up invoking OmniboxPopupModel::OnResultChanged which clears it.
   autocomplete_controller_->Start(AutocompleteInput(
diff --git a/chrome/browser/ui/omnibox/omnibox_controller.h b/chrome/browser/ui/omnibox/omnibox_controller.h
index 977bd4c..e5e2d97 100644
--- a/chrome/browser/ui/omnibox/omnibox_controller.h
+++ b/chrome/browser/ui/omnibox/omnibox_controller.h
@@ -48,8 +48,7 @@
       AutocompleteInput::PageClassification current_page_classification,
       bool prevent_inline_autocomplete,
       bool prefer_keyword,
-      bool allow_exact_keyword_match,
-      int omnibox_start_margin) const;
+      bool allow_exact_keyword_match) const;
 
   // AutocompleteControllerDelegate:
   virtual void OnResultChanged(bool default_match_changed) OVERRIDE;
diff --git a/chrome/browser/ui/omnibox/omnibox_current_page_delegate.h b/chrome/browser/ui/omnibox/omnibox_current_page_delegate.h
index b21495b..560b2c3 100644
--- a/chrome/browser/ui/omnibox/omnibox_current_page_delegate.h
+++ b/chrome/browser/ui/omnibox/omnibox_current_page_delegate.h
@@ -35,6 +35,9 @@
   // Returns true if the visible entry is a New Tab Page rendered by Instant.
   virtual bool IsInstantNTP() const = 0;
 
+  // Returns true if the committed entry is a search results page.
+  virtual bool IsSearchResultsPage() const = 0;
+
   // Returns whether the current page is loading.
   virtual bool IsLoading() const = 0;
 
diff --git a/chrome/browser/ui/omnibox/omnibox_current_page_delegate_impl.cc b/chrome/browser/ui/omnibox/omnibox_current_page_delegate_impl.cc
index e26f8d5..952497c 100644
--- a/chrome/browser/ui/omnibox/omnibox_current_page_delegate_impl.cc
+++ b/chrome/browser/ui/omnibox/omnibox_current_page_delegate_impl.cc
@@ -11,6 +11,8 @@
 #include "chrome/browser/predictors/autocomplete_action_predictor_factory.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/search/search.h"
+#include "chrome/browser/search_engines/template_url_service.h"
+#include "chrome/browser/search_engines/template_url_service_factory.h"
 #include "chrome/browser/sessions/session_tab_helper.h"
 #include "chrome/browser/ui/omnibox/omnibox_edit_controller.h"
 #include "chrome/browser/ui/search/search_tab_helper.h"
@@ -40,6 +42,13 @@
   return chrome::IsInstantNTP(controller_->GetWebContents());
 }
 
+bool OmniboxCurrentPageDelegateImpl::IsSearchResultsPage() const {
+  Profile* profile = Profile::FromBrowserContext(
+      controller_->GetWebContents()->GetBrowserContext());
+  return TemplateURLServiceFactory::GetForProfile(profile)->
+      IsSearchResultsPageFromDefaultSearchProvider(GetURL());
+}
+
 bool OmniboxCurrentPageDelegateImpl::IsLoading() const {
   return controller_->GetWebContents()->IsLoading();
 }
diff --git a/chrome/browser/ui/omnibox/omnibox_current_page_delegate_impl.h b/chrome/browser/ui/omnibox/omnibox_current_page_delegate_impl.h
index 5546ad0..9f5b024 100644
--- a/chrome/browser/ui/omnibox/omnibox_current_page_delegate_impl.h
+++ b/chrome/browser/ui/omnibox/omnibox_current_page_delegate_impl.h
@@ -21,6 +21,7 @@
   virtual bool CurrentPageExists() const OVERRIDE;
   virtual const GURL& GetURL() const OVERRIDE;
   virtual bool IsInstantNTP() const OVERRIDE;
+  virtual bool IsSearchResultsPage() const OVERRIDE;
   virtual bool IsLoading() const OVERRIDE;
   virtual content::NavigationController&
       GetNavigationController() const OVERRIDE;
diff --git a/chrome/browser/ui/omnibox/omnibox_edit_controller.h b/chrome/browser/ui/omnibox/omnibox_edit_controller.h
index 5825500..b651739 100644
--- a/chrome/browser/ui/omnibox/omnibox_edit_controller.h
+++ b/chrome/browser/ui/omnibox/omnibox_edit_controller.h
@@ -18,7 +18,6 @@
 
 namespace gfx {
 class Image;
-class Rect;
 }
 
 // I am in hack-and-slash mode right now.
@@ -70,9 +69,6 @@
   // Returns the WebContents of the currently active tab.
   virtual content::WebContents* GetWebContents() const = 0;
 
-  // Returns the bounds for the omnibox.
-  virtual gfx::Rect GetOmniboxBounds() const = 0;
-
  protected:
   virtual ~OmniboxEditController() {}
 };
diff --git a/chrome/browser/ui/omnibox/omnibox_edit_model.cc b/chrome/browser/ui/omnibox/omnibox_edit_model.cc
index b4c9087..4ee0baf 100644
--- a/chrome/browser/ui/omnibox/omnibox_edit_model.cc
+++ b/chrome/browser/ui/omnibox/omnibox_edit_model.cc
@@ -502,8 +502,7 @@
       (has_selected_text && inline_autocomplete_text_.empty()) ||
       (paste_state_ != NONE),
       keyword_is_selected,
-      keyword_is_selected || allow_exact_keyword_match_,
-      controller_->GetOmniboxBounds().x());
+      keyword_is_selected || allow_exact_keyword_match_);
 }
 
 void OmniboxEditModel::StopAutocomplete() {
@@ -728,12 +727,11 @@
 
     // Track whether the destination URL sends us to a search results page
     // using the default search provider.
-    TemplateURL* default_provider =
-        TemplateURLServiceFactory::GetForProfile(profile_)->
-            GetDefaultSearchProvider();
-    if (default_provider && default_provider->IsSearchURL(destination_url))
+    if (TemplateURLServiceFactory::GetForProfile(profile_)->
+        IsSearchResultsPageFromDefaultSearchProvider(destination_url)) {
       content::RecordAction(
           UserMetricsAction("OmniboxDestinationURLIsSearchOnDSP"));
+    }
 
     // This calls RevertAll again.
     base::AutoReset<bool> tmp(&in_revert_, true);
@@ -860,8 +858,9 @@
 }
 
 bool OmniboxEditModel::OnEscapeKeyPressed() {
+  const AutocompleteMatch& match = CurrentMatch(NULL);
   if (has_temporary_text_) {
-    if (CurrentMatch(NULL).destination_url != original_url_) {
+    if (match.destination_url != original_url_) {
       RevertTemporaryText(true);
       return true;
     }
@@ -879,7 +878,10 @@
   // When the permanent text isn't all selected we still fall through to the
   // SelectAll() call below so users can arrow around in the text and then hit
   // <esc> to quickly replace all the text; this matches IE.
-  if (!user_input_in_progress_ && view_->IsSelectAll())
+  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())
     return false;
 
   if (!user_text_.empty()) {
@@ -1294,6 +1296,9 @@
   if (view_->toolbar_model()->WouldReplaceSearchURLWithSearchTerms(true)) {
     return AutocompleteInput::SEARCH_RESULT_PAGE_DOING_SEARCH_TERM_REPLACEMENT;
   }
+  if (delegate_->IsSearchResultsPage()) {
+    return AutocompleteInput::SEARCH_RESULT_PAGE_NO_SEARCH_TERM_REPLACEMENT;
+  }
   return AutocompleteInput::OTHER;
 }
 
diff --git a/chrome/browser/ui/omnibox/omnibox_edit_unittest.cc b/chrome/browser/ui/omnibox/omnibox_edit_unittest.cc
index 7fd366a..1424011 100644
--- a/chrome/browser/ui/omnibox/omnibox_edit_unittest.cc
+++ b/chrome/browser/ui/omnibox/omnibox_edit_unittest.cc
@@ -14,7 +14,6 @@
 #include "testing/gtest/include/gtest/gtest.h"
 #include "ui/gfx/font.h"
 #include "ui/gfx/image/image.h"
-#include "ui/gfx/rect.h"
 
 using content::WebContents;
 
@@ -105,7 +104,6 @@
   virtual WebContents* GetWebContents() const OVERRIDE {
     return NULL;
   }
-  virtual gfx::Rect GetOmniboxBounds() const OVERRIDE { return gfx::Rect(); }
 
  private:
   DISALLOW_COPY_AND_ASSIGN(TestingOmniboxEditController);
diff --git a/chrome/browser/ui/omnibox/omnibox_popup_non_view.cc b/chrome/browser/ui/omnibox/omnibox_popup_non_view.cc
deleted file mode 100644
index 4c22d7e..0000000
--- a/chrome/browser/ui/omnibox/omnibox_popup_non_view.cc
+++ /dev/null
@@ -1,39 +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/ui/omnibox/omnibox_popup_non_view.h"
-
-#include "ui/gfx/image/image.h"
-#include "ui/gfx/rect.h"
-
-OmniboxPopupNonView::OmniboxPopupNonView(OmniboxEditModel* edit_model)
-  : model_(this, edit_model),
-    is_open_(false) {
-}
-
-OmniboxPopupNonView::~OmniboxPopupNonView() {
-}
-
-bool OmniboxPopupNonView::IsOpen() const {
-  return is_open_;
-}
-
-void OmniboxPopupNonView::InvalidateLine(size_t line) {
-}
-
-void OmniboxPopupNonView::UpdatePopupAppearance() {
-  is_open_ = !model_.result().empty();
-}
-
-gfx::Rect OmniboxPopupNonView::GetTargetBounds() {
-  // Non-view bounds never obscure the page, so return an empty rect.
-  return gfx::Rect();
-}
-
-void OmniboxPopupNonView::PaintUpdatesNow() {
-  // TODO(beng): remove this from the interface.
-}
-
-void OmniboxPopupNonView::OnDragCanceled() {
-}
diff --git a/chrome/browser/ui/omnibox/omnibox_popup_non_view.h b/chrome/browser/ui/omnibox/omnibox_popup_non_view.h
deleted file mode 100644
index 5e9b24b..0000000
--- a/chrome/browser/ui/omnibox/omnibox_popup_non_view.h
+++ /dev/null
@@ -1,46 +0,0 @@
-// Copyright 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_UI_OMNIBOX_OMNIBOX_POPUP_NON_VIEW_H_
-#define CHROME_BROWSER_UI_OMNIBOX_OMNIBOX_POPUP_NON_VIEW_H_
-
-#include "chrome/browser/ui/omnibox/omnibox_popup_model.h"
-#include "chrome/browser/ui/omnibox/omnibox_popup_view.h"
-
-class OmniboxEditModel;
-
-// A view representing the contents of the omnibox popup.  This headless view is
-// used when Instant is doing the actual rendering of the suggestions.  The
-// Omnibox still needs a model-like object, so that is provided here.  But the
-// view portion itself is not displayed.
-class OmniboxPopupNonView : public OmniboxPopupView {
- public:
-  explicit OmniboxPopupNonView(OmniboxEditModel* edit_model);
-
-  // Overridden from OmniboxPopupView:
-  virtual bool IsOpen() const OVERRIDE;
-  virtual void InvalidateLine(size_t line) OVERRIDE;
-  virtual void UpdatePopupAppearance() OVERRIDE;
-  virtual gfx::Rect GetTargetBounds() OVERRIDE;
-  virtual void PaintUpdatesNow() OVERRIDE;
-  virtual void OnDragCanceled() OVERRIDE;
-
- protected:
-  virtual ~OmniboxPopupNonView();
-
- private:
-  OmniboxPopupModel model_;
-
-  // |is_open_| reflects whether the OmniboxEditModel has a non-empty result
-  // set. However, we can't get rid of this variable and just use the model's
-  // state directly, as there's at least one situation when the model's result
-  // set has been emptied, but the popup should still be considered to be open
-  // until UpdatePopupAppearance() is called (cf: |was_open| in
-  // OmniboxEditModel::OnResultChanged()).
-  bool is_open_;
-
-  DISALLOW_COPY_AND_ASSIGN(OmniboxPopupNonView);
-};
-
-#endif  // CHROME_BROWSER_UI_OMNIBOX_OMNIBOX_POPUP_NON_VIEW_H_
diff --git a/chrome/browser/ui/omnibox/omnibox_view.cc b/chrome/browser/ui/omnibox/omnibox_view.cc
index 50cc536..9d8f50f 100644
--- a/chrome/browser/ui/omnibox/omnibox_view.cc
+++ b/chrome/browser/ui/omnibox/omnibox_view.cc
@@ -24,6 +24,26 @@
 }
 
 // static
+string16 OmniboxView::SanitizeTextForPaste(const string16& text) {
+  // Check for non-newline whitespace; if found, collapse whitespace runs down
+  // to single spaces.
+  // TODO(shess): It may also make sense to ignore leading or
+  // trailing whitespace when making this determination.
+  for (size_t i = 0; i < text.size(); ++i) {
+    if (IsWhitespace(text[i]) && text[i] != '\n' && text[i] != '\r') {
+      const string16 collapsed = CollapseWhitespace(text, false);
+      // If the user is pasting all-whitespace, paste a single space
+      // rather than nothing, since pasting nothing feels broken.
+      return collapsed.empty() ?
+          ASCIIToUTF16(" ") : StripJavascriptSchemas(collapsed);
+    }
+  }
+
+  // Otherwise, all whitespace is newlines; remove it entirely.
+  return StripJavascriptSchemas(CollapseWhitespace(text, true));
+}
+
+// static
 string16 OmniboxView::GetClipboardText() {
   // Try text format.
   ui::Clipboard* clipboard = ui::Clipboard::GetForCurrentThread();
@@ -31,26 +51,7 @@
                                    ui::Clipboard::BUFFER_STANDARD)) {
     string16 text;
     clipboard->ReadText(ui::Clipboard::BUFFER_STANDARD, &text);
-
-    // If the input contains non-newline whitespace, treat it as
-    // search data and convert newlines to spaces.  For instance, a
-    // street address.
-    // TODO(shess): It may also make sense to ignore leading or
-    // trailing whitespace when making this determination.
-    for (size_t i = 0; i < text.size(); ++i) {
-      if (IsWhitespace(text[i]) && text[i] != '\n' && text[i] != '\r') {
-        const string16 collapsed = CollapseWhitespace(text, false);
-        // If the user is pasting all-whitespace, paste a single space
-        // rather than nothing, since pasting nothing feels broken.
-        return collapsed.empty() ?
-            ASCIIToUTF16(" ") : StripJavascriptSchemas(collapsed);
-      }
-    }
-
-    // Otherwise, the only whitespace in |text| is newlines.  Remove
-    // these entirely, because users are most likely pasting URLs
-    // split into multiple lines by terminals, email programs, etc.
-    return StripJavascriptSchemas(CollapseWhitespace(text, true));
+    return SanitizeTextForPaste(text);
   }
 
   // Try bookmark format.
diff --git a/chrome/browser/ui/omnibox/omnibox_view.h b/chrome/browser/ui/omnibox/omnibox_view.h
index 9fb5b94..a138de5 100644
--- a/chrome/browser/ui/omnibox/omnibox_view.h
+++ b/chrome/browser/ui/omnibox/omnibox_view.h
@@ -231,10 +231,18 @@
   virtual int OnPerformDrop(const ui::DropTargetEvent& event) = 0;
 #endif
 
-  // Returns a string with any leading javascript schemas stripped from the
-  // input text.
+  // Returns |text| with any leading javascript schemas stripped.
   static string16 StripJavascriptSchemas(const string16& text);
 
+  // First, calls StripJavascriptSchemas().  Then automatically collapses
+  // internal whitespace as follows:
+  // * If the only whitespace in |text| is newlines, users are most likely
+  // pasting in URLs split into multiple lines by terminals, email programs,
+  // etc. So all newlines are removed.
+  // * Otherwise, users may be pasting in search data, e.g. street addresses. In
+  // this case, runs of whitespace are collapsed down to single spaces.
+  static string16 SanitizeTextForPaste(const string16& text);
+
   // Returns the current clipboard contents as a string that can be pasted in.
   // In addition to just getting CF_UNICODETEXT out, this can also extract URLs
   // from bookmarks on the clipboard.
diff --git a/chrome/browser/ui/omnibox/omnibox_view_unittest.cc b/chrome/browser/ui/omnibox/omnibox_view_unittest.cc
index c00574b..24607d3 100644
--- a/chrome/browser/ui/omnibox/omnibox_view_unittest.cc
+++ b/chrome/browser/ui/omnibox/omnibox_view_unittest.cc
@@ -44,6 +44,26 @@
   }
 }
 
+TEST_F(OmniboxViewTest, SanitizeTextForPaste) {
+  // Broken URL has newlines stripped.
+  const string16 kWrappedURL(ASCIIToUTF16(
+      "http://www.chromium.org/developers/testing/chromium-\n"
+      "build-infrastructure/tour-of-the-chromium-buildbot"));
+
+  const string16 kFixedURL(ASCIIToUTF16(
+      "http://www.chromium.org/developers/testing/chromium-"
+      "build-infrastructure/tour-of-the-chromium-buildbot"));
+  EXPECT_EQ(kFixedURL, OmniboxView::SanitizeTextForPaste(kWrappedURL));
+
+  // Multi-line address is converted to a single-line address.
+  const string16 kWrappedAddress(ASCIIToUTF16(
+      "1600 Amphitheatre Parkway\nMountain View, CA"));
+
+  const string16 kFixedAddress(ASCIIToUTF16(
+      "1600 Amphitheatre Parkway Mountain View, CA"));
+  EXPECT_EQ(kFixedAddress, OmniboxView::SanitizeTextForPaste(kWrappedAddress));
+}
+
 TEST_F(OmniboxViewTest, GetClipboardText) {
   ui::Clipboard* clipboard = ui::Clipboard::GetForCurrentThread();
 
@@ -107,34 +127,6 @@
     clipboard_writer.WriteHTML(kMarkup, kURL);
   }
   EXPECT_TRUE(OmniboxView::GetClipboardText().empty());
-
-  // Broken URL has newlines stripped.
-  {
-    const string16 kWrappedURL(ASCIIToUTF16(
-        "http://www.chromium.org/developers/testing/chromium-\n"
-        "build-infrastructure/tour-of-the-chromium-buildbot"));
-    ui::ScopedClipboardWriter clipboard_writer(clipboard,
-                                               ui::Clipboard::BUFFER_STANDARD);
-    clipboard_writer.WriteText(kWrappedURL);
-  }
-
-  const string16 kFixedURL(ASCIIToUTF16(
-        "http://www.chromium.org/developers/testing/chromium-"
-        "build-infrastructure/tour-of-the-chromium-buildbot"));
-  EXPECT_EQ(kFixedURL, OmniboxView::GetClipboardText());
-
-  // Multi-line address is converted to a single-line address.
-  {
-    const string16 kWrappedAddress(ASCIIToUTF16(
-        "1600 Amphitheatre Parkway\nMountain View, CA"));
-    ui::ScopedClipboardWriter clipboard_writer(clipboard,
-                                               ui::Clipboard::BUFFER_STANDARD);
-    clipboard_writer.WriteText(kWrappedAddress);
-  }
-
-  const string16 kFixedAddress(ASCIIToUTF16(
-      "1600 Amphitheatre Parkway Mountain View, CA"));
-  EXPECT_EQ(kFixedAddress, OmniboxView::GetClipboardText());
 }
 
 }  // namespace
diff --git a/chrome/browser/ui/pdf/pdf_tab_helper.cc b/chrome/browser/ui/pdf/pdf_tab_helper.cc
index d78bb81..126b8a7 100644
--- a/chrome/browser/ui/pdf/pdf_tab_helper.cc
+++ b/chrome/browser/ui/pdf/pdf_tab_helper.cc
@@ -4,7 +4,7 @@
 
 #include "chrome/browser/ui/pdf/pdf_tab_helper.h"
 
-#include "chrome/browser/download/download_util.h"
+#include "chrome/browser/download/download_stats.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_finder.h"
 #include "chrome/browser/ui/browser_window.h"
@@ -75,7 +75,7 @@
 
 void PDFTabHelper::OnSaveURLAs(const GURL& url,
                                const content::Referrer& referrer) {
-  download_util::RecordDownloadSource(download_util::INITIATED_BY_PDF_SAVE);
+  RecordDownloadSource(DOWNLOAD_INITIATED_BY_PDF_SAVE);
   web_contents()->SaveFrame(url, referrer);
 }
 
diff --git a/chrome/browser/ui/search/instant_controller.cc b/chrome/browser/ui/search/instant_controller.cc
index 8c86635..3b42999 100644
--- a/chrome/browser/ui/search/instant_controller.cc
+++ b/chrome/browser/ui/search/instant_controller.cc
@@ -307,27 +307,7 @@
 void InstantController::FocusOmnibox(const content::WebContents* contents,
                                      OmniboxFocusState state) {
   DCHECK(IsContentsFrom(instant_tab(), contents));
-
-  // Do not add a default case in the switch block for the following reasons:
-  // (1) Explicitly handle the new states. If new states are added in the
-  // OmniboxFocusState, the compiler will warn the developer to handle the new
-  // states.
-  // (2) An attacker may control the renderer and sends the browser process a
-  // malformed IPC. This function responds to the invalid |state| values by
-  // doing nothing instead of crashing the browser process (intentional no-op).
-  switch (state) {
-    case OMNIBOX_FOCUS_VISIBLE:
-      // TODO(samarth): re-enable this once setValue() correctly handles
-      // URL-shaped queries.
-      // browser_->FocusOmnibox(true);
-      break;
-    case OMNIBOX_FOCUS_INVISIBLE:
-      browser_->FocusOmnibox(false);
-      break;
-    case OMNIBOX_FOCUS_NONE:
-      contents->GetView()->Focus();
-      break;
-  }
+  browser_->FocusOmnibox(state);
 }
 
 void InstantController::NavigateToURL(const content::WebContents* contents,
@@ -351,6 +331,16 @@
   browser_->OpenURL(url, transition, disposition);
 }
 
+void InstantController::PasteIntoOmnibox(const content::WebContents* contents,
+      const string16& text) {
+  if (search_mode_.is_origin_default())
+    return;
+
+  DCHECK(IsContentsFrom(instant_tab(), contents));
+
+  browser_->PasteIntoOmnibox(text);
+}
+
 void InstantController::ResetInstantTab() {
   if (!search_mode_.is_origin_default()) {
     content::WebContents* active_tab = browser_->GetActiveWebContents();
diff --git a/chrome/browser/ui/search/instant_controller.h b/chrome/browser/ui/search/instant_controller.h
index e117a3a..412a9b3 100644
--- a/chrome/browser/ui/search/instant_controller.h
+++ b/chrome/browser/ui/search/instant_controller.h
@@ -33,6 +33,10 @@
 class WebContents;
 }
 
+namespace gfx {
+class Rect;
+}
+
 // Macro used for logging debug events. |message| should be a std::string.
 #define LOG_INSTANT_DEBUG_EVENT(controller, message) \
     controller->LogDebugEvent(message)
@@ -93,6 +97,11 @@
     return debug_events_;
   }
 
+  // Gets the stored start-edge margin and width of the omnibox.
+  const gfx::Rect omnibox_bounds() {
+    return omnibox_bounds_;
+  }
+
   // Used by BrowserInstantController to notify InstantController about the
   // instant support change event for the active web contents.
   void InstantSupportChanged(InstantSupportState instant_support);
@@ -155,6 +164,8 @@
       content::PageTransition transition,
       WindowOpenDisposition disposition,
       bool is_search_type) OVERRIDE;
+  virtual void PasteIntoOmnibox(const content::WebContents* contents,
+                                const string16& text) OVERRIDE;
   virtual void InstantPageLoadFailed(content::WebContents* contents) OVERRIDE;
 
   // Invoked by the InstantLoader when the Instant page wants to delete a
diff --git a/chrome/browser/ui/search/instant_loader.cc b/chrome/browser/ui/search/instant_loader.cc
index 4daf19a..949cf60 100644
--- a/chrome/browser/ui/search/instant_loader.cc
+++ b/chrome/browser/ui/search/instant_loader.cc
@@ -107,8 +107,10 @@
 
   SearchTabHelper::CreateForWebContents(contents());
 
+#if !defined(OS_ANDROID)
   // Observers.
   extensions::WebNavigationTabObserver::CreateForWebContents(contents());
+#endif  // OS_ANDROID
 
   // Favicons, required by the Task Manager.
   FaviconTabHelper::CreateForWebContents(contents());
diff --git a/chrome/browser/ui/search/instant_ntp_prerenderer.cc b/chrome/browser/ui/search/instant_ntp_prerenderer.cc
index 2edfc11..7b3957a 100644
--- a/chrome/browser/ui/search/instant_ntp_prerenderer.cc
+++ b/chrome/browser/ui/search/instant_ntp_prerenderer.cc
@@ -197,29 +197,37 @@
 }
 
 void InstantNTPPrerenderer::InstantPageAboutToNavigateMainFrame(
-    const content::WebContents* contents,
-    const GURL& url) {
+    const content::WebContents* /* contents */,
+    const GURL& /* url */) {
   NOTREACHED();
 }
 
-void InstantNTPPrerenderer::FocusOmnibox(const content::WebContents* contents,
-                                         OmniboxFocusState state) {
+void InstantNTPPrerenderer::FocusOmnibox(
+    const content::WebContents* /* contents */,
+    OmniboxFocusState /* state */) {
   NOTREACHED();
 }
 
-void InstantNTPPrerenderer::NavigateToURL(const content::WebContents* contents,
-                                          const GURL& url,
-                                          content::PageTransition transition,
-                                          WindowOpenDisposition disposition,
-                                          bool is_search_type) {
+void InstantNTPPrerenderer::NavigateToURL(
+    const content::WebContents* /* contents */,
+    const GURL& /* url */,
+    content::PageTransition /* transition */,
+    WindowOpenDisposition /* disposition */,
+    bool /* is_search_type */) {
   NOTREACHED();
 }
 
-void InstantNTPPrerenderer::DeleteMostVisitedItem(const GURL& url) {
+void InstantNTPPrerenderer::PasteIntoOmnibox(
+    const content::WebContents* /* contents */,
+    const string16& /* text */) {
   NOTREACHED();
 }
 
-void InstantNTPPrerenderer::UndoMostVisitedDeletion(const GURL& url) {
+void InstantNTPPrerenderer::DeleteMostVisitedItem(const GURL& /* url */) {
+  NOTREACHED();
+}
+
+void InstantNTPPrerenderer::UndoMostVisitedDeletion(const GURL& /* url */) {
   NOTREACHED();
 }
 
diff --git a/chrome/browser/ui/search/instant_ntp_prerenderer.h b/chrome/browser/ui/search/instant_ntp_prerenderer.h
index 8fbaf83..933e0a8 100644
--- a/chrome/browser/ui/search/instant_ntp_prerenderer.h
+++ b/chrome/browser/ui/search/instant_ntp_prerenderer.h
@@ -130,6 +130,8 @@
                              content::PageTransition transition,
                              WindowOpenDisposition disposition,
                              bool is_search_type) OVERRIDE;
+  virtual void PasteIntoOmnibox(const content::WebContents* contents,
+                                const string16& text) OVERRIDE;
   virtual void DeleteMostVisitedItem(const GURL& url) OVERRIDE;
   virtual void UndoMostVisitedDeletion(const GURL& url) OVERRIDE;
   virtual void UndoAllMostVisitedDeletions() OVERRIDE;
diff --git a/chrome/browser/ui/search/instant_page.cc b/chrome/browser/ui/search/instant_page.cc
index f963d2d..9149ea7 100644
--- a/chrome/browser/ui/search/instant_page.cc
+++ b/chrome/browser/ui/search/instant_page.cc
@@ -122,6 +122,10 @@
   return false;
 }
 
+bool InstantPage::ShouldProcessPasteIntoOmnibox() {
+  return false;
+}
+
 bool InstantPage::ShouldProcessDeleteMostVisitedItem() {
   return false;
 }
@@ -143,6 +147,8 @@
     IPC_MESSAGE_HANDLER(ChromeViewHostMsg_FocusOmnibox, OnFocusOmnibox)
     IPC_MESSAGE_HANDLER(ChromeViewHostMsg_SearchBoxNavigate,
                         OnSearchBoxNavigate);
+    IPC_MESSAGE_HANDLER(ChromeViewHostMsg_PasteAndOpenDropdown,
+                        OnSearchBoxPaste);
     IPC_MESSAGE_HANDLER(ChromeViewHostMsg_CountMouseover, OnCountMouseover);
     IPC_MESSAGE_HANDLER(ChromeViewHostMsg_SearchBoxDeleteMostVisitedItem,
                         OnDeleteMostVisitedItem);
@@ -244,6 +250,17 @@
       contents(), url, transition, disposition, is_search_type);
 }
 
+void InstantPage::OnSearchBoxPaste(int page_id, const string16& text) {
+  if (!contents()->IsActiveEntry(page_id))
+    return;
+
+  SearchTabHelper::FromWebContents(contents())->InstantSupportChanged(true);
+  if (!ShouldProcessPasteIntoOmnibox())
+    return;
+
+  delegate_->PasteIntoOmnibox(contents(), text);
+}
+
 void InstantPage::OnCountMouseover(int page_id) {
   if (!contents()->IsActiveEntry(page_id))
     return;
diff --git a/chrome/browser/ui/search/instant_page.h b/chrome/browser/ui/search/instant_page.h
index 926ad5e..1cb5dfe 100644
--- a/chrome/browser/ui/search/instant_page.h
+++ b/chrome/browser/ui/search/instant_page.h
@@ -72,6 +72,11 @@
                                WindowOpenDisposition disposition,
                                bool is_search_type) = 0;
 
+    // Called when the page wants to paste the |text| (or the clipboard content
+    // if the |text| is empty) into the omnibox.
+    virtual void PasteIntoOmnibox(const content::WebContents* contents,
+                                  const string16& text) = 0;
+
     // Called when the SearchBox wants to delete a Most Visited item.
     virtual void DeleteMostVisitedItem(const GURL& url) = 0;
 
@@ -133,6 +138,7 @@
   virtual bool ShouldProcessAboutToNavigateMainFrame();
   virtual bool ShouldProcessFocusOmnibox();
   virtual bool ShouldProcessNavigateToURL();
+  virtual bool ShouldProcessPasteIntoOmnibox();
   virtual bool ShouldProcessDeleteMostVisitedItem();
   virtual bool ShouldProcessUndoMostVisitedDeletion();
   virtual bool ShouldProcessUndoAllMostVisitedDeletions();
@@ -188,6 +194,7 @@
                            content::PageTransition transition,
                            WindowOpenDisposition disposition,
                            bool is_search_type);
+  void OnSearchBoxPaste(int page_id, const string16& text);
   void OnCountMouseover(int page_id);
   void OnDeleteMostVisitedItem(int page_id, const GURL& url);
   void OnUndoMostVisitedDeletion(int page_id, const GURL& url);
diff --git a/chrome/browser/ui/search/instant_page_unittest.cc b/chrome/browser/ui/search/instant_page_unittest.cc
index 3a537c4..c8e838c 100644
--- a/chrome/browser/ui/search/instant_page_unittest.cc
+++ b/chrome/browser/ui/search/instant_page_unittest.cc
@@ -46,6 +46,9 @@
                     content::PageTransition transition,
                     WindowOpenDisposition disposition,
                     bool is_search_type));
+  MOCK_METHOD2(PasteIntoOmnibox,
+               void(const content::WebContents* contents,
+                    const string16& text));
   MOCK_METHOD1(DeleteMostVisitedItem, void(const GURL& url));
   MOCK_METHOD1(UndoMostVisitedDeletion, void(const GURL& url));
   MOCK_METHOD0(UndoAllMostVisitedDeletions, void());
diff --git a/chrome/browser/ui/search/instant_tab.cc b/chrome/browser/ui/search/instant_tab.cc
index ef2500d..3112930 100644
--- a/chrome/browser/ui/search/instant_tab.cc
+++ b/chrome/browser/ui/search/instant_tab.cc
@@ -46,6 +46,10 @@
   return true;
 }
 
+bool InstantTab::ShouldProcessPasteIntoOmnibox() {
+  return true;
+}
+
 bool InstantTab::ShouldProcessDeleteMostVisitedItem() {
   return true;
 }
diff --git a/chrome/browser/ui/search/instant_tab.h b/chrome/browser/ui/search/instant_tab.h
index 2aac53d..b608490 100644
--- a/chrome/browser/ui/search/instant_tab.h
+++ b/chrome/browser/ui/search/instant_tab.h
@@ -33,6 +33,7 @@
   virtual bool ShouldProcessAboutToNavigateMainFrame() OVERRIDE;
   virtual bool ShouldProcessFocusOmnibox() OVERRIDE;
   virtual bool ShouldProcessNavigateToURL() OVERRIDE;
+  virtual bool ShouldProcessPasteIntoOmnibox() OVERRIDE;
   virtual bool ShouldProcessDeleteMostVisitedItem() OVERRIDE;
   virtual bool ShouldProcessUndoMostVisitedDeletion() OVERRIDE;
   virtual bool ShouldProcessUndoAllMostVisitedDeletions() OVERRIDE;
diff --git a/chrome/browser/ui/search/search_tab_helper.cc b/chrome/browser/ui/search/search_tab_helper.cc
index 6dc1b7f..077e7f6 100644
--- a/chrome/browser/ui/search/search_tab_helper.cc
+++ b/chrome/browser/ui/search/search_tab_helper.cc
@@ -4,10 +4,13 @@
 
 #include "chrome/browser/ui/search/search_tab_helper.h"
 
+#include "build/build_config.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/search/instant_service.h"
 #include "chrome/browser/search/instant_service_factory.h"
 #include "chrome/browser/search/search.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/browser_finder.h"
 #include "chrome/common/render_messages.h"
 #include "chrome/common/url_constants.h"
 #include "content/public/browser/navigation_controller.h"
@@ -57,6 +60,20 @@
           contents->GetRenderProcessHost()->GetID());
 }
 
+// Updates the location bar to reflect |contents| Instant support state.
+void UpdateLocationBar(content::WebContents* contents) {
+// iOS and Android doesn't use the Instant framework.
+#if !defined(OS_IOS) && !defined(OS_ANDROID)
+  if (!contents)
+    return;
+
+  Browser* browser = chrome::FindBrowserWithWebContents(contents);
+  if (!browser)
+    return;
+  browser->OnWebContentsInstantSupportDisabled(contents);
+#endif
+}
+
 }  // namespace
 
 SearchTabHelper::SearchTabHelper(content::WebContents* web_contents)
@@ -107,8 +124,18 @@
   if (!is_search_enabled_)
     return;
 
-  model_.SetInstantSupportState(instant_support ? INSTANT_SUPPORT_YES :
-                                                  INSTANT_SUPPORT_NO);
+  InstantSupportState new_state = instant_support ? INSTANT_SUPPORT_YES :
+      INSTANT_SUPPORT_NO;
+
+  model_.SetInstantSupportState(new_state);
+
+  content::NavigationEntry* entry =
+      web_contents_->GetController().GetVisibleEntry();
+  if (entry) {
+    chrome::SetInstantSupportStateInNavigationEntry(new_state, entry);
+    if (!instant_support)
+      UpdateLocationBar(web_contents_);
+  }
 }
 
 bool SearchTabHelper::SupportsInstant() const {
@@ -127,6 +154,10 @@
 
   UpdateMode(true, false);
 
+  content::NavigationEntry* entry =
+      web_contents_->GetController().GetVisibleEntry();
+  DCHECK(entry);
+
   // Already determined the instant support state for this page, do not reset
   // the instant support state.
   //
@@ -139,11 +170,22 @@
   // crbug.com/251330 for more details.
   if (load_details->is_in_page ||
       load_details->type == content::NAVIGATION_TYPE_IN_PAGE) {
+    // When an "in-page" navigation happens, we will not receive a
+    // DidFinishLoad() event. Therefore, we will not determine the Instant
+    // support for the navigated page. So, copy over the Instant support from
+    // the previous entry. If the page does not support Instant, update the
+    // location bar from here to turn off search terms replacement.
+    chrome::SetInstantSupportStateInNavigationEntry(model_.instant_support(),
+                                                    entry);
+    if (model_.instant_support() == INSTANT_SUPPORT_NO)
+      UpdateLocationBar(web_contents_);
     return;
   }
 
   model_.SetInstantSupportState(INSTANT_SUPPORT_UNKNOWN);
   model_.SetVoiceSearchSupported(false);
+  chrome::SetInstantSupportStateInNavigationEntry(model_.instant_support(),
+                                                  entry);
 }
 
 void SearchTabHelper::DidNavigateMainFrame(
diff --git a/chrome/browser/ui/sync/one_click_signin_helper.cc b/chrome/browser/ui/sync/one_click_signin_helper.cc
index 17f2519..46f030d 100644
--- a/chrome/browser/ui/sync/one_click_signin_helper.cc
+++ b/chrome/browser/ui/sync/one_click_signin_helper.cc
@@ -93,7 +93,7 @@
                 const std::string& session_index,
                 const std::string& email,
                 const std::string& password,
-                bool force_same_tab_navigation,
+                content::WebContents* web_contents,
                 bool untrusted_confirmation_required,
                 signin::Source source,
                 OneClickSigninSyncStarter::Callback callback);
@@ -104,7 +104,11 @@
   std::string session_index;
   std::string email;
   std::string password;
-  bool force_same_tab_navigation;
+
+  // Web contents in which the sync setup page should be displayed,
+  // if necessary. Can be NULL.
+  content::WebContents* web_contents;
+
   OneClickSigninSyncStarter::ConfirmationRequired confirmation_required;
   signin::Source source;
   OneClickSigninSyncStarter::Callback callback;
@@ -116,7 +120,7 @@
                              const std::string& session_index,
                              const std::string& email,
                              const std::string& password,
-                             bool force_same_tab_navigation,
+                             content::WebContents* web_contents,
                              bool untrusted_confirmation_required,
                              signin::Source source,
                              OneClickSigninSyncStarter::Callback callback)
@@ -126,7 +130,7 @@
       session_index(session_index),
       email(email),
       password(password),
-      force_same_tab_navigation(force_same_tab_navigation),
+      web_contents(web_contents),
       source(source),
       callback(callback) {
   if (untrusted_confirmation_required) {
@@ -243,7 +247,7 @@
   // The starter deletes itself once its done.
   new OneClickSigninSyncStarter(args.profile, args.browser, args.session_index,
                                 args.email, args.password, start_mode,
-                                args.force_same_tab_navigation,
+                                args.web_contents,
                                 args.confirmation_required,
                                 args.source,
                                 args.callback);
@@ -258,8 +262,6 @@
               one_click_signin::HISTOGRAM_AUTO_WITH_DEFAULTS :
               one_click_signin::HISTOGRAM_AUTO_WITH_ADVANCED;
       break;
-      action = one_click_signin::HISTOGRAM_AUTO_WITH_DEFAULTS;
-      break;
     case OneClickSigninHelper::AUTO_ACCEPT_CONFIGURE:
       DCHECK(start_mode == OneClickSigninSyncStarter::CONFIGURE_SYNC_FIRST);
       action = one_click_signin::HISTOGRAM_AUTO_WITH_ADVANCED;
@@ -1052,9 +1054,9 @@
 void OneClickSigninHelper::DidNavigateMainFrame(
     const content::LoadCommittedDetails& details,
     const content::FrameNavigateParams& params) {
-  // If we navigate to a non-sign-in URL, make sure that the renderer process
-  // is no longer considered the trusted sign-in process.
   if (!SigninManager::IsWebBasedSigninFlowURL(params.url)) {
+    // Make sure the renderer process is no longer considered the trusted
+    // sign-in process when a navigation to a non-sign-in URL occurs.
     Profile* profile =
         Profile::FromBrowserContext(web_contents()->GetBrowserContext());
     SigninManager* manager = profile ?
@@ -1062,6 +1064,14 @@
     int process_id = web_contents()->GetRenderProcessHost()->GetID();
     if (manager && manager->IsSigninProcess(process_id))
       manager->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
+    // cleaned (crbug.com/269421).
+    if (!content::PageTransitionIsWebTriggerable(params.transition) &&
+        auto_accept_ != AUTO_ACCEPT_NONE) {
+      CleanTransientState();
+    }
   }
 }
 
@@ -1145,8 +1155,9 @@
   // checked, the source parameter will indicate settings.  This will only be
   // communicated back to chrome when Gaia redirects to the continue URL, and
   // this is considered here a last minute change to the source.  See a little
-  // further below for when this variable is set to true.
-  bool force_same_tab_navigation = false;
+  // further below for when this variable is set to a web contents that must be
+  // used to show the sync setup page.
+  content::WebContents* sync_setup_contents = NULL;
 
   if (!continue_url_match && IsValidGaiaSigninRedirectOrResponseURL(url))
     return;
@@ -1182,8 +1193,10 @@
     signin::Source source = signin::GetSourceForPromoURL(url);
     if (source != source_) {
       source_ = source;
-      force_same_tab_navigation = source == signin::SOURCE_SETTINGS;
-      switched_to_advanced_ = source == signin::SOURCE_SETTINGS;
+      if (source == signin::SOURCE_SETTINGS) {
+        sync_setup_contents = web_contents();
+        switched_to_advanced_ = true;
+      }
     }
   }
 
@@ -1204,12 +1217,13 @@
       SigninManager::DisableOneClickSignIn(profile);
       // Start syncing with the default settings - prompt the user to sign in
       // first.
-      StartSync(StartSyncArgs(profile, browser, auto_accept_,
-                              session_index_, email_, password_,
-                              false /* force_same_tab_navigation */,
-                              true /* confirmation_required */, source_,
-                              CreateSyncStarterCallback()),
-                OneClickSigninSyncStarter::SYNC_WITH_DEFAULT_SETTINGS);
+      StartSync(
+          StartSyncArgs(profile, browser, auto_accept_,
+                        session_index_, email_, password_,
+                        NULL /* don't force to show sync setup in same tab */,
+                        true /* confirmation_required */, source_,
+                        CreateSyncStarterCallback()),
+          OneClickSigninSyncStarter::SYNC_WITH_DEFAULT_SETTINGS);
       break;
     case AUTO_ACCEPT_CONFIGURE:
       LogOneClickHistogramValue(one_click_signin::HISTOGRAM_ACCEPTED);
@@ -1218,8 +1232,9 @@
       // Display the extra confirmation (even in the SAML case) in case this
       // was an untrusted renderer.
       StartSync(
-          StartSyncArgs(profile, browser, auto_accept_, session_index_, email_,
-                        password_, false /* force_same_tab_navigation */,
+          StartSyncArgs(profile, browser, auto_accept_,
+                        session_index_, email_, password_,
+                        NULL  /* don't force to show sync setup in same tab */,
                         true /* confirmation_required */, source_,
                         CreateSyncStarterCallback()),
           OneClickSigninSyncStarter::CONFIGURE_SYNC_FIRST);
@@ -1259,6 +1274,8 @@
 
         // No need to display a second confirmation so pass false below.
         // TODO(atwilson): Move this into OneClickSigninSyncStarter.
+        // If |sync_setup_contents| is deleted before the callback execution,
+        // the tab modal dialog is closed and the callback is never executed.
         ConfirmEmailDialogDelegate::AskForConfirmation(
             contents,
             last_email,
@@ -1267,7 +1284,7 @@
                 &StartExplicitSync,
                 StartSyncArgs(profile, browser, auto_accept_,
                               session_index_, email_, password_,
-                              force_same_tab_navigation,
+                              sync_setup_contents,
                               false /* confirmation_required */, source_,
                               CreateSyncStarterCallback()),
                 contents,
@@ -1275,7 +1292,7 @@
       } else {
         StartSync(
             StartSyncArgs(profile, browser, auto_accept_, session_index_,
-                          email_, password_, force_same_tab_navigation,
+                          email_, password_, sync_setup_contents,
                           untrusted_confirmation_required_, source_,
                           CreateSyncStarterCallback()),
             start_mode);
diff --git a/chrome/browser/ui/sync/one_click_signin_helper.h b/chrome/browser/ui/sync/one_click_signin_helper.h
index 79d9086..46f7765 100644
--- a/chrome/browser/ui/sync/one_click_signin_helper.h
+++ b/chrome/browser/ui/sync/one_click_signin_helper.h
@@ -52,7 +52,7 @@
     AUTO_ACCEPT_ACCEPTED,
 
     // User has explicitly accepted to sign in, but wants to configure sync
-    // settings before turing it on.
+    // settings before turning it on.
     AUTO_ACCEPT_CONFIGURE,
 
     // User has explicitly rejected to sign in.  Furthermore, the user does
@@ -133,6 +133,8 @@
                            ShowSigninBubbleAfterSigninComplete);
   FRIEND_TEST_ALL_PREFIXES(OneClickSigninHelperTest, SigninCancelled);
   FRIEND_TEST_ALL_PREFIXES(OneClickSigninHelperTest, SigninFailed);
+  FRIEND_TEST_ALL_PREFIXES(OneClickSigninHelperTest,
+                           CleanTransientStateOnNavigate);
   FRIEND_TEST_ALL_PREFIXES(OneClickSigninHelperIOTest, CanOfferOnIOThread);
   FRIEND_TEST_ALL_PREFIXES(OneClickSigninHelperIOTest,
                            CanOfferOnIOThreadIncognito);
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 aebcbfa..1406217 100644
--- a/chrome/browser/ui/sync/one_click_signin_helper_unittest.cc
+++ b/chrome/browser/ui/sync/one_click_signin_helper_unittest.cc
@@ -28,7 +28,9 @@
 #include "chrome/test/base/testing_profile.h"
 #include "chrome/test/base/testing_profile_manager.h"
 #include "content/public/browser/browser_context.h"
+#include "content/public/browser/navigation_details.h"
 #include "content/public/browser/web_contents.h"
+#include "content/public/common/frame_navigate_params.h"
 #include "content/public/common/password_form.h"
 #include "content/public/common/url_constants.h"
 #include "content/public/test/mock_render_process_host.h"
@@ -670,6 +672,27 @@
   EXPECT_EQ("user@gmail.com", signin_manager_->GetAuthenticatedUsername());
 }
 
+// Checks that the state of OneClickSigninHelper is cleaned when there is a
+// navigation away from the sign in flow that is not triggered by the
+// web contents.
+TEST_F(OneClickSigninHelperTest, CleanTransientStateOnNavigate) {
+  content::WebContents* contents = web_contents();
+
+  OneClickSigninHelper::CreateForWebContents(contents);
+  OneClickSigninHelper* helper =
+      OneClickSigninHelper::FromWebContents(contents);
+  helper->SetDoNotClearPendingEmailForTesting();
+  helper->auto_accept_ = OneClickSigninHelper::AUTO_ACCEPT_EXPLICIT;
+
+  content::LoadCommittedDetails details;
+  content::FrameNavigateParams params;
+  params.url = GURL("http://crbug.com");
+  params.transition = content::PAGE_TRANSITION_TYPED;
+  helper->DidNavigateMainFrame(details, params);
+
+  EXPECT_EQ(OneClickSigninHelper::AUTO_ACCEPT_NONE, helper->auto_accept_);
+}
+
 // I/O thread tests
 
 TEST_F(OneClickSigninHelperIOTest, CanOfferOnIOThread) {
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 d037dab..884c09d 100644
--- a/chrome/browser/ui/sync/one_click_signin_sync_starter.cc
+++ b/chrome/browser/ui/sync/one_click_signin_sync_starter.cc
@@ -48,12 +48,12 @@
     const std::string& email,
     const std::string& password,
     StartSyncMode start_mode,
-    bool force_same_tab_navigation,
+    content::WebContents* web_contents,
     ConfirmationRequired confirmation_required,
     signin::Source source,
     Callback sync_setup_completed_callback)
-    : start_mode_(start_mode),
-      force_same_tab_navigation_(force_same_tab_navigation),
+    : content::WebContentsObserver(web_contents),
+      start_mode_(start_mode),
       confirmation_required_(confirmation_required),
       source_(source),
       sync_setup_completed_callback_(sync_setup_completed_callback),
@@ -424,8 +424,8 @@
     EnsureBrowser();
     if (profile_sync_service) {
       // Need to navigate to the settings page and display the sync UI.
-      if (force_same_tab_navigation_) {
-        ShowSyncSettingsPageOnSameTab();
+      if (web_contents()) {
+        ShowSyncSettingsPageInWebContents(web_contents());
       } else {
         // If the user is setting up sync for the first time, let them configure
         // advanced sync settings. However, in the case of re-authentication,
@@ -459,12 +459,21 @@
     service->SetSetupInProgress(false);
 }
 
-void OneClickSigninSyncStarter::ShowSyncSettingsPageOnSameTab() {
+void OneClickSigninSyncStarter::ShowSyncSettingsPageInWebContents(
+    content::WebContents* contents) {
   std::string url = std::string(chrome::kChromeUISettingsURL) +
       chrome::kSyncSetupSubPage;
-  chrome::NavigateParams params(
-      browser_, GURL(url), content::PAGE_TRANSITION_AUTO_TOPLEVEL);
-  params.disposition = CURRENT_TAB;
-  params.window_action = chrome::NavigateParams::SHOW_WINDOW;
-  chrome::Navigate(&params);
+  content::OpenURLParams params(GURL(url),
+                                content::Referrer(),
+                                CURRENT_TAB,
+                                content::PAGE_TRANSITION_AUTO_TOPLEVEL,
+                                false);
+  contents->OpenURL(params);
+
+  // Activate the tab.
+  Browser* browser = chrome::FindBrowserWithWebContents(contents);
+  int content_index =
+      browser->tab_strip_model()->GetIndexOfWebContents(contents);
+  browser->tab_strip_model()->ActivateTabAt(content_index,
+                                            false /* user_gesture */);
 }
diff --git a/chrome/browser/ui/sync/one_click_signin_sync_starter.h b/chrome/browser/ui/sync/one_click_signin_sync_starter.h
index 3fc359e..11c3ce5 100644
--- a/chrome/browser/ui/sync/one_click_signin_sync_starter.h
+++ b/chrome/browser/ui/sync/one_click_signin_sync_starter.h
@@ -17,10 +17,15 @@
 #include "chrome/browser/ui/browser_list_observer.h"
 #include "chrome/browser/ui/host_desktop.h"
 #include "chrome/browser/ui/sync/profile_signin_confirmation_helper.h"
+#include "content/public/browser/web_contents_observer.h"
 
 class Browser;
 class ProfileSyncService;
 
+namespace content {
+class WebContents;
+}  // namespace content
+
 namespace policy {
 class CloudPolicyClient;
 }
@@ -29,7 +34,8 @@
 // starts the sync machine.  Instances of this class delete themselves once
 // the job is done.
 class OneClickSigninSyncStarter : public SigninTracker::Observer,
-                                  public chrome::BrowserListObserver {
+                                  public chrome::BrowserListObserver,
+                                  public content::WebContentsObserver {
  public:
   enum StartSyncMode {
     // Starts the process of signing the user in with the SigninManager, and
@@ -75,6 +81,9 @@
   // OneClickSigninSyncStarter from a browser, provide both.
   // If |display_confirmation| is true, the user will be prompted to confirm the
   // signin before signin completes.
+  // |web_contents| is used to show the sync setup page, if necessary. If NULL,
+  // the sync setup page will be loaded in either a new tab or a tab that is
+  // already showing it.
   // |callback| is always executed before OneClickSigninSyncStarter is deleted.
   // It can be empty.
   OneClickSigninSyncStarter(Profile* profile,
@@ -83,7 +92,7 @@
                             const std::string& email,
                             const std::string& password,
                             StartSyncMode start_mode,
-                            bool force_same_tab_navigation,
+                            content::WebContents* web_contents,
                             ConfirmationRequired display_confirmation,
                             signin::Source source,
                             Callback callback);
@@ -178,8 +187,8 @@
   // dialog if |configure_sync| is true.
   void ShowSettingsPageInNewTab(bool configure_sync);
 
-  // Displays the sync configuration UI in the same tab.
-  void ShowSyncSettingsPageOnSameTab();
+  // Displays the sync configuration UI in the provided web contents.
+  void ShowSyncSettingsPageInWebContents(content::WebContents* contents);
 
   // Shows the post-signin confirmation bubble. If |custom_message| is empty,
   // the default "You are signed in" message is displayed.
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 2d12642..57820cb 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
@@ -60,7 +60,7 @@
       kTestingUsername,
       std::string(),
       OneClickSigninSyncStarter::SYNC_WITH_DEFAULT_SETTINGS,
-      false,
+      NULL,
       OneClickSigninSyncStarter::NO_CONFIRMATION,
       signin::SOURCE_UNKNOWN,
       callback
diff --git a/chrome/browser/ui/toolbar/wrench_menu_model.cc b/chrome/browser/ui/toolbar/wrench_menu_model.cc
index ab5998f..38118fa 100644
--- a/chrome/browser/ui/toolbar/wrench_menu_model.cc
+++ b/chrome/browser/ui/toolbar/wrench_menu_model.cc
@@ -468,6 +468,44 @@
       tab_strip_model_(NULL) {
 }
 
+bool WrenchMenuModel::ShouldShowNewIncognitoWindowMenuItem() {
+  if (browser_->profile()->IsManaged())
+    return false;
+
+#if defined(OS_WIN)
+  if (win8::IsSingleWindowMetroMode() &&
+      browser_->profile()->HasOffTheRecordProfile()) {
+    return false;
+  }
+#endif
+
+#if defined(OS_CHROMEOS)
+  if (CommandLine::ForCurrentProcess()->HasSwitch(
+      chromeos::switches::kGuestSession)) {
+    return false;
+  }
+#endif
+
+  return true;
+}
+
+bool WrenchMenuModel::ShouldShowNewWindowMenuItem() {
+#if defined(OS_WIN)
+  if (!win8::IsSingleWindowMetroMode())
+    return true;
+
+  // In Win8's single window Metro mode, we only show the New Window options
+  // if there isn't already a window of the requested type (incognito or not)
+  // that is available.
+  return browser_->profile()->IsOffTheRecord() &&
+      !chrome::FindBrowserWithProfile(
+          browser_->profile()->GetOriginalProfile(),
+          browser_->host_desktop_type());
+#else
+  return true;
+#endif
+}
+
 void WrenchMenuModel::Build(bool is_new_menu) {
 #if defined(OS_WIN)
   AddItem(IDC_VIEW_INCOMPATIBILITIES,
@@ -480,25 +518,13 @@
 #endif
 
   AddItemWithStringId(IDC_NEW_TAB, IDS_NEW_TAB);
-#if defined(OS_WIN)
-  if (win8::IsSingleWindowMetroMode()) {
-    // In Win8's single window Metro mode, we only show the New Window options
-    // if there isn't already a window of the requested type (incognito or not)
-    // that is available.
-    if (browser_->profile()->IsOffTheRecord()) {
-      if (chrome::FindBrowserWithProfile(
-              browser_->profile()->GetOriginalProfile(),
-              browser_->host_desktop_type()) == NULL) {
-        AddItemWithStringId(IDC_NEW_WINDOW, IDS_NEW_WINDOW);
-      }
-    } else if (!browser_->profile()->HasOffTheRecordProfile()) {
-      AddItemWithStringId(IDC_NEW_INCOGNITO_WINDOW, IDS_NEW_INCOGNITO_WINDOW);
-    }
-  } else {
-    AddItemWithStringId(IDC_NEW_WINDOW, IDS_NEW_WINDOW);
+  if (ShouldShowNewIncognitoWindowMenuItem())
     AddItemWithStringId(IDC_NEW_INCOGNITO_WINDOW, IDS_NEW_INCOGNITO_WINDOW);
-  }
-#if !defined(NDEBUG) && defined(USE_ASH)
+
+  if (ShouldShowNewWindowMenuItem())
+    AddItemWithStringId(IDC_NEW_WINDOW, IDS_NEW_WINDOW);
+
+#if defined(OS_WIN) && !defined(NDEBUG) && defined(USE_ASH)
   if (base::win::GetVersion() < base::win::VERSION_WIN8 &&
       chrome::HOST_DESKTOP_TYPE_NATIVE != chrome::HOST_DESKTOP_TYPE_ASH) {
     AddItemWithStringId(IDC_TOGGLE_ASH_DESKTOP,
@@ -506,17 +532,6 @@
                                                     IDS_OPEN_ASH_DESKTOP);
   }
 #endif
-#else  // defined(OS_WIN)
-  AddItemWithStringId(IDC_NEW_WINDOW, IDS_NEW_WINDOW);
-#if defined(OS_CHROMEOS)
-  if (!CommandLine::ForCurrentProcess()->HasSwitch(
-          chromeos::switches::kGuestSession))
-    AddItemWithStringId(IDC_NEW_INCOGNITO_WINDOW, IDS_NEW_INCOGNITO_WINDOW);
-#else
-  AddItemWithStringId(IDC_NEW_INCOGNITO_WINDOW, IDS_NEW_INCOGNITO_WINDOW);
-#endif
-
-#endif  // else of defined(OS_WIN)
 
   bookmark_sub_menu_model_.reset(new BookmarkSubMenuModel(this, browser_));
   AddSubMenuWithStringId(IDC_BOOKMARKS_MENU, IDS_BOOKMARKS_MENU,
diff --git a/chrome/browser/ui/toolbar/wrench_menu_model.h b/chrome/browser/ui/toolbar/wrench_menu_model.h
index cf9df0d..417e023 100644
--- a/chrome/browser/ui/toolbar/wrench_menu_model.h
+++ b/chrome/browser/ui/toolbar/wrench_menu_model.h
@@ -149,6 +149,9 @@
 
   void OnZoomLevelChanged(const content::HostZoomMap::ZoomLevelChange& change);
 
+  bool ShouldShowNewIncognitoWindowMenuItem();
+  bool ShouldShowNewWindowMenuItem();
+
   // Models for the special menu items with buttons.
   scoped_ptr<ui::ButtonMenuItemModel> edit_menu_item_model_;
   scoped_ptr<ui::ButtonMenuItemModel> zoom_menu_item_model_;
diff --git a/chrome/browser/ui/uma_browsing_activity_observer.cc b/chrome/browser/ui/uma_browsing_activity_observer.cc
index 1db2777..046da4f 100644
--- a/chrome/browser/ui/uma_browsing_activity_observer.cc
+++ b/chrome/browser/ui/uma_browsing_activity_observer.cc
@@ -6,14 +6,19 @@
 
 #include "base/metrics/histogram.h"
 #include "chrome/browser/chrome_notification_types.h"
+#include "chrome/browser/search_engines/template_url_service.h"
+#include "chrome/browser/search_engines/template_url_service_factory.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_finder.h"
 #include "chrome/browser/ui/browser_iterator.h"
 #include "chrome/browser/ui/browser_window.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
+#include "content/public/browser/navigation_controller.h"
 #include "content/public/browser/navigation_details.h"
+#include "content/public/browser/navigation_entry.h"
 #include "content/public/browser/notification_service.h"
 #include "content/public/browser/render_process_host.h"
+#include "content/public/browser/user_metrics.h"
 
 namespace chrome {
 namespace {
@@ -47,6 +52,20 @@
   if (type == content::NOTIFICATION_NAV_ENTRY_COMMITTED) {
     const content::LoadCommittedDetails& load =
         *content::Details<content::LoadCommittedDetails>(details).ptr();
+
+    content::NavigationController* controller =
+      content::Source<content::NavigationController>(source).ptr();
+    // Track whether the page loaded is a search results page (SRP). Track
+    // the non-SRP navigations as well so there is a control.
+    content::RecordAction(content::UserMetricsAction("NavEntryCommitted"));
+    if (TemplateURLServiceFactory::GetForProfile(
+            Profile::FromBrowserContext(controller->GetBrowserContext()))->
+            IsSearchResultsPageFromDefaultSearchProvider(
+                load.entry->GetURL())) {
+      content::RecordAction(
+          content::UserMetricsAction("NavEntryCommitted.SRP"));
+    }
+
     if (!load.is_navigation_to_different_page())
       return;  // Don't log for subframes or other trivial types.
 
diff --git a/chrome/browser/ui/views/app_list/app_list_controller_win.cc b/chrome/browser/ui/views/app_list/app_list_controller_win.cc
index b87598a..46bdc93 100644
--- a/chrome/browser/ui/views/app_list/app_list_controller_win.cc
+++ b/chrome/browser/ui/views/app_list/app_list_controller_win.cc
@@ -281,6 +281,138 @@
   DISALLOW_COPY_AND_ASSIGN(ScopedKeepAlive);
 };
 
+class ActivationTracker {
+ public:
+  ActivationTracker(app_list::AppListView* view,
+                    const base::Closure& on_active_lost)
+      : view_(view),
+        on_active_lost_(on_active_lost),
+        regain_next_lost_focus_(false),
+        preserving_focus_for_taskbar_menu_(false) {
+  }
+
+  void RegainNextLostFocus() {
+    regain_next_lost_focus_ = true;
+  }
+
+  void OnActivationChanged(bool active) {
+    const int kFocusCheckIntervalMS = 250;
+    if (active) {
+      timer_.Stop();
+      return;
+    }
+
+    preserving_focus_for_taskbar_menu_ = false;
+    timer_.Start(FROM_HERE,
+                 base::TimeDelta::FromMilliseconds(kFocusCheckIntervalMS), this,
+                 &ActivationTracker::CheckTaskbarOrViewHasFocus);
+  }
+
+  void OnViewHidden() {
+    timer_.Stop();
+  }
+
+  void CheckTaskbarOrViewHasFocus() {
+    // Remember if the taskbar had focus without the right mouse button being
+    // down.
+    bool was_preserving_focus = preserving_focus_for_taskbar_menu_;
+    preserving_focus_for_taskbar_menu_ = false;
+
+    // First get the taskbar and jump lists windows (the jump list is the
+    // context menu which the taskbar uses).
+    HWND jump_list_hwnd = FindWindow(L"DV2ControlHost", NULL);
+    HWND taskbar_hwnd = FindWindow(kTrayClassName, NULL);
+
+    // This code is designed to hide the app launcher when it loses focus,
+    // except for the cases necessary to allow the launcher to be pinned or
+    // closed via the taskbar context menu.
+    // First work out if the left or right button is currently down.
+    int swapped = GetSystemMetrics(SM_SWAPBUTTON);
+    int left_button = swapped ? VK_RBUTTON : VK_LBUTTON;
+    bool left_button_down = GetAsyncKeyState(left_button) < 0;
+    int right_button = swapped ? VK_LBUTTON : VK_RBUTTON;
+    bool right_button_down = GetAsyncKeyState(right_button) < 0;
+
+    // Now get the window that currently has focus.
+    HWND focused_hwnd = GetForegroundWindow();
+    if (!focused_hwnd) {
+      // Sometimes the focused window is NULL. This can happen when the focus is
+      // changing due to a mouse button press. If the button is still being
+      // pressed the launcher should not be hidden.
+      if (right_button_down || left_button_down)
+        return;
+
+      // If the focused window is NULL, and the mouse button is not being
+      // pressed, then the launcher no longer has focus.
+      on_active_lost_.Run();
+      return;
+    }
+
+    while (focused_hwnd) {
+      // If the focused window is the right click menu (called a jump list) or
+      // the app list, don't hide the launcher.
+      if (focused_hwnd == jump_list_hwnd ||
+          focused_hwnd == view_->GetHWND()) {
+        return;
+      }
+
+      if (focused_hwnd == taskbar_hwnd) {
+        // If the focused window is the taskbar, and the right button is down,
+        // don't hide the launcher as the user might be bringing up the menu.
+        if (right_button_down)
+          return;
+
+        // There is a short period between the right mouse button being down
+        // and the menu gaining focus, where the taskbar has focus and no button
+        // is down. If the taskbar is observed in this state once the launcher
+        // is not dismissed. If it happens twice in a row it is dismissed.
+        if (!was_preserving_focus) {
+          preserving_focus_for_taskbar_menu_ = true;
+          return;
+        }
+
+        break;
+      }
+      focused_hwnd = GetParent(focused_hwnd);
+    }
+
+    if (regain_next_lost_focus_) {
+      regain_next_lost_focus_ = false;
+      view_->GetWidget()->Activate();
+      return;
+    }
+
+    // If we get here, the focused window is not the taskbar, it's context menu,
+    // or the app list.
+    on_active_lost_.Run();
+  }
+
+ private:
+  // The window to track the active state of.
+  app_list::AppListView* view_;
+
+  // Called to request |view_| be closed.
+  base::Closure on_active_lost_;
+
+  // True if we are anticipating that the app list will lose focus, and we want
+  // to take it back. This is used when switching out of Metro mode, and the
+  // browser regains focus after showing the app list.
+  bool regain_next_lost_focus_;
+
+  // When the context menu on the app list's taskbar icon is brought up the
+  // app list should not be hidden, but it should be if the taskbar is clicked
+  // on. There can be a period of time when the taskbar gets focus between a
+  // right mouse click and the menu showing; to prevent hiding the app launcher
+  // when this happens it is kept visible if the taskbar is seen briefly without
+  // the right mouse button down, but not if this happens twice in a row.
+  bool preserving_focus_for_taskbar_menu_;
+
+  // Timer used to check if the taskbar or app list is active. Using a timer
+  // means we don't need to hook Windows, which is apparently not possible
+  // since Vista (and is not nice at any time).
+  base::RepeatingTimer<ActivationTracker> timer_;
+};
+
 // The AppListController class manages global resources needed for the app
 // list to operate, and controls when the app list is opened and closed.
 // TODO(tapted): Rename this class to AppListServiceWin and move entire file to
@@ -307,6 +439,7 @@
   // AppListService overrides:
   virtual void HandleFirstRun() OVERRIDE;
   virtual void Init(Profile* initial_profile) OVERRIDE;
+  virtual void CreateForProfile(Profile* requested_profile) OVERRIDE;
   virtual void ShowForProfile(Profile* requested_profile) OVERRIDE;
   virtual void DismissAppList() OVERRIDE;
   virtual bool IsAppListVisible() const OVERRIDE;
@@ -332,9 +465,12 @@
   void LoadProfileForWarmup();
   void OnLoadProfileForWarmup(Profile* initial_profile);
 
-  // Create or recreate, and initialize |current_view_| from
-  // |requested_profile|.
-  void PopulateViewFromProfile(Profile* requested_profile);
+  // Creates an AppListView.
+  app_list::AppListView* CreateAppListView();
+
+  // Customizes the app list |hwnd| for Windows (eg: disable aero peek, set up
+  // restart params).
+  void SetWindowAttributes(HWND hwnd);
 
   // Utility methods for showing the app list.
   gfx::Point FindAnchorPoint(const gfx::Display& display,
@@ -348,9 +484,6 @@
   // periodically whenever the app list does not have focus.
   void CheckTaskbarOrViewHasFocus();
 
-  // Returns the underlying HWND for the AppList.
-  HWND GetAppListHWND() const;
-
   // Utilities to manage browser process keep alive for the view itself. Note
   // keep alives are also used when asynchronously loading profiles.
   void EnsureHaveKeepAliveForView();
@@ -359,13 +492,7 @@
   // Weak pointer. The view manages its own lifetime.
   app_list::AppListView* current_view_;
 
-  // Weak pointer. The view owns the view delegate.
-  AppListViewDelegate* view_delegate_;
-
-  // Timer used to check if the taskbar or app list is active. Using a timer
-  // means we don't need to hook Windows, which is apparently not possible
-  // since Vista (and is not nice at any time).
-  base::RepeatingTimer<AppListController> timer_;
+  scoped_ptr<ActivationTracker> activation_tracker_;
 
   app_list::PaginationModel pagination_model_;
 
@@ -375,19 +502,6 @@
   // Used to keep the browser process alive while the app list is visible.
   scoped_ptr<ScopedKeepAlive> keep_alive_;
 
-  // True if we are anticipating that the app list will lose focus, and we want
-  // to take it back. This is used when switching out of Metro mode, and the
-  // browser regains focus after showing the app list.
-  bool regain_first_lost_focus_;
-
-  // When the context menu on the app list's taskbar icon is brought up the
-  // app list should not be hidden, but it should be if the taskbar is clicked
-  // on. There can be a period of time when the taskbar gets focus between a
-  // right mouse click and the menu showing; to prevent hiding the app launcher
-  // when this happens it is kept visible if the taskbar is seen briefly without
-  // the right mouse button down, but not if this happens twice in a row.
-  bool preserving_focus_for_taskbar_menu_;
-
   bool enable_app_list_on_next_init_;
 
   base::WeakPtrFactory<AppListController> weak_factory_;
@@ -482,10 +596,7 @@
 
 AppListController::AppListController()
     : current_view_(NULL),
-      view_delegate_(NULL),
       can_close_app_list_(true),
-      regain_first_lost_focus_(false),
-      preserving_focus_for_taskbar_menu_(false),
       enable_app_list_on_next_init_(false),
       weak_factory_(this) {}
 
@@ -536,7 +647,7 @@
   SetProfilePath(requested_profile->GetPath());
 
   DismissAppList();
-  PopulateViewFromProfile(requested_profile);
+  CreateForProfile(requested_profile);
 
   DCHECK(current_view_);
   EnsureHaveKeepAliveForView();
@@ -550,32 +661,45 @@
 
 void AppListController::ShowAppListDuringModeSwitch(
     Profile* requested_profile) {
-  regain_first_lost_focus_ = true;
   ShowForProfile(requested_profile);
+  activation_tracker_->RegainNextLostFocus();
 }
 
-void AppListController::PopulateViewFromProfile(Profile* requested_profile) {
+void AppListController::CreateForProfile(Profile* requested_profile) {
+  // Aura has problems with layered windows and bubble delegates. The app
+  // launcher has a trick where it only hides the window when it is dismissed,
+  // reshowing it again later. This does not work with win aura for some
+  // reason. This change temporarily makes it always get recreated, only on win
+  // aura. See http://crbug.com/176186.
 #if !defined(USE_AURA)
   if (requested_profile == profile())
     return;
 #endif
 
   SetProfile(requested_profile);
+  current_view_ = CreateAppListView();
+  activation_tracker_.reset(new ActivationTracker(current_view_,
+      base::Bind(&AppListController::DismissAppList, base::Unretained(this))));
+}
 
+app_list::AppListView* AppListController::CreateAppListView() {
   // The controller will be owned by the view delegate, and the delegate is
   // owned by the app list view. The app list view manages it's own lifetime.
-  view_delegate_ = new AppListViewDelegate(CreateControllerDelegate(),
-                                           profile());
-  current_view_ = new app_list::AppListView(view_delegate_);
+  AppListViewDelegate* view_delegate =
+      new AppListViewDelegate(CreateControllerDelegate(), profile());
+  app_list::AppListView* view = new app_list::AppListView(view_delegate);
   gfx::Point cursor = gfx::Screen::GetNativeScreen()->GetCursorScreenPoint();
-  current_view_->InitAsBubble(NULL,
-                              &pagination_model_,
-                              NULL,
-                              cursor,
-                              views::BubbleBorder::FLOAT,
-                              false /* border_accepts_events */);
-  HWND hwnd = GetAppListHWND();
+  view->InitAsBubble(NULL,
+                     &pagination_model_,
+                     NULL,
+                     cursor,
+                     views::BubbleBorder::FLOAT,
+                     false /* border_accepts_events */);
+  SetWindowAttributes(view->GetHWND());
+  return view;
+}
 
+void AppListController::SetWindowAttributes(HWND hwnd) {
   // Vista and lower do not offer pinning to the taskbar, which makes any
   // presence on the taskbar useless. So, hide the window on the taskbar
   // for these versions of Windows.
@@ -609,7 +733,7 @@
 void AppListController::DismissAppList() {
   if (IsAppListVisible() && can_close_app_list_) {
     current_view_->GetWidget()->Hide();
-    timer_.Stop();
+    activation_tracker_->OnViewHidden();
     FreeAnyKeepAliveForView();
   }
 }
@@ -617,22 +741,12 @@
 void AppListController::AppListClosing() {
   FreeAnyKeepAliveForView();
   current_view_ = NULL;
-  view_delegate_ = NULL;
+  activation_tracker_.reset();
   SetProfile(NULL);
-  timer_.Stop();
 }
 
 void AppListController::AppListActivationChanged(bool active) {
-  const int kFocusCheckIntervalMS = 250;
-  if (active) {
-    timer_.Stop();
-    return;
-  }
-
-  preserving_focus_for_taskbar_menu_ = false;
-  timer_.Start(FROM_HERE,
-               base::TimeDelta::FromMilliseconds(kFocusCheckIntervalMS), this,
-               &AppListController::CheckTaskbarOrViewHasFocus);
+  activation_tracker_->OnActivationChanged(active);
 }
 
 // Attempts to find the bounds of the Windows taskbar. Returns true on success.
@@ -748,97 +862,6 @@
   return result;
 }
 
-void AppListController::CheckTaskbarOrViewHasFocus() {
-  // Remember if the taskbar had focus without the right mouse button being
-  // down.
-  bool was_preserving_focus = preserving_focus_for_taskbar_menu_;
-  preserving_focus_for_taskbar_menu_ = false;
-
-  // Don't bother checking if the view has been closed.
-  if (!current_view_)
-    return;
-
-  // First get the taskbar and jump lists windows (the jump list is the
-  // context menu which the taskbar uses).
-  HWND jump_list_hwnd = FindWindow(L"DV2ControlHost", NULL);
-  HWND taskbar_hwnd = FindWindow(kTrayClassName, NULL);
-
-  HWND app_list_hwnd = GetAppListHWND();
-
-  // This code is designed to hide the app launcher when it loses focus, except
-  // for the cases necessary to allow the launcher to be pinned or closed via
-  // the taskbar context menu.
-  // First work out if the left or right button is currently down.
-  int swapped = GetSystemMetrics(SM_SWAPBUTTON);
-  int left_button = swapped ? VK_RBUTTON : VK_LBUTTON;
-  bool left_button_down = GetAsyncKeyState(left_button) < 0;
-  int right_button = swapped ? VK_LBUTTON : VK_RBUTTON;
-  bool right_button_down = GetAsyncKeyState(right_button) < 0;
-
-  // Now get the window that currently has focus.
-  HWND focused_hwnd = GetForegroundWindow();
-  if (!focused_hwnd) {
-    // Sometimes the focused window is NULL. This can happen when the focus is
-    // changing due to a mouse button press. If the button is still being
-    // pressed the launcher should not be hidden.
-    if (right_button_down || left_button_down)
-      return;
-
-    // If the focused window is NULL, and the mouse button is not being pressed,
-    // then the launcher no longer has focus so hide it.
-    DismissAppList();
-    return;
-  }
-
-  while (focused_hwnd) {
-    // If the focused window is the right click menu (called a jump list) or
-    // the app list, don't hide the launcher.
-    if (focused_hwnd == jump_list_hwnd ||
-        focused_hwnd == app_list_hwnd) {
-      return;
-    }
-
-    if (focused_hwnd == taskbar_hwnd) {
-      // If the focused window is the taskbar, and the right button is down,
-      // don't hide the launcher as the user might be bringing up the menu.
-      if (right_button_down)
-        return;
-
-      // There is a short period between the right mouse button being down
-      // and the menu gaining focus, where the taskbar has focus and no button
-      // is down. If the taskbar is observed in this state once the launcher
-      // is not dismissed. If it happens twice in a row it is dismissed.
-      if (!was_preserving_focus) {
-        preserving_focus_for_taskbar_menu_ = true;
-        return;
-      }
-
-      break;
-    }
-    focused_hwnd = GetParent(focused_hwnd);
-  }
-
-  if (regain_first_lost_focus_) {
-    regain_first_lost_focus_ = false;
-    current_view_->GetWidget()->Activate();
-    return;
-  }
-
-  // If we get here, the focused window is not the taskbar, it's context menu,
-  // or the app list, so close the app list.
-  DismissAppList();
-}
-
-HWND AppListController::GetAppListHWND() const {
-#if defined(USE_AURA)
-  gfx::NativeWindow window =
-      current_view_->GetWidget()->GetTopLevelWidget()->GetNativeWindow();
-  return window->GetRootWindow()->GetAcceleratedWidget();
-#else
-  return current_view_->GetWidget()->GetTopLevelWidget()->GetNativeWindow();
-#endif
-}
-
 void AppListController::EnsureHaveKeepAliveForView() {
   if (!keep_alive_)
     keep_alive_.reset(new ScopedKeepAlive());
@@ -853,7 +876,7 @@
   if (!IsWarmupNeeded())
     return;
 
-  PopulateViewFromProfile(initial_profile);
+  CreateForProfile(initial_profile);
   current_view_->Prerender();
 }
 
@@ -877,6 +900,7 @@
   if (enable_app_list_on_next_init_) {
     enable_app_list_on_next_init_ = false;
     EnableAppList(initial_profile);
+    CreateShortcut();
   }
 
   PrefService* prefs = g_browser_process->local_state();
@@ -906,6 +930,7 @@
           chrome_launcher_support::USER_LEVEL_INSTALLATION);
     }
     EnableAppList(initial_profile);
+    CreateShortcut();
   }
 #endif
 
diff --git a/chrome/browser/ui/views/apps/native_app_window_views.cc b/chrome/browser/ui/views/apps/native_app_window_views.cc
index 31b52a7..3ceb272 100644
--- a/chrome/browser/ui/views/apps/native_app_window_views.cc
+++ b/chrome/browser/ui/views/apps/native_app_window_views.cc
@@ -317,12 +317,26 @@
   // On Ash, restore fullscreen.
   if (IsFullscreen())
     return ui::SHOW_STATE_FULLSCREEN;
+
   // Use kRestoreShowStateKey in case a window is minimized/hidden.
   ui::WindowShowState restore_state =
       window_->GetNativeWindow()->GetProperty(
           aura::client::kRestoreShowStateKey);
-  if (restore_state != ui::SHOW_STATE_MINIMIZED)
-    return restore_state;
+  // Whitelist states to return so that invalid and transient states
+  // are not saved and used to restore windows when they are recreated.
+  switch (restore_state) {
+    case ui::SHOW_STATE_NORMAL:
+    case ui::SHOW_STATE_MAXIMIZED:
+    case ui::SHOW_STATE_FULLSCREEN:
+    case ui::SHOW_STATE_DETACHED:
+      return restore_state;
+
+    case ui::SHOW_STATE_DEFAULT:
+    case ui::SHOW_STATE_MINIMIZED:
+    case ui::SHOW_STATE_INACTIVE:
+    case ui::SHOW_STATE_END:
+      return ui::SHOW_STATE_NORMAL;
+  }
 #endif
   return ui::SHOW_STATE_NORMAL;
 }
diff --git a/chrome/browser/ui/views/autofill/autofill_credit_card_bubble_views.cc b/chrome/browser/ui/views/autofill/autofill_credit_card_bubble_views.cc
deleted file mode 100644
index 48f7167..0000000
--- a/chrome/browser/ui/views/autofill/autofill_credit_card_bubble_views.cc
+++ /dev/null
@@ -1,116 +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/ui/views/autofill/autofill_credit_card_bubble_views.h"
-
-#include "chrome/browser/ui/autofill/autofill_credit_card_bubble_controller.h"
-#include "chrome/browser/ui/browser.h"
-#include "chrome/browser/ui/browser_finder.h"
-#include "chrome/browser/ui/views/frame/browser_view.h"
-#include "chrome/browser/ui/views/location_bar/location_bar_view.h"
-#include "ui/gfx/font.h"
-#include "ui/gfx/insets.h"
-#include "ui/gfx/size.h"
-#include "ui/views/bubble/bubble_frame_view.h"
-#include "ui/views/controls/link.h"
-#include "ui/views/controls/styled_label.h"
-#include "ui/views/layout/box_layout.h"
-#include "ui/views/layout/layout_constants.h"
-#include "ui/views/view.h"
-#include "ui/views/widget/widget.h"
-
-namespace autofill {
-
-namespace {
-
-// Get the view this bubble will be anchored to via |controller|.
-views::View* GetAnchor(
-    const base::WeakPtr<AutofillCreditCardBubbleController>& controller) {
-  Browser* browser =
-      chrome::FindBrowserWithWebContents(controller->web_contents());
-  BrowserView* browser_view = BrowserView::GetBrowserViewForBrowser(browser);
-  return browser_view->GetLocationBarView()->autofill_credit_card_view();
-}
-
-}  // namespace
-
-AutofillCreditCardBubbleViews::~AutofillCreditCardBubbleViews() {}
-
-void AutofillCreditCardBubbleViews::Show() {
-  // TODO(dbeam): investigate why this steals focus from the web contents.
-  views::BubbleDelegateView::CreateBubble(this);
-
-  GetWidget()->Show();
-
-  // This bubble doesn't render correctly on Windows without calling
-  // |SizeToContents()|. This must be called after showing the widget.
-  SizeToContents();
-}
-
-void AutofillCreditCardBubbleViews::Hide() {
-  GetWidget()->Close();
-}
-
-bool AutofillCreditCardBubbleViews::IsHiding() const {
-  return GetWidget() && GetWidget()->IsClosed();
-}
-
-string16 AutofillCreditCardBubbleViews::GetWindowTitle() const {
-  return controller_->BubbleTitle();
-}
-
-void AutofillCreditCardBubbleViews::Init() {
-  SetLayoutManager(new views::BoxLayout(views::BoxLayout::kVertical, 0, 0,
-                                        views::kRelatedControlVerticalSpacing));
-
-  views::StyledLabel::RangeStyleInfo bold;
-  bold.font_style = gfx::Font::BOLD;
-  const std::vector<ui::Range>& ranges = controller_->BubbleTextRanges();
-
-  views::StyledLabel* contents =
-      new views::StyledLabel(controller_->BubbleText(), NULL);
-  for (size_t i = 0; i < ranges.size(); ++i) {
-    contents->AddStyleRange(ranges[i], bold);
-  }
-  AddChildView(contents);
-
-  views::Link* link = new views::Link();
-  link->SetHorizontalAlignment(gfx::ALIGN_LEFT);
-  link->SetText(controller_->LinkText());
-  link->set_listener(this);
-  AddChildView(link);
-}
-
-gfx::Size AutofillCreditCardBubbleViews::GetPreferredSize() {
-  return gfx::Size(
-      AutofillCreditCardBubbleViews::kContentWidth,
-      GetHeightForWidth(AutofillCreditCardBubble::kContentWidth));
-}
-
-void AutofillCreditCardBubbleViews::LinkClicked(views::Link* source,
-                                                int event_flags) {
-  if (controller_)
-    controller_->OnLinkClicked();
-}
-
-// static
-base::WeakPtr<AutofillCreditCardBubble> AutofillCreditCardBubble::Create(
-    const base::WeakPtr<AutofillCreditCardBubbleController>& controller) {
-  AutofillCreditCardBubbleViews* bubble =
-      new AutofillCreditCardBubbleViews(controller);
-  return bubble->weak_ptr_factory_.GetWeakPtr();
-}
-
-AutofillCreditCardBubbleViews::AutofillCreditCardBubbleViews(
-    const base::WeakPtr<AutofillCreditCardBubbleController>& controller)
-    : BubbleDelegateView(GetAnchor(controller), views::BubbleBorder::TOP_RIGHT),
-      controller_(controller),
-      weak_ptr_factory_(this) {
-  // Match bookmarks bubble view's anchor view insets and margins.
-  set_anchor_view_insets(gfx::Insets(7, 0, 7, 0));
-  set_margins(gfx::Insets(0, 19, 18, 18));
-  set_move_with_anchor(true);
-}
-
-}  // namespace autofill
diff --git a/chrome/browser/ui/views/autofill/autofill_credit_card_bubble_views.h b/chrome/browser/ui/views/autofill/autofill_credit_card_bubble_views.h
deleted file mode 100644
index 9d8e8f1..0000000
--- a/chrome/browser/ui/views/autofill/autofill_credit_card_bubble_views.h
+++ /dev/null
@@ -1,58 +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_UI_VIEWS_AUTOFILL_AUTOFILL_CREDIT_CARD_BUBBLE_VIEWS_H_
-#define CHROME_BROWSER_UI_VIEWS_AUTOFILL_AUTOFILL_CREDIT_CARD_BUBBLE_VIEWS_H_
-
-#include "base/basictypes.h"
-#include "base/compiler_specific.h"
-#include "base/memory/weak_ptr.h"
-#include "chrome/browser/ui/autofill/autofill_credit_card_bubble.h"
-#include "ui/views/bubble/bubble_delegate.h"
-#include "ui/views/controls/link_listener.h"
-
-namespace autofill {
-
-class AutofillCreditCardBubbleController;
-
-// Views toolkit implementation of AutofillCreditCard bubble (an educational
-// bubble shown after a successful submission of the Autofill dialog).
-class AutofillCreditCardBubbleViews : public AutofillCreditCardBubble,
-                                      public views::BubbleDelegateView,
-                                      public views::LinkListener {
- public:
-  virtual ~AutofillCreditCardBubbleViews();
-
-  // AutofillCreditCardBubble:
-  virtual void Show() OVERRIDE;
-  virtual void Hide() OVERRIDE;
-  virtual bool IsHiding() const OVERRIDE;
-
-  // views::BubbleDelegateView:
-  virtual string16 GetWindowTitle() const OVERRIDE;
-  virtual void Init() OVERRIDE;
-  virtual gfx::Size GetPreferredSize() OVERRIDE;
-
-  // views::LinkListener:
-  virtual void LinkClicked(views::Link* source, int event_flags) OVERRIDE;
-
- private:
-  friend base::WeakPtr<AutofillCreditCardBubble>
-      AutofillCreditCardBubble::Create(
-          const base::WeakPtr<AutofillCreditCardBubbleController>& controller);
-
-  explicit AutofillCreditCardBubbleViews(
-     const base::WeakPtr<AutofillCreditCardBubbleController>& controller);
-
-  // Controller that drives this bubble. Invalid when hiding.
-  base::WeakPtr<AutofillCreditCardBubbleController> controller_;
-
-  base::WeakPtrFactory<AutofillCreditCardBubble> weak_ptr_factory_;
-
-  DISALLOW_COPY_AND_ASSIGN(AutofillCreditCardBubbleViews);
-};
-
-}  // namespace autofill
-
-#endif  // CHROME_BROWSER_UI_VIEWS_AUTOFILL_AUTOFILL_CREDIT_CARD_BUBBLE_VIEWS_H_
diff --git a/chrome/browser/ui/views/autofill/generated_credit_card_bubble_views.cc b/chrome/browser/ui/views/autofill/generated_credit_card_bubble_views.cc
new file mode 100644
index 0000000..8bc4766
--- /dev/null
+++ b/chrome/browser/ui/views/autofill/generated_credit_card_bubble_views.cc
@@ -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.
+
+#include "chrome/browser/ui/views/autofill/generated_credit_card_bubble_views.h"
+
+#include "chrome/browser/ui/autofill/generated_credit_card_bubble_controller.h"
+#include "chrome/browser/ui/browser_finder.h"
+#include "chrome/browser/ui/views/frame/browser_view.h"
+#include "chrome/browser/ui/views/location_bar/location_bar_view.h"
+#include "ui/gfx/font.h"
+#include "ui/gfx/insets.h"
+#include "ui/gfx/size.h"
+#include "ui/views/bubble/bubble_frame_view.h"
+#include "ui/views/controls/styled_label.h"
+#include "ui/views/layout/box_layout.h"
+#include "ui/views/layout/layout_constants.h"
+#include "ui/views/widget/widget.h"
+
+namespace autofill {
+
+namespace {
+
+// Get the view this bubble will be anchored to via |controller|.
+views::View* GetAnchor(
+    const base::WeakPtr<GeneratedCreditCardBubbleController>& controller) {
+  BrowserView* browser_view = BrowserView::GetBrowserViewForBrowser(
+      chrome::FindBrowserWithWebContents(controller->web_contents()));
+  return browser_view->GetLocationBarView()->generated_credit_card_view();
+}
+
+}  // namespace
+
+GeneratedCreditCardBubbleViews::~GeneratedCreditCardBubbleViews() {}
+
+void GeneratedCreditCardBubbleViews::Show() {
+  // TODO(dbeam): investigate why this steals focus from the web contents.
+  views::BubbleDelegateView::CreateBubble(this)->Show();
+
+  // This bubble doesn't render correctly on Windows without calling
+  // |SizeToContents()|. This must be called after showing the widget.
+  SizeToContents();
+}
+
+void GeneratedCreditCardBubbleViews::Hide() {
+  GetWidget()->Close();
+}
+
+bool GeneratedCreditCardBubbleViews::IsHiding() const {
+  return GetWidget() && GetWidget()->IsClosed();
+}
+
+gfx::Size GeneratedCreditCardBubbleViews::GetPreferredSize() {
+  return gfx::Size(
+      GeneratedCreditCardBubbleView::kContentsWidth,
+      GetHeightForWidth(GeneratedCreditCardBubbleViews::kContentsWidth));
+}
+
+base::string16 GeneratedCreditCardBubbleViews::GetWindowTitle() const {
+  return controller_ ? controller_->TitleText() : base::string16();
+}
+
+void GeneratedCreditCardBubbleViews::Init() {
+  SetLayoutManager(new views::BoxLayout(views::BoxLayout::kVertical, 0, 0,
+                                        views::kRelatedControlVerticalSpacing));
+
+  const base::string16& contents_text = controller_->ContentsText();
+  views::StyledLabel* contents = new views::StyledLabel(contents_text, this);
+
+  const std::vector<TextRange>& text_ranges = controller_->ContentsTextRanges();
+  for (size_t i = 0; i < text_ranges.size(); ++i) {
+    views::StyledLabel::RangeStyleInfo style;
+
+    if (text_ranges[i].is_link)
+      style = views::StyledLabel::RangeStyleInfo::CreateForLink();
+    else
+      style.font_style = gfx::Font::BOLD;
+
+    contents->AddStyleRange(text_ranges[i].range, style);
+  }
+
+  AddChildView(contents);
+}
+
+void GeneratedCreditCardBubbleViews::StyledLabelLinkClicked(const ui::Range& r,
+                                                            int event_flags) {
+  if (controller_)
+    controller_->OnLinkClicked();
+}
+
+// static
+base::WeakPtr<GeneratedCreditCardBubbleView>
+    GeneratedCreditCardBubbleView::Create(
+        const base::WeakPtr<GeneratedCreditCardBubbleController>& controller) {
+  return (new GeneratedCreditCardBubbleViews(controller))->weak_ptr_factory_.
+      GetWeakPtr();
+}
+
+GeneratedCreditCardBubbleViews::GeneratedCreditCardBubbleViews(
+    const base::WeakPtr<GeneratedCreditCardBubbleController>& controller)
+    : BubbleDelegateView(GetAnchor(controller), views::BubbleBorder::TOP_RIGHT),
+      controller_(controller),
+      weak_ptr_factory_(this) {
+  gfx::Insets insets = views::BubbleFrameView::GetTitleInsets();
+  set_margins(gfx::Insets(0, insets.left(), insets.top(), insets.left()));
+}
+
+}  // namespace autofill
diff --git a/chrome/browser/ui/views/autofill/generated_credit_card_bubble_views.h b/chrome/browser/ui/views/autofill/generated_credit_card_bubble_views.h
new file mode 100644
index 0000000..5ee786a
--- /dev/null
+++ b/chrome/browser/ui/views/autofill/generated_credit_card_bubble_views.h
@@ -0,0 +1,60 @@
+// 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_UI_VIEWS_AUTOFILL_GENERATED_CREDIT_CARD_BUBBLE_VIEWS_H_
+#define CHROME_BROWSER_UI_VIEWS_AUTOFILL_GENERATED_CREDIT_CARD_BUBBLE_VIEWS_H_
+
+#include "base/basictypes.h"
+#include "base/compiler_specific.h"
+#include "base/memory/weak_ptr.h"
+#include "chrome/browser/ui/autofill/generated_credit_card_bubble_view.h"
+#include "ui/views/bubble/bubble_delegate.h"
+#include "ui/views/controls/styled_label_listener.h"
+
+namespace autofill {
+
+class GeneratedCreditCardBubbleController;
+
+// Views toolkit implementation of the GeneratedCreditCardBubbleView (an
+// educational bubble shown after a successful generation of a new credit card
+// number).
+class GeneratedCreditCardBubbleViews : public GeneratedCreditCardBubbleView,
+                                       public views::BubbleDelegateView,
+                                       public views::StyledLabelListener {
+ public:
+  virtual ~GeneratedCreditCardBubbleViews();
+
+  // GeneratedCreditCardBubbleView:
+  virtual void Show() OVERRIDE;
+  virtual void Hide() OVERRIDE;
+  virtual bool IsHiding() const OVERRIDE;
+
+  // views::BubbleDelegateView:
+  virtual gfx::Size GetPreferredSize() OVERRIDE;
+  virtual base::string16 GetWindowTitle() const OVERRIDE;
+  virtual void Init() OVERRIDE;
+
+  // views::StyledLabelListener:
+  virtual void StyledLabelLinkClicked(const ui::Range& range, int event_flags)
+      OVERRIDE;
+
+ private:
+  friend base::WeakPtr<GeneratedCreditCardBubbleView>
+      GeneratedCreditCardBubbleView::Create(
+          const base::WeakPtr<GeneratedCreditCardBubbleController>& controller);
+
+  explicit GeneratedCreditCardBubbleViews(
+     const base::WeakPtr<GeneratedCreditCardBubbleController>& controller);
+
+  // Controller that drives this bubble. May be invalid when hiding.
+  base::WeakPtr<GeneratedCreditCardBubbleController> controller_;
+
+  base::WeakPtrFactory<GeneratedCreditCardBubbleView> weak_ptr_factory_;
+
+  DISALLOW_COPY_AND_ASSIGN(GeneratedCreditCardBubbleViews);
+};
+
+}  // namespace autofill
+
+#endif  // CHROME_BROWSER_UI_VIEWS_AUTOFILL_GENERATED_CREDIT_CARD_BUBBLE_VIEWS_H_
diff --git a/chrome/browser/ui/views/autofill/new_credit_card_bubble_views.cc b/chrome/browser/ui/views/autofill/new_credit_card_bubble_views.cc
new file mode 100644
index 0000000..496860c
--- /dev/null
+++ b/chrome/browser/ui/views/autofill/new_credit_card_bubble_views.cc
@@ -0,0 +1,121 @@
+// 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/ui/views/autofill/new_credit_card_bubble_views.h"
+
+#include "chrome/browser/ui/autofill/new_credit_card_bubble_controller.h"
+#include "chrome/browser/ui/browser_finder.h"
+#include "chrome/browser/ui/host_desktop.h"
+#include "chrome/browser/ui/views/frame/browser_view.h"
+#include "chrome/browser/ui/views/toolbar_view.h"
+#include "ui/gfx/insets.h"
+#include "ui/gfx/size.h"
+#include "ui/views/bubble/bubble_frame_view.h"
+#include "ui/views/controls/image_view.h"
+#include "ui/views/controls/link.h"
+#include "ui/views/layout/box_layout.h"
+#include "ui/views/layout/layout_constants.h"
+#include "ui/views/view.h"
+#include "ui/views/widget/widget.h"
+
+namespace autofill {
+
+namespace {
+
+// Get the view this bubble will be anchored to via |controller|.
+views::View* GetAnchor(NewCreditCardBubbleController* controller) {
+  Browser* browser = chrome::FindTabbedBrowser(controller->profile(), false,
+                                               chrome::GetActiveDesktop());
+  if (!browser)
+    return NULL;
+  BrowserView* browser_view = BrowserView::GetBrowserViewForBrowser(browser);
+  return browser_view->GetToolbarView()->app_menu();
+}
+
+}  // namespace
+
+NewCreditCardBubbleViews::~NewCreditCardBubbleViews() {
+  controller_->OnBubbleDestroyed();
+}
+
+void NewCreditCardBubbleViews::Show() {
+  // TODO(dbeam): investigate why this steals focus from the web contents.
+  views::BubbleDelegateView::CreateBubble(this)->Show();
+
+  // This bubble doesn't render correctly on Windows without calling
+  // |SizeToContents()|. This must be called after showing the widget.
+  SizeToContents();
+}
+
+void NewCreditCardBubbleViews::Hide() {
+  GetWidget()->Close();
+}
+
+gfx::Size NewCreditCardBubbleViews::GetPreferredSize() {
+  return gfx::Size(
+      NewCreditCardBubbleView::kContentsWidth,
+      GetHeightForWidth(NewCreditCardBubbleView::kContentsWidth));
+}
+
+void NewCreditCardBubbleViews::Init() {
+  SetLayoutManager(new views::BoxLayout(views::BoxLayout::kVertical, 0, 0,
+                                        views::kRelatedControlVerticalSpacing));
+
+  views::View* card_container = new views::View();
+  card_container->SetLayoutManager(
+      new views::BoxLayout(views::BoxLayout::kVertical, 0, 0, 10));
+
+  views::View* card_desc_view = new views::View();
+  card_desc_view->SetLayoutManager(
+      new views::BoxLayout(views::BoxLayout::kHorizontal, 0, 0, 10));
+
+  views::ImageView* card_icon = new views::ImageView();
+  const CreditCardDescription& card_desc = controller_->CardDescription();
+  card_icon->SetImage(card_desc.icon.AsImageSkia());
+  card_desc_view->AddChildView(card_icon);
+
+  views::Label* card_name = new views::Label(card_desc.name);
+  card_name->SetHorizontalAlignment(gfx::ALIGN_LEFT);
+  card_desc_view->AddChildView(card_name);
+  card_container->AddChildView(card_desc_view);
+
+  views::Label* desc = new views::Label(card_desc.description);
+  desc->SetHorizontalAlignment(gfx::ALIGN_LEFT);
+  desc->SetMultiLine(true);
+  card_container->AddChildView(desc);
+
+  AddChildView(card_container);
+
+  views::Link* link = new views::Link(controller_->LinkText());
+  link->SetHorizontalAlignment(gfx::ALIGN_LEFT);
+  link->set_listener(this);
+  AddChildView(link);
+}
+
+base::string16 NewCreditCardBubbleViews::GetWindowTitle() const {
+  return controller_->TitleText();
+}
+
+void NewCreditCardBubbleViews::LinkClicked(views::Link* source,
+                                           int event_flags) {
+  controller_->OnLinkClicked();
+}
+
+// static
+base::WeakPtr<NewCreditCardBubbleView> NewCreditCardBubbleView::Create(
+    NewCreditCardBubbleController* controller) {
+  NewCreditCardBubbleViews* bubble = new NewCreditCardBubbleViews(controller);
+  return bubble->weak_ptr_factory_.GetWeakPtr();
+}
+
+NewCreditCardBubbleViews::NewCreditCardBubbleViews(
+    NewCreditCardBubbleController* controller)
+    : BubbleDelegateView(GetAnchor(controller), views::BubbleBorder::TOP_RIGHT),
+      controller_(controller),
+      weak_ptr_factory_(this) {
+  gfx::Insets insets = views::BubbleFrameView::GetTitleInsets();
+  set_margins(gfx::Insets(0, insets.left(), insets.top(), insets.left()));
+}
+
+}  // namespace autofill
diff --git a/chrome/browser/ui/views/autofill/new_credit_card_bubble_views.h b/chrome/browser/ui/views/autofill/new_credit_card_bubble_views.h
new file mode 100644
index 0000000..fe57246
--- /dev/null
+++ b/chrome/browser/ui/views/autofill/new_credit_card_bubble_views.h
@@ -0,0 +1,56 @@
+// 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_UI_VIEWS_AUTOFILL_NEW_CREDIT_CARD_BUBBLE_VIEWS_H_
+#define CHROME_BROWSER_UI_VIEWS_AUTOFILL_NEW_CREDIT_CARD_BUBBLE_VIEWS_H_
+
+#include "base/basictypes.h"
+#include "base/compiler_specific.h"
+#include "base/memory/weak_ptr.h"
+#include "chrome/browser/ui/autofill/new_credit_card_bubble_view.h"
+#include "ui/views/bubble/bubble_delegate.h"
+#include "ui/views/controls/link_listener.h"
+
+namespace autofill {
+
+class NewCreditCardBubbleController;
+
+// Views toolkit implementation of NewCreditCardBubbleView (a bubble shown after
+// a user saved a new card locally in Chrome).
+class NewCreditCardBubbleViews : public NewCreditCardBubbleView,
+                                 public views::BubbleDelegateView,
+                                 public views::LinkListener {
+ public:
+  virtual ~NewCreditCardBubbleViews();
+
+  // NewCreditCardBubbleView:
+  virtual void Show() OVERRIDE;
+  virtual void Hide() OVERRIDE;
+
+  // views::BubbleDelegateView:
+  virtual gfx::Size GetPreferredSize() OVERRIDE;
+  virtual base::string16 GetWindowTitle() const OVERRIDE;
+  virtual void Init() OVERRIDE;
+
+  // views::LinkListener:
+  virtual void LinkClicked(views::Link* source, int event_flags) OVERRIDE;
+
+ private:
+  friend base::WeakPtr<NewCreditCardBubbleView> NewCreditCardBubbleView::Create(
+      NewCreditCardBubbleController* controller);
+
+  explicit NewCreditCardBubbleViews(
+     NewCreditCardBubbleController* controller);
+
+  // Controller that drives this bubble. Never NULL; outlives this class.
+  NewCreditCardBubbleController* controller_;
+
+  base::WeakPtrFactory<NewCreditCardBubbleView> weak_ptr_factory_;
+
+  DISALLOW_COPY_AND_ASSIGN(NewCreditCardBubbleViews);
+};
+
+}  // namespace autofill
+
+#endif  // CHROME_BROWSER_UI_VIEWS_AUTOFILL_NEW_CREDIT_CARD_BUBBLE_VIEWS_H_
diff --git a/chrome/browser/ui/views/avatar_menu_button_browsertest.cc b/chrome/browser/ui/views/avatar_menu_button_browsertest.cc
index 9a4fdfa..6270e8f 100644
--- a/chrome/browser/ui/views/avatar_menu_button_browsertest.cc
+++ b/chrome/browser/ui/views/avatar_menu_button_browsertest.cc
@@ -193,7 +193,7 @@
   EXPECT_EQ(starting_tab_count + 1, final_tab_count);
 
   GURL tab_url = browser()->tab_strip_model()->GetActiveWebContents()->GetURL();
-  EXPECT_EQ(std::string(chrome::kChromeUIUserChooserURL), tab_url.spec());
+  EXPECT_EQ(std::string(chrome::kChromeUIUserManagerURL), tab_url.spec());
 }
 
 INSTANTIATE_TEST_CASE_P(Old, AvatarMenuButtonTest, testing::Values(false));
diff --git a/chrome/browser/ui/views/desktop_media_picker_views.cc b/chrome/browser/ui/views/desktop_media_picker_views.cc
index 685c155..b21ea7f 100644
--- a/chrome/browser/ui/views/desktop_media_picker_views.cc
+++ b/chrome/browser/ui/views/desktop_media_picker_views.cc
@@ -23,6 +23,8 @@
 #include "ui/views/window/dialog_client_view.h"
 #include "ui/views/window/dialog_delegate.h"
 
+using content::DesktopMediaID;
+
 namespace {
 
 const int kThumbnailWidth = 160;
@@ -49,7 +51,7 @@
 class DesktopMediaSourceView : public views::View {
  public:
   DesktopMediaSourceView(DesktopMediaListView* parent,
-                         DesktopMediaPickerModel::SourceId source_id);
+                         DesktopMediaID source_id);
   virtual ~DesktopMediaSourceView();
 
   // Updates thumbnail and title from |source|.
@@ -57,7 +59,7 @@
   void SetThumbnail(const gfx::ImageSkia& thumbnail);
 
   // Id for the source shown by this View.
-  const DesktopMediaPickerModel::SourceId& source_id() const {
+  const DesktopMediaID& source_id() const {
     return source_id_;
   }
 
@@ -79,8 +81,7 @@
 
  private:
   DesktopMediaListView* parent_;
-
-  DesktopMediaPickerModel::SourceId source_id_;
+  DesktopMediaID source_id_;
 
   views::ImageView* image_view_;
   views::Label* label_;
@@ -166,7 +167,7 @@
   DesktopMediaPickerViews();
   virtual ~DesktopMediaPickerViews();
 
-  void NotifyDialogResult(DesktopMediaPickerModel::SourceId source);
+  void NotifyDialogResult(DesktopMediaID source);
 
   // DesktopMediaPicker overrides.
   virtual void Show(gfx::NativeWindow context,
@@ -188,7 +189,7 @@
 
 DesktopMediaSourceView::DesktopMediaSourceView(
     DesktopMediaListView* parent,
-    DesktopMediaPickerModel::SourceId source_id)
+    DesktopMediaID source_id)
     : parent_(parent),
       source_id_(source_id),
       image_view_(new views::ImageView()),
@@ -491,7 +492,7 @@
   // Ok button should only be enabled when a source is selected.
   DCHECK(selection);
 
-  DesktopMediaPickerModel::SourceId source;
+  DesktopMediaID source;
   if (selection)
     source = selection->source_id();
 
@@ -504,10 +505,8 @@
 
 void DesktopMediaPickerDialogView::DeleteDelegate() {
   // If the dialog is being closed then notify the parent about it.
-  if (parent_) {
-    parent_->NotifyDialogResult(
-        DesktopMediaPickerModel::SourceId(content::MEDIA_NO_SERVICE, 0));
-  }
+  if (parent_)
+    parent_->NotifyDialogResult(DesktopMediaID());
   delete this;
 }
 
@@ -537,7 +536,7 @@
 }
 
 void DesktopMediaPickerViews::NotifyDialogResult(
-    DesktopMediaPickerModel::SourceId source) {
+    DesktopMediaID source) {
   // Once this method is called the |dialog_| will close and destroy itself.
   dialog_->DetachParent();
   dialog_ = NULL;
diff --git a/chrome/browser/ui/views/download/download_shelf_view.cc b/chrome/browser/ui/views/download/download_shelf_view.cc
index c737a85..e16536f 100644
--- a/chrome/browser/ui/views/download/download_shelf_view.cc
+++ b/chrome/browser/ui/views/download/download_shelf_view.cc
@@ -10,7 +10,7 @@
 #include "base/logging.h"
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/browser/download/download_item_model.h"
-#include "chrome/browser/download/download_util.h"
+#include "chrome/browser/download/download_stats.h"
 #include "chrome/browser/themes/theme_properties.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/chrome_pages.h"
@@ -406,9 +406,8 @@
     if (download_views_[i]->download()->GetState() == DownloadItem::IN_PROGRESS)
       ++num_in_progress;
   }
-  download_util::RecordShelfClose(download_views_.size(),
-                                  num_in_progress,
-                                  reason == AUTOMATIC);
+  RecordDownloadShelfClose(
+      download_views_.size(), num_in_progress, reason == AUTOMATIC);
   parent_->SetDownloadShelfVisible(false);
   shelf_animation_->Hide();
 }
diff --git a/chrome/browser/ui/views/frame/OWNERS b/chrome/browser/ui/views/frame/OWNERS
index 3ef69af..14b3d0e 100644
--- a/chrome/browser/ui/views/frame/OWNERS
+++ b/chrome/browser/ui/views/frame/OWNERS
@@ -4,3 +4,5 @@
 
 # For Ash or other non-Windows-specific changes
 jamescook@chromium.org
+
+per-file immersive_mode_controller*=pkotwicz@chromium.org
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 e6ccb3e..9b0f1a7 100644
--- a/chrome/browser/ui/views/frame/global_menu_bar_x11.cc
+++ b/chrome/browser/ui/views/frame/global_menu_bar_x11.cc
@@ -9,27 +9,45 @@
 
 #include "base/logging.h"
 #include "base/prefs/pref_service.h"
+#include "base/stl_util.h"
+#include "base/strings/string_number_conversions.h"
 #include "base/strings/stringprintf.h"
+#include "base/strings/utf_string_conversions.h"
 #include "chrome/app/chrome_command_ids.h"
+#include "chrome/browser/chrome_notification_types.h"
+#include "chrome/browser/history/top_sites.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/sessions/tab_restore_service.h"
+#include "chrome/browser/sessions/tab_restore_service_factory.h"
+#include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_commands.h"
+#include "chrome/browser/ui/browser_tab_restore_service_delegate.h"
 #include "chrome/browser/ui/views/frame/browser_desktop_root_window_host_x11.h"
 #include "chrome/browser/ui/views/frame/browser_view.h"
 #include "chrome/browser/ui/views/frame/global_menu_bar_registrar_x11.h"
 #include "chrome/common/pref_names.h"
+#include "content/public/browser/notification_source.h"
 #include "grit/generated_resources.h"
 #include "ui/base/accelerators/menu_label_accelerator_util_linux.h"
 #include "ui/base/keycodes/keyboard_code_conversion_x.h"
 #include "ui/base/l10n/l10n_util.h"
+#include "ui/base/text/text_elider.h"
 
 // libdbusmenu-glib types
 typedef struct _DbusmenuMenuitem DbusmenuMenuitem;
 typedef DbusmenuMenuitem* (*dbusmenu_menuitem_new_func)();
-typedef DbusmenuMenuitem* (*dbusmenu_menuitem_new_with_id_func)(int id);
-
-typedef int (*dbusmenu_menuitem_get_id_func)(DbusmenuMenuitem* item);
+typedef bool (*dbusmenu_menuitem_child_add_position_func)(
+    DbusmenuMenuitem* parent,
+    DbusmenuMenuitem* child,
+    unsigned int position);
 typedef DbusmenuMenuitem* (*dbusmenu_menuitem_child_append_func)(
     DbusmenuMenuitem* parent,
     DbusmenuMenuitem* child);
+typedef bool (*dbusmenu_menuitem_child_delete_func)(
+    DbusmenuMenuitem* parent,
+    DbusmenuMenuitem* child);
+typedef GList* (*dbusmenu_menuitem_get_children_func)(
+    DbusmenuMenuitem* item);
 typedef DbusmenuMenuitem* (*dbusmenu_menuitem_property_set_func)(
     DbusmenuMenuitem* item,
     const char* property,
@@ -65,9 +83,10 @@
 
 // DbusmenuMenuItem methods:
 dbusmenu_menuitem_new_func menuitem_new = NULL;
-dbusmenu_menuitem_new_with_id_func menuitem_new_with_id = NULL;
-dbusmenu_menuitem_get_id_func menuitem_get_id = NULL;
+dbusmenu_menuitem_get_children_func menuitem_get_children = NULL;
+dbusmenu_menuitem_child_add_position_func menuitem_child_add_position = NULL;
 dbusmenu_menuitem_child_append_func menuitem_child_append = NULL;
+dbusmenu_menuitem_child_delete_func menuitem_child_delete = NULL;
 dbusmenu_menuitem_property_set_func menuitem_property_set = NULL;
 dbusmenu_menuitem_property_set_variant_func menuitem_property_set_variant =
     NULL;
@@ -90,10 +109,30 @@
 const char kTypeCheckmark[] = "checkmark";
 const char kTypeSeparator[] = "separator";
 
-// Constants used in menu definitions
+// Data set on GObjectgs.
+const char kTypeTag[] = "type-tag";
+const char kHistoryItem[] = "history-item";
+
+// The maximum number of most visited items to display.
+const unsigned int kMostVisitedCount = 8;
+
+// The number of recently closed items to get.
+const unsigned int kRecentlyClosedCount = 8;
+
+// Menus more than this many chars long will get trimmed.
+const int kMaximumMenuWidthInChars = 50;
+
+// Constants used in menu definitions.
 const int MENU_SEPARATOR =-1;
 const int MENU_END = -2;
-const int MENU_DISABLED_LABEL = -3;
+const int MENU_DISABLED_ID = -3;
+
+// These tag values are used to refer to menu itesm.
+const int TAG_NORMAL = 0;
+const int TAG_MOST_VISITED = 1;
+const int TAG_RECENTLY_CLOSED = 2;
+const int TAG_MOST_VISITED_HEADER = 3;
+const int TAG_RECENTLY_CLOSED_HEADER = 4;
 
 GlobalMenuBarCommand file_menu[] = {
   { IDS_NEW_TAB, IDC_NEW_TAB },
@@ -136,7 +175,6 @@
   { MENU_END, MENU_END }
 };
 
-
 GlobalMenuBarCommand view_menu[] = {
   { IDS_SHOW_BOOKMARK_BAR, IDC_SHOW_BOOKMARK_BAR },
 
@@ -155,7 +193,25 @@
   { MENU_END, MENU_END }
 };
 
-// TODO(erg): History menu.
+GlobalMenuBarCommand history_menu[] = {
+  { IDS_HISTORY_HOME_LINUX, IDC_HOME },
+  { IDS_HISTORY_BACK_LINUX, IDC_BACK },
+  { IDS_HISTORY_FORWARD_LINUX, IDC_FORWARD },
+
+  { MENU_SEPARATOR, MENU_SEPARATOR },
+
+  { IDS_HISTORY_VISITED_LINUX, MENU_DISABLED_ID, TAG_MOST_VISITED_HEADER },
+
+  { MENU_SEPARATOR, MENU_SEPARATOR },
+
+  { IDS_HISTORY_CLOSED_LINUX, MENU_DISABLED_ID, TAG_RECENTLY_CLOSED_HEADER },
+
+  { MENU_SEPARATOR, MENU_SEPARATOR },
+
+  { IDS_SHOWFULLHISTORY_LINK, IDC_SHOW_HISTORY },
+
+  { MENU_END, MENU_END }
+};
 
 GlobalMenuBarCommand tools_menu[] = {
   { IDS_SHOW_DOWNLOADS, IDC_SHOW_DOWNLOADS },
@@ -182,7 +238,6 @@
   { MENU_END, MENU_END }
 };
 
-
 void EnsureMethodsLoaded() {
   static bool attempted_load = false;
   if (attempted_load)
@@ -196,12 +251,15 @@
   // DbusmenuMenuItem methods.
   menuitem_new = reinterpret_cast<dbusmenu_menuitem_new_func>(
       dlsym(dbusmenu_lib, "dbusmenu_menuitem_new"));
-  menuitem_new_with_id = reinterpret_cast<dbusmenu_menuitem_new_with_id_func>(
-      dlsym(dbusmenu_lib, "dbusmenu_menuitem_new_with_id"));
-  menuitem_get_id = reinterpret_cast<dbusmenu_menuitem_get_id_func>(
-      dlsym(dbusmenu_lib, "dbusmenu_menuitem_get_id"));
+  menuitem_child_add_position =
+      reinterpret_cast<dbusmenu_menuitem_child_add_position_func>(
+          dlsym(dbusmenu_lib, "dbusmenu_menuitem_child_add_position"));
   menuitem_child_append = reinterpret_cast<dbusmenu_menuitem_child_append_func>(
       dlsym(dbusmenu_lib, "dbusmenu_menuitem_child_append"));
+  menuitem_child_delete = reinterpret_cast<dbusmenu_menuitem_child_delete_func>(
+      dlsym(dbusmenu_lib, "dbusmenu_menuitem_child_delete"));
+  menuitem_get_children = reinterpret_cast<dbusmenu_menuitem_get_children_func>(
+      dlsym(dbusmenu_lib, "dbusmenu_menuitem_get_children"));
   menuitem_property_set = reinterpret_cast<dbusmenu_menuitem_property_set_func>(
       dlsym(dbusmenu_lib, "dbusmenu_menuitem_property_set"));
   menuitem_property_set_variant =
@@ -223,13 +281,43 @@
 
 }  // namespace
 
+struct GlobalMenuBarX11::HistoryItem {
+  HistoryItem() : session_id(0) {}
+
+  // The title for the menu item.
+  string16 title;
+  // The URL that will be navigated to if the user selects this item.
+  GURL url;
+
+  // This ID is unique for a browser session and can be passed to the
+  // TabRestoreService to re-open the closed window or tab that this
+  // references. A non-0 session ID indicates that this is an entry can be
+  // restored that way. Otherwise, the URL will be used to open the item and
+  // this ID will be 0.
+  SessionID::id_type session_id;
+
+  // If the HistoryItem is a window, this will be the vector of tabs. Note
+  // that this is a list of weak references. The |menu_item_map_| is the owner
+  // of all items. If it is not a window, then the entry is a single page and
+  // the vector will be empty.
+  std::vector<HistoryItem*> tabs;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(HistoryItem);
+};
+
 GlobalMenuBarX11::GlobalMenuBarX11(BrowserView* browser_view,
                                    BrowserDesktopRootWindowHostX11* host)
     : browser_(browser_view->browser()),
+      profile_(browser_->profile()),
       browser_view_(browser_view),
       host_(host),
       server_(NULL),
-      root_item_(NULL) {
+      root_item_(NULL),
+      history_menu_(NULL),
+      top_sites_(NULL),
+      tab_restore_service_(NULL),
+      weak_ptr_factory_(this) {
   EnsureMethodsLoaded();
 
   if (server_new)
@@ -239,6 +327,10 @@
 GlobalMenuBarX11::~GlobalMenuBarX11() {
   if (server_) {
     Disable();
+
+    if (tab_restore_service_)
+      tab_restore_service_->RemoveObserver(this);
+
     g_object_unref(server_);
     host_->RemoveObserver(this);
   }
@@ -249,6 +341,26 @@
   return base::StringPrintf("/com/canonical/menu/%lX", xid);
 }
 
+DbusmenuMenuitem* GlobalMenuBarX11::BuildSeparator() {
+  DbusmenuMenuitem* item = menuitem_new();
+  menuitem_property_set(item, kPropertyType, kTypeSeparator);
+  menuitem_property_set_bool(item, kPropertyVisible, true);
+  return item;
+}
+
+DbusmenuMenuitem* GlobalMenuBarX11::BuildMenuItem(
+    const std::string& label,
+    int tag_id) {
+  DbusmenuMenuitem* item = menuitem_new();
+  menuitem_property_set(item, kPropertyLabel, label.c_str());
+  menuitem_property_set_bool(item, kPropertyVisible, true);
+
+  if (tag_id)
+    g_object_set_data(G_OBJECT(item), kTypeTag, GINT_TO_POINTER(tag_id));
+
+  return item;
+}
+
 void GlobalMenuBarX11::InitServer(unsigned long xid) {
   std::string path = GetPathForWindow(xid);
   server_ = server_new(path.c_str());
@@ -257,13 +369,20 @@
   menuitem_property_set(root_item_, kPropertyLabel, "Root");
   menuitem_property_set_bool(root_item_, kPropertyVisible, true);
 
-  BuildMenuFrom(root_item_, IDS_FILE_MENU_LINUX, &id_to_menu_item_, file_menu);
-  BuildMenuFrom(root_item_, IDS_EDIT_MENU_LINUX, &id_to_menu_item_, edit_menu);
-  BuildMenuFrom(root_item_, IDS_VIEW_MENU_LINUX, &id_to_menu_item_, view_menu);
-  // TODO(erg): History menu.
-  BuildMenuFrom(root_item_, IDS_TOOLS_MENU_LINUX, &id_to_menu_item_,
-                tools_menu);
-  BuildMenuFrom(root_item_, IDS_HELP_MENU_LINUX, &id_to_menu_item_, help_menu);
+  // First build static menu content.
+  BuildStaticMenu(root_item_, IDS_FILE_MENU_LINUX, file_menu);
+  BuildStaticMenu(root_item_, IDS_EDIT_MENU_LINUX, edit_menu);
+  BuildStaticMenu(root_item_, IDS_VIEW_MENU_LINUX, view_menu);
+  history_menu_ = BuildStaticMenu(
+      root_item_, IDS_HISTORY_MENU_LINUX, history_menu);
+  BuildStaticMenu(root_item_, IDS_TOOLS_MENU_LINUX, tools_menu);
+  BuildStaticMenu(root_item_, IDS_HELP_MENU_LINUX, help_menu);
+
+  // We have to connect to |history_menu_item|'s "activate" signal instead of
+  // |history_menu|'s "show" signal because we are not supposed to modify the
+  // menu during "show"
+  g_signal_connect(history_menu_, "about-to-show",
+                   G_CALLBACK(OnHistoryMenuAboutToShowThunk), this);
 
   for (CommandIDMenuItemMap::const_iterator it = id_to_menu_item_.begin();
        it != id_to_menu_item_.end(); ++it) {
@@ -284,6 +403,16 @@
                  base::Unretained(this)));
   OnBookmarkBarVisibilityChanged();
 
+  top_sites_ = profile_->GetTopSites();
+  if (top_sites_) {
+    GetTopSitesData();
+
+    // Register for notification when TopSites changes so that we can update
+    // ourself.
+    registrar_.Add(this, chrome::NOTIFICATION_TOP_SITES_CHANGED,
+                   content::Source<history::TopSites>(top_sites_));
+  }
+
   server_set_root(server_, root_item_);
 }
 
@@ -297,10 +426,9 @@
   pref_change_registrar_.RemoveAll();
 }
 
-void GlobalMenuBarX11::BuildMenuFrom(
+DbusmenuMenuitem* GlobalMenuBarX11::BuildStaticMenu(
     DbusmenuMenuitem* parent,
     int menu_str_id,
-    std::map<int, DbusmenuMenuitem*>* id_to_menu_item,
     GlobalMenuBarCommand* commands) {
   DbusmenuMenuitem* top = menuitem_new();
   menuitem_property_set(
@@ -310,48 +438,37 @@
   menuitem_property_set_bool(top, kPropertyVisible, true);
 
   for (int i = 0; commands[i].str_id != MENU_END; ++i) {
-    DbusmenuMenuitem* menu_item = BuildMenuItem(
-        commands[i].str_id, commands[i].command, commands[i].tag,
-        id_to_menu_item);
+    DbusmenuMenuitem* menu_item = NULL;
+    int command_id = commands[i].command;
+    if (commands[i].str_id == MENU_SEPARATOR) {
+      menu_item = BuildSeparator();
+    } else {
+      std::string label = ui::ConvertAcceleratorsFromWindowsStyle(
+          l10n_util::GetStringUTF8(commands[i].str_id));
+
+      menu_item = BuildMenuItem(label, commands[i].tag);
+
+      if (command_id == MENU_DISABLED_ID) {
+        menuitem_property_set_bool(menu_item, kPropertyEnabled, false);
+      } else {
+        if (command_id == IDC_SHOW_BOOKMARK_BAR)
+          menuitem_property_set(menu_item, kPropertyToggleType, kTypeCheckmark);
+
+        id_to_menu_item_.insert(std::make_pair(command_id, menu_item));
+        g_object_set_data(G_OBJECT(menu_item), "command-id",
+                          GINT_TO_POINTER(command_id));
+        g_signal_connect(menu_item, "item-activated",
+                         G_CALLBACK(OnItemActivatedThunk), this);
+      }
+    }
+
     menuitem_child_append(top, menu_item);
+    g_object_unref(menu_item);
   }
 
   menuitem_child_append(parent, top);
-}
-
-DbusmenuMenuitem* GlobalMenuBarX11::BuildMenuItem(
-    int string_id,
-    int command_id,
-    int tag_id,
-    std::map<int, DbusmenuMenuitem*>* id_to_menu_item) {
-  DbusmenuMenuitem* item = menuitem_new();
-
-  if (string_id == MENU_SEPARATOR) {
-    menuitem_property_set(item, kPropertyType, kTypeSeparator);
-  } else {
-    std::string label = ui::ConvertAcceleratorsFromWindowsStyle(
-        l10n_util::GetStringUTF8(string_id));
-    menuitem_property_set(item, kPropertyLabel, label.c_str());
-
-    if (command_id == IDC_SHOW_BOOKMARK_BAR)
-      menuitem_property_set(item, kPropertyToggleType, kTypeCheckmark);
-
-    if (tag_id)
-      g_object_set_data(G_OBJECT(item), "type-tag", GINT_TO_POINTER(tag_id));
-
-    if (command_id == MENU_DISABLED_LABEL) {
-      menuitem_property_set_bool(item, kPropertyEnabled, false);
-    } else {
-      id_to_menu_item->insert(std::make_pair(command_id, item));
-      g_object_set_data(G_OBJECT(item), "command-id",
-                        GINT_TO_POINTER(command_id));
-      g_signal_connect(item, "item-activated",
-                       G_CALLBACK(OnItemActivatedThunk), this);
-    }
-  }
-
-  menuitem_property_set_bool(item, kPropertyVisible, true);
-  return item;
+  g_object_unref(top);
+  return top;
 }
 
 void GlobalMenuBarX11::RegisterAccelerator(DbusmenuMenuitem* item,
@@ -384,6 +501,70 @@
   menuitem_property_set_variant(item, kPropertyShortcut, outside_array);
 }
 
+GlobalMenuBarX11::HistoryItem* GlobalMenuBarX11::HistoryItemForTab(
+    const TabRestoreService::Tab& entry) {
+  const sessions::SerializedNavigationEntry& current_navigation =
+      entry.navigations.at(entry.current_navigation_index);
+  HistoryItem* item = new HistoryItem();
+  item->title = current_navigation.title();
+  item->url = current_navigation.virtual_url();
+  item->session_id = entry.id;
+
+  return item;
+}
+
+void GlobalMenuBarX11::AddHistoryItemToMenu(HistoryItem* item,
+                                            DbusmenuMenuitem* menu,
+                                            int tag,
+                                            int index) {
+  string16 title = item->title;
+  std::string url_string = item->url.possibly_invalid_spec();
+
+  if (title.empty())
+    title = UTF8ToUTF16(url_string);
+  ui::ElideString(title, kMaximumMenuWidthInChars, &title);
+
+  DbusmenuMenuitem* menu_item = BuildMenuItem(UTF16ToUTF8(title), tag);
+  g_signal_connect(menu_item, "item-activated",
+                   G_CALLBACK(OnHistoryItemActivatedThunk), this);
+
+  g_object_set_data_full(G_OBJECT(menu_item), kHistoryItem, item,
+                         DeleteHistoryItem);
+  menuitem_child_add_position(menu, menu_item, index);
+  g_object_unref(menu_item);
+}
+
+void GlobalMenuBarX11::GetTopSitesData() {
+  DCHECK(top_sites_);
+
+  top_sites_->GetMostVisitedURLs(
+      base::Bind(&GlobalMenuBarX11::OnTopSitesReceived,
+                 weak_ptr_factory_.GetWeakPtr()));
+}
+
+void GlobalMenuBarX11::OnTopSitesReceived(
+    const history::MostVisitedURLList& visited_list) {
+  ClearMenuSection(history_menu_, TAG_MOST_VISITED);
+
+  int index = GetIndexOfMenuItemWithTag(history_menu_,
+                                        TAG_MOST_VISITED_HEADER) + 1;
+
+  for (size_t i = 0; i < visited_list.size() && i < kMostVisitedCount; ++i) {
+    const history::MostVisitedURL& visited = visited_list[i];
+    if (visited.url.spec().empty())
+      break;  // This is the signal that there are no more real visited sites.
+
+    HistoryItem* item = new HistoryItem();
+    item->title = visited.title;
+    item->url = visited.url;
+
+    AddHistoryItemToMenu(item,
+                         history_menu_,
+                         TAG_MOST_VISITED,
+                         index++);
+  }
+}
+
 void GlobalMenuBarX11::OnBookmarkBarVisibilityChanged() {
   CommandIDMenuItemMap::iterator it =
       id_to_menu_item_.find(IDC_SHOW_BOOKMARK_BAR);
@@ -396,12 +577,152 @@
   }
 }
 
+int GlobalMenuBarX11::GetIndexOfMenuItemWithTag(DbusmenuMenuitem* menu,
+                                                int tag_id) {
+  GList* childs = menuitem_get_children(menu);
+  int i = 0;
+  for (; childs != NULL; childs = childs->next, i++) {
+    int tag =
+        GPOINTER_TO_INT(g_object_get_data(G_OBJECT(childs->data), kTypeTag));
+    if (tag == tag_id)
+      return i;
+  }
+
+  NOTREACHED();
+  return -1;
+}
+
+void GlobalMenuBarX11::ClearMenuSection(DbusmenuMenuitem* menu, int tag_id) {
+  std::vector<DbusmenuMenuitem*> menuitems_to_delete;
+
+  GList* childs = menuitem_get_children(menu);
+  for (; childs != NULL; childs = childs->next) {
+    DbusmenuMenuitem* current_item = reinterpret_cast<DbusmenuMenuitem*>(
+        childs->data);
+    ClearMenuSection(current_item, tag_id);
+
+    int tag =
+        GPOINTER_TO_INT(g_object_get_data(G_OBJECT(childs->data), kTypeTag));
+    if (tag == tag_id)
+      menuitems_to_delete.push_back(current_item);
+  }
+
+  for (std::vector<DbusmenuMenuitem*>::const_iterator it =
+           menuitems_to_delete.begin(); it != menuitems_to_delete.end(); ++it) {
+    menuitem_child_delete(menu, *it);
+  }
+}
+
+// static
+void GlobalMenuBarX11::DeleteHistoryItem(void* void_item) {
+  HistoryItem* item =
+      reinterpret_cast<GlobalMenuBarX11::HistoryItem*>(void_item);
+  delete item;
+}
+
 void GlobalMenuBarX11::EnabledStateChangedForCommand(int id, bool enabled) {
   CommandIDMenuItemMap::iterator it = id_to_menu_item_.find(id);
   if (it != id_to_menu_item_.end())
     menuitem_property_set_bool(it->second, kPropertyEnabled, enabled);
 }
 
+void GlobalMenuBarX11::Observe(int type,
+                               const content::NotificationSource& source,
+                               const content::NotificationDetails& details) {
+  if (type == chrome::NOTIFICATION_TOP_SITES_CHANGED) {
+    GetTopSitesData();
+  } else {
+    NOTREACHED();
+  }
+}
+
+void GlobalMenuBarX11::TabRestoreServiceChanged(TabRestoreService* service) {
+  const TabRestoreService::Entries& entries = service->entries();
+
+  ClearMenuSection(history_menu_, TAG_RECENTLY_CLOSED);
+
+  // We'll get the index the "Recently Closed" header. (This can vary depending
+  // on the number of "Most Visited" items.
+  int index = GetIndexOfMenuItemWithTag(history_menu_,
+                                        TAG_RECENTLY_CLOSED_HEADER) + 1;
+
+  unsigned int added_count = 0;
+  for (TabRestoreService::Entries::const_iterator it = entries.begin();
+       it != entries.end() && added_count < kRecentlyClosedCount; ++it) {
+    TabRestoreService::Entry* entry = *it;
+
+    if (entry->type == TabRestoreService::WINDOW) {
+      TabRestoreService::Window* entry_win =
+          static_cast<TabRestoreService::Window*>(entry);
+      std::vector<TabRestoreService::Tab>& tabs = entry_win->tabs;
+      if (tabs.empty())
+        continue;
+
+      // Create the item for the parent/window.
+      HistoryItem* item = new HistoryItem();
+      item->session_id = entry_win->id;
+
+      std::string title = item->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()));
+      DbusmenuMenuitem* parent_item = BuildMenuItem(
+          title, TAG_RECENTLY_CLOSED);
+      menuitem_child_add_position(history_menu_, parent_item, index++);
+      g_object_unref(parent_item);
+
+      // The mac version of this code allows the user to click on the parent
+      // menu item to have the same effect as clicking the restore window
+      // submenu item. GTK+ helpfully activates a menu item when it shows a
+      // submenu so toss that feature out.
+      DbusmenuMenuitem* restore_item = BuildMenuItem(
+          l10n_util::GetStringUTF8(
+              IDS_HISTORY_CLOSED_RESTORE_WINDOW_LINUX).c_str(),
+          TAG_RECENTLY_CLOSED);
+      g_signal_connect(restore_item, "item-activated",
+                       G_CALLBACK(OnHistoryItemActivatedThunk), this);
+      g_object_set_data_full(G_OBJECT(restore_item), kHistoryItem, item,
+                             DeleteHistoryItem);
+      menuitem_child_append(parent_item, restore_item);
+      g_object_unref(restore_item);
+
+      DbusmenuMenuitem* separator = BuildSeparator();
+      menuitem_child_append(parent_item, separator);
+      g_object_unref(separator);
+
+      // Loop over the window's tabs and add them to the submenu.
+      int subindex = 2;
+      std::vector<TabRestoreService::Tab>::const_iterator iter;
+      for (iter = tabs.begin(); iter != tabs.end(); ++iter) {
+        TabRestoreService::Tab tab = *iter;
+        HistoryItem* tab_item = HistoryItemForTab(tab);
+        item->tabs.push_back(tab_item);
+        AddHistoryItemToMenu(tab_item,
+                             parent_item,
+                             TAG_RECENTLY_CLOSED,
+                             subindex++);
+      }
+
+      ++added_count;
+    } else if (entry->type == TabRestoreService::TAB) {
+      TabRestoreService::Tab* tab = static_cast<TabRestoreService::Tab*>(entry);
+      HistoryItem* item = HistoryItemForTab(*tab);
+      AddHistoryItemToMenu(item,
+                           history_menu_,
+                           TAG_RECENTLY_CLOSED,
+                           index++);
+      ++added_count;
+    }
+  }
+}
+
+void GlobalMenuBarX11::TabRestoreServiceDestroyed(
+    TabRestoreService* service) {
+  tab_restore_service_ = NULL;
+}
+
 void GlobalMenuBarX11::OnWindowMapped(unsigned long xid) {
   if (!server_)
     InitServer(xid);
@@ -418,3 +739,44 @@
   int id = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(item), "command-id"));
   chrome::ExecuteCommand(browser_, id);
 }
+
+void GlobalMenuBarX11::OnHistoryItemActivated(DbusmenuMenuitem* sender,
+                                              unsigned int timestamp) {
+  // Note: We don't have access to the event modifiers used to click the menu
+  // item since that happens in a different process.
+  HistoryItem* item = reinterpret_cast<HistoryItem*>(
+      g_object_get_data(G_OBJECT(sender), kHistoryItem));
+
+  // If this item can be restored using TabRestoreService, do so. Otherwise,
+  // just load the URL.
+  TabRestoreService* service =
+      TabRestoreServiceFactory::GetForProfile(profile_);
+  if (item->session_id && service) {
+    service->RestoreEntryById(browser_->tab_restore_service_delegate(),
+                              item->session_id, browser_->host_desktop_type(),
+                              UNKNOWN);
+  } else {
+    DCHECK(item->url.is_valid());
+    browser_->OpenURL(content::OpenURLParams(
+        item->url,
+        content::Referrer(),
+        NEW_FOREGROUND_TAB,
+        content::PAGE_TRANSITION_AUTO_BOOKMARK,
+        false));
+  }
+}
+
+void GlobalMenuBarX11::OnHistoryMenuAboutToShow(DbusmenuMenuitem* item) {
+  if (!tab_restore_service_) {
+    tab_restore_service_ = TabRestoreServiceFactory::GetForProfile(profile_);
+    if (tab_restore_service_) {
+      tab_restore_service_->LoadTabsFromLastSession();
+      tab_restore_service_->AddObserver(this);
+
+      // If LoadTabsFromLastSession doesn't load tabs, it won't call
+      // TabRestoreServiceChanged(). This ensures that all new windows after
+      // the first one will have their menus populated correctly.
+      TabRestoreServiceChanged(tab_restore_service_);
+    }
+  }
+}
diff --git a/chrome/browser/ui/views/frame/global_menu_bar_x11.h b/chrome/browser/ui/views/frame/global_menu_bar_x11.h
index 46f8cf3..269153e 100644
--- a/chrome/browser/ui/views/frame/global_menu_bar_x11.h
+++ b/chrome/browser/ui/views/frame/global_menu_bar_x11.h
@@ -11,18 +11,29 @@
 #include "base/compiler_specific.h"
 #include "base/prefs/pref_change_registrar.h"
 #include "chrome/browser/command_observer.h"
+#include "chrome/browser/common/cancelable_request.h"
+#include "chrome/browser/history/history_types.h"
+#include "chrome/browser/sessions/tab_restore_service.h"
+#include "chrome/browser/sessions/tab_restore_service_observer.h"
+#include "content/public/browser/notification_observer.h"
+#include "content/public/browser/notification_registrar.h"
 #include "ui/base/glib/glib_signal.h"
 #include "ui/views/widget/desktop_aura/desktop_root_window_host_observer_x11.h"
 
 typedef struct _DbusmenuMenuitem DbusmenuMenuitem;
 typedef struct _DbusmenuServer   DbusmenuServer;
 
+namespace history {
+class TopSites;
+}
+
 namespace ui {
 class Accelerator;
 }
 
 class Browser;
 class BrowserView;
+class Profile;
 
 class BrowserDesktopRootWindowHostX11;
 struct GlobalMenuBarCommand;
@@ -36,6 +47,8 @@
 // interface directly with the lower level libdbusmenu-glib, which we
 // opportunistically dlopen() since not everyone is running Ubuntu.
 class GlobalMenuBarX11 : public CommandObserver,
+                         public content::NotificationObserver,
+                         public TabRestoreServiceObserver,
                          public views::DesktopRootWindowHostObserverX11 {
  public:
   GlobalMenuBarX11(BrowserView* browser_view,
@@ -46,8 +59,16 @@
   static std::string GetPathForWindow(unsigned long xid);
 
  private:
+  struct HistoryItem;
   typedef std::map<int, DbusmenuMenuitem*> CommandIDMenuItemMap;
 
+  // Builds a separator.
+  DbusmenuMenuitem* BuildSeparator();
+
+  // Creates an individual menu item from a title and command, and subscribes
+  // to the activation signal.
+  DbusmenuMenuitem* BuildMenuItem(const std::string& label, int tag_id);
+
   // Creates a DbusmenuServer, and attaches all the menu items.
   void InitServer(unsigned long xid);
 
@@ -56,37 +77,68 @@
 
   // Creates a whole menu defined with |commands| and titled with the string
   // |menu_str_id|. Then appends it to |parent|.
-  void BuildMenuFrom(DbusmenuMenuitem* parent,
-                     int menu_str_id,
-                     CommandIDMenuItemMap* id_to_menu_item,
-                     GlobalMenuBarCommand* commands);
-
-  // Creates an individual menu item from a title and command, and subscribes
-  // to the activation signal.
-  DbusmenuMenuitem* BuildMenuItem(
-      int string_id,
-      int command_id,
-      int tag_id,
-      CommandIDMenuItemMap* id_to_menu_item);
+  DbusmenuMenuitem* BuildStaticMenu(DbusmenuMenuitem* parent,
+                                    int menu_str_id,
+                                    GlobalMenuBarCommand* commands);
 
   // Sets the accelerator for |item|.
   void RegisterAccelerator(DbusmenuMenuitem* item,
                            const ui::Accelerator& accelerator);
 
+  // Creates a HistoryItem from the data in |entry|.
+  HistoryItem* HistoryItemForTab(const TabRestoreService::Tab& entry);
+
+  // Creates a menu item form |item| and inserts it in |menu| at |index|.
+  void AddHistoryItemToMenu(HistoryItem* item,
+                            DbusmenuMenuitem* menu,
+                            int tag,
+                            int index);
+
+  // Sends a message off to History for data.
+  void GetTopSitesData();
+
+  // Callback to receive data requested from GetTopSitesData().
+  void OnTopSitesReceived(const history::MostVisitedURLList& visited_list);
+
   // Updates the visibility of the bookmark bar on pref changes.
   void OnBookmarkBarVisibilityChanged();
 
+  // Find the first index of the item in |menu| with the tag |tag_id|.
+  int GetIndexOfMenuItemWithTag(DbusmenuMenuitem* menu, int tag_id);
+
+  // This will remove all menu items in |menu| with |tag| as their tag. This
+  // clears state about HistoryItems* that we keep to prevent that data from
+  // going stale. That's why this method recurses into its child menus.
+  void ClearMenuSection(DbusmenuMenuitem* menu, int tag_id);
+
+  // Deleter function for HistoryItem implementation detail.
+  static void DeleteHistoryItem(void* void_item);
+
   // Overridden from CommandObserver:
   virtual void EnabledStateChangedForCommand(int id, bool enabled) OVERRIDE;
 
-  // Overridden from DesktopRootWindowHostObserverX11:
+  // Overridden from content::NotificationObserver:
+  virtual void Observe(int type,
+                       const content::NotificationSource& source,
+                       const content::NotificationDetails& details) OVERRIDE;
+
+  // Overridden from TabRestoreServiceObserver:
+  virtual void TabRestoreServiceChanged(TabRestoreService* service) OVERRIDE;
+  virtual void TabRestoreServiceDestroyed(TabRestoreService* service) OVERRIDE;
+
+  // Overridden from views::DesktopRootWindowHostObserverX11:
   virtual void OnWindowMapped(unsigned long xid) OVERRIDE;
   virtual void OnWindowUnmapped(unsigned long xid) OVERRIDE;
 
   CHROMEG_CALLBACK_1(GlobalMenuBarX11, void, OnItemActivated, DbusmenuMenuitem*,
                      unsigned int);
+  CHROMEG_CALLBACK_1(GlobalMenuBarX11, void, OnHistoryItemActivated,
+                     DbusmenuMenuitem*, unsigned int);
+  CHROMEG_CALLBACK_0(GlobalMenuBarX11, void, OnHistoryMenuAboutToShow,
+                     DbusmenuMenuitem*);
 
   Browser* browser_;
+  Profile* profile_;
   BrowserView* browser_view_;
   BrowserDesktopRootWindowHostX11* host_;
 
@@ -96,10 +148,20 @@
 
   DbusmenuServer* server_;
   DbusmenuMenuitem* root_item_;
+  DbusmenuMenuitem* history_menu_;
 
   // Tracks value of the kShowBookmarkBar preference.
   PrefChangeRegistrar pref_change_registrar_;
 
+  history::TopSites* top_sites_;
+
+  TabRestoreService* tab_restore_service_;  // weak
+
+  content::NotificationRegistrar registrar_;
+
+  // For callbacks may be run after destruction.
+  base::WeakPtrFactory<GlobalMenuBarX11> weak_ptr_factory_;
+
   DISALLOW_COPY_AND_ASSIGN(GlobalMenuBarX11);
 };
 
diff --git a/chrome/browser/ui/views/frame/immersive_mode_controller_ash.cc b/chrome/browser/ui/views/frame/immersive_mode_controller_ash.cc
index e469a3c..37ab716 100644
--- a/chrome/browser/ui/views/frame/immersive_mode_controller_ash.cc
+++ b/chrome/browser/ui/views/frame/immersive_mode_controller_ash.cc
@@ -353,7 +353,7 @@
 
     if (reveal_state_ == REVEALED) {
       // Reveal was unsuccessful. Reacquire the revealed locks if appropriate.
-      UpdateLocatedEventRevealedLock(NULL);
+      UpdateLocatedEventRevealedLock(NULL, ALLOW_REVEAL_WHILE_CLOSING_NO);
       UpdateFocusRevealedLock();
     }
   } else {
@@ -440,7 +440,7 @@
     return;
 
   if (IsRevealed())
-    UpdateLocatedEventRevealedLock(event);
+    UpdateLocatedEventRevealedLock(event, ALLOW_REVEAL_WHILE_CLOSING_NO);
 
   // Trigger a reveal if the cursor pauses at the top of the screen for a
   // while.
@@ -452,7 +452,7 @@
   if (!enabled_ || event->type() != ui::ET_TOUCH_PRESSED)
     return;
 
-  UpdateLocatedEventRevealedLock(event);
+  UpdateLocatedEventRevealedLock(event, ALLOW_REVEAL_WHILE_CLOSING_NO);
 }
 
 void ImmersiveModeControllerAsh::OnGestureEvent(ui::GestureEvent* event) {
@@ -493,15 +493,6 @@
 
 void ImmersiveModeControllerAsh::OnDidChangeFocus(views::View* focused_before,
                                                   views::View* focused_now) {
-  scoped_ptr<ImmersiveRevealedLock> lock;
-  if (reveal_state_ == REVEALED || reveal_state_ == SLIDING_OPEN) {
-    // Acquire a lock so that if UpdateLocatedEventRevealedLock() or
-    // UpdateFocusRevealedLock() ends the reveal, it occurs after the
-    // function terminates. This is useful in tests.
-    lock.reset(GetRevealedLock(ANIMATE_REVEAL_YES));
-  }
-
-  UpdateLocatedEventRevealedLock(NULL);
   UpdateFocusRevealedLock();
 }
 
@@ -517,20 +508,21 @@
 void ImmersiveModeControllerAsh::OnWidgetActivationChanged(
     views::Widget* widget,
     bool active) {
-  scoped_ptr<ImmersiveRevealedLock> lock;
-  if (reveal_state_ == REVEALED || reveal_state_ == SLIDING_OPEN) {
-    // Acquire a lock so that if UpdateLocatedEventRevealedLock() or
-    // UpdateFocusRevealedLock() ends the reveal, it occurs after the
-    // function terminates. This is useful in tests.
-    lock.reset(GetRevealedLock(ANIMATE_REVEAL_YES));
-  }
-
   // Mouse hover should not initiate revealing the top-of-window views while
   // |native_window_| is inactive.
   top_edge_hover_timer_.Stop();
 
-  UpdateLocatedEventRevealedLock(NULL);
   UpdateFocusRevealedLock();
+
+  // Allow the top-of-window views to stay revealed if all of the revealed locks
+  // were released in the process of activating |widget| but the mouse is still
+  // hovered above the top-of-window views. For instance, if the bubble which
+  // has been keeping the top-of-window views revealed is hidden but the mouse
+  // is hovered above the top-of-window views, the top-of-window views should
+  // stay revealed. We cannot call UpdateLocatedEventRevealedLock() from
+  // BubbleManager::UpdateRevealedLock() because |widget| is not yet active
+  // at that time.
+  UpdateLocatedEventRevealedLock(NULL, ALLOW_REVEAL_WHILE_CLOSING_YES);
 }
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -623,12 +615,12 @@
 void ImmersiveModeControllerAsh::StartRevealForTest(bool hovered) {
   MaybeStartReveal(ANIMATE_NO);
   MoveMouse(top_container_, hovered);
-  UpdateLocatedEventRevealedLock(NULL);
+  UpdateLocatedEventRevealedLock(NULL, ALLOW_REVEAL_WHILE_CLOSING_NO);
 }
 
 void ImmersiveModeControllerAsh::SetMouseHoveredForTest(bool hovered) {
   MoveMouse(top_container_, hovered);
-  UpdateLocatedEventRevealedLock(NULL);
+  UpdateLocatedEventRevealedLock(NULL, ALLOW_REVEAL_WHILE_CLOSING_NO);
 }
 
 void ImmersiveModeControllerAsh::DisableAnimationsForTest() {
@@ -746,7 +738,8 @@
 }
 
 void ImmersiveModeControllerAsh::UpdateLocatedEventRevealedLock(
-    ui::LocatedEvent* event) {
+    ui::LocatedEvent* event,
+    AllowRevealWhileClosing allow_reveal_while_closing) {
   if (!enabled_)
     return;
   DCHECK(!event || event->IsMouseEvent() || event->IsTouchEvent());
@@ -755,8 +748,11 @@
   // views are sliding closed or are closed with the following exceptions:
   // - Hovering at y = 0 which is handled in OnMouseEvent().
   // - Doing a SWIPE_OPEN edge gesture which is handled in OnGestureEvent().
-  if (reveal_state_ == SLIDING_CLOSED || reveal_state_ == CLOSED)
+  if (reveal_state_ == CLOSED ||
+      (reveal_state_ == SLIDING_CLOSED &&
+       allow_reveal_while_closing == ALLOW_REVEAL_WHILE_CLOSING_NO)) {
     return;
+  }
 
   // Neither the mouse nor touch should keep the top-of-window views revealed if
   // |native_window_| is not active.
@@ -895,7 +891,7 @@
         return true;
 
       // Ending the reveal was unsuccessful. Reaquire the locks if appropriate.
-      UpdateLocatedEventRevealedLock(NULL);
+      UpdateLocatedEventRevealedLock(NULL, ALLOW_REVEAL_WHILE_CLOSING_NO);
       UpdateFocusRevealedLock();
     }
   }
@@ -1031,7 +1027,7 @@
 
   // The user may not have moved the mouse since the reveal was initiated.
   // Update the revealed lock to reflect the mouse's current state.
-  UpdateLocatedEventRevealedLock(NULL);
+  UpdateLocatedEventRevealedLock(NULL, ALLOW_REVEAL_WHILE_CLOSING_NO);
 }
 
 void ImmersiveModeControllerAsh::MaybeEndReveal(Animate animate) {
@@ -1123,19 +1119,31 @@
 
 bool ImmersiveModeControllerAsh::ShouldHandleGestureEvent(
     const gfx::Point& location) const {
+  gfx::Rect top_container_bounds_in_screen =
+      top_container_->GetBoundsInScreen();
+
   // All of the gestures that are of interest start in a region with left &
   // right edges agreeing with |top_container_|. When CLOSED it is difficult to
   // hit the bounds due to small size of the tab strip, so the hit target needs
-  // to be extended on the bottom, thus the inset call. Finally there may be a
-  // bezel sensor off screen logically above |top_container_| thus the test
-  // needs to include gestures starting above.
-  gfx::Rect near_bounds = top_container_->GetBoundsInScreen();
+  // to be extended on the bottom, thus the inset call.
+  gfx::Rect near_bounds = top_container_bounds_in_screen;
   if (reveal_state_ == CLOSED)
     near_bounds.Inset(gfx::Insets(0, 0, -kNearTopContainerDistance, 0));
-  return near_bounds.Contains(location) ||
-      ((location.y() < near_bounds.y()) &&
-       (location.x() >= near_bounds.x()) &&
-       (location.x() < near_bounds.right()));
+  if (near_bounds.Contains(location))
+    return true;
+
+  // There may be a bezel sensor off screen logically above |top_container_|
+  // thus the test needs to include gestures starting above, but this needs to
+  // be distinguished from events originating on another screen from
+  // (potentially) an extended desktop. The check for the event not contained by
+  // the closest screen ensures that the event is from a valid bezel and can be
+  // interpreted as such.
+  gfx::Rect screen_bounds =
+      ash::Shell::GetScreen()->GetDisplayNearestPoint(location).bounds();
+  return (!screen_bounds.Contains(location) &&
+          location.y() < top_container_bounds_in_screen.y() &&
+          location.x() >= top_container_bounds_in_screen.x() &&
+          location.x() < top_container_bounds_in_screen.right());
 }
 
 void ImmersiveModeControllerAsh::SetRenderWindowTopInsetsForTouch(
@@ -1143,10 +1151,13 @@
   content::WebContents* contents = delegate_->GetWebContents();
   if (contents) {
     aura::Window* window = contents->GetView()->GetContentNativeView();
-    gfx::Insets inset(top_inset, 0, 0, 0);
-    window->SetHitTestBoundsOverrideOuter(
-        window->hit_test_bounds_override_outer_mouse(),
-        inset);
+    // |window| is NULL if the renderer crashed.
+    if (window) {
+      gfx::Insets inset(top_inset, 0, 0, 0);
+      window->SetHitTestBoundsOverrideOuter(
+          window->hit_test_bounds_override_outer_mouse(),
+          inset);
+    }
   }
 }
 
diff --git a/chrome/browser/ui/views/frame/immersive_mode_controller_ash.h b/chrome/browser/ui/views/frame/immersive_mode_controller_ash.h
index 482c5b2..c904f05 100644
--- a/chrome/browser/ui/views/frame/immersive_mode_controller_ash.h
+++ b/chrome/browser/ui/views/frame/immersive_mode_controller_ash.h
@@ -118,6 +118,10 @@
  private:
   friend class ImmersiveModeControllerAshTest;
 
+  enum AllowRevealWhileClosing {
+    ALLOW_REVEAL_WHILE_CLOSING_YES,
+    ALLOW_REVEAL_WHILE_CLOSING_NO
+  };
   enum Animate {
     ANIMATE_NO,
     ANIMATE_SLOW,
@@ -156,7 +160,12 @@
   // Updates |located_event_revealed_lock_| based on the current mouse state and
   // the current touch state.
   // |event| is NULL if the source event is not known.
-  void UpdateLocatedEventRevealedLock(ui::LocatedEvent* event);
+  // |allow_reveal_while_closing| indicates whether the mouse and touch
+  // are allowed to initiate a reveal while the top-of-window views are sliding
+  // closed.
+  void UpdateLocatedEventRevealedLock(
+      ui::LocatedEvent* event,
+      AllowRevealWhileClosing allow_reveal_while_closing);
 
   // Acquires |located_event_revealed_lock_| if it is not already held.
   void AcquireLocatedEventRevealedLock();
diff --git a/chrome/browser/ui/views/frame/immersive_mode_controller_ash_unittest.cc b/chrome/browser/ui/views/frame/immersive_mode_controller_ash_unittest.cc
index d91bbd8..c983c9a 100644
--- a/chrome/browser/ui/views/frame/immersive_mode_controller_ash_unittest.cc
+++ b/chrome/browser/ui/views/frame/immersive_mode_controller_ash_unittest.cc
@@ -13,6 +13,7 @@
 #include "ui/aura/root_window.h"
 #include "ui/aura/test/event_generator.h"
 #include "ui/aura/window.h"
+#include "ui/base/animation/slide_animation.h"
 #include "ui/views/bubble/bubble_delegate.h"
 
 // For now, immersive fullscreen is Chrome OS only.
@@ -96,7 +97,21 @@
     widget_->GetContentsView()->AddChildView(top_container_);
 
     controller_->Init(delegate_.get(), widget_, top_container_);
-    controller_->DisableAnimationsForTest();
+    SetAnimationsDisabled(true);
+  }
+
+  // Enable or disable the immersive mode controller's animations. When the
+  // immersive mode controller's animations are disabled, some behavior is
+  // slightly different. In particular, the behavior is different when there
+  // is a transfer in which lock keeps the top-of-window views revealed (eg
+  // bubble keeps top-of-window views revealed -> mouse keeps top-of-window
+  // views revealed). It is necessary to temparily enable the immersive
+  // controller's animations to get the correct behavior in tests.
+  void SetAnimationsDisabled(bool disabled) {
+    controller_->animations_disabled_for_test_ = disabled;
+    // Force any in progress animations to finish.
+    if (disabled)
+      controller_->animation_->End();
   }
 
   // Attempt to reveal the top-of-window views via |modality|.
@@ -654,14 +669,25 @@
   bubble_widget2->Close();
   EXPECT_FALSE(controller()->IsRevealed());
 
-  // 2) Test that the top-of-window views stay revealed as long as at least one
-  // bubble anchored to a child of the top container is visible.
-  views::BubbleDelegateView* bubble_delegate3(new views::BubbleDelegateView(
-      child_view, views::BubbleBorder::NONE));
-  bubble_delegate3->set_use_focusless(true);
-  views::Widget* bubble_widget3(views::BubbleDelegateView::CreateBubble(
-      bubble_delegate3));
+  // 2) Test that transitioning from keeping the top-of-window views revealed
+  // because of a bubble to keeping the top-of-window views revealed because of
+  // mouse hover by activating |top_container_widget| works.
+  views::Widget* bubble_widget3 = views::BubbleDelegateView::CreateBubble(
+      new views::BubbleDelegateView(child_view, views::BubbleBorder::NONE));
   bubble_widget3->Show();
+  SetHovered(true);
+  EXPECT_TRUE(controller()->IsRevealed());
+
+  SetAnimationsDisabled(false);
+  // Activating |top_container_widget| will close |bubble_widget3|.
+  top_container_widget->Activate();
+  SetAnimationsDisabled(true);
+  EXPECT_TRUE(controller()->IsRevealed());
+
+  // 3) Test that the top-of-window views stay revealed as long as at least one
+  // bubble anchored to a child of the top container is visible.
+  SetHovered(false);
+  EXPECT_FALSE(controller()->IsRevealed());
 
   views::BubbleDelegateView* bubble_delegate4(new views::BubbleDelegateView(
       child_view, views::BubbleBorder::NONE));
@@ -670,44 +696,51 @@
       bubble_delegate4));
   bubble_widget4->Show();
 
-  EXPECT_TRUE(controller()->IsRevealed());
-  bubble_widget3->Hide();
+  views::BubbleDelegateView* bubble_delegate5(new views::BubbleDelegateView(
+      child_view, views::BubbleBorder::NONE));
+  bubble_delegate5->set_use_focusless(true);
+  views::Widget* bubble_widget5(views::BubbleDelegateView::CreateBubble(
+      bubble_delegate5));
+  bubble_widget5->Show();
+
   EXPECT_TRUE(controller()->IsRevealed());
   bubble_widget4->Hide();
+  EXPECT_TRUE(controller()->IsRevealed());
+  bubble_widget5->Hide();
   EXPECT_FALSE(controller()->IsRevealed());
-  bubble_widget4->Show();
+  bubble_widget5->Show();
   EXPECT_TRUE(controller()->IsRevealed());
 
-  // 3) Test that visibility changes which occur while immersive fullscreen is
+  // 4) Test that visibility changes which occur while immersive fullscreen is
   // disabled are handled upon reenabling immersive fullscreen.
   controller()->SetEnabled(false);
-  bubble_widget4->Hide();
+  bubble_widget5->Hide();
   controller()->SetEnabled(true);
   EXPECT_FALSE(controller()->IsRevealed());
 
-  // We do not need |bubble_widget3| or |bubble_widget4| anymore, close them.
-  bubble_widget3->Close();
+  // We do not need |bubble_widget4| or |bubble_widget5| anymore, close them.
   bubble_widget4->Close();
+  bubble_widget5->Close();
 
-  // 4) Test that a bubble added while immersive fullscreen is disabled is
+  // 5) Test that a bubble added while immersive fullscreen is disabled is
   // handled upon reenabling immersive fullscreen.
   controller()->SetEnabled(false);
 
-  views::Widget* bubble_widget5 = views::BubbleDelegateView::CreateBubble(
+  views::Widget* bubble_widget6 = views::BubbleDelegateView::CreateBubble(
       new views::BubbleDelegateView(child_view, views::BubbleBorder::NONE));
-  bubble_widget5->Show();
+  bubble_widget6->Show();
 
   controller()->SetEnabled(true);
   EXPECT_TRUE(controller()->IsRevealed());
 
-  bubble_widget5->Close();
+  bubble_widget6->Close();
 
-  // 5) Test that a bubble which is not anchored to a child of the
+  // 6) Test that a bubble which is not anchored to a child of the
   // TopContainerView does not trigger a reveal or keep the
   // top-of-window views revealed if they are already revealed.
-  views::Widget* bubble_widget6 = views::BubbleDelegateView::CreateBubble(
+  views::Widget* bubble_widget7 = views::BubbleDelegateView::CreateBubble(
       new views::BubbleDelegateView(unrelated_view, views::BubbleBorder::NONE));
-  bubble_widget6->Show();
+  bubble_widget7->Show();
   EXPECT_FALSE(controller()->IsRevealed());
 
   // Activating |top_container_widget| will close |bubble_widget6|.
@@ -715,12 +748,12 @@
   AttemptReveal(MODALITY_MOUSE);
   EXPECT_TRUE(controller()->IsRevealed());
 
-  views::Widget* bubble_widget7 = views::BubbleDelegateView::CreateBubble(
+  views::Widget* bubble_widget8 = views::BubbleDelegateView::CreateBubble(
       new views::BubbleDelegateView(unrelated_view, views::BubbleBorder::NONE));
-  bubble_widget7->Show();
+  bubble_widget8->Show();
   SetHovered(false);
   EXPECT_FALSE(controller()->IsRevealed());
-  bubble_widget7->Close();
+  bubble_widget8->Close();
 }
 
 #endif  // defined(OS_WIN)
diff --git a/chrome/browser/ui/views/location_bar/autofill_credit_card_view.cc b/chrome/browser/ui/views/location_bar/autofill_credit_card_view.cc
deleted file mode 100644
index 21e7208..0000000
--- a/chrome/browser/ui/views/location_bar/autofill_credit_card_view.cc
+++ /dev/null
@@ -1,52 +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/ui/views/location_bar/autofill_credit_card_view.h"
-
-#include "chrome/browser/ui/autofill/autofill_credit_card_bubble_controller.h"
-#include "chrome/browser/ui/toolbar/toolbar_model.h"
-#include "ui/gfx/image/image.h"
-
-AutofillCreditCardView::AutofillCreditCardView(
-    ToolbarModel* toolbar_model,
-    LocationBarView::Delegate* delegate)
-    : toolbar_model_(toolbar_model),
-      delegate_(delegate) {
-  Update();
-}
-
-AutofillCreditCardView::~AutofillCreditCardView() {}
-
-void AutofillCreditCardView::Update() {
-  autofill::AutofillCreditCardBubbleController* controller = GetController();
-  if (controller && !controller->AnchorIcon().IsEmpty()) {
-    SetVisible(true);
-    SetImage(controller->AnchorIcon().AsImageSkia());
-  } else {
-    SetVisible(false);
-    SetImage(NULL);
-  }
-}
-
-// TODO(dbeam): figure out what to do for a tooltip and accessibility.
-
-bool AutofillCreditCardView::CanHandleClick() const {
-  autofill::AutofillCreditCardBubbleController* controller = GetController();
-  return controller && !controller->IsHiding();
-}
-
-void AutofillCreditCardView::OnClick() {
-  autofill::AutofillCreditCardBubbleController* controller = GetController();
-  if (controller)
-    controller->OnAnchorClicked();
-}
-
-autofill::AutofillCreditCardBubbleController* AutofillCreditCardView::
-    GetController() const {
-  content::WebContents* wc = delegate_->GetWebContents();
-  if (!wc || toolbar_model_->GetInputInProgress())
-    return NULL;
-
-  return autofill::AutofillCreditCardBubbleController::FromWebContents(wc);
-}
diff --git a/chrome/browser/ui/views/location_bar/autofill_credit_card_view.h b/chrome/browser/ui/views/location_bar/autofill_credit_card_view.h
deleted file mode 100644
index 169c5f2..0000000
--- a/chrome/browser/ui/views/location_bar/autofill_credit_card_view.h
+++ /dev/null
@@ -1,54 +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_UI_VIEWS_LOCATION_BAR_AUTOFILL_CREDIT_CARD_VIEW_H_
-#define CHROME_BROWSER_UI_VIEWS_LOCATION_BAR_AUTOFILL_CREDIT_CARD_VIEW_H_
-
-#include "base/basictypes.h"
-#include "base/compiler_specific.h"
-#include "chrome/browser/ui/autofill/autofill_credit_card_bubble_controller.h"
-#include "chrome/browser/ui/views/location_bar/location_bar_decoration_view.h"
-#include "chrome/browser/ui/views/location_bar/location_bar_view.h"
-#include "ui/views/controls/image_view.h"
-
-class ToolbarModel;
-
-namespace autofill {
-class AutofillCreditCardBubbleController;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-//
-// AutofillCreditCardView
-//
-//  An icon that shows up in the omnibox after successfully submitting the
-//  Autofill dialog. Used as an anchor and click target to show the associated
-//  bubble with more details about the credit cards saved or used.
-//
-////////////////////////////////////////////////////////////////////////////////
-class AutofillCreditCardView : public LocationBarDecorationView {
- public:
-  AutofillCreditCardView(ToolbarModel* toolbar_model,
-                         LocationBarView::Delegate* delegate);
-  virtual ~AutofillCreditCardView();
-
-  void Update();
-
- protected:
-  // LocationBarDecorationView:
-  virtual bool CanHandleClick() const OVERRIDE;
-  virtual void OnClick() OVERRIDE;
-
- private:
-  // Helper to get the AutofillCreditCardBubbleController associated with the
-  // current web contents.
-  autofill::AutofillCreditCardBubbleController* GetController() const;
-
-  ToolbarModel* toolbar_model_;  // weak; outlives us.
-  LocationBarView::Delegate* delegate_;  // weak; outlives us.
-
-  DISALLOW_COPY_AND_ASSIGN(AutofillCreditCardView);
-};
-
-#endif  // CHROME_BROWSER_UI_VIEWS_LOCATION_BAR_AUTOFILL_CREDIT_CARD_VIEW_H_
diff --git a/chrome/browser/ui/views/location_bar/content_setting_image_view.cc b/chrome/browser/ui/views/location_bar/content_setting_image_view.cc
index 014c3da..6d05e4f 100644
--- a/chrome/browser/ui/views/location_bar/content_setting_image_view.cc
+++ b/chrome/browser/ui/views/location_bar/content_setting_image_view.cc
@@ -83,7 +83,7 @@
   text_label_->SetElideBehavior(views::Label::NO_ELIDE);
   AddChildView(text_label_);
 
-  TouchableLocationBarView::Init(this);
+  LocationBarView::InitTouchableLocationBarChildView(this);
 
   slide_animator_.SetSlideDuration(kAnimationDurationMS);
   slide_animator_.SetTweenType(ui::Tween::LINEAR);
@@ -94,10 +94,6 @@
     bubble_widget_->RemoveObserver(this);
 }
 
-int ContentSettingImageView::GetBuiltInHorizontalPadding() const {
-  return GetBuiltInHorizontalPaddingImpl();
-}
-
 void ContentSettingImageView::Update(content::WebContents* web_contents) {
   // Note: We explicitly want to call this even if |web_contents| is NULL, so we
   // get hidden properly while the user is editing the omnibox.
diff --git a/chrome/browser/ui/views/location_bar/content_setting_image_view.h b/chrome/browser/ui/views/location_bar/content_setting_image_view.h
index 4d59678..350b3fd 100644
--- a/chrome/browser/ui/views/location_bar/content_setting_image_view.h
+++ b/chrome/browser/ui/views/location_bar/content_setting_image_view.h
@@ -6,7 +6,6 @@
 #define CHROME_BROWSER_UI_VIEWS_LOCATION_BAR_CONTENT_SETTING_IMAGE_VIEW_H_
 
 #include "base/memory/scoped_ptr.h"
-#include "chrome/browser/ui/views/location_bar/touchable_location_bar_view.h"
 #include "chrome/common/content_settings_types.h"
 #include "ui/base/animation/animation_delegate.h"
 #include "ui/base/animation/slide_animation.h"
@@ -30,8 +29,7 @@
 // The ContentSettingImageView displays an icon and optional text label for
 // various content settings affordances in the location bar (i.e. plugin
 // blocking, geolocation).
-class ContentSettingImageView : public TouchableLocationBarView,
-                                public ui::AnimationDelegate,
+class ContentSettingImageView : public ui::AnimationDelegate,
                                 public views::View,
                                 public views::WidgetObserver {
  public:
@@ -43,9 +41,6 @@
                           SkColor parent_background_color);
   virtual ~ContentSettingImageView();
 
-  // TouchableLocationBarView:
-  virtual int GetBuiltInHorizontalPadding() const OVERRIDE;
-
   // Update the decoration from the shown WebContents.
   void Update(content::WebContents* web_contents);
 
diff --git a/chrome/browser/ui/views/location_bar/generated_credit_card_view.cc b/chrome/browser/ui/views/location_bar/generated_credit_card_view.cc
new file mode 100644
index 0000000..ff914b6
--- /dev/null
+++ b/chrome/browser/ui/views/location_bar/generated_credit_card_view.cc
@@ -0,0 +1,52 @@
+// 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/ui/views/location_bar/generated_credit_card_view.h"
+
+#include "chrome/browser/ui/autofill/generated_credit_card_bubble_controller.h"
+#include "chrome/browser/ui/toolbar/toolbar_model.h"
+#include "ui/gfx/image/image.h"
+
+GeneratedCreditCardView::GeneratedCreditCardView(
+    ToolbarModel* toolbar_model,
+    LocationBarView::Delegate* delegate)
+    : toolbar_model_(toolbar_model),
+      delegate_(delegate) {
+  Update();
+}
+
+GeneratedCreditCardView::~GeneratedCreditCardView() {}
+
+void GeneratedCreditCardView::Update() {
+  autofill::GeneratedCreditCardBubbleController* controller = GetController();
+  if (controller && !controller->AnchorIcon().IsEmpty()) {
+    SetVisible(true);
+    SetImage(controller->AnchorIcon().AsImageSkia());
+  } else {
+    SetVisible(false);
+    SetImage(NULL);
+  }
+}
+
+// TODO(dbeam): figure out what to do for a tooltip and accessibility.
+
+bool GeneratedCreditCardView::CanHandleClick() const {
+  autofill::GeneratedCreditCardBubbleController* controller = GetController();
+  return controller && !controller->IsHiding();
+}
+
+void GeneratedCreditCardView::OnClick() {
+  autofill::GeneratedCreditCardBubbleController* controller = GetController();
+  if (controller)
+    controller->OnAnchorClicked();
+}
+
+autofill::GeneratedCreditCardBubbleController* GeneratedCreditCardView::
+    GetController() const {
+  content::WebContents* wc = delegate_->GetWebContents();
+  if (!wc || toolbar_model_->GetInputInProgress())
+    return NULL;
+
+  return autofill::GeneratedCreditCardBubbleController::FromWebContents(wc);
+}
diff --git a/chrome/browser/ui/views/location_bar/generated_credit_card_view.h b/chrome/browser/ui/views/location_bar/generated_credit_card_view.h
new file mode 100644
index 0000000..c741985
--- /dev/null
+++ b/chrome/browser/ui/views/location_bar/generated_credit_card_view.h
@@ -0,0 +1,54 @@
+// 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_UI_VIEWS_LOCATION_BAR_GENERATED_CREDIT_CARD_VIEW_H_
+#define CHROME_BROWSER_UI_VIEWS_LOCATION_BAR_GENERATED_CREDIT_CARD_VIEW_H_
+
+#include "base/basictypes.h"
+#include "base/compiler_specific.h"
+#include "chrome/browser/ui/autofill/generated_credit_card_bubble_controller.h"
+#include "chrome/browser/ui/views/location_bar/location_bar_decoration_view.h"
+#include "chrome/browser/ui/views/location_bar/location_bar_view.h"
+#include "ui/views/controls/image_view.h"
+
+class ToolbarModel;
+
+namespace autofill {
+class GeneratedCreditCardBubbleController;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// GeneratedCreditCardView
+//
+//  An icon that shows up in the omnibox after successfully generating a credit
+//  card number. Used as an anchor and click target to show the associated
+//  bubble with more details about the credit cards saved or used.
+//
+////////////////////////////////////////////////////////////////////////////////
+class GeneratedCreditCardView : public LocationBarDecorationView {
+ public:
+  GeneratedCreditCardView(ToolbarModel* toolbar_model,
+                         LocationBarView::Delegate* delegate);
+  virtual ~GeneratedCreditCardView();
+
+  void Update();
+
+ protected:
+  // LocationBarDecorationView:
+  virtual bool CanHandleClick() const OVERRIDE;
+  virtual void OnClick() OVERRIDE;
+
+ private:
+  // Helper to get the GeneratedCreditCardBubbleController associated with the
+  // current web contents.
+  autofill::GeneratedCreditCardBubbleController* GetController() const;
+
+  ToolbarModel* toolbar_model_;  // weak; outlives us.
+  LocationBarView::Delegate* delegate_;  // weak; outlives us.
+
+  DISALLOW_COPY_AND_ASSIGN(GeneratedCreditCardView);
+};
+
+#endif  // CHROME_BROWSER_UI_VIEWS_LOCATION_BAR_GENERATED_CREDIT_CARD_VIEW_H_
diff --git a/chrome/browser/ui/views/location_bar/location_bar_decoration_view.cc b/chrome/browser/ui/views/location_bar/location_bar_decoration_view.cc
index 443e368..c0bf64c 100644
--- a/chrome/browser/ui/views/location_bar/location_bar_decoration_view.cc
+++ b/chrome/browser/ui/views/location_bar/location_bar_decoration_view.cc
@@ -4,12 +4,13 @@
 
 #include "chrome/browser/ui/views/location_bar/location_bar_decoration_view.h"
 
+#include "chrome/browser/ui/views/location_bar/location_bar_view.h"
 #include "ui/base/events/event.h"
 
 LocationBarDecorationView::LocationBarDecorationView()
     : could_handle_click_(true) {
   set_accessibility_focusable(true);
-  TouchableLocationBarView::Init(this);
+  LocationBarView::InitTouchableLocationBarChildView(this);
 }
 
 LocationBarDecorationView::~LocationBarDecorationView() {}
@@ -48,10 +49,6 @@
   }
 }
 
-int LocationBarDecorationView::GetBuiltInHorizontalPadding() const {
-  return GetBuiltInHorizontalPaddingImpl();
-}
-
 bool LocationBarDecorationView::CanHandleClick() const {
   return true;
 }
diff --git a/chrome/browser/ui/views/location_bar/location_bar_decoration_view.h b/chrome/browser/ui/views/location_bar/location_bar_decoration_view.h
index 58e69db..117417b 100644
--- a/chrome/browser/ui/views/location_bar/location_bar_decoration_view.h
+++ b/chrome/browser/ui/views/location_bar/location_bar_decoration_view.h
@@ -7,7 +7,6 @@
 
 #include "base/basictypes.h"
 #include "base/compiler_specific.h"
-#include "chrome/browser/ui/views/location_bar/touchable_location_bar_view.h"
 #include "ui/views/controls/image_view.h"
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -18,8 +17,7 @@
 //  in the omnibox (like the bookmarks star or SSL lock).
 //
 ////////////////////////////////////////////////////////////////////////////////
-class LocationBarDecorationView : public views::ImageView,
-                                  public TouchableLocationBarView {
+class LocationBarDecorationView : public views::ImageView {
  public:
   LocationBarDecorationView();
   virtual ~LocationBarDecorationView();
@@ -30,9 +28,6 @@
   virtual bool OnKeyPressed(const ui::KeyEvent& event) OVERRIDE;
   virtual void OnGestureEvent(ui::GestureEvent* event) OVERRIDE;
 
-  // TouchableLocationBarView:
-  virtual int GetBuiltInHorizontalPadding() const OVERRIDE;
-
  protected:
   // Whether this icon should currently be able to process a mouse click. Called
   // both on mouse up and mouse down; must return true both times to for
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 72a84ce..64bdc85 100644
--- a/chrome/browser/ui/views/location_bar/location_bar_view.cc
+++ b/chrome/browser/ui/views/location_bar/location_bar_view.cc
@@ -38,13 +38,12 @@
 #include "chrome/browser/ui/views/bookmarks/bookmark_prompt_view.h"
 #include "chrome/browser/ui/views/browser_dialogs.h"
 #include "chrome/browser/ui/views/extensions/extension_popup.h"
-#include "chrome/browser/ui/views/location_bar/autofill_credit_card_view.h"
 #include "chrome/browser/ui/views/location_bar/content_setting_image_view.h"
 #include "chrome/browser/ui/views/location_bar/ev_bubble_view.h"
+#include "chrome/browser/ui/views/location_bar/generated_credit_card_view.h"
 #include "chrome/browser/ui/views/location_bar/keyword_hint_view.h"
 #include "chrome/browser/ui/views/location_bar/location_bar_layout.h"
 #include "chrome/browser/ui/views/location_bar/location_icon_view.h"
-#include "chrome/browser/ui/views/location_bar/mic_search_view.h"
 #include "chrome/browser/ui/views/location_bar/open_pdf_in_reader_view.h"
 #include "chrome/browser/ui/views/location_bar/page_action_image_view.h"
 #include "chrome/browser/ui/views/location_bar/page_action_with_badge_view.h"
@@ -79,6 +78,7 @@
 #include "ui/views/background.h"
 #include "ui/views/border.h"
 #include "ui/views/button_drag_utils.h"
+#include "ui/views/controls/button/image_button.h"
 #include "ui/views/controls/label.h"
 #include "ui/views/controls/textfield/textfield.h"
 #include "ui/views/widget/widget.h"
@@ -185,7 +185,7 @@
       keyword_hint_view_(NULL),
       mic_search_view_(NULL),
       zoom_view_(NULL),
-      autofill_credit_card_view_(NULL),
+      generated_credit_card_view_(NULL),
       open_pdf_in_reader_view_(NULL),
       script_bubble_icon_view_(NULL),
       star_view_(NULL),
@@ -227,6 +227,15 @@
     browser_->search_model()->RemoveObserver(this);
 }
 
+// static
+void LocationBarView::InitTouchableLocationBarChildView(views::View* view) {
+  int horizontal_padding = GetBuiltInHorizontalPaddingForChildViews();
+  if (horizontal_padding != 0) {
+    view->set_border(views::Border::CreateEmptyBorder(
+        3, horizontal_padding, 3, horizontal_padding));
+  }
+}
+
 void LocationBarView::Init() {
   // We need to be in a Widget, otherwise GetNativeTheme() may change and we're
   // not prepared for that.
@@ -314,8 +323,19 @@
       background_color);
   AddChildView(keyword_hint_view_);
 
-  mic_search_view_ = new MicSearchView(this);
+  mic_search_view_ = new views::ImageButton(this);
+  mic_search_view_->set_id(VIEW_ID_MIC_SEARCH_BUTTON);
+  mic_search_view_->set_accessibility_focusable(true);
+  mic_search_view_->SetTooltipText(
+      l10n_util::GetStringUTF16(IDS_TOOLTIP_MIC_SEARCH));
+  mic_search_view_->SetImage(
+      views::Button::STATE_NORMAL,
+      ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed(
+          IDR_OMNIBOX_MIC_SEARCH));
+  mic_search_view_->SetImageAlignment(views::ImageButton::ALIGN_CENTER,
+                                      views::ImageButton::ALIGN_MIDDLE);
   mic_search_view_->SetVisible(false);
+  InitTouchableLocationBarChildView(mic_search_view_);
   AddChildView(mic_search_view_);
 
   for (int i = 0; i < CONTENT_SETTINGS_NUM_TYPES; ++i) {
@@ -328,8 +348,8 @@
     AddChildView(content_blocked_view);
   }
 
-  autofill_credit_card_view_ = new AutofillCreditCardView(model_, delegate_);
-  AddChildView(autofill_credit_card_view_);
+  generated_credit_card_view_ = new GeneratedCreditCardView(model_, delegate_);
+  AddChildView(generated_credit_card_view_);
 
   zoom_view_ = new ZoomView(model_, delegate_);
   zoom_view_->set_id(VIEW_ID_ZOOM_BUTTON);
@@ -467,7 +487,7 @@
       !model_->GetInputInProgress() && browser_ &&
       browser_->search_model()->voice_search_supported());
   RefreshContentSettingViews();
-  autofill_credit_card_view_->Update();
+  generated_credit_card_view_->Update();
   ZoomBubbleView::CloseBubble();
   RefreshZoomView();
   RefreshPageActionViews();
@@ -530,8 +550,8 @@
   SchedulePaint();
 }
 
-void LocationBarView::UpdateAutofillCreditCardView() {
-  autofill_credit_card_view_->Update();
+void LocationBarView::UpdateGeneratedCreditCardView() {
+  generated_credit_card_view_->Update();
   Layout();
   SchedulePaint();
 }
@@ -716,25 +736,25 @@
   } else {
     leading_decorations.AddDecoration(
         vertical_edge_thickness(), location_height,
-        location_icon_view_->GetBuiltInHorizontalPadding(),
+        GetBuiltInHorizontalPaddingForChildViews(),
         location_icon_view_);
   }
 
   if (star_view_ && star_view_->visible()) {
     trailing_decorations.AddDecoration(
         vertical_edge_thickness(), location_height,
-        star_view_->GetBuiltInHorizontalPadding(), star_view_);
+        GetBuiltInHorizontalPaddingForChildViews(), star_view_);
   }
   if (script_bubble_icon_view_ && script_bubble_icon_view_->visible()) {
     trailing_decorations.AddDecoration(
         vertical_edge_thickness(), location_height,
-        script_bubble_icon_view_->GetBuiltInHorizontalPadding(),
+        GetBuiltInHorizontalPaddingForChildViews(),
         script_bubble_icon_view_);
   }
   if (open_pdf_in_reader_view_ && open_pdf_in_reader_view_->visible()) {
     trailing_decorations.AddDecoration(
         vertical_edge_thickness(), location_height,
-        open_pdf_in_reader_view_->GetBuiltInHorizontalPadding(),
+        GetBuiltInHorizontalPaddingForChildViews(),
         open_pdf_in_reader_view_);
   }
   for (PageActionViews::const_iterator i(page_action_views_.begin());
@@ -742,7 +762,7 @@
     if ((*i)->visible()) {
       trailing_decorations.AddDecoration(
           vertical_edge_thickness(), location_height,
-          (*i)->GetBuiltInHorizontalPadding(), (*i));
+          GetBuiltInHorizontalPaddingForChildViews(), (*i));
     }
   }
   if (zoom_view_->visible()) {
@@ -755,13 +775,13 @@
     if ((*i)->visible()) {
       trailing_decorations.AddDecoration(
           bubble_location_y, bubble_height, false, 0, item_padding,
-          item_padding, (*i)->GetBuiltInHorizontalPadding(), (*i));
+          item_padding, GetBuiltInHorizontalPaddingForChildViews(), (*i));
     }
   }
-  if (autofill_credit_card_view_->visible()) {
+  if (generated_credit_card_view_->visible()) {
     trailing_decorations.AddDecoration(vertical_edge_thickness(),
                                        location_height, 0,
-                                       autofill_credit_card_view_);
+                                       generated_credit_card_view_);
   }
   if (mic_search_view_->visible()) {
     trailing_decorations.AddDecoration(vertical_edge_thickness(),
@@ -993,8 +1013,8 @@
 }
 #endif
 
-views::View* LocationBarView::autofill_credit_card_view() {
-  return autofill_credit_card_view_;
+views::View* LocationBarView::generated_credit_card_view() {
+  return generated_credit_card_view_;
 }
 
 void LocationBarView::OnAutocompleteAccept(
@@ -1078,8 +1098,10 @@
   return delegate_->GetWebContents();
 }
 
-gfx::Rect LocationBarView::GetOmniboxBounds() const {
-  return bounds();
+// static
+int LocationBarView::GetBuiltInHorizontalPaddingForChildViews() {
+  return (ui::GetDisplayLayout() == ui::LAYOUT_TOUCH) ?
+      GetItemPadding() / 2 : 0;
 }
 
 int LocationBarView::GetHorizontalEdgeThickness() const {
@@ -1237,8 +1259,8 @@
        page_action_view != page_action_views_.end();
        ++page_action_view) {
     gfx::Rect bounds = (*page_action_view)->bounds();
-    int horizontal_padding = GetItemPadding() -
-        (*page_action_view)->GetBuiltInHorizontalPadding();
+    int horizontal_padding =
+        GetItemPadding() - GetBuiltInHorizontalPaddingForChildViews();
     // Make the bounding rectangle include the whole vertical range of the
     // location bar, and the mid-point pixels between adjacent page actions.
     //
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 96151da..2c14ff7 100644
--- a/chrome/browser/ui/views/location_bar/location_bar_view.h
+++ b/chrome/browser/ui/views/location_bar/location_bar_view.h
@@ -32,17 +32,16 @@
 #endif
 
 class ActionBoxButtonView;
-class AutofillCreditCardView;
 class CommandUpdater;
 class ContentSettingBubbleModelDelegate;
 class ContentSettingImageView;
 class EVBubbleView;
 class ExtensionAction;
 class GURL;
+class GeneratedCreditCardView;
 class InstantController;
 class KeywordHintView;
 class LocationIconView;
-class MicSearchView;
 class OpenPDFInReaderView;
 class PageActionWithBadgeView;
 class PageActionImageView;
@@ -55,6 +54,7 @@
 
 namespace views {
 class BubbleDelegateView;
+class ImageButton;
 class Label;
 class Widget;
 }
@@ -140,6 +140,12 @@
 
   virtual ~LocationBarView();
 
+  // Uses GetBuiltInHorizontalPaddingForChildViews() to optionally add
+  // additional padding (via an empty border) to |view|. This should be called
+  // during creation on all child views which are potentially touchable so that
+  // when touch is enabled they will have sufficient padding.
+  static void InitTouchableLocationBarChildView(views::View* view);
+
   // Initializes the LocationBarView.
   void Init();
 
@@ -245,7 +251,7 @@
 
   views::View* location_entry_view() const { return location_entry_view_; }
 
-  views::View* autofill_credit_card_view();
+  views::View* generated_credit_card_view();
 
   // OmniboxEditController:
   virtual void OnAutocompleteAccept(const GURL& url,
@@ -261,7 +267,6 @@
   virtual string16 GetTitle() const OVERRIDE;
   virtual InstantController* GetInstant() OVERRIDE;
   virtual content::WebContents* GetWebContents() const OVERRIDE;
-  virtual gfx::Rect GetOmniboxBounds() const OVERRIDE;
 
   // views::View:
   virtual const char* GetClassName() const OVERRIDE;
@@ -297,7 +302,7 @@
   virtual void UpdatePageActions() OVERRIDE;
   virtual void InvalidatePageActions() OVERRIDE;
   virtual void UpdateOpenPDFInReaderPrompt() OVERRIDE;
-  virtual void UpdateAutofillCreditCardView() OVERRIDE;
+  virtual void UpdateGeneratedCreditCardView() OVERRIDE;
   virtual void SaveStateToContents(content::WebContents* contents) OVERRIDE;
   virtual void Revert() OVERRIDE;
   virtual const OmniboxView* GetLocationEntry() const OVERRIDE;
@@ -333,11 +338,10 @@
   // Returns the position and width that the popup should be, and also the left
   // edge that the results should align themselves to (which will leave some
   // border on the left of the popup).
-  void GetOmniboxPopupPositioningInfo(
-      gfx::Point* top_left_screen_coord,
-      int* popup_width,
-      int* left_margin,
-      int* right_margin);
+  void GetOmniboxPopupPositioningInfo(gfx::Point* top_left_screen_coord,
+                                      int* popup_width,
+                                      int* left_margin,
+                                      int* right_margin);
 
   // Space between items in the location bar, as well as between items and the
   // edges.
@@ -362,6 +366,11 @@
   friend class PageActionWithBadgeView;
   typedef std::vector<PageActionWithBadgeView*> PageActionViews;
 
+  // Returns the number of pixels of built-in padding to the left and right for
+  // child views. This is nonzero when touch UI is enabled so as to space out
+  // child views for easier targeting. See InitTouchableLocationBarChildView().
+  static int GetBuiltInHorizontalPaddingForChildViews();
+
   // Returns the thickness of any visible left and right edge, in pixels.
   int GetHorizontalEdgeThickness() const;
 
@@ -475,7 +484,7 @@
   KeywordHintView* keyword_hint_view_;
 
   // The voice search icon.
-  MicSearchView* mic_search_view_;
+  views::ImageButton* mic_search_view_;
 
   // The content setting views.
   ContentSettingViews content_setting_views_;
@@ -483,8 +492,8 @@
   // The zoom icon.
   ZoomView* zoom_view_;
 
-  // A bubble that shows after successful submission of the Autofill dialog.
-  AutofillCreditCardView* autofill_credit_card_view_;
+  // A bubble that shows after successfully generating a new credit card number.
+  GeneratedCreditCardView* generated_credit_card_view_;
 
   // The icon to open a PDF in Reader.
   OpenPDFInReaderView* open_pdf_in_reader_view_;
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 1772e91..0526b6a 100644
--- a/chrome/browser/ui/views/location_bar/location_icon_view.cc
+++ b/chrome/browser/ui/views/location_bar/location_icon_view.cc
@@ -5,13 +5,14 @@
 #include "chrome/browser/ui/views/location_bar/location_icon_view.h"
 
 #include "base/strings/utf_string_conversions.h"
+#include "chrome/browser/ui/views/location_bar/location_bar_view.h"
 #include "grit/generated_resources.h"
 #include "ui/base/l10n/l10n_util.h"
 
 LocationIconView::LocationIconView(LocationBarView* location_bar)
     : page_info_helper_(this, location_bar) {
   SetTooltipText(l10n_util::GetStringUTF16(IDS_TOOLTIP_LOCATION_ICON));
-  TouchableLocationBarView::Init(this);
+  LocationBarView::InitTouchableLocationBarChildView(this);
 }
 
 LocationIconView::~LocationIconView() {
@@ -34,14 +35,7 @@
   }
 }
 
-int LocationIconView::GetBuiltInHorizontalPadding() const {
-  return GetBuiltInHorizontalPaddingImpl();
-}
-
 void LocationIconView::ShowTooltip(bool show) {
-  if (show) {
-    SetTooltipText(l10n_util::GetStringUTF16(IDS_TOOLTIP_LOCATION_ICON));
-  } else {
-    SetTooltipText(string16());
-  }
+  SetTooltipText(show ?
+      l10n_util::GetStringUTF16(IDS_TOOLTIP_LOCATION_ICON) : base::string16());
 }
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 ba12c5f..2d6ad0c 100644
--- a/chrome/browser/ui/views/location_bar/location_icon_view.h
+++ b/chrome/browser/ui/views/location_bar/location_icon_view.h
@@ -6,7 +6,6 @@
 #define CHROME_BROWSER_UI_VIEWS_LOCATION_BAR_LOCATION_ICON_VIEW_H_
 
 #include "chrome/browser/ui/views/location_bar/page_info_helper.h"
-#include "chrome/browser/ui/views/location_bar/touchable_location_bar_view.h"
 #include "ui/views/controls/image_view.h"
 
 class LocationBarView;
@@ -14,22 +13,18 @@
 // LocationIconView is used to display an icon to the left of the edit field.
 // This shows the user's current action while editing, the page security
 // status on https pages, or a globe for other URLs.
-class LocationIconView : public views::ImageView,
-                         public TouchableLocationBarView {
+class LocationIconView : public views::ImageView {
  public:
   explicit LocationIconView(LocationBarView* location_bar);
   virtual ~LocationIconView();
 
-  // Overridden from views::ImageView:
+  // views::ImageView:
   virtual bool OnMousePressed(const ui::MouseEvent& event) OVERRIDE;
   virtual void OnMouseReleased(const ui::MouseEvent& event) OVERRIDE;
 
-  // Overridden from ui::EventHandler:
+  // ui::EventHandler:
   virtual void OnGestureEvent(ui::GestureEvent* event) OVERRIDE;
 
-  // TouchableLocationBarView.
-  virtual int GetBuiltInHorizontalPadding() const OVERRIDE;
-
   // Whether we should show the tooltip for this icon or not.
   void ShowTooltip(bool show);
 
diff --git a/chrome/browser/ui/views/location_bar/mic_search_view.cc b/chrome/browser/ui/views/location_bar/mic_search_view.cc
deleted file mode 100644
index 31f67d6..0000000
--- a/chrome/browser/ui/views/location_bar/mic_search_view.cc
+++ /dev/null
@@ -1,31 +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/ui/views/location_bar/mic_search_view.h"
-
-#include "chrome/browser/ui/view_ids.h"
-#include "grit/generated_resources.h"
-#include "grit/theme_resources.h"
-#include "ui/base/accessibility/accessible_view_state.h"
-#include "ui/base/l10n/l10n_util.h"
-#include "ui/base/resource/resource_bundle.h"
-
-MicSearchView::MicSearchView(views::ButtonListener* button_listener)
-    : views::ImageButton(button_listener) {
-  set_id(VIEW_ID_MIC_SEARCH_BUTTON);
-  set_accessibility_focusable(true);
-  SetTooltipText(l10n_util::GetStringUTF16(IDS_TOOLTIP_MIC_SEARCH));
-  SetImage(STATE_NORMAL,
-           ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed(
-               IDR_OMNIBOX_MIC_SEARCH));
-  SetImageAlignment(ALIGN_CENTER, ALIGN_MIDDLE);
-  TouchableLocationBarView::Init(this);
-}
-
-MicSearchView::~MicSearchView() {
-}
-
-int MicSearchView::GetBuiltInHorizontalPadding() const {
-  return GetBuiltInHorizontalPaddingImpl();
-}
diff --git a/chrome/browser/ui/views/location_bar/mic_search_view.h b/chrome/browser/ui/views/location_bar/mic_search_view.h
deleted file mode 100644
index 30159a7..0000000
--- a/chrome/browser/ui/views/location_bar/mic_search_view.h
+++ /dev/null
@@ -1,26 +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_UI_VIEWS_LOCATION_BAR_MIC_SEARCH_VIEW_H_
-#define CHROME_BROWSER_UI_VIEWS_LOCATION_BAR_MIC_SEARCH_VIEW_H_
-
-#include "chrome/browser/ui/views/location_bar/touchable_location_bar_view.h"
-#include "ui/views/controls/button/image_button.h"
-
-class CommandUpdater;
-
-class MicSearchView : public views::ImageButton,
-                      public TouchableLocationBarView {
- public:
-  explicit MicSearchView(views::ButtonListener* button_listener);
-  virtual ~MicSearchView();
-
-  // TouchableLocationBarView:
-  virtual int GetBuiltInHorizontalPadding() const OVERRIDE;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(MicSearchView);
-};
-
-#endif  // CHROME_BROWSER_UI_VIEWS_LOCATION_BAR_MIC_SEARCH_VIEW_H_
diff --git a/chrome/browser/ui/views/location_bar/open_pdf_in_reader_view.cc b/chrome/browser/ui/views/location_bar/open_pdf_in_reader_view.cc
index dc3a005..33607ad 100644
--- a/chrome/browser/ui/views/location_bar/open_pdf_in_reader_view.cc
+++ b/chrome/browser/ui/views/location_bar/open_pdf_in_reader_view.cc
@@ -5,6 +5,7 @@
 #include "chrome/browser/ui/views/location_bar/open_pdf_in_reader_view.h"
 
 #include "chrome/browser/ui/pdf/pdf_tab_helper.h"
+#include "chrome/browser/ui/views/location_bar/location_bar_view.h"
 #include "chrome/browser/ui/views/open_pdf_in_reader_bubble_view.h"
 #include "grit/generated_resources.h"
 #include "grit/theme_resources.h"
@@ -18,12 +19,10 @@
       bubble_(NULL),
       model_(NULL) {
   set_accessibility_focusable(true);
-  SetImage(
-      ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed(
-          IDR_OMNIBOX_PDF_ICON));
-  SetTooltipText(
-      l10n_util::GetStringUTF16(IDS_PDF_BUBBLE_OPEN_IN_READER_LINK));
-  TouchableLocationBarView::Init(this);
+  SetImage(ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed(
+      IDR_OMNIBOX_PDF_ICON));
+  SetTooltipText(l10n_util::GetStringUTF16(IDS_PDF_BUBBLE_OPEN_IN_READER_LINK));
+  LocationBarView::InitTouchableLocationBarChildView(this);
 }
 
 OpenPDFInReaderView::~OpenPDFInReaderView() {
@@ -41,10 +40,6 @@
   SetVisible(!!model_);
 }
 
-int OpenPDFInReaderView::GetBuiltInHorizontalPadding() const {
-  return GetBuiltInHorizontalPaddingImpl();
-}
-
 void OpenPDFInReaderView::ShowBubble() {
   if (bubble_)
     return;
diff --git a/chrome/browser/ui/views/location_bar/open_pdf_in_reader_view.h b/chrome/browser/ui/views/location_bar/open_pdf_in_reader_view.h
index da90fbc..867e8d8 100644
--- a/chrome/browser/ui/views/location_bar/open_pdf_in_reader_view.h
+++ b/chrome/browser/ui/views/location_bar/open_pdf_in_reader_view.h
@@ -5,7 +5,6 @@
 #ifndef CHROME_BROWSER_UI_VIEWS_LOCATION_BAR_OPEN_PDF_IN_READER_VIEW_H_
 #define CHROME_BROWSER_UI_VIEWS_LOCATION_BAR_OPEN_PDF_IN_READER_VIEW_H_
 
-#include "chrome/browser/ui/views/location_bar/touchable_location_bar_view.h"
 #include "ui/views/controls/image_view.h"
 #include "ui/views/widget/widget_observer.h"
 
@@ -19,27 +18,23 @@
 
 // A Page Action image view for the "Open PDF in Reader" bubble.
 class OpenPDFInReaderView : public views::ImageView,
-                            public TouchableLocationBarView,
-                            views::WidgetObserver {
+                            public views::WidgetObserver {
  public:
   explicit OpenPDFInReaderView(LocationBarView* location_bar_view);
   virtual ~OpenPDFInReaderView();
 
   void Update(content::WebContents* web_contents);
 
-  // TouchableLocationBarView overrides:
-  virtual int GetBuiltInHorizontalPadding() const OVERRIDE;
-
  private:
   void ShowBubble();
 
-  // views::ImageView overrides:
+  // views::ImageView:
   virtual void GetAccessibleState(ui::AccessibleViewState* state) OVERRIDE;
   virtual bool OnMousePressed(const ui::MouseEvent& event) OVERRIDE;
   virtual void OnMouseReleased(const ui::MouseEvent& event) OVERRIDE;
   virtual bool OnKeyPressed(const ui::KeyEvent& event) OVERRIDE;
 
-  // views::WidgetObserver override:
+  // views::WidgetObserver:
   virtual void OnWidgetDestroying(views::Widget* widget) OVERRIDE;
 
   // The LocationBarView hosting this view.
@@ -50,7 +45,7 @@
   // Weak pointer; owned by the PDFTabHelper of the currently active tab.
   OpenPDFInReaderPromptDelegate* model_;
 
-  DISALLOW_IMPLICIT_CONSTRUCTORS(OpenPDFInReaderView);
+  DISALLOW_COPY_AND_ASSIGN(OpenPDFInReaderView);
 };
 
 #endif  // CHROME_BROWSER_UI_VIEWS_LOCATION_BAR_OPEN_PDF_IN_READER_VIEW_H_
diff --git a/chrome/browser/ui/views/location_bar/page_action_with_badge_view.cc b/chrome/browser/ui/views/location_bar/page_action_with_badge_view.cc
index b148c8e..4bb9cca 100644
--- a/chrome/browser/ui/views/location_bar/page_action_with_badge_view.cc
+++ b/chrome/browser/ui/views/location_bar/page_action_with_badge_view.cc
@@ -4,6 +4,7 @@
 
 #include "chrome/browser/ui/views/location_bar/page_action_with_badge_view.h"
 
+#include "chrome/browser/ui/views/location_bar/location_bar_view.h"
 #include "chrome/browser/ui/views/location_bar/page_action_image_view.h"
 #include "chrome/common/extensions/manifest_handlers/icons_handler.h"
 #include "ui/base/accessibility/accessible_view_state.h"
@@ -14,7 +15,7 @@
     PageActionImageView* image_view) {
   image_view_ = image_view;
   AddChildView(image_view_);
-  TouchableLocationBarView::Init(this);
+  LocationBarView::InitTouchableLocationBarChildView(this);
 }
 
 void PageActionWithBadgeView::GetAccessibleState(
@@ -27,10 +28,6 @@
                    extensions::IconsInfo::kPageActionIconMaxSize);
 }
 
-int PageActionWithBadgeView::GetBuiltInHorizontalPadding() const {
-  return GetBuiltInHorizontalPaddingImpl();
-}
-
 void PageActionWithBadgeView::Layout() {
   // We have 25 pixels of vertical space in the Omnibox to play with, so even
   // sized icons (such as 16x16) have either a 5 or a 4 pixel whitespace
diff --git a/chrome/browser/ui/views/location_bar/page_action_with_badge_view.h b/chrome/browser/ui/views/location_bar/page_action_with_badge_view.h
index 7118b98..82cf0e0 100644
--- a/chrome/browser/ui/views/location_bar/page_action_with_badge_view.h
+++ b/chrome/browser/ui/views/location_bar/page_action_with_badge_view.h
@@ -6,7 +6,6 @@
 #define CHROME_BROWSER_UI_VIEWS_LOCATION_BAR_PAGE_ACTION_WITH_BADGE_VIEW_H_
 
 #include "base/compiler_specific.h"
-#include "chrome/browser/ui/views/location_bar/touchable_location_bar_view.h"
 #include "ui/gfx/size.h"
 #include "ui/views/view.h"
 
@@ -18,21 +17,16 @@
 }
 
 // A container for the PageActionImageView plus its badge.
-class PageActionWithBadgeView
-    : public views::View,
-      public TouchableLocationBarView {
+class PageActionWithBadgeView : public views::View {
  public:
   explicit PageActionWithBadgeView(PageActionImageView* image_view);
 
   PageActionImageView* image_view() { return image_view_; }
 
-  // View overrides:
+  // views::View:
   virtual void GetAccessibleState(ui::AccessibleViewState* state) OVERRIDE;
   virtual gfx::Size GetPreferredSize() OVERRIDE;
 
-  // TouchableLocationBarView.
-  virtual int GetBuiltInHorizontalPadding() const OVERRIDE;
-
   void UpdateVisibility(content::WebContents* contents, const GURL& url);
 
  private:
diff --git a/chrome/browser/ui/views/location_bar/script_bubble_icon_view.cc b/chrome/browser/ui/views/location_bar/script_bubble_icon_view.cc
index 92a8411..82952c5 100644
--- a/chrome/browser/ui/views/location_bar/script_bubble_icon_view.cc
+++ b/chrome/browser/ui/views/location_bar/script_bubble_icon_view.cc
@@ -25,16 +25,12 @@
   set_id(VIEW_ID_SCRIPT_BUBBLE);
   SetTooltipText(l10n_util::GetStringUTF16(IDS_TOOLTIP_SCRIPT_BUBBLE));
   set_accessibility_focusable(true);
-  TouchableLocationBarView::Init(this);
+  LocationBarView::InitTouchableLocationBarChildView(this);
 }
 
 ScriptBubbleIconView::~ScriptBubbleIconView() {
 }
 
-int ScriptBubbleIconView::GetBuiltInHorizontalPadding() const {
-  return GetBuiltInHorizontalPaddingImpl();
-}
-
 void ScriptBubbleIconView::SetScriptCount(size_t script_count) {
   script_count_ = script_count;
   gfx::ImageSkia* icon =
diff --git a/chrome/browser/ui/views/location_bar/script_bubble_icon_view.h b/chrome/browser/ui/views/location_bar/script_bubble_icon_view.h
index 2b72463..8e04e9e 100644
--- a/chrome/browser/ui/views/location_bar/script_bubble_icon_view.h
+++ b/chrome/browser/ui/views/location_bar/script_bubble_icon_view.h
@@ -6,38 +6,31 @@
 #define CHROME_BROWSER_UI_VIEWS_LOCATION_BAR_SCRIPT_BUBBLE_ICON_VIEW_H_
 
 #include "chrome/browser/ui/views/location_bar/location_bar_view.h"
-#include "chrome/browser/ui/views/location_bar/touchable_location_bar_view.h"
 #include "ui/views/controls/image_view.h"
 
-class CommandUpdater;
-
 // The ScriptBubbleIconView is the code behind the script bubble icon
 // that we show in the Omnibox badged with a number to represent how many
 // extensions are running content_scripts in the current page.
-class ScriptBubbleIconView : public views::ImageView,
-                             public TouchableLocationBarView {
+class ScriptBubbleIconView : public views::ImageView {
  public:
   explicit ScriptBubbleIconView(
       LocationBarView::Delegate* location_bar_delegate);
   virtual ~ScriptBubbleIconView();
 
-  // TouchableLocationBarView methods.
-  virtual int GetBuiltInHorizontalPadding() const OVERRIDE;
-
   // Updates the number shown on the script bubble icon.
   void SetScriptCount(size_t script_count);
 
  private:
-  // views::View methods.
+  // views::View:
   virtual void Layout() OVERRIDE;
 
-  // views::ImageView methods.
+  // views::ImageView:
   virtual void GetAccessibleState(ui::AccessibleViewState* state) OVERRIDE;
   virtual bool OnMousePressed(const ui::MouseEvent& event) OVERRIDE;
   virtual void OnMouseReleased(const ui::MouseEvent& event) OVERRIDE;
   virtual bool OnKeyPressed(const ui::KeyEvent& event) OVERRIDE;
 
-  // ui::EventHandler overrides:
+  // ui::EventHandler:
   virtual void OnGestureEvent(ui::GestureEvent* event) OVERRIDE;
 
   // Shows the script bubble, anchored to anchor_view.
@@ -50,7 +43,7 @@
   // The last reported script count.
   size_t script_count_;
 
-  DISALLOW_IMPLICIT_CONSTRUCTORS(ScriptBubbleIconView);
+  DISALLOW_COPY_AND_ASSIGN(ScriptBubbleIconView);
 };
 
 #endif  // CHROME_BROWSER_UI_VIEWS_LOCATION_BAR_SCRIPT_BUBBLE_ICON_VIEW_H_
diff --git a/chrome/browser/ui/views/location_bar/star_view.cc b/chrome/browser/ui/views/location_bar/star_view.cc
index d07328e..1bf0b70 100644
--- a/chrome/browser/ui/views/location_bar/star_view.cc
+++ b/chrome/browser/ui/views/location_bar/star_view.cc
@@ -11,6 +11,7 @@
 #include "chrome/browser/command_updater.h"
 #include "chrome/browser/ui/view_ids.h"
 #include "chrome/browser/ui/views/browser_dialogs.h"
+#include "chrome/browser/ui/views/location_bar/location_bar_view.h"
 #include "grit/generated_resources.h"
 #include "grit/theme_resources.h"
 #include "ui/base/accessibility/accessible_view_state.h"
@@ -24,16 +25,12 @@
   set_id(VIEW_ID_STAR_BUTTON);
   SetToggled(false);
   set_accessibility_focusable(true);
-  TouchableLocationBarView::Init(this);
+  LocationBarView::InitTouchableLocationBarChildView(this);
 }
 
 StarView::~StarView() {
 }
 
-int StarView::GetBuiltInHorizontalPadding() const {
-  return GetBuiltInHorizontalPaddingImpl();
-}
-
 void StarView::SetToggled(bool on) {
   SetTooltipText(l10n_util::GetStringUTF16(
       on ? IDS_TOOLTIP_STARRED : IDS_TOOLTIP_STAR));
diff --git a/chrome/browser/ui/views/location_bar/star_view.h b/chrome/browser/ui/views/location_bar/star_view.h
index bac32f0..a2c7b95 100644
--- a/chrome/browser/ui/views/location_bar/star_view.h
+++ b/chrome/browser/ui/views/location_bar/star_view.h
@@ -5,19 +5,15 @@
 #ifndef CHROME_BROWSER_UI_VIEWS_LOCATION_BAR_STAR_VIEW_H_
 #define CHROME_BROWSER_UI_VIEWS_LOCATION_BAR_STAR_VIEW_H_
 
-#include "chrome/browser/ui/views/location_bar/touchable_location_bar_view.h"
 #include "ui/views/controls/image_view.h"
 
 class CommandUpdater;
 
-class StarView : public views::ImageView, public TouchableLocationBarView {
+class StarView : public views::ImageView {
  public:
   explicit StarView(CommandUpdater* command_updater);
   virtual ~StarView();
 
-  // TouchableLocationBarView:
-  virtual int GetBuiltInHorizontalPadding() const OVERRIDE;
-
   // Toggles the star on or off.
   void SetToggled(bool on);
 
@@ -30,7 +26,7 @@
   virtual void OnMouseReleased(const ui::MouseEvent& event) OVERRIDE;
   virtual bool OnKeyPressed(const ui::KeyEvent& event) OVERRIDE;
 
-  // ui::EventHandler overrides:
+  // ui::EventHandler:
   virtual void OnGestureEvent(ui::GestureEvent* event) OVERRIDE;
 
   // The CommandUpdater for the Browser object that owns the location bar.
diff --git a/chrome/browser/ui/views/location_bar/touchable_location_bar_view.cc b/chrome/browser/ui/views/location_bar/touchable_location_bar_view.cc
deleted file mode 100644
index 26c222e..0000000
--- a/chrome/browser/ui/views/location_bar/touchable_location_bar_view.cc
+++ /dev/null
@@ -1,24 +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/ui/views/location_bar/touchable_location_bar_view.h"
-
-#include "chrome/browser/ui/views/location_bar/location_bar_view.h"
-#include "ui/base/layout.h"
-#include "ui/views/border.h"
-
-// static
-void TouchableLocationBarView::Init(views::View* view) {
-  int horizontal_padding = GetBuiltInHorizontalPaddingImpl();
-  if (horizontal_padding != 0) {
-    view->set_border(views::Border::CreateEmptyBorder(
-        3, horizontal_padding, 3, horizontal_padding));
-  }
-}
-
-// static
-int TouchableLocationBarView::GetBuiltInHorizontalPaddingImpl() {
-  return ui::GetDisplayLayout() == ui::LAYOUT_TOUCH ?
-      LocationBarView::GetItemPadding() / 2 : 0;
-}
diff --git a/chrome/browser/ui/views/location_bar/touchable_location_bar_view.h b/chrome/browser/ui/views/location_bar/touchable_location_bar_view.h
deleted file mode 100644
index aaba2b9..0000000
--- a/chrome/browser/ui/views/location_bar/touchable_location_bar_view.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_BROWSER_UI_VIEWS_LOCATION_BAR_TOUCHABLE_LOCATION_BAR_VIEW_H_
-#define CHROME_BROWSER_UI_VIEWS_LOCATION_BAR_TOUCHABLE_LOCATION_BAR_VIEW_H_
-
-#include "ui/views/view.h"
-
-// An interface for a View in within the LocationBar that knows how to
-// increase its size (without affecting visual layout) in a touch
-// layout, to increase the size of the touch target.  Its border
-// extends a few pixels up and down, which doesn't affect layout, and
-// extends half of the padding used between items in the location bar
-// to the left and right.
-//
-// To make your location bar View extend itself into the padding
-// around it to get an enlarged touch target, inherit from
-// TouchableLocationBarView interface, implement its
-// GetBuiltInHorizontalPadding method by calling
-// GetBuiltInHorizontalPaddingImpl, and call
-// TouchableLocationBarView::Init() from your constructor.
-class TouchableLocationBarView {
- public:
-  // Returns the number of pixels of built-in padding to the left and
-  // right of the image for this view.
-  virtual int GetBuiltInHorizontalPadding() const = 0;
-
- protected:
-  // Call this from the constructor (or during early initialization)
-  // of a class that inherits from TouchableLocationBarView.
-  static void Init(views::View* view);
-
-  // Use this to implement GetBuiltInHorizontalPadding().
-  static int GetBuiltInHorizontalPaddingImpl();
-};
-
-#endif  // CHROME_BROWSER_UI_VIEWS_LOCATION_BAR_TOUCHABLE_LOCATION_BAR_VIEW_H_
diff --git a/chrome/browser/ui/views/location_bar/zoom_view.cc b/chrome/browser/ui/views/location_bar/zoom_view.cc
index 2a1c39d..34b432a 100644
--- a/chrome/browser/ui/views/location_bar/zoom_view.cc
+++ b/chrome/browser/ui/views/location_bar/zoom_view.cc
@@ -22,7 +22,7 @@
       location_bar_delegate_(location_bar_delegate) {
   set_accessibility_focusable(true);
   Update(NULL);
-  TouchableLocationBarView::Init(this);
+  LocationBarView::InitTouchableLocationBarChildView(this);
 }
 
 ZoomView::~ZoomView() {
@@ -80,10 +80,6 @@
   }
 }
 
-int ZoomView::GetBuiltInHorizontalPadding() const {
-  return GetBuiltInHorizontalPaddingImpl();
-}
-
 void ZoomView::ActivateBubble() {
   ZoomBubbleView::ShowBubble(location_bar_delegate_->GetWebContents(), false);
 }
diff --git a/chrome/browser/ui/views/location_bar/zoom_view.h b/chrome/browser/ui/views/location_bar/zoom_view.h
index 4610f81..bc3876d 100644
--- a/chrome/browser/ui/views/location_bar/zoom_view.h
+++ b/chrome/browser/ui/views/location_bar/zoom_view.h
@@ -8,15 +8,13 @@
 #include "base/basictypes.h"
 #include "base/compiler_specific.h"
 #include "chrome/browser/ui/views/location_bar/location_bar_view.h"
-#include "chrome/browser/ui/views/location_bar/touchable_location_bar_view.h"
 #include "ui/views/controls/image_view.h"
 
 class ToolbarModel;
 class ZoomController;
 
 // View for the zoom icon in the Omnibox.
-class ZoomView : public views::ImageView,
-                 public TouchableLocationBarView {
+class ZoomView : public views::ImageView {
  public:
   // Clicking on the ZoomView shows a ZoomBubbleView, which requires the current
   // WebContents. Because the current WebContents changes as the user switches
@@ -43,9 +41,6 @@
   // ui::EventHandler:
   virtual void OnGestureEvent(ui::GestureEvent* event) OVERRIDE;
 
-  // TouchableLocationBarView.
-  virtual int GetBuiltInHorizontalPadding() const OVERRIDE;
-
   // Helper method to show and focus the zoom bubble associated with this
   // widget.
   void ActivateBubble();
diff --git a/chrome/browser/ui/views/message_center/web_notification_tray.cc b/chrome/browser/ui/views/message_center/web_notification_tray.cc
index b3faf1a..5fcf10a 100644
--- a/chrome/browser/ui/views/message_center/web_notification_tray.cc
+++ b/chrome/browser/ui/views/message_center/web_notification_tray.cc
@@ -132,7 +132,6 @@
       should_update_tray_content_(true) {
   message_center_tray_.reset(
       new MessageCenterTray(this, g_browser_process->message_center()));
-  OnMessageCenterTrayChanged();
 }
 
 WebNotificationTray::~WebNotificationTray() {
diff --git a/chrome/browser/ui/views/omnibox/omnibox_popup_contents_view.cc b/chrome/browser/ui/views/omnibox/omnibox_popup_contents_view.cc
index c5dfb4b..2d9094d 100644
--- a/chrome/browser/ui/views/omnibox/omnibox_popup_contents_view.cc
+++ b/chrome/browser/ui/views/omnibox/omnibox_popup_contents_view.cc
@@ -6,7 +6,6 @@
 
 #include "chrome/browser/search/search.h"
 #include "chrome/browser/themes/theme_properties.h"
-#include "chrome/browser/ui/omnibox/omnibox_popup_non_view.h"
 #include "chrome/browser/ui/omnibox/omnibox_view.h"
 #include "chrome/browser/ui/views/location_bar/location_bar_view.h"
 #include "chrome/browser/ui/views/omnibox/omnibox_result_view.h"
@@ -57,11 +56,6 @@
     OmniboxView* omnibox_view,
     OmniboxEditModel* edit_model,
     LocationBarView* location_bar_view) {
-#if defined(HTML_INSTANT_EXTENDED_POPUP)
-  if (chrome::IsInstantExtendedAPIEnabled())
-    return new OmniboxPopupNonView(edit_model);
-#endif
-
   OmniboxPopupContentsView* view = NULL;
   if (ui::GetDisplayLayout() == ui::LAYOUT_TOUCH) {
     view = new TouchOmniboxPopupContentsView(
@@ -165,7 +159,8 @@
 }
 
 void OmniboxPopupContentsView::UpdatePopupAppearance() {
-  if (model_->result().empty() ||
+  const size_t hidden_matches = model_->result().ShouldHideTopMatch() ? 1 : 0;
+  if (model_->result().size() <= hidden_matches ||
       omnibox_view_->IsImeShowingPopup()) {
     // No matches or the IME is showing a popup window which may overlap
     // the omnibox popup window.  Close any existing popup.
@@ -188,7 +183,7 @@
   for (size_t i = 0; i < result_size; ++i) {
     OmniboxResultView* view = result_view_at(i);
     view->SetMatch(GetMatchAtIndex(i));
-    view->SetVisible(true);
+    view->SetVisible(i >= hidden_matches);
   }
   for (size_t i = result_size; i < AutocompleteResult::kMaxMatches; ++i)
     child_at(i)->SetVisible(false);
@@ -393,7 +388,8 @@
 int OmniboxPopupContentsView::CalculatePopupHeight() {
   DCHECK_GE(static_cast<size_t>(child_count()), model_->result().size());
   int popup_height = 0;
-  for (size_t i = 0; i < model_->result().size(); ++i)
+  for (size_t i = model_->result().ShouldHideTopMatch() ? 1 : 0;
+       i < model_->result().size(); ++i)
     popup_height += child_at(i)->GetPreferredSize().height();
 
   // Add enough space on the top and bottom so it looks like there is the same
@@ -488,7 +484,7 @@
     views::View* child = child_at(i);
     gfx::Point point_in_child_coords(point);
     View::ConvertPointToTarget(this, child, &point_in_child_coords);
-    if (child->HitTestPoint(point_in_child_coords))
+    if (child->visible() && child->HitTestPoint(point_in_child_coords))
       return i;
   }
   return OmniboxPopupModel::kNoMatch;
diff --git a/chrome/browser/ui/views/profile_chooser_view.cc b/chrome/browser/ui/views/profile_chooser_view.cc
index afcd69f..af7ee91 100644
--- a/chrome/browser/ui/views/profile_chooser_view.cc
+++ b/chrome/browser/ui/views/profile_chooser_view.cc
@@ -119,7 +119,7 @@
   if (sender == guest_button_view_) {
     avatar_menu_model_->SwitchToGuestProfileWindow(browser_);
   } else if (sender == users_button_view_) {
-    chrome::ShowSingletonTab(browser_, GURL(chrome::kChromeUIUserChooserURL));
+    chrome::ShowSingletonTab(browser_, GURL(chrome::kChromeUIUserManagerURL));
   } else {
     DCHECK_EQ(sender, signout_current_profile_view_);
     avatar_menu_model_->BeginSignOut();
diff --git a/chrome/browser/ui/views/select_file_dialog_extension.cc b/chrome/browser/ui/views/select_file_dialog_extension.cc
index 538dbed..e3324aa 100644
--- a/chrome/browser/ui/views/select_file_dialog_extension.cc
+++ b/chrome/browser/ui/views/select_file_dialog_extension.cc
@@ -6,6 +6,7 @@
 
 #include "apps/native_app_window.h"
 #include "apps/shell_window.h"
+#include "apps/shell_window_registry.h"
 #include "base/bind.h"
 #include "base/callback.h"
 #include "base/logging.h"
@@ -17,7 +18,6 @@
 #include "chrome/browser/extensions/extension_host.h"
 #include "chrome/browser/extensions/extension_service.h"
 #include "chrome/browser/extensions/extension_system.h"
-#include "chrome/browser/extensions/shell_window_registry.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/sessions/session_tab_helper.h"
 #include "chrome/browser/ui/browser.h"
@@ -270,7 +270,7 @@
     if (!owner_browser) {
       // If an owner_window was supplied but we couldn't find a browser, this
       // could be for a shell window.
-      shell_window = extensions::ShellWindowRegistry::
+      shell_window = apps::ShellWindowRegistry::
           GetShellWindowForNativeWindowAnyProfile(owner_window);
     }
   }
diff --git a/chrome/browser/ui/views/tabs/tab.cc b/chrome/browser/ui/views/tabs/tab.cc
index f556be5..fde9889 100644
--- a/chrome/browser/ui/views/tabs/tab.cc
+++ b/chrome/browser/ui/views/tabs/tab.cc
@@ -238,6 +238,10 @@
 const SkColor kImmersiveActiveTabColor = SkColorSetRGB(235, 235, 235);
 const SkColor kImmersiveInactiveTabColor = SkColorSetRGB(190, 190, 190);
 
+// The minimum opacity (out of 1) when a tab (either active or inactive) is
+// throbbing in the immersive mode light strip.
+const double kImmersiveTabMinThrobOpacity = 0.66;
+
 // Number of steps in the immersive mode loading animation.
 const int kImmersiveLoadingStepCount = 32;
 
@@ -1115,9 +1119,13 @@
 
 void Tab::PaintImmersiveTab(gfx::Canvas* canvas) {
   // Use transparency for the draw-attention animation.
-  int alpha = (tab_animation_ && tab_animation_->is_animating())
-                  ? static_cast<int>(GetThrobValue() * 255)
-                  : 255;
+  int alpha = 255;
+  if (tab_animation_ &&
+      tab_animation_->is_animating() &&
+      !data().mini) {
+    alpha = tab_animation_->CurrentValueBetween(
+        255, static_cast<int>(255 * kImmersiveTabMinThrobOpacity));
+  }
 
   // Draw a gray rectangle to represent the tab. This works for mini-tabs as
   // well as regular ones. The active tab has a brigher bar.
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 abcf5f5..560c344 100644
--- a/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc
+++ b/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc
@@ -46,7 +46,7 @@
 #include "chrome/browser/ui/webui/profiler_ui.h"
 #include "chrome/browser/ui/webui/quota_internals/quota_internals_ui.h"
 #include "chrome/browser/ui/webui/signin/profile_signin_confirmation_ui.h"
-#include "chrome/browser/ui/webui/signin/user_chooser_ui.h"
+#include "chrome/browser/ui/webui/signin/user_manager_ui.h"
 #include "chrome/browser/ui/webui/signin_internals_ui.h"
 #include "chrome/browser/ui/webui/sync_internals_ui.h"
 #include "chrome/browser/ui/webui/translate_internals/translate_internals_ui.h"
@@ -104,6 +104,7 @@
 #include "chrome/browser/ui/webui/chromeos/proxy_settings_ui.h"
 #include "chrome/browser/ui/webui/chromeos/salsa_ui.h"
 #include "chrome/browser/ui/webui/chromeos/sim_unlock_ui.h"
+#include "chrome/browser/ui/webui/chromeos/slow_ui.h"
 #include "chrome/browser/ui/webui/chromeos/system_info_ui.h"
 #endif
 
@@ -361,6 +362,8 @@
     return &NewWebUI<SalsaUI>;
   if (url.host() == chrome::kChromeUISimUnlockHost)
     return &NewWebUI<chromeos::SimUnlockUI>;
+  if (url.host() == chrome::kChromeUISlowHost)
+    return &NewWebUI<chromeos::SlowUI>;
   if (url.host() == chrome::kChromeUISystemInfoHost)
     return &NewWebUI<chromeos::SystemInfoUI>;
 #endif  // defined(OS_CHROMEOS)
@@ -393,10 +396,10 @@
 #endif
 
 #if !defined(OS_CHROMEOS) && !defined(OS_ANDROID) && !defined(OS_IOS)
-  if (url.host() == chrome::kChromeUIUserChooserHost &&
+  if (url.host() == chrome::kChromeUIUserManagerHost &&
       CommandLine::ForCurrentProcess()->HasSwitch(
           switches::kNewProfileManagement))
-    return &NewWebUI<UserChooserUI>;
+    return &NewWebUI<UserManagerUI>;
 #endif
 
   if (url.host() == chrome::kChromeUIChromeURLsHost ||
diff --git a/chrome/browser/ui/webui/chromeos/login/core_oobe_handler.cc b/chrome/browser/ui/webui/chromeos/login/core_oobe_handler.cc
index d07dd47..ef91bc0 100644
--- a/chrome/browser/ui/webui/chromeos/login/core_oobe_handler.cc
+++ b/chrome/browser/ui/webui/chromeos/login/core_oobe_handler.cc
@@ -120,6 +120,8 @@
               &CoreOobeHandler::HandleEnableSpokenFeedback);
   AddCallback("setDeviceRequisition",
               &CoreOobeHandler::HandleSetDeviceRequisition);
+  AddCallback("skipToLoginForTesting",
+              &CoreOobeHandler::HandleSkipToLoginForTesting);
 }
 
 void CoreOobeHandler::ShowSignInError(
@@ -222,6 +224,11 @@
       SetDeviceRequisition(requisition);
 }
 
+void CoreOobeHandler::HandleSkipToLoginForTesting() {
+  if (WizardController::default_controller())
+      WizardController::default_controller()->SkipToLoginForTesting();
+}
+
 void CoreOobeHandler::ShowOobeUI(bool show) {
   if (show == show_oobe_ui_)
     return;
diff --git a/chrome/browser/ui/webui/chromeos/login/core_oobe_handler.h b/chrome/browser/ui/webui/chromeos/login/core_oobe_handler.h
index 7ecd9e6..7b67f47 100644
--- a/chrome/browser/ui/webui/chromeos/login/core_oobe_handler.h
+++ b/chrome/browser/ui/webui/chromeos/login/core_oobe_handler.h
@@ -85,6 +85,7 @@
   void HandleSkipUpdateEnrollAfterEula();
   void HandleUpdateCurrentScreen(const std::string& screen);
   void HandleSetDeviceRequisition(const std::string& requisition);
+  void HandleSkipToLoginForTesting();
 
   // Updates a11y menu state based on the current a11y features state(on/off).
   void UpdateA11yState();
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 bc47831..40d0b1d 100644
--- a/chrome/browser/ui/webui/chromeos/login/error_screen_handler.cc
+++ b/chrome/browser/ui/webui/chromeos/login/error_screen_handler.cc
@@ -59,6 +59,7 @@
   ShowScreen(OobeUI::kScreenErrorMessage, params);
   NetworkErrorShown();
   EnableLazyDetection();
+  LOG(WARNING) << "Offline message is displayed";
 }
 
 void ErrorScreenHandler::Hide() {
@@ -68,6 +69,7 @@
   if (GetScreenName(parent_screen_, &screen_name))
     ShowScreen(screen_name.c_str(), NULL);
   DisableLazyDetection();
+  LOG(WARNING) << "Offline message is hidden";
 }
 
 void ErrorScreenHandler::FixCaptivePortal() {
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 164a96c..bfaa5e4 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
@@ -51,6 +51,10 @@
       "managedUserCreationFlowGotitButtonTitle",
        IDS_CREATE_LOCALLY_MANAGED_USER_CREATION_GOT_IT_BUTTON_TITLE);
 
+  builder->Add("createManagedUserIntroTextTitle",
+               IDS_CREATE_LOCALLY_MANAGED_INTRO_TEXT_TITLE);
+  builder->Add("createManagedUserIntroAlternateText",
+               IDS_CREATE_LOCALLY_MANAGED_INTRO_ALTERNATE_TEXT);
   builder->Add("createManagedUserIntroText1",
                IDS_CREATE_LOCALLY_MANAGED_INTRO_TEXT_1);
   builder->Add("createManagedUserIntroManagerItem1",
diff --git a/chrome/browser/ui/webui/chromeos/login/network_state_informer.cc b/chrome/browser/ui/webui/chromeos/login/network_state_informer.cc
index f090f56..8ec6ccb 100644
--- a/chrome/browser/ui/webui/chromeos/login/network_state_informer.cc
+++ b/chrome/browser/ui/webui/chromeos/login/network_state_informer.cc
@@ -17,13 +17,6 @@
 #include "net/proxy/proxy_config.h"
 #include "third_party/cros_system_api/dbus/service_constants.h"
 
-namespace {
-
-// Timeout to smooth temporary network state transitions for flaky networks.
-const int kNetworkStateCheckDelaySec = 3;
-
-}  // namespace
-
 namespace chromeos {
 
 NetworkStateInformer::NetworkStateInformer()
@@ -71,50 +64,17 @@
 }
 
 void NetworkStateInformer::NetworkManagerChanged() {
-  const NetworkState* default_network =
-      NetworkHandler::Get()->network_state_handler()->DefaultNetwork();
-  State new_state = OFFLINE;
-  std::string new_network_service_path;
-  if (default_network) {
-    new_state = GetNetworkState(default_network);
-    new_network_service_path = default_network->path();
-  }
-  if ((state_ != ONLINE && (new_state == ONLINE || new_state == CONNECTING)) ||
-      (state_ == ONLINE && (new_state == ONLINE || new_state == CONNECTING) &&
-       new_network_service_path != last_online_service_path_) ||
-      (new_state == CAPTIVE_PORTAL &&
-       new_network_service_path == last_network_service_path_)) {
-    last_network_service_path_ = new_network_service_path;
-    if (new_state == ONLINE)
-      last_online_service_path_ = new_network_service_path;
-    // Transitions {OFFLINE, PORTAL} -> ONLINE and connections to
-    // different network are processed without delay.
-    // Transitions {OFFLINE, ONLINE} -> PORTAL in the same network are
-    // also processed without delay.
-    UpdateStateAndNotify();
-  } else {
-    check_state_.Cancel();
-    check_state_.Reset(
-        base::Bind(&NetworkStateInformer::UpdateStateAndNotify,
-                   weak_ptr_factory_.GetWeakPtr()));
-    base::MessageLoop::current()->PostDelayedTask(
-        FROM_HERE,
-        check_state_.callback(),
-        base::TimeDelta::FromSeconds(kNetworkStateCheckDelaySec));
-  }
+  UpdateStateAndNotify();
 }
 
 void NetworkStateInformer::DefaultNetworkChanged(const NetworkState* network) {
-  NetworkManagerChanged();
+  UpdateStateAndNotify();
 }
 
 void NetworkStateInformer::OnPortalDetectionCompleted(
     const NetworkState* network,
     const NetworkPortalDetector::CaptivePortalState& state) {
-  if (NetworkHandler::IsInitialized() &&
-      NetworkHandler::Get()->network_state_handler()->DefaultNetwork() ==
-      network)
-    NetworkManagerChanged();
+  UpdateStateAndNotify();
 }
 
 void NetworkStateInformer::Observe(
@@ -130,26 +90,27 @@
 }
 
 void NetworkStateInformer::OnPortalDetected() {
-  SendStateToObservers(ErrorScreenActor::ERROR_REASON_PORTAL_DETECTED);
+  UpdateStateAndNotify();
 }
 
 bool NetworkStateInformer::UpdateState() {
-  State new_state = OFFLINE;
-
   const NetworkState* default_network =
       NetworkHandler::Get()->network_state_handler()->DefaultNetwork();
+  State new_state = OFFLINE;
+  std::string new_network_path;
+  std::string new_network_type;
   if (default_network) {
     new_state = GetNetworkState(default_network);
-    last_network_service_path_ = default_network->path();
-    last_network_type_ = default_network->type();
+    new_network_path = default_network->path();
+    new_network_type = default_network->type();
   }
 
   bool updated = (new_state != state_) ||
-      (new_state != OFFLINE &&
-       last_network_service_path_ != last_connected_service_path_);
+      (new_network_path != network_path_) ||
+      (new_network_type != network_type_);
   state_ = new_state;
-  if (state_ != OFFLINE)
-    last_connected_service_path_ = last_network_service_path_;
+  network_path_ = new_network_path;
+  network_type_ = new_network_type;
 
   if (updated && state_ == ONLINE) {
     FOR_EACH_OBSERVER(NetworkStateInformerObserver, observers_,
@@ -160,9 +121,6 @@
 }
 
 void NetworkStateInformer::UpdateStateAndNotify() {
-  // Cancel pending update request if any.
-  check_state_.Cancel();
-
   if (UpdateState())
     SendStateToObservers(ErrorScreenActor::ERROR_REASON_NETWORK_STATE_CHANGED);
   else
@@ -172,7 +130,7 @@
 void NetworkStateInformer::SendStateToObservers(
     ErrorScreenActor::ErrorReason reason) {
   FOR_EACH_OBSERVER(NetworkStateInformerObserver, observers_,
-      UpdateState(state_, reason));
+      UpdateState(reason));
 }
 
 NetworkStateInformer::State NetworkStateInformer::GetNetworkState(
diff --git a/chrome/browser/ui/webui/chromeos/login/network_state_informer.h b/chrome/browser/ui/webui/chromeos/login/network_state_informer.h
index 85710d8..69b2766 100644
--- a/chrome/browser/ui/webui/chromeos/login/network_state_informer.h
+++ b/chrome/browser/ui/webui/chromeos/login/network_state_informer.h
@@ -49,8 +49,7 @@
     NetworkStateInformerObserver() {}
     virtual ~NetworkStateInformerObserver() {}
 
-    virtual void UpdateState(State state,
-                             ErrorScreenActor::ErrorReason reason) = 0;
+    virtual void UpdateState(ErrorScreenActor::ErrorReason reason) = 0;
     virtual void OnNetworkReady() {}
   };
 
@@ -81,18 +80,9 @@
   // CaptivePortalWindowProxyDelegate implementation:
   virtual void OnPortalDetected() OVERRIDE;
 
-  // Returns active network's service path. It can be used to uniquely
-  // identify the network.
-  std::string active_network_service_path() {
-    return last_online_service_path_;
-  }
-
-  bool is_online() { return state_ == ONLINE; }
   State state() const { return state_; }
-  std::string last_network_service_path() const {
-    return last_network_service_path_;
-  }
-  std::string last_network_type() const { return last_network_type_; }
+  std::string network_path() const { return network_path_; }
+  std::string network_type() const { return network_type_; }
 
  private:
   friend class base::RefCounted<NetworkStateInformer>;
@@ -108,14 +98,12 @@
   State GetNetworkState(const NetworkState* network);
   bool IsProxyConfigured(const NetworkState* network);
 
-  content::NotificationRegistrar registrar_;
   State state_;
+  std::string network_path_;
+  std::string network_type_;
+
   ObserverList<NetworkStateInformerObserver> observers_;
-  std::string last_online_service_path_;
-  std::string last_connected_service_path_;
-  std::string last_network_service_path_;
-  std::string last_network_type_;
-  base::CancelableClosure check_state_;
+  content::NotificationRegistrar registrar_;
 
   base::WeakPtrFactory<NetworkStateInformer> weak_ptr_factory_;
 };
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 535842b..fb40ab3 100644
--- a/chrome/browser/ui/webui/chromeos/login/reset_screen_handler.cc
+++ b/chrome/browser/ui/webui/chromeos/login/reset_screen_handler.cc
@@ -70,7 +70,8 @@
                 IDS_RESET_SCREEN_WARNING_MSG,
                 IDS_SHORT_PRODUCT_NAME);
 
-  if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kFirstBoot)) {
+  if (CommandLine::ForCurrentProcess()->HasSwitch(
+          switches::kFirstExecAfterBoot)) {
     builder->AddF("resetWarningDetails",
                   IDS_RESET_SCREEN_WARNING_DETAILS,
                   IDS_SHORT_PRODUCT_NAME);
@@ -104,7 +105,8 @@
 }
 
 void ResetScreenHandler::HandleOnReset() {
-  if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kFirstBoot)) {
+  if (CommandLine::ForCurrentProcess()->HasSwitch(
+          switches::kFirstExecAfterBoot)) {
     chromeos::DBusThreadManager::Get()->GetSessionManagerClient()->
         StartDeviceWipe();
   } else {
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 c3c4831..922a60d 100644
--- a/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.cc
+++ b/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.cc
@@ -238,15 +238,6 @@
   return network->name();
 }
 
-// Returns network unique id by service path.
-std::string GetNetworkUniqueId(const std::string& service_path) {
-  const NetworkState* network = NetworkHandler::Get()->network_state_handler()->
-      GetNetworkState(service_path);
-  if (!network)
-    return std::string();
-  return network->guid();
-}
-
 // Returns captive portal state for a network by its service path.
 NetworkPortalDetector::CaptivePortalState GetCaptivePortalState(
     const std::string& service_path) {
@@ -560,9 +551,8 @@
   MaybePreloadAuthExtension();
 }
 
-void SigninScreenHandler::UpdateState(NetworkStateInformer::State state,
-                                      ErrorScreenActor::ErrorReason reason) {
-  UpdateStateInternal(state, reason, false);
+void SigninScreenHandler::UpdateState(ErrorScreenActor::ErrorReason reason) {
+  UpdateStateInternal(reason, false);
 }
 
 // SigninScreenHandler, private: -----------------------------------------------
@@ -586,7 +576,6 @@
 
 // TODO (ygorshenin@): split this method into small parts.
 void SigninScreenHandler::UpdateStateInternal(
-    NetworkStateInformer::State state,
     ErrorScreenActor::ErrorReason reason,
     bool force_update) {
   // Do nothing once user has signed in or sign in is in progress.
@@ -598,16 +587,15 @@
     return;
   }
 
-  const std::string service_path =
-      network_state_informer_->last_network_service_path();
-  const std::string network_id =
-      GetNetworkUniqueId(service_path);
+  NetworkStateInformer::State state = network_state_informer_->state();
+  const std::string network_path = network_state_informer_->network_path();
+  const std::string network_name = GetNetworkName(network_path);
 
   // Skip "update" notification about OFFLINE state from
   // NetworkStateInformer if previous notification already was
   // delayed.
-  if (state == NetworkStateInformer::OFFLINE &&
-      reason == ErrorScreenActor::ERROR_REASON_UPDATE &&
+  if ((state == NetworkStateInformer::OFFLINE || has_pending_auth_ui_) &&
+      !force_update &&
       !update_state_closure_.IsCancelled()) {
     return;
   }
@@ -616,31 +604,23 @@
   // will be tested well.
   LOG(WARNING) << "SigninScreenHandler::UpdateStateInternal(): "
                << "state=" << NetworkStateStatusString(state) << ", "
-               << "network_id=" << network_id << ", "
+               << "network_name=" << network_name << ", "
                << "reason=" << ErrorReasonString(reason) << ", "
                << "force_update=" << force_update;
   update_state_closure_.Cancel();
 
-  // Delay UpdateStateInternal() call in the following cases:
-  // 1. this is the first call and it's about offline state of the
-  //    current network. This can happen because device is just powered
-  //    up and network stack isn't ready now.
-  // 2. proxy auth ui is displayed. UpdateStateCall() is delayed to
-  //    prevent screen change behind proxy auth ui.
-  if ((state == NetworkStateInformer::OFFLINE && is_first_update_state_call_) ||
+  if ((state == NetworkStateInformer::OFFLINE && !force_update) ||
       has_pending_auth_ui_) {
-    is_first_update_state_call_ = false;
     update_state_closure_.Reset(
         base::Bind(
             &SigninScreenHandler::UpdateStateInternal,
-            weak_factory_.GetWeakPtr(), state, reason, force_update));
+            weak_factory_.GetWeakPtr(), reason, true));
     base::MessageLoop::current()->PostDelayedTask(
         FROM_HERE,
         update_state_closure_.callback(),
         base::TimeDelta::FromSeconds(kOfflineTimeoutSec));
     return;
   }
-  is_first_update_state_call_ = false;
 
   // Don't show or hide error screen if we're in connecting state.
   if (state == NetworkStateInformer::CONNECTING && !force_update) {
@@ -648,7 +628,7 @@
       // First notification about CONNECTING state.
       connecting_closure_.Reset(
           base::Bind(&SigninScreenHandler::UpdateStateInternal,
-                     weak_factory_.GetWeakPtr(), state, reason, true));
+                     weak_factory_.GetWeakPtr(), reason, true));
       base::MessageLoop::current()->PostDelayedTask(
           FROM_HERE,
           connecting_closure_.callback(),
@@ -715,19 +695,15 @@
 void SigninScreenHandler::SetupAndShowOfflineMessage(
     NetworkStateInformer:: State state,
     ErrorScreenActor::ErrorReason reason) {
-  const std::string service_path =
-      network_state_informer_->last_network_service_path();
-  const std::string network_id = GetNetworkUniqueId(service_path);
+  const std::string network_path = network_state_informer_->network_path();
   const bool is_under_captive_portal = IsUnderCaptivePortal(state, reason);
   const bool is_proxy_error = IsProxyError(state, reason, frame_error_);
   const bool is_gaia_loading_timeout =
       (reason == ErrorScreenActor::ERROR_REASON_LOADING_TIMEOUT);
 
-  LOG(WARNING) << "Offline message is displayed";
-
   // Record portal detection stats only if we're going to show or
   // change state of the error screen.
-  RecordNetworkPortalDetectorStats(service_path);
+  RecordNetworkPortalDetectorStats(network_path);
 
   if (is_proxy_error) {
     error_screen_actor_->SetErrorState(ErrorScreen::ERROR_STATE_PROXY,
@@ -742,7 +718,7 @@
          ErrorScreen::ERROR_STATE_PORTAL)) {
       error_screen_actor_->FixCaptivePortal();
     }
-    const std::string network_name = GetNetworkName(service_path);
+    const std::string network_name = GetNetworkName(network_path);
     error_screen_actor_->SetErrorState(ErrorScreen::ERROR_STATE_PORTAL,
                                        network_name);
   } else if (is_gaia_loading_timeout) {
@@ -765,9 +741,8 @@
 
   if (GetCurrentScreen() != OobeUI::SCREEN_ERROR_MESSAGE) {
     DictionaryValue params;
-    const std::string connection_type =
-        network_state_informer_->last_network_type();
-    params.SetString("lastNetworkType", connection_type);
+    const std::string network_type = network_state_informer_->network_type();
+    params.SetString("lastNetworkType", network_type);
     error_screen_actor_->SetUIState(ErrorScreen::UI_STATE_SIGNIN);
     error_screen_actor_->Show(OobeUI::SCREEN_GAIA_SIGNIN, &params);
   }
@@ -779,7 +754,6 @@
   if (!IsSigninScreenHiddenByError())
     return;
 
-  LOG(WARNING) << "Offline message is hidden";
   error_screen_actor_->Hide();
 
   // Forces a reload for Gaia screen on hiding error message.
@@ -855,9 +829,7 @@
               &SigninScreenHandler::HandleAccountPickerReady);
   AddCallback("wallpaperReady", &SigninScreenHandler::HandleWallpaperReady);
   AddCallback("loginWebuiReady", &SigninScreenHandler::HandleLoginWebuiReady);
-  AddCallback("demoWebuiReady", &SigninScreenHandler::HandleDemoWebuiReady);
   AddCallback("signOutUser", &SigninScreenHandler::HandleSignOutUser);
-  AddCallback("userImagesLoaded", &SigninScreenHandler::HandleUserImagesLoaded);
   AddCallback("networkErrorShown",
               &SigninScreenHandler::HandleNetworkErrorShown);
   AddCallback("openProxySettings",
@@ -1074,11 +1046,10 @@
   if (!dns_cleared_ || !cookies_cleared_ || !delegate_)
     return;
 
-  std::string active_network =
-      network_state_informer_->active_network_service_path();
+  std::string active_network_path = network_state_informer_->network_path();
   if (gaia_silent_load_ &&
-      (!network_state_informer_->is_online() ||
-       gaia_silent_load_network_ != active_network)) {
+      (network_state_informer_->state() != NetworkStateInformer::ONLINE ||
+       gaia_silent_load_network_ != active_network_path)) {
     // Network has changed. Force Gaia reload.
     gaia_silent_load_ = false;
     // Gaia page will be realoded, so focus isn't stolen anymore.
@@ -1106,8 +1077,7 @@
       HandleLoginWebuiReady();
   }
 
-  UpdateState(network_state_informer_->state(),
-              ErrorScreenActor::ERROR_REASON_UPDATE);
+  UpdateState(ErrorScreenActor::ERROR_REASON_UPDATE);
 }
 
 
@@ -1514,25 +1484,11 @@
     SubmitLoginFormForTest();
 }
 
-void SigninScreenHandler::HandleDemoWebuiReady() {
-  content::NotificationService::current()->Notify(
-      chrome::NOTIFICATION_DEMO_WEBUI_LOADED,
-      content::NotificationService::AllSources(),
-      content::NotificationService::NoDetails());
-}
-
 void SigninScreenHandler::HandleSignOutUser() {
   if (delegate_)
     delegate_->Signout();
 }
 
-void SigninScreenHandler::HandleUserImagesLoaded() {
-  content::NotificationService::current()->Notify(
-      chrome::NOTIFICATION_LOGIN_USER_IMAGES_LOADED,
-      content::NotificationService::AllSources(),
-      content::NotificationService::NoDetails());
-}
-
 void SigninScreenHandler::HandleNetworkErrorShown() {
   content::NotificationService::current()->Notify(
       chrome::NOTIFICATION_LOGIN_NETWORK_ERROR_SHOWN,
@@ -1634,18 +1590,14 @@
 
   if (network_state_informer_->state() != NetworkStateInformer::ONLINE)
     return;
-  if (frame_state_ == FRAME_STATE_LOADED) {
-    UpdateState(network_state_informer_->state(),
-                ErrorScreenActor::ERROR_REASON_UPDATE);
-  } else if (frame_state_ == FRAME_STATE_ERROR) {
-    UpdateState(network_state_informer_->state(),
-                ErrorScreenActor::ERROR_REASON_FRAME_ERROR);
-  }
+  if (frame_state_ == FRAME_STATE_LOADED)
+    UpdateState(ErrorScreenActor::ERROR_REASON_UPDATE);
+  else if (frame_state_ == FRAME_STATE_ERROR)
+    UpdateState(ErrorScreenActor::ERROR_REASON_FRAME_ERROR);
 }
 
 void SigninScreenHandler::HandleShowLoadingTimeoutError() {
-  UpdateState(network_state_informer_->state(),
-              ErrorScreenActor::ERROR_REASON_LOADING_TIMEOUT);
+  UpdateState(ErrorScreenActor::ERROR_REASON_LOADING_TIMEOUT);
 }
 
 void SigninScreenHandler::HandleUpdateOfflineLogin(bool offline_login_active) {
@@ -1688,10 +1640,9 @@
       !ScreenLocker::default_screen_locker() &&
       !cookies_cleared_ &&
       !dns_clear_task_running_ &&
-      network_state_informer_->is_online()) {
+      network_state_informer_->state() == NetworkStateInformer::ONLINE) {
     gaia_silent_load_ = true;
-    gaia_silent_load_network_ =
-        network_state_informer_->active_network_service_path();
+    gaia_silent_load_network_ = network_state_informer_->network_path();
     LoadAuthExtension(true, true, false);
   }
 }
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 f5fbd6b..1d51afc 100644
--- a/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.h
+++ b/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.h
@@ -191,9 +191,7 @@
 
   // NetworkStateInformer::NetworkStateInformerObserver implementation:
   virtual void OnNetworkReady() OVERRIDE;
-
-  virtual void UpdateState(NetworkStateInformer::State state,
-                           ErrorScreenActor::ErrorReason reason) OVERRIDE;
+  virtual void UpdateState(ErrorScreenActor::ErrorReason reason) OVERRIDE;
 
   // Required Local State preferences.
   static void RegisterPrefs(PrefRegistrySimple* registry);
@@ -222,8 +220,7 @@
   // |params| argument.
   void UpdateUIState(UIState ui_state, DictionaryValue* params);
 
-  void UpdateStateInternal(NetworkStateInformer::State state,
-                           ErrorScreenActor::ErrorReason reason,
+  void UpdateStateInternal(ErrorScreenActor::ErrorReason reason,
                            bool force_update);
   void SetupAndShowOfflineMessage(NetworkStateInformer::State state,
                                   ErrorScreenActor::ErrorReason reason);
@@ -314,9 +311,7 @@
   void HandleAccountPickerReady();
   void HandleWallpaperReady();
   void HandleLoginWebuiReady();
-  void HandleDemoWebuiReady();
   void HandleSignOutUser();
-  void HandleUserImagesLoaded();
   void HandleNetworkErrorShown();
   void HandleOpenProxySettings();
   void HandleLoginVisible(const std::string& source);
diff --git a/chrome/browser/ui/webui/chromeos/sim_unlock_ui.cc b/chrome/browser/ui/webui/chromeos/sim_unlock_ui.cc
index 5da85d1..9fd266c 100644
--- a/chrome/browser/ui/webui/chromeos/sim_unlock_ui.cc
+++ b/chrome/browser/ui/webui/chromeos/sim_unlock_ui.cc
@@ -151,7 +151,8 @@
   class TaskProxy : public base::RefCountedThreadSafe<TaskProxy> {
    public:
     explicit TaskProxy(const base::WeakPtr<SimUnlockHandler>& handler)
-        : handler_(handler) {
+        : handler_(handler),
+          code_type_() {
     }
 
     TaskProxy(const base::WeakPtr<SimUnlockHandler>& handler,
diff --git a/chrome/browser/ui/webui/chromeos/slow_ui.cc b/chrome/browser/ui/webui/chromeos/slow_ui.cc
new file mode 100644
index 0000000..ddf64c4
--- /dev/null
+++ b/chrome/browser/ui/webui/chromeos/slow_ui.cc
@@ -0,0 +1,139 @@
+// 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/ui/webui/chromeos/slow_ui.h"
+
+#include <string>
+
+#include "base/bind.h"
+#include "base/prefs/pref_change_registrar.h"
+#include "base/prefs/pref_service.h"
+#include "base/values.h"
+#include "chrome/browser/profiles/profile.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"
+#include "content/public/browser/web_ui_data_source.h"
+#include "content/public/browser/web_ui_message_handler.h"
+#include "grit/browser_resources.h"
+#include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/webui/jstemplate_builder.h"
+#include "ui/webui/web_ui_util.h"
+
+using content::WebUIMessageHandler;
+
+namespace {
+
+// JS API callbacks names.
+const char kJsApiDisableTracing[] = "disableTracing";
+const char kJsApiEnableTracing[] = "enableTracing";
+const char kJsApiLoadComplete[] = "loadComplete";
+
+// Page JS API function names.
+const char kJsApiTracingPrefChanged[] = "options.Slow.tracingPrefChanged";
+
+}  // namespace
+
+namespace chromeos {
+
+content::WebUIDataSource* CreateSlowUIHTMLSource() {
+  content::WebUIDataSource* source =
+      content::WebUIDataSource::Create(chrome::kChromeUISlowHost);
+
+  source->SetUseJsonJSFormatV2();
+  source->AddLocalizedString("slowDisable", IDS_SLOW_DISABLE);
+  source->AddLocalizedString("slowEnable", IDS_SLOW_ENABLE);
+  source->AddLocalizedString("slowDescription", IDS_SLOW_DESCRIPTION);
+  source->AddLocalizedString("slowWarning", IDS_SLOW_WARNING);
+
+  source->SetJsonPath("strings.js");
+  source->AddResourcePath("slow.js", IDR_SLOW_JS);
+  source->SetDefaultResource(IDR_SLOW_HTML);
+  return source;
+}
+
+// The handler for Javascript messages related to the "slow" view.
+class SlowHandler : public WebUIMessageHandler {
+ public:
+  explicit SlowHandler(Profile* profile);
+  virtual ~SlowHandler();
+
+  // WebUIMessageHandler implementation.
+  virtual void RegisterMessages() OVERRIDE;
+
+ private:
+  void UpdatePage();
+
+  // Handlers for JS WebUI messages.
+  void HandleDisable(const ListValue* args);
+  void HandleEnable(const ListValue* args);
+  void LoadComplete(const ListValue* args);
+
+  Profile* profile_;
+  scoped_ptr<PrefChangeRegistrar> user_pref_registrar_;
+
+  DISALLOW_COPY_AND_ASSIGN(SlowHandler);
+};
+
+// SlowHandler ------------------------------------------------------------
+
+SlowHandler::SlowHandler(Profile* profile) : profile_(profile) {
+}
+
+SlowHandler::~SlowHandler() {
+}
+
+void SlowHandler::RegisterMessages() {
+  web_ui()->RegisterMessageCallback(kJsApiDisableTracing,
+      base::Bind(&SlowHandler::HandleDisable, base::Unretained(this)));
+  web_ui()->RegisterMessageCallback(kJsApiEnableTracing,
+      base::Bind(&SlowHandler::HandleEnable, base::Unretained(this)));
+  web_ui()->RegisterMessageCallback(kJsApiLoadComplete,
+      base::Bind(&SlowHandler::LoadComplete, base::Unretained(this)));
+
+  user_pref_registrar_.reset(new PrefChangeRegistrar);
+  user_pref_registrar_->Init(profile_->GetPrefs());
+  user_pref_registrar_->Add(prefs::kPerformanceTracingEnabled,
+                            base::Bind(&SlowHandler::UpdatePage,
+                                       base::Unretained(this)));
+}
+
+void SlowHandler::HandleDisable(const ListValue* args) {
+  PrefService* pref_service = profile_->GetPrefs();
+  pref_service->SetBoolean(prefs::kPerformanceTracingEnabled, false);
+}
+
+void SlowHandler::HandleEnable(const ListValue* args) {
+  PrefService* pref_service = profile_->GetPrefs();
+  pref_service->SetBoolean(prefs::kPerformanceTracingEnabled, true);
+}
+
+void SlowHandler::LoadComplete(const ListValue* args) {
+  UpdatePage();
+}
+
+void SlowHandler::UpdatePage() {
+  PrefService* pref_service = profile_->GetPrefs();
+  bool enabled = pref_service->GetBoolean(prefs::kPerformanceTracingEnabled);
+  base::FundamentalValue pref_value(enabled);
+  web_ui()->CallJavascriptFunction(kJsApiTracingPrefChanged, pref_value);
+}
+
+// SlowUI -----------------------------------------------------------------
+
+SlowUI::SlowUI(content::WebUI* web_ui) : WebUIController(web_ui) {
+  Profile* profile = Profile::FromWebUI(web_ui);
+
+  SlowHandler* handler = new SlowHandler(profile);
+  web_ui->AddMessageHandler(handler);
+
+  // Set up the chrome://slow/ source.
+  content::WebUIDataSource::Add(profile, CreateSlowUIHTMLSource());
+}
+
+}  // namespace chromeos
+
diff --git a/chrome/browser/ui/webui/chromeos/slow_ui.h b/chrome/browser/ui/webui/chromeos/slow_ui.h
new file mode 100644
index 0000000..1a3e1b6
--- /dev/null
+++ b/chrome/browser/ui/webui/chromeos/slow_ui.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 CHROME_BROWSER_UI_WEBUI_CHROMEOS_SLOW_UI_H_
+#define CHROME_BROWSER_UI_WEBUI_CHROMEOS_SLOW_UI_H_
+
+#include "content/public/browser/web_ui_controller.h"
+
+namespace chromeos {
+
+// A custom WebUI that allows users to enable and disable performance tracing
+// for feedback reports.
+class SlowUI : public content::WebUIController {
+ public:
+  explicit SlowUI(content::WebUI* web_ui);
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(SlowUI);
+};
+
+}  // namespace chromeos
+
+#endif  // CHROME_BROWSER_UI_WEBUI_CHROMEOS_SLOW_UI_H_
+
diff --git a/chrome/browser/ui/webui/chromeos/system_info_ui.cc b/chrome/browser/ui/webui/chromeos/system_info_ui.cc
index d711523..3040b9d 100644
--- a/chrome/browser/ui/webui/chromeos/system_info_ui.cc
+++ b/chrome/browser/ui/webui/chromeos/system_info_ui.cc
@@ -18,7 +18,7 @@
 #include "base/threading/thread.h"
 #include "base/time/time.h"
 #include "base/values.h"
-#include "chrome/browser/chromeos/system_logs/system_logs_fetcher.h"
+#include "chrome/browser/chromeos/system_logs/about_system_logs_fetcher.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/common/chrome_paths.h"
 #include "chrome/common/url_constants.h"
@@ -110,7 +110,7 @@
   path_ = path;
   callback_ = callback;
 
-  SystemLogsFetcher* fetcher = new SystemLogsFetcher();
+  AboutSystemLogsFetcher* fetcher = new AboutSystemLogsFetcher();
   fetcher->Fetch(base::Bind(&SystemInfoUIHTMLSource::SysInfoComplete,
                             weak_ptr_factory_.GetWeakPtr()));
 }
diff --git a/chrome/browser/ui/webui/downloads_dom_handler.cc b/chrome/browser/ui/webui/downloads_dom_handler.cc
index d9938b2..6415b54 100644
--- a/chrome/browser/ui/webui/downloads_dom_handler.cc
+++ b/chrome/browser/ui/webui/downloads_dom_handler.cc
@@ -13,6 +13,7 @@
 #include "base/i18n/rtl.h"
 #include "base/i18n/time_formatting.h"
 #include "base/memory/singleton.h"
+#include "base/metrics/field_trial.h"
 #include "base/metrics/histogram.h"
 #include "base/prefs/pref_service.h"
 #include "base/strings/string_piece.h"
@@ -50,10 +51,6 @@
 #include "ui/base/l10n/time_format.h"
 #include "ui/gfx/image/image.h"
 
-#if defined(OS_CHROMEOS)
-#include "chrome/browser/chromeos/extensions/file_manager/file_manager_util.h"
-#endif
-
 using content::BrowserContext;
 using content::BrowserThread;
 using content::UserMetricsAction;
@@ -184,9 +181,23 @@
                    content::DOWNLOAD_DANGER_TYPE_DANGEROUS_HOST ||
                download_item->GetDangerType() ==
                    content::DOWNLOAD_DANGER_TYPE_POTENTIALLY_UNWANTED);
+        std::string trial_condition =
+            base::FieldTrialList::FindFullName(download_util::kFinchTrialName);
         const char* danger_type_value =
             GetDangerTypeString(download_item->GetDangerType());
         file_value->SetString("danger_type", danger_type_value);
+        if (!trial_condition.empty()) {
+          base::string16 finch_string;
+          content::DownloadDangerType danger_type =
+              download_item->GetDangerType();
+          if (danger_type == content::DOWNLOAD_DANGER_TYPE_DANGEROUS_URL ||
+              danger_type == content::DOWNLOAD_DANGER_TYPE_DANGEROUS_CONTENT ||
+              danger_type == content::DOWNLOAD_DANGER_TYPE_DANGEROUS_HOST) {
+            finch_string = download_util::AssembleMalwareFinchString(
+                trial_condition, file_name);
+          }
+          file_value->SetString("finch_string", finch_string);
+        }
       } else if (download_item->IsPaused()) {
         file_value->SetString("state", "PAUSED");
       } else {
@@ -247,8 +258,7 @@
 }  // namespace
 
 DownloadsDOMHandler::DownloadsDOMHandler(content::DownloadManager* dlm)
-    : search_text_(),
-      main_notifier_(dlm, this),
+    : main_notifier_(dlm, this),
       update_scheduled_(false),
       weak_ptr_factory_(this) {
   // Create our fileicon data source.
@@ -323,16 +333,14 @@
     content::DownloadManager* manager,
     content::DownloadItem* download_item) {
   if (IsDownloadDisplayable(*download_item)) {
-    if (!search_text_.empty()) {
+    if (search_terms_ && !search_terms_->empty()) {
       // Don't CallDownloadUpdated() if download_item doesn't match
-      // search_text_.
+      // search_terms_.
       // TODO(benjhayden): Consider splitting MatchesQuery() out to a function.
       content::DownloadManager::DownloadVector all_items, filtered_items;
       all_items.push_back(download_item);
       DownloadQuery query;
-      scoped_ptr<base::Value> query_text(base::Value::CreateStringValue(
-          search_text_));
-      query.AddFilter(DownloadQuery::FILTER_QUERY, *query_text.get());
+      query.AddFilter(DownloadQuery::FILTER_QUERY, *search_terms_.get());
       query.Search(all_items.begin(), all_items.end(), &filtered_items);
       if (filtered_items.empty())
         return;
@@ -364,7 +372,7 @@
 
 void DownloadsDOMHandler::HandleGetDownloads(const base::ListValue* args) {
   CountDownloadsDOMEvents(DOWNLOADS_DOM_EVENT_GET_DOWNLOADS);
-  search_text_ = ExtractStringValue(args);
+  search_terms_.reset((args && !args->empty()) ? args->DeepCopy() : NULL);
   SendCurrentDownloads();
 }
 
@@ -508,10 +516,8 @@
     original_notifier_->GetManager()->CheckForHistoryFilesRemoval();
   }
   DownloadQuery query;
-  if (!search_text_.empty()) {
-    scoped_ptr<base::Value> query_text(base::Value::CreateStringValue(
-        search_text_));
-    query.AddFilter(DownloadQuery::FILTER_QUERY, *query_text.get());
+  if (search_terms_ && !search_terms_->empty()) {
+    query.AddFilter(DownloadQuery::FILTER_QUERY, *search_terms_.get());
   }
   query.AddFilter(base::Bind(&IsDownloadDisplayable));
   query.AddSorter(DownloadQuery::SORT_START_TIME, DownloadQuery::DESCENDING);
diff --git a/chrome/browser/ui/webui/downloads_dom_handler.h b/chrome/browser/ui/webui/downloads_dom_handler.h
index aee7ed1..8b5d23c 100644
--- a/chrome/browser/ui/webui/downloads_dom_handler.h
+++ b/chrome/browser/ui/webui/downloads_dom_handler.h
@@ -130,8 +130,8 @@
   // Returns the download that is referred to in a given value.
   content::DownloadItem* GetDownloadByValue(const base::ListValue* args);
 
-  // Current search text.
-  string16 search_text_;
+  // Current search terms.
+  scoped_ptr<base::ListValue> search_terms_;
 
   // Notifies OnDownload*() and provides safe access to the DownloadManager.
   AllDownloadItemNotifier main_notifier_;
diff --git a/chrome/browser/ui/webui/downloads_dom_handler_browsertest.cc b/chrome/browser/ui/webui/downloads_dom_handler_browsertest.cc
index 9c445dc..34c5619 100644
--- a/chrome/browser/ui/webui/downloads_dom_handler_browsertest.cc
+++ b/chrome/browser/ui/webui/downloads_dom_handler_browsertest.cc
@@ -146,6 +146,8 @@
         GURL(std::string()),
         current,
         current,
+        std::string(),
+        std::string(),
         128,
         128,
         content::DownloadItem::COMPLETE,
diff --git a/chrome/browser/ui/webui/extensions/extension_settings_handler.cc b/chrome/browser/ui/webui/extensions/extension_settings_handler.cc
index 37c1c1a..ac1482c 100644
--- a/chrome/browser/ui/webui/extensions/extension_settings_handler.cc
+++ b/chrome/browser/ui/webui/extensions/extension_settings_handler.cc
@@ -8,6 +8,7 @@
 #include "apps/app_restore_service.h"
 #include "apps/saved_files_service.h"
 #include "apps/shell_window.h"
+#include "apps/shell_window_registry.h"
 #include "base/auto_reset.h"
 #include "base/base64.h"
 #include "base/bind.h"
@@ -34,7 +35,6 @@
 #include "chrome/browser/extensions/extension_warning_set.h"
 #include "chrome/browser/extensions/lazy_background_task_queue.h"
 #include "chrome/browser/extensions/management_policy.h"
-#include "chrome/browser/extensions/shell_window_registry.h"
 #include "chrome/browser/extensions/unpacked_installer.h"
 #include "chrome/browser/extensions/updater/extension_updater.h"
 #include "chrome/browser/google/google_util.h"
@@ -1037,13 +1037,13 @@
     const Extension* extension,
     Profile* profile,
     std::vector<ExtensionPage>* result) {
-  ShellWindowRegistry* registry = ShellWindowRegistry::Get(profile);
+  apps::ShellWindowRegistry* registry = apps::ShellWindowRegistry::Get(profile);
   if (!registry) return;
 
-  const ShellWindowRegistry::ShellWindowList windows =
+  const apps::ShellWindowRegistry::ShellWindowList windows =
       registry->GetShellWindowsForApp(extension->id());
 
-  for (ShellWindowRegistry::const_iterator it = windows.begin();
+  for (apps::ShellWindowRegistry::const_iterator it = windows.begin();
        it != windows.end(); ++it) {
     WebContents* web_contents = (*it)->web_contents();
     RenderViewHost* host = web_contents->GetRenderViewHost();
diff --git a/chrome/browser/ui/webui/extensions/install_extension_handler.cc b/chrome/browser/ui/webui/extensions/install_extension_handler.cc
index 17e466d..72aa3e3 100644
--- a/chrome/browser/ui/webui/extensions/install_extension_handler.cc
+++ b/chrome/browser/ui/webui/extensions/install_extension_handler.cc
@@ -96,9 +96,11 @@
 
   Profile* profile = Profile::FromBrowserContext(
       web_ui()->GetWebContents()->GetBrowserContext());
+  scoped_ptr<ExtensionInstallPrompt> prompt(
+      new ExtensionInstallPrompt(web_ui()->GetWebContents()));
   scoped_refptr<CrxInstaller> crx_installer(CrxInstaller::Create(
       ExtensionSystem::Get(profile)->extension_service(),
-      new ExtensionInstallPrompt(web_ui()->GetWebContents())));
+      prompt.Pass()));
   crx_installer->set_error_on_unsupported_requirements(true);
   crx_installer->set_off_store_install_allow_reason(
       CrxInstaller::OffStoreInstallAllowedFromSettingsPage);
diff --git a/chrome/browser/ui/webui/feedback_ui.cc b/chrome/browser/ui/webui/feedback_ui.cc
index 0f58e2c..72863a6 100644
--- a/chrome/browser/ui/webui/feedback_ui.cc
+++ b/chrome/browser/ui/webui/feedback_ui.cc
@@ -24,6 +24,7 @@
 #include "chrome/browser/download/download_prefs.h"
 #include "chrome/browser/feedback/feedback_data.h"
 #include "chrome/browser/feedback/feedback_util.h"
+#include "chrome/browser/feedback/tracing_manager.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/profiles/profile_manager.h"
 #include "chrome/browser/signin/signin_manager.h"
@@ -65,7 +66,7 @@
 #include "chrome/browser/chromeos/drive/file_system_interface.h"
 #include "chrome/browser/chromeos/drive/file_system_util.h"
 #include "chrome/browser/chromeos/login/user_manager.h"
-#include "chrome/browser/chromeos/system_logs/system_logs_fetcher.h"
+#include "chrome/browser/chromeos/system_logs/system_logs_fetcher_base.h"
 #include "ui/aura/root_window.h"
 #include "ui/aura/window.h"
 #endif
@@ -86,6 +87,7 @@
 #if defined(OS_CHROMEOS)
 
 const char kTimestampParameter[] = "timestamp=";
+const char kTraceIdParameter[] = "traceId=";
 
 const size_t kMaxSavedScreenshots = 2;
 size_t kMaxNumScanFiles = 1000;
@@ -236,6 +238,13 @@
 #if defined(OS_CHROMEOS)
   feedback_url = feedback_url + "&" + kTimestampParameter +
                  net::EscapeUrlEncodedData(timestamp, false);
+
+  // The manager is only available if tracing is enabled.
+  if (TracingManager* manager = TracingManager::Get()) {
+    int trace_id = manager->RequestTrace();
+    feedback_url = feedback_url + "&" + kTraceIdParameter +
+                   base::IntToString(trace_id);
+  }
 #endif
   chrome::ShowSingletonTab(browser, GURL(feedback_url));
 }
@@ -307,6 +316,8 @@
   source->AddLocalizedString("user-email", IDS_FEEDBACK_USER_EMAIL_LABEL);
 
 #if defined(OS_CHROMEOS)
+  source->AddLocalizedString("performance-trace",
+                             IDS_FEEDBACK_INCLUDE_PERFORMANCE_TRACE_CHECKBOX);
   source->AddLocalizedString("sysinfo",
                              IDS_FEEDBACK_INCLUDE_SYSTEM_INFORMATION_CHKBOX);
   source->AddLocalizedString("currentscreenshots",
@@ -608,6 +619,11 @@
   (*i++)->GetAsString(&sys_info_checkbox);
   bool send_sys_info = (sys_info_checkbox == "true");
 
+  std::string trace_id_str;
+  (*i++)->GetAsString(&trace_id_str);
+  int trace_id = 0;
+  base::StringToInt(trace_id_str, &trace_id);
+
   std::string attached_filename;
   scoped_ptr<std::string> attached_filedata;
   // If we have an attached file, we'll still have more data in the list.
@@ -645,6 +661,7 @@
   feedback_data_->set_attached_filename(attached_filename);
   feedback_data_->set_send_sys_info(send_sys_info);
   feedback_data_->set_timestamp(timestamp_);
+  feedback_data_->set_trace_id(trace_id);
 #endif
 
   // Signal the feedback object that the data from the feedback page has been
diff --git a/chrome/browser/ui/webui/flash_ui.cc b/chrome/browser/ui/webui/flash_ui.cc
index 52b70e3..bcd03e7 100644
--- a/chrome/browser/ui/webui/flash_ui.cc
+++ b/chrome/browser/ui/webui/flash_ui.cc
@@ -33,6 +33,7 @@
 #include "content/public/browser/web_ui.h"
 #include "content/public/browser/web_ui_data_source.h"
 #include "content/public/browser/web_ui_message_handler.h"
+#include "content/public/common/content_constants.h"
 #include "content/public/common/webplugininfo.h"
 #include "gpu/config/gpu_info.h"
 #include "grit/browser_resources.h"
@@ -41,7 +42,6 @@
 #include "grit/theme_resources.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/base/resource/resource_bundle.h"
-#include "webkit/plugins/plugin_constants.h"
 
 #if defined(OS_WIN)
 #include "base/win/windows_version.h"
@@ -268,7 +268,7 @@
   // Obtain the version of the Flash plugins.
   std::vector<content::WebPluginInfo> info_array;
   PluginService::GetInstance()->GetPluginInfoArray(
-      GURL(), kFlashPluginSwfMimeType, false, &info_array, NULL);
+      GURL(), content::kFlashPluginSwfMimeType, false, &info_array, NULL);
   if (info_array.empty()) {
     AddPair(list, ASCIIToUTF16(kFlashPlugin), "Not installed");
   } else {
diff --git a/chrome/browser/ui/webui/history_ui.cc b/chrome/browser/ui/webui/history_ui.cc
index 7a3f570..2b1f49e 100644
--- a/chrome/browser/ui/webui/history_ui.cc
+++ b/chrome/browser/ui/webui/history_ui.cc
@@ -184,6 +184,7 @@
   source->SetUseJsonJSFormatV2();
   source->DisableDenyXFrameOptions();
   source->AddBoolean("isManagedProfile", profile->IsManaged());
+  source->AddBoolean("showDeleteVisitUI", !profile->IsManaged());
 
   return source;
 }
diff --git a/chrome/browser/ui/webui/inline_login_ui.cc b/chrome/browser/ui/webui/inline_login_ui.cc
index 967d214..da5e138 100644
--- a/chrome/browser/ui/webui/inline_login_ui.cc
+++ b/chrome/browser/ui/webui/inline_login_ui.cc
@@ -132,7 +132,7 @@
         profile_, NULL, "0" /* session_index 0 for the default user */,
         UTF16ToASCII(email), UTF16ToASCII(password),
         OneClickSigninSyncStarter::SYNC_WITH_DEFAULT_SETTINGS,
-        true /* force_same_tab_navigation */,
+        web_ui()->GetWebContents(),
         OneClickSigninSyncStarter::NO_CONFIRMATION,
         signin::SOURCE_UNKNOWN,
         OneClickSigninSyncStarter::Callback());
diff --git a/chrome/browser/ui/webui/nacl_ui.cc b/chrome/browser/ui/webui/nacl_ui.cc
index b08affb..f38de6b 100644
--- a/chrome/browser/ui/webui/nacl_ui.cc
+++ b/chrome/browser/ui/webui/nacl_ui.cc
@@ -11,6 +11,7 @@
 #include "base/bind_helpers.h"
 #include "base/command_line.h"
 #include "base/file_util.h"
+#include "base/json/json_file_value_serializer.h"
 #include "base/memory/weak_ptr.h"
 #include "base/path_service.h"
 #include "base/strings/string16.h"
@@ -77,6 +78,7 @@
   // WebUIMessageHandler implementation.
   virtual void RegisterMessages() OVERRIDE;
 
+ private:
   // Callback for the "requestNaClInfo" message.
   void HandleRequestNaClInfo(const ListValue* args);
 
@@ -84,11 +86,10 @@
   void OnGotPlugins(const std::vector<content::WebPluginInfo>& plugins);
 
   // A helper callback that receives the result of checking if PNaCl path
-  // exists. |is_valid| is true if the PNaCl path that was returned by
-  // PathService is valid, and false otherwise.
-  void DidValidatePnaclPath(bool* is_valid);
+  // exists and checking the PNaCl |version|. |is_valid| is true if the PNaCl
+  // path that was returned by PathService is valid, and false otherwise.
+  void DidCheckPathAndVersion(bool* is_valid, std::string* version);
 
- private:
   // Called when enough information is gathered to return data back to the page.
   void MaybeRespondToPage();
 
@@ -108,7 +109,8 @@
   // Adds the list of plugins for NaCl to list.
   void AddPluginList(ListValue* list);
 
-  // Adds the information relevant to PNaCl (e.g., enablement, paths) to list.
+  // Adds the information relevant to PNaCl (e.g., enablement, paths, version)
+  // to the list.
   void AddPnaclInfo(ListValue* list);
 
   // Adds the information relevant to NaCl to list.
@@ -124,6 +126,7 @@
   // that does not exists, so it needs to be validated.
   bool pnacl_path_validated_;
   bool pnacl_path_exists_;
+  std::string pnacl_version_string_;
 
   DISALLOW_COPY_AND_ASSIGN(NaClDomHandler);
 };
@@ -265,12 +268,9 @@
     AddPair(list,
             ASCIIToUTF16("PNaCl translator path"),
             pnacl_path.LossyDisplayName());
-    // Version string is part of the directory name:
-    // pnacl/<version>/_platform_specific/<arch>/[files]
-    // Keep in sync with pnacl_component_installer.cc.
     AddPair(list,
             ASCIIToUTF16("PNaCl translator version"),
-            pnacl_path.DirName().DirName().BaseName().LossyDisplayName());
+            ASCIIToUTF16(pnacl_version_string_));
   }
   AddLineBreak(list);
 }
@@ -289,7 +289,7 @@
 
 void NaClDomHandler::HandleRequestNaClInfo(const ListValue* args) {
   page_has_requested_data_ = true;
-  // Force re-validation of pnacl's path in the next call to
+  // Force re-validation of PNaCl's path in the next call to
   // MaybeRespondToPage(), in case PNaCl went from not-installed
   // to installed since the request.
   pnacl_path_validated_ = false;
@@ -318,16 +318,35 @@
   naclInfo->Set("naclInfo", list.release());
 }
 
-void NaClDomHandler::DidValidatePnaclPath(bool* is_valid) {
+void NaClDomHandler::DidCheckPathAndVersion(bool* is_valid,
+                                            std::string* version) {
   pnacl_path_validated_ = true;
   pnacl_path_exists_ = *is_valid;
+  pnacl_version_string_ = *version;
   MaybeRespondToPage();
 }
 
-void ValidatePnaclPath(bool* is_valid) {
+void CheckVersion(const base::FilePath& pnacl_path, std::string* version) {
+  base::FilePath pnacl_json_path =
+      pnacl_path.Append(FILE_PATH_LITERAL("pnacl_public_pnacl_json"));
+  JSONFileValueSerializer serializer(pnacl_json_path);
+  std::string error;
+  scoped_ptr<base::Value> root(serializer.Deserialize(NULL, &error));
+  if (!root || !root->IsType(base::Value::TYPE_DICTIONARY))
+    return;
+
+  // Now try to get the field. This may leave version empty if the
+  // the "get" fails (no key, or wrong type).
+  static_cast<base::DictionaryValue*>(root.get())->
+      GetStringASCII("pnacl-version", version);
+}
+
+void CheckPathAndVersion(bool* is_valid, std::string* version) {
   base::FilePath pnacl_path;
   bool got_path = PathService::Get(chrome::DIR_PNACL_COMPONENT, &pnacl_path);
   *is_valid = got_path && !pnacl_path.empty() && base::PathExists(pnacl_path);
+  if (*is_valid)
+    CheckVersion(pnacl_path, version);
 }
 
 void NaClDomHandler::MaybeRespondToPage() {
@@ -338,12 +357,14 @@
 
   if (!pnacl_path_validated_) {
     bool* is_valid = new bool;
+    std::string* version_string = new std::string;
     BrowserThread::PostBlockingPoolTaskAndReply(
         FROM_HERE,
-        base::Bind(&ValidatePnaclPath, is_valid),
-        base::Bind(&NaClDomHandler::DidValidatePnaclPath,
+        base::Bind(&CheckPathAndVersion, is_valid, version_string),
+        base::Bind(&NaClDomHandler::DidCheckPathAndVersion,
                    weak_ptr_factory_.GetWeakPtr(),
-                   base::Owned(is_valid)));
+                   base::Owned(is_valid),
+                   base::Owned(version_string)));
     return;
   }
 
diff --git a/chrome/browser/ui/webui/ntp/android/new_tab_page_ready_handler.cc b/chrome/browser/ui/webui/ntp/android/new_tab_page_ready_handler.cc
index d81f34b..4e3f727 100644
--- a/chrome/browser/ui/webui/ntp/android/new_tab_page_ready_handler.cc
+++ b/chrome/browser/ui/webui/ntp/android/new_tab_page_ready_handler.cc
@@ -7,8 +7,7 @@
 #include "base/bind.h"
 #include "base/logging.h"
 #include "base/values.h"
-#include "chrome/browser/chrome_notification_types.h"
-#include "content/public/browser/notification_service.h"
+#include "chrome/browser/android/tab_android.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/browser/web_ui.h"
 
@@ -36,10 +35,10 @@
 
 void NewTabPageReadyHandler::HandleNewTabPageReady(
     const ListValue* args) {
-  content::NotificationService::current()->Notify(
-      chrome::NOTIFICATION_NEW_TAB_READY,
-      content::Source<content::WebContents>(web_ui()->GetWebContents()),
-      content::NotificationService::NoDetails());
+  TabAndroid* tab = TabAndroid::FromWebContents(web_ui()->GetWebContents());
+  if (!tab)
+    return;
+  tab->OnNewTabPageReady();
 }
 
 void NewTabPageReadyHandler::HandleNewTabPageUnexpectedNavigation(
diff --git a/chrome/browser/ui/webui/ntp/app_launcher_handler.cc b/chrome/browser/ui/webui/ntp/app_launcher_handler.cc
index 6d7d9ee..4de0128 100644
--- a/chrome/browser/ui/webui/ntp/app_launcher_handler.cc
+++ b/chrome/browser/ui/webui/ntp/app_launcher_handler.cc
@@ -317,12 +317,6 @@
       }
       break;
     }
-    // The promo may not load until a couple seconds after the first NTP view,
-    // so we listen for the load notification and notify the NTP when ready.
-    case chrome::NOTIFICATION_WEB_STORE_PROMO_LOADED:
-      // TODO(estade): Try to get rid of this inefficient operation.
-      HandleGetApps(NULL);
-      break;
     case chrome::NOTIFICATION_EXTENSION_INSTALL_ERROR: {
       CrxInstaller* crx_installer = content::Source<CrxInstaller>(source).ptr();
       if (!Profile::FromWebUI(web_ui())->IsSameProfile(
@@ -454,8 +448,6 @@
     registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_LAUNCHER_REORDERED,
         content::Source<ExtensionSorting>(
             extension_service_->extension_prefs()->extension_sorting()));
-    registrar_.Add(this, chrome::NOTIFICATION_WEB_STORE_PROMO_LOADED,
-        content::Source<Profile>(profile));
     registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_INSTALL_ERROR,
         content::Source<CrxInstaller>(NULL));
     registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_LOAD_ERROR,
@@ -727,7 +719,7 @@
   }
 
   scoped_refptr<CrxInstaller> installer(
-      CrxInstaller::Create(extension_service_, NULL));
+      CrxInstaller::CreateSilent(extension_service_));
   installer->set_error_on_unsupported_requirements(true);
   installer->set_page_ordinal(install_info->page_ordinal);
   installer->InstallWebApp(*web_app);
diff --git a/chrome/browser/ui/webui/options/browser_options_handler.cc b/chrome/browser/ui/webui/options/browser_options_handler.cc
index bc9f5c1..7fc38bd 100644
--- a/chrome/browser/ui/webui/options/browser_options_handler.cc
+++ b/chrome/browser/ui/webui/options/browser_options_handler.cc
@@ -585,6 +585,10 @@
       "themesReset",
       base::Bind(&BrowserOptionsHandler::ThemesReset,
                  base::Unretained(this)));
+  web_ui()->RegisterMessageCallback(
+      "requestProfilesInfo",
+      base::Bind(&BrowserOptionsHandler::HandleRequestProfilesInfo,
+                 base::Unretained(this)));
 #if defined(OS_LINUX) && !defined(OS_CHROMEOS)
   web_ui()->RegisterMessageCallback(
       "themesSetNative",
@@ -1484,6 +1488,10 @@
   chrome::AttemptRestart();
 }
 
+void BrowserOptionsHandler::HandleRequestProfilesInfo(const ListValue* args) {
+  SendProfilesInfo();
+}
+
 #if !defined(OS_CHROMEOS)
 void BrowserOptionsHandler::ShowNetworkProxySettings(const ListValue* args) {
   content::RecordAction(UserMetricsAction("Options_ShowProxySettings"));
diff --git a/chrome/browser/ui/webui/options/browser_options_handler.h b/chrome/browser/ui/webui/options/browser_options_handler.h
index 6dbc64d..b0ca806 100644
--- a/chrome/browser/ui/webui/options/browser_options_handler.h
+++ b/chrome/browser/ui/webui/options/browser_options_handler.h
@@ -228,6 +228,9 @@
   // Callback for the "restartBrowser" message. Restores all tabs on restart.
   void HandleRestartBrowser(const ListValue* args);
 
+  // Callback for "requestProfilesInfo" message.
+  void HandleRequestProfilesInfo(const ListValue* args);
+
 #if !defined(OS_CHROMEOS)
   // Callback for the "showNetworkProxySettings" message. This will invoke
   // an appropriate dialog for configuring proxy settings.
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 8861b50..d02c3b3 100644
--- a/chrome/browser/ui/webui/options/chromeos/display_options_handler.cc
+++ b/chrome/browser/ui/webui/options/chromeos/display_options_handler.cc
@@ -9,6 +9,7 @@
 #include "ash/display/display_controller.h"
 #include "ash/display/display_manager.h"
 #include "ash/display/output_configurator_animation.h"
+#include "ash/display/resolution_notification_controller.h"
 #include "ash/screen_ash.h"
 #include "ash/shell.h"
 #include "base/bind.h"
@@ -19,6 +20,7 @@
 #include "chrome/browser/chromeos/display/display_preferences.h"
 #include "chromeos/display/output_configurator.h"
 #include "content/public/browser/web_ui.h"
+#include "grit/ash_strings.h"
 #include "grit/generated_resources.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/gfx/display.h"
@@ -100,11 +102,11 @@
   localized_strings->SetString("orientation0", l10n_util::GetStringUTF16(
       IDS_OPTIONS_SETTINGS_DISPLAY_OPTIONS_STANDARD_ORIENTATION));
   localized_strings->SetString("orientation90", l10n_util::GetStringUTF16(
-      IDS_OPTIONS_SETTINGS_DISPLAY_OPTIONS_ORIENTATION_90));
+      IDS_ASH_STATUS_TRAY_DISPLAY_ORIENTATION_90));
   localized_strings->SetString("orientation180", l10n_util::GetStringUTF16(
-      IDS_OPTIONS_SETTINGS_DISPLAY_OPTIONS_ORIENTATION_180));
+      IDS_ASH_STATUS_TRAY_DISPLAY_ORIENTATION_180));
   localized_strings->SetString("orientation270", l10n_util::GetStringUTF16(
-      IDS_OPTIONS_SETTINGS_DISPLAY_OPTIONS_ORIENTATION_270));
+      IDS_ASH_STATUS_TRAY_DISPLAY_ORIENTATION_270));
   localized_strings->SetString(
       "startCalibratingOverscan", l10n_util::GetStringUTF16(
           IDS_OPTIONS_SETTINGS_DISPLAY_OPTIONS_START_CALIBRATING_OVERSCAN));
@@ -343,9 +345,34 @@
     return;
   }
 
-  // TODO(mukai): creates a confirmation dialog.
-  GetDisplayManager()->SetDisplayResolution(
-      display_id, gfx::ToFlooredSize(gfx::SizeF(width, height)));
+  const ash::internal::DisplayInfo& display_info =
+      GetDisplayManager()->GetDisplayInfo(display_id);
+  gfx::Size new_resolution = gfx::ToFlooredSize(gfx::SizeF(width, height));
+  gfx::Size old_resolution = display_info.size_in_pixel();
+  bool has_new_resolution = false;
+  bool has_old_resolution = false;
+  for (size_t i = 0; i < display_info.resolutions().size(); ++i) {
+    ash::internal::Resolution resolution = display_info.resolutions()[i];
+    if (resolution.size == new_resolution)
+      has_new_resolution = true;
+    if (resolution.size == old_resolution)
+      has_old_resolution = true;
+  }
+  if (!has_new_resolution) {
+    LOG(ERROR) << "No new resolution " << new_resolution.ToString()
+               << " is found in the display info " << display_info.ToString();
+    return;
+  }
+  if (!has_old_resolution) {
+    LOG(ERROR) << "No old resolution " << old_resolution.ToString()
+               << " is found in the display info " << display_info.ToString();
+    return;
+  }
+
+  ash::Shell::GetInstance()->resolution_notification_controller()->
+      SetDisplayResolutionAndNotify(
+          display_id, old_resolution, new_resolution,
+          base::Bind(&StoreDisplayPrefs));
 }
 
 void DisplayOptionsHandler::HandleSetOrientation(const base::ListValue* args) {
diff --git a/chrome/browser/ui/webui/options/chromeos/internet_options_handler.cc b/chrome/browser/ui/webui/options/chromeos/internet_options_handler.cc
index 7cb13218..6537a55 100644
--- a/chrome/browser/ui/webui/options/chromeos/internet_options_handler.cc
+++ b/chrome/browser/ui/webui/options/chromeos/internet_options_handler.cc
@@ -281,15 +281,6 @@
       base::Bind(&ShillError, "SetNetworkProperty"));
 }
 
-const base::DictionaryValue* FindPolicyForActiveUser(
-    const NetworkState* network,
-    onc::ONCSource* onc_source) {
-  const User* user = UserManager::Get()->GetActiveUser();
-  std::string username_hash = user ? user->username_hash() : std::string();
-  return NetworkHandler::Get()->managed_network_configuration_handler()
-      ->FindPolicyByGUID(username_hash, network->guid(), onc_source);
-}
-
 std::string ActivationStateString(const std::string& activation_state) {
   int id;
   if (activation_state == flimflam::kActivationStateActivated)
@@ -656,7 +647,8 @@
   dictionary->SetString(kTagUsername, username);
 
   onc::ONCSource onc_source = onc::ONC_SOURCE_NONE;
-  const base::DictionaryValue* onc = FindPolicyForActiveUser(vpn, &onc_source);
+  const base::DictionaryValue* onc =
+      network_connect::FindPolicyForActiveUser(vpn, &onc_source);
 
   NetworkPropertyUIData hostname_ui_data;
   hostname_ui_data.ParseOncProperty(
@@ -945,6 +937,7 @@
   web_ui()->CallJavascriptFunction(kSetDefaultNetworkIconsFunction,
                                    dictionary);
   NetworkHandler::Get()->network_state_handler()->RequestScan();
+  RefreshNetworkData();
 }
 
 void InternetOptionsHandler::RegisterMessages() {
@@ -1164,7 +1157,7 @@
     const NetworkState* network =
         handler->FirstNetworkByType(flimflam::kTypeCellular);
     if (network) {
-      chromeos::network_connect::ActivateCellular(network->path());
+      ash::network_connect::ActivateCellular(network->path());
       UpdateConnectionData(network->path());
     }
   }
@@ -1446,7 +1439,7 @@
 
   onc::ONCSource onc_source = onc::ONC_SOURCE_NONE;
   const base::DictionaryValue* onc =
-      FindPolicyForActiveUser(network, &onc_source);
+      network_connect::FindPolicyForActiveUser(network, &onc_source);
   const NetworkPropertyUIData property_ui_data(onc_source);
 
   base::DictionaryValue dictionary;
@@ -1691,7 +1684,7 @@
     // caching them (will be done for the new UI).
     const base::DictionaryValue& device_properties = device->properties();
     const NetworkPropertyUIData cellular_property_ui_data(
-        cellular->onc_source());
+        cellular->ui_data().onc_source());
     CopyStringFromDictionary(device_properties, flimflam::kManufacturerProperty,
                             kTagManufacturer, dictionary);
     CopyStringFromDictionary(device_properties, flimflam::kModelIDProperty,
@@ -1849,17 +1842,16 @@
                    weak_factory_.GetWeakPtr()),
         base::Bind(&ShillError, "NetworkCommand: " + command));
   } else if (command == kTagConnect) {
-    network_connect::ConnectToNetwork(
-        service_path, GetNativeWindow());
+    ash::network_connect::ConnectToNetwork(service_path, GetNativeWindow());
   } else if (command == kTagDisconnect) {
     NetworkHandler::Get()->network_connection_handler()->DisconnectNetwork(
         service_path,
         base::Bind(&base::DoNothing),
         base::Bind(&ShillError, "NetworkCommand: " + command));
   } else if (command == kTagConfigure) {
-    NetworkConfigView::ShowForPath(service_path, GetNativeWindow());
+    NetworkConfigView::Show(service_path, GetNativeWindow());
   } else if (command == kTagActivate && type == flimflam::kTypeCellular) {
-    network_connect::ActivateCellular(service_path);
+    ash::network_connect::ActivateCellular(service_path);
     // Activation may update network properties (e.g. ActivationState), so
     // request them here in case they change.
     UpdateConnectionData(service_path);
@@ -1871,9 +1863,9 @@
 
 void InternetOptionsHandler::AddConnection(const std::string& type) {
   if (type == flimflam::kTypeWifi)
-    NetworkConfigView::ShowForType(chromeos::TYPE_WIFI, GetNativeWindow());
+    NetworkConfigView::ShowForType(flimflam::kTypeWifi, GetNativeWindow());
   else if (type == flimflam::kTypeVPN)
-    NetworkConfigView::ShowForType(chromeos::TYPE_VPN, GetNativeWindow());
+    NetworkConfigView::ShowForType(flimflam::kTypeVPN, GetNativeWindow());
   else if (type == flimflam::kTypeCellular)
     ChooseMobileNetworkDialog::ShowDialog(GetNativeWindow());
   else
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 3d11f05..0b578e0 100644
--- a/chrome/browser/ui/webui/options/clear_browser_data_handler.cc
+++ b/chrome/browser/ui/webui/options/clear_browser_data_handler.cc
@@ -133,6 +133,8 @@
     time_list->Append(option);
   }
   localized_strings->Set("clearBrowserDataTimeList", time_list);
+  localized_strings->SetBoolean("showDeleteBrowsingHistoryCheckboxes",
+                                !Profile::FromWebUI(web_ui())->IsManaged());
 }
 
 void ClearBrowserDataHandler::RegisterMessages() {
diff --git a/chrome/browser/ui/webui/options/import_data_handler.cc b/chrome/browser/ui/webui/options/import_data_handler.cc
index b456d25..cc12315 100644
--- a/chrome/browser/ui/webui/options/import_data_handler.cc
+++ b/chrome/browser/ui/webui/options/import_data_handler.cc
@@ -22,6 +22,8 @@
 #include "chrome/browser/importer/importer_uma.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/browser_finder.h"
+#include "chrome/browser/ui/browser_window.h"
+#include "chrome/browser/ui/chrome_select_file_policy.h"
 #include "content/public/browser/web_ui.h"
 #include "grit/chromium_strings.h"
 #include "grit/generated_resources.h"
@@ -34,11 +36,14 @@
 }
 
 ImportDataHandler::~ImportDataHandler() {
-  if (importer_list_.get())
+  if (importer_list_)
     importer_list_->set_observer(NULL);
 
   if (importer_host_)
     importer_host_->set_observer(NULL);
+
+  if (select_file_dialog_)
+    select_file_dialog_->ListenerDestroyed();
 }
 
 void ImportDataHandler::GetLocalizedValues(DictionaryValue* localized_strings) {
@@ -52,10 +57,12 @@
     { "importFavorites", IDS_IMPORT_FAVORITES_CHKBOX },
     { "importSearch", IDS_IMPORT_SEARCH_ENGINES_CHKBOX },
     { "importPasswords", IDS_IMPORT_PASSWORDS_CHKBOX },
+    { "importChooseFile", IDS_IMPORT_CHOOSE_FILE },
     { "importCommit", IDS_IMPORT_COMMIT },
     { "noProfileFound", IDS_IMPORT_NO_PROFILE_FOUND },
     { "importSucceeded", IDS_IMPORT_SUCCEEDED },
     { "findYourImportedBookmarks", IDS_IMPORT_FIND_YOUR_BOOKMARKS },
+    { "macPasswordKeychain", IDS_IMPORT_PASSWORD_KEYCHAIN_WARNING },
   };
 
   RegisterStrings(localized_strings, resources, arraysize(resources));
@@ -70,8 +77,13 @@
 }
 
 void ImportDataHandler::RegisterMessages() {
-  web_ui()->RegisterMessageCallback("importData",
+  web_ui()->RegisterMessageCallback(
+      "importData",
       base::Bind(&ImportDataHandler::ImportData, base::Unretained(this)));
+  web_ui()->RegisterMessageCallback(
+      "chooseBookmarksFile",
+      base::Bind(&ImportDataHandler::HandleChooseBookmarksFile,
+                 base::Unretained(this)));
 }
 
 void ImportDataHandler::ImportData(const ListValue* args) {
@@ -150,6 +162,13 @@
     browser_profile->SetBoolean("search",
         (browser_services & importer::SEARCH_ENGINES) != 0);
 
+    browser_profile->SetBoolean("show_bottom_bar",
+#if defined(OS_MACOSX)
+        source_profile.importer_type == importer::TYPE_SAFARI);
+#else
+        false);
+#endif
+
     browser_profiles.Append(browser_profile);
   }
 
@@ -183,4 +202,47 @@
   }
 }
 
+void ImportDataHandler::FileSelected(const base::FilePath& path,
+                                     int index,
+                                     void* params) {
+  base::FundamentalValue importing(true);
+  web_ui()->CallJavascriptFunction("ImportDataOverlay.setImportingState",
+                                   importing);
+  import_did_succeed_ = false;
+
+  importer_host_ = new ExternalProcessImporterHost();
+  importer_host_->set_observer(this);
+
+  importer::SourceProfile source_profile;
+  source_profile.importer_type = importer::TYPE_BOOKMARKS_FILE;
+  source_profile.source_path = path;
+
+  Profile* profile = Profile::FromWebUI(web_ui());
+
+  importer_host_->StartImportSettings(
+      source_profile, profile, importer::FAVORITES, new ProfileWriter(profile));
+}
+
+void ImportDataHandler::HandleChooseBookmarksFile(const base::ListValue* args) {
+  DCHECK(args && args->empty());
+  select_file_dialog_ = ui::SelectFileDialog::Create(
+      this, new ChromeSelectFilePolicy(web_ui()->GetWebContents()));
+
+  ui::SelectFileDialog::FileTypeInfo file_type_info;
+  file_type_info.extensions.resize(1);
+  file_type_info.extensions[0].push_back(FILE_PATH_LITERAL("html"));
+
+  Browser* browser =
+      chrome::FindBrowserWithWebContents(web_ui()->GetWebContents());
+
+  select_file_dialog_->SelectFile(ui::SelectFileDialog::SELECT_OPEN_FILE,
+                                  base::string16(),
+                                  base::FilePath(),
+                                  &file_type_info,
+                                  0,
+                                  base::FilePath::StringType(),
+                                  browser->window()->GetNativeWindow(),
+                                  NULL);
+}
+
 }  // namespace options
diff --git a/chrome/browser/ui/webui/options/import_data_handler.h b/chrome/browser/ui/webui/options/import_data_handler.h
index 79bd035..08ca902 100644
--- a/chrome/browser/ui/webui/options/import_data_handler.h
+++ b/chrome/browser/ui/webui/options/import_data_handler.h
@@ -12,6 +12,7 @@
 #include "chrome/browser/importer/importer_progress_observer.h"
 #include "chrome/browser/ui/webui/options/options_ui.h"
 #include "chrome/common/importer/importer_data_types.h"
+#include "ui/shell_dialogs/select_file_dialog.h"
 
 class ExternalProcessImporterHost;
 class ImporterList;
@@ -21,7 +22,8 @@
 // Chrome personal stuff import data overlay UI handler.
 class ImportDataHandler : public OptionsPageUIHandler,
                           public importer::ImporterListObserver,
-                          public importer::ImporterProgressObserver {
+                          public importer::ImporterProgressObserver,
+                          public ui::SelectFileDialog::Listener {
  public:
   ImportDataHandler();
   virtual ~ImportDataHandler();
@@ -32,7 +34,7 @@
   virtual void InitializeHandler() OVERRIDE;
   virtual void InitializePage() OVERRIDE;
 
-  // WebUIMessageHandler:
+  // content::WebUIMessageHandler:
   virtual void RegisterMessages() OVERRIDE;
 
  private:
@@ -47,6 +49,14 @@
   virtual void ImportItemEnded(importer::ImportItem item) OVERRIDE;
   virtual void ImportEnded() OVERRIDE;
 
+  // ui::SelectFileDialog::Listener:
+  virtual void FileSelected(const base::FilePath& path,
+                            int index,
+                            void* params) OVERRIDE;
+
+  // Opens a file selection dialog to choose the bookmarks HTML file.
+  void HandleChooseBookmarksFile(const base::ListValue* args);
+
   scoped_refptr<ImporterList> importer_list_;
 
   // If non-null it means importing is in progress. ImporterHost takes care
@@ -55,6 +65,8 @@
 
   bool import_did_succeed_;
 
+  scoped_refptr<ui::SelectFileDialog> select_file_dialog_;
+
   DISALLOW_COPY_AND_ASSIGN(ImportDataHandler);
 };
 
diff --git a/chrome/browser/ui/webui/options/manage_profile_handler.cc b/chrome/browser/ui/webui/options/manage_profile_handler.cc
index 4c78ff3..a7d0152 100644
--- a/chrome/browser/ui/webui/options/manage_profile_handler.cc
+++ b/chrome/browser/ui/webui/options/manage_profile_handler.cc
@@ -27,6 +27,8 @@
 #include "chrome/browser/profiles/profiles_state.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/ui/browser_finder.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/common/pref_names.h"
@@ -65,11 +67,11 @@
     Profile::CreateStatus status) {
   if (status == Profile::CREATE_STATUS_INITIALIZED) {
     profiles::FindOrCreateNewWindowForProfile(
-      profile,
-      chrome::startup::IS_PROCESS_STARTUP,
-      chrome::startup::IS_FIRST_RUN,
-      desktop_type,
-      false);
+        profile,
+        chrome::startup::IS_PROCESS_STARTUP,
+        chrome::startup::IS_FIRST_RUN,
+        desktop_type,
+        false);
   }
 }
 
@@ -92,9 +94,13 @@
         IDS_PROFILES_MANAGE_DUPLICATE_NAME_ERROR },
     { "manageProfilesIconLabel", IDS_PROFILES_MANAGE_ICON_LABEL },
     { "manageProfilesManagedSignedInLabel",
-    IDS_PROFILES_CREATE_MANAGED_SIGNED_IN_LABEL },
+        IDS_PROFILES_CREATE_MANAGED_SIGNED_IN_LABEL },
     { "manageProfilesManagedNotSignedInLabel",
         IDS_PROFILES_CREATE_MANAGED_NOT_SIGNED_IN_LABEL },
+    { "manageProfilesManagedAccountDetailsOutOfDate",
+        IDS_PROFILES_CREATE_MANAGED_ACCOUNT_DETAILS_OUT_OF_DATE_LABEL },
+    { "manageProfilesManagedSignInAgainLink",
+        IDS_PROFILES_CREATE_MANAGED_ACCOUNT_SIGN_IN_AGAIN_LINK },
     { "manageProfilesManagedNotSignedInLink",
         IDS_PROFILES_CREATE_MANAGED_NOT_SIGNED_IN_LINK },
     { "manageProfilesSelectExistingManagedProfileLabel",
@@ -443,13 +449,20 @@
 
 void ManageProfileHandler::RequestCreateProfileUpdate(
     const base::ListValue* args) {
+  Profile* profile = Profile::FromWebUI(web_ui());
   SigninManagerBase* manager =
-      SigninManagerFactory::GetForProfile(Profile::FromWebUI(web_ui()));
+      SigninManagerFactory::GetForProfile(profile);
   string16 username = UTF8ToUTF16(manager->GetAuthenticatedUsername());
-  StringValue username_value(username);
+  ProfileSyncService* service =
+     ProfileSyncServiceFactory::GetForProfile(profile);
+  GoogleServiceAuthError::State state = service->GetAuthError().state();
+  bool has_error = (state == GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS ||
+                    state == GoogleServiceAuthError::USER_NOT_SIGNED_UP ||
+                    state == GoogleServiceAuthError::ACCOUNT_DELETED ||
+                    state == GoogleServiceAuthError::ACCOUNT_DISABLED);
   web_ui()->CallJavascriptFunction("CreateProfileOverlay.updateSignedInStatus",
-                                   username_value);
-
+                                   base::StringValue(username),
+                                   base::FundamentalValue(has_error));
   OnCreateManagedUserPrefChange();
 }
 
diff --git a/chrome/browser/ui/webui/options/reset_profile_settings_handler.cc b/chrome/browser/ui/webui/options/reset_profile_settings_handler.cc
index 6222f91..a726a26 100644
--- a/chrome/browser/ui/webui/options/reset_profile_settings_handler.cc
+++ b/chrome/browser/ui/webui/options/reset_profile_settings_handler.cc
@@ -95,7 +95,7 @@
     ResettableSettingsSnapshot current_snapshot(profile);
     int difference = setting_snapshot_->FindDifferentFields(current_snapshot);
     if (difference) {
-      setting_snapshot_->SubtractStartupURLs(current_snapshot);
+      setting_snapshot_->Subtract(current_snapshot);
       std::string report = SerializeSettingsReport(*setting_snapshot_,
                                                    difference);
       SendSettingsFeedback(report, profile);
diff --git a/chrome/browser/ui/webui/signin/user_chooser_ui.h b/chrome/browser/ui/webui/signin/user_chooser_ui.h
deleted file mode 100644
index 4799bd7..0000000
--- a/chrome/browser/ui/webui/signin/user_chooser_ui.h
+++ /dev/null
@@ -1,35 +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_UI_WEBUI_SIGNIN_USER_CHOOSER_UI_H_
-#define CHROME_BROWSER_UI_WEBUI_SIGNIN_USER_CHOOSER_UI_H_
-
-#include "content/public/browser/web_ui_controller.h"
-
-class UserChooserScreenHandler;
-
-namespace base {
-class DictionaryValue;
-}
-namespace content {
-class WebUIDataSource;
-}
-
-// A WebUI dialog to display available users.
-class UserChooserUI : public content::WebUIController {
- public:
-  explicit UserChooserUI(content::WebUI* web_ui);
-  virtual ~UserChooserUI();
-
- private:
-  content::WebUIDataSource* CreateUIDataSource(
-      const base::DictionaryValue& localized_strings);
-  void GetLocalizedStrings(base::DictionaryValue* localized_strings);
-
-  UserChooserScreenHandler* user_chooser_screen_handler_;
-
-  DISALLOW_COPY_AND_ASSIGN(UserChooserUI);
-};
-
-#endif  // CHROME_BROWSER_UI_WEBUI_SIGNIN_USER_CHOOSER_UI_H_
diff --git a/chrome/browser/ui/webui/signin/user_chooser_screen_handler.cc b/chrome/browser/ui/webui/signin/user_manager_screen_handler.cc
similarity index 83%
rename from chrome/browser/ui/webui/signin/user_chooser_screen_handler.cc
rename to chrome/browser/ui/webui/signin/user_manager_screen_handler.cc
index c132816..3405777 100644
--- a/chrome/browser/ui/webui/signin/user_chooser_screen_handler.cc
+++ b/chrome/browser/ui/webui/signin/user_manager_screen_handler.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 "chrome/browser/ui/webui/signin/user_chooser_screen_handler.h"
+#include "chrome/browser/ui/webui/signin/user_manager_screen_handler.h"
 
 #include "base/bind.h"
 #include "base/value_conversions.h"
@@ -56,11 +56,11 @@
 const char kSourceAccountPicker[] = "account-picker";
 
 // JS API callback names.
-const char kJsApiUserChooserInitialize[] = "userChooserInitialize";
-const char kJsApiUserChooserAddUser[] = "addUser";
-const char kJsApiUserChooserLaunchGuest[] = "launchGuest";
-const char kJsApiUserChooserLaunchUser[] = "launchUser";
-const char kJsApiUserChooserRemoveUser[] = "removeUser";
+const char kJsApiUserManagerInitialize[] = "userManagerInitialize";
+const char kJsApiUserManagerAddUser[] = "addUser";
+const char kJsApiUserManagerLaunchGuest[] = "launchGuest";
+const char kJsApiUserManagerLaunchUser[] = "launchUser";
+const char kJsApiUserManagerRemoveUser[] = "removeUser";
 
 const size_t kAvatarIconSize = 160;
 
@@ -99,15 +99,15 @@
 
 // ProfileUpdateObserver ------------------------------------------------------
 
-class UserChooserScreenHandler::ProfileUpdateObserver
+class UserManagerScreenHandler::ProfileUpdateObserver
     : public ProfileInfoCacheObserver {
  public:
   ProfileUpdateObserver(
-      ProfileManager* profile_manager, UserChooserScreenHandler* handler)
+      ProfileManager* profile_manager, UserManagerScreenHandler* handler)
       : profile_manager_(profile_manager),
-        user_chooser_handler_(handler) {
+        user_manager_handler_(handler) {
     DCHECK(profile_manager_);
-    DCHECK(user_chooser_handler_);
+    DCHECK(user_manager_handler_);
     profile_manager_->GetProfileInfoCache().AddObserver(this);
   }
 
@@ -121,12 +121,12 @@
   // If any change has been made to a profile, propagate it to all the
   // visible user manager screens.
   virtual void OnProfileAdded(const base::FilePath& profile_path) OVERRIDE {
-    user_chooser_handler_->SendUserList();
+    user_manager_handler_->SendUserList();
   }
 
   virtual void OnProfileWasRemoved(const base::FilePath& profile_path,
                                    const string16& profile_name) OVERRIDE {
-    user_chooser_handler_->SendUserList();
+    user_manager_handler_->SendUserList();
   }
 
   virtual void OnProfileWillBeRemoved(
@@ -137,45 +137,45 @@
 
   virtual void OnProfileNameChanged(const base::FilePath& profile_path,
                                     const string16& old_profile_name) OVERRIDE {
-    user_chooser_handler_->SendUserList();
+    user_manager_handler_->SendUserList();
   }
 
   virtual void OnProfileAvatarChanged(
       const base::FilePath& profile_path) OVERRIDE {
-    user_chooser_handler_->SendUserList();
+    user_manager_handler_->SendUserList();
   }
 
   ProfileManager* profile_manager_;
 
-  UserChooserScreenHandler* user_chooser_handler_;  // Weak; owns us.
+  UserManagerScreenHandler* user_manager_handler_;  // Weak; owns us.
 
   DISALLOW_COPY_AND_ASSIGN(ProfileUpdateObserver);
 };
 
-// UserChooserScreenHandler ---------------------------------------------------
+// UserManagerScreenHandler ---------------------------------------------------
 
-UserChooserScreenHandler::UserChooserScreenHandler() {
+UserManagerScreenHandler::UserManagerScreenHandler() {
   profileInfoCacheObserver_.reset(
-      new UserChooserScreenHandler::ProfileUpdateObserver(
+      new UserManagerScreenHandler::ProfileUpdateObserver(
           g_browser_process->profile_manager(), this));
 }
 
-UserChooserScreenHandler::~UserChooserScreenHandler() {
+UserManagerScreenHandler::~UserManagerScreenHandler() {
 }
 
-void UserChooserScreenHandler::HandleInitialize(const base::ListValue* args) {
+void UserManagerScreenHandler::HandleInitialize(const base::ListValue* args) {
   SendUserList();
-  web_ui()->CallJavascriptFunction("cr.ui.Oobe.showUserChooserScreen");
+  web_ui()->CallJavascriptFunction("cr.ui.Oobe.showUserManagerScreen");
 }
 
-void UserChooserScreenHandler::HandleAddUser(const base::ListValue* args) {
+void UserManagerScreenHandler::HandleAddUser(const base::ListValue* args) {
   // TODO(noms): Should redirect to a sign in page.
   chrome::ShowSingletonTab(chrome::FindBrowserWithWebContents(
       web_ui()->GetWebContents()),
       GURL("chrome://settings/createProfile"));
 }
 
-void UserChooserScreenHandler::HandleRemoveUser(const base::ListValue* args) {
+void UserManagerScreenHandler::HandleRemoveUser(const base::ListValue* args) {
   DCHECK(args);
   const Value* profile_path_value;
   if (!args->Get(0, &profile_path_value))
@@ -203,12 +203,12 @@
       base::Bind(&OpenNewWindowForProfile, desktop_type));
 }
 
-void UserChooserScreenHandler::HandleLaunchGuest(const base::ListValue* args) {
+void UserManagerScreenHandler::HandleLaunchGuest(const base::ListValue* args) {
   AvatarMenuModel::SwitchToGuestProfileWindow(
       chrome::FindBrowserWithWebContents(web_ui()->GetWebContents()));
 }
 
-void UserChooserScreenHandler::HandleLaunchUser(const base::ListValue* args) {
+void UserManagerScreenHandler::HandleLaunchUser(const base::ListValue* args) {
   string16 emailAddress;
   string16 displayName;
 
@@ -232,21 +232,21 @@
   }
 }
 
-void UserChooserScreenHandler::RegisterMessages() {
-  web_ui()->RegisterMessageCallback(kJsApiUserChooserInitialize,
-      base::Bind(&UserChooserScreenHandler::HandleInitialize,
+void UserManagerScreenHandler::RegisterMessages() {
+  web_ui()->RegisterMessageCallback(kJsApiUserManagerInitialize,
+      base::Bind(&UserManagerScreenHandler::HandleInitialize,
                  base::Unretained(this)));
-  web_ui()->RegisterMessageCallback(kJsApiUserChooserAddUser,
-      base::Bind(&UserChooserScreenHandler::HandleAddUser,
+  web_ui()->RegisterMessageCallback(kJsApiUserManagerAddUser,
+      base::Bind(&UserManagerScreenHandler::HandleAddUser,
                  base::Unretained(this)));
-  web_ui()->RegisterMessageCallback(kJsApiUserChooserLaunchGuest,
-      base::Bind(&UserChooserScreenHandler::HandleLaunchGuest,
+  web_ui()->RegisterMessageCallback(kJsApiUserManagerLaunchGuest,
+      base::Bind(&UserManagerScreenHandler::HandleLaunchGuest,
                  base::Unretained(this)));
-  web_ui()->RegisterMessageCallback(kJsApiUserChooserLaunchUser,
-      base::Bind(&UserChooserScreenHandler::HandleLaunchUser,
+  web_ui()->RegisterMessageCallback(kJsApiUserManagerLaunchUser,
+      base::Bind(&UserManagerScreenHandler::HandleLaunchUser,
                  base::Unretained(this)));
-  web_ui()->RegisterMessageCallback(kJsApiUserChooserRemoveUser,
-      base::Bind(&UserChooserScreenHandler::HandleRemoveUser,
+  web_ui()->RegisterMessageCallback(kJsApiUserManagerRemoveUser,
+      base::Bind(&UserManagerScreenHandler::HandleRemoveUser,
                  base::Unretained(this)));
 
   const content::WebUI::MessageCallback& kDoNothingCallback =
@@ -261,11 +261,9 @@
   web_ui()->RegisterMessageCallback("loadWallpaper", kDoNothingCallback);
   web_ui()->RegisterMessageCallback("updateCurrentScreen", kDoNothingCallback);
   web_ui()->RegisterMessageCallback("loginVisible", kDoNothingCallback);
-  // Unused callbacks from user_pod_row.js
-  web_ui()->RegisterMessageCallback("userImagesLoaded", kDoNothingCallback);
 }
 
-void UserChooserScreenHandler::GetLocalizedValues(
+void UserManagerScreenHandler::GetLocalizedValues(
     base::DictionaryValue* localized_strings) {
   // For Control Bar.
   localized_strings->SetString("signedIn",
@@ -283,7 +281,8 @@
   // For AccountPickerScreen.
   localized_strings->SetString("screenType", "login-add-user");
   localized_strings->SetString("highlightStrength", "normal");
-  localized_strings->SetString("title", "User Chooser");
+  localized_strings->SetString("title",
+      l10n_util::GetStringUTF16(IDS_USER_MANAGER_SCREEN_TITLE));
   localized_strings->SetString("passwordHint",
       l10n_util::GetStringUTF16(IDS_LOGIN_POD_EMPTY_PASSWORD_TEXT));
   localized_strings->SetString("podMenuButtonAccessibleName",
@@ -311,7 +310,7 @@
   localized_strings->SetString("publicAccountEnterAccessibleName", string16());
  }
 
-void UserChooserScreenHandler::SendUserList() {
+void UserManagerScreenHandler::SendUserList() {
   ListValue users_list;
   base::FilePath active_profile_path =
       web_ui()->GetWebContents()->GetBrowserContext()->GetPath();
diff --git a/chrome/browser/ui/webui/signin/user_chooser_screen_handler.h b/chrome/browser/ui/webui/signin/user_manager_screen_handler.h
similarity index 77%
rename from chrome/browser/ui/webui/signin/user_chooser_screen_handler.h
rename to chrome/browser/ui/webui/signin/user_manager_screen_handler.h
index 8169d8c..4ac7297 100644
--- a/chrome/browser/ui/webui/signin/user_chooser_screen_handler.h
+++ b/chrome/browser/ui/webui/signin/user_manager_screen_handler.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROME_BROWSER_UI_WEBUI_SIGNIN_USER_CHOOSER_SCREEN_HANDLER_H_
-#define CHROME_BROWSER_UI_WEBUI_SIGNIN_USER_CHOOSER_SCREEN_HANDLER_H_
+#ifndef CHROME_BROWSER_UI_WEBUI_SIGNIN_USER_MANAGER_SCREEN_HANDLER_H_
+#define CHROME_BROWSER_UI_WEBUI_SIGNIN_USER_MANAGER_SCREEN_HANDLER_H_
 
 #include "base/compiler_specific.h"
 #include "base/memory/scoped_ptr.h"
@@ -15,10 +15,10 @@
 class ListValue;
 }
 
-class UserChooserScreenHandler : public content::WebUIMessageHandler {
+class UserManagerScreenHandler : public content::WebUIMessageHandler {
  public:
-  UserChooserScreenHandler();
-  virtual ~UserChooserScreenHandler();
+  UserManagerScreenHandler();
+  virtual ~UserManagerScreenHandler();
 
   // WebUIMessageHandler implementation.
   virtual void RegisterMessages() OVERRIDE;
@@ -43,7 +43,7 @@
   // modified, so that the displayed user pods can be updated.
   scoped_ptr<ProfileUpdateObserver> profileInfoCacheObserver_;
 
-  DISALLOW_COPY_AND_ASSIGN(UserChooserScreenHandler);
+  DISALLOW_COPY_AND_ASSIGN(UserManagerScreenHandler);
 };
 
-#endif  // CHROME_BROWSER_UI_WEBUI_SIGNIN_USER_CHOOSER_SCREEN_HANDLER_H_
+#endif  // CHROME_BROWSER_UI_WEBUI_SIGNIN_USER_MANAGER_SCREEN_HANDLER_H_
diff --git a/chrome/browser/ui/webui/signin/user_chooser_ui.cc b/chrome/browser/ui/webui/signin/user_manager_ui.cc
similarity index 71%
rename from chrome/browser/ui/webui/signin/user_chooser_ui.cc
rename to chrome/browser/ui/webui/signin/user_manager_ui.cc
index 0664716..67e8ed5 100644
--- a/chrome/browser/ui/webui/signin/user_chooser_ui.cc
+++ b/chrome/browser/ui/webui/signin/user_manager_ui.cc
@@ -2,11 +2,11 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/ui/webui/signin/user_chooser_ui.h"
+#include "chrome/browser/ui/webui/signin/user_manager_ui.h"
 
 #include "base/values.h"
 #include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/ui/webui/signin/user_chooser_screen_handler.h"
+#include "chrome/browser/ui/webui/signin/user_manager_screen_handler.h"
 #include "chrome/browser/ui/webui/theme_source.h"
 #include "chrome/common/url_constants.h"
 #include "content/public/browser/web_ui.h"
@@ -18,17 +18,17 @@
 namespace {
   // JS file names.
   const char kStringsJSPath[] = "strings.js";
-  const char kUserChooserJSPath[] = "user_chooser.js";
+  const char kUserManagerJSPath[] = "user_manager.js";
   const char kHeaderBarJSPath[] = "header_bar.js";
   const char kAccountPickerJSPath[] = "screen_account_picker.js";
 }
 
-UserChooserUI::UserChooserUI(content::WebUI* web_ui)
+UserManagerUI::UserManagerUI(content::WebUI* web_ui)
   : WebUIController(web_ui) {
   // The web_ui object takes ownership of the handler, and will
   // destroy it when it (the WebUI) is destroyed.
-  user_chooser_screen_handler_ = new UserChooserScreenHandler();
-  web_ui->AddMessageHandler(user_chooser_screen_handler_);
+  user_manager_screen_handler_ = new UserManagerScreenHandler();
+  web_ui->AddMessageHandler(user_manager_screen_handler_);
 
   base::DictionaryValue localized_strings;
   GetLocalizedStrings(&localized_strings);
@@ -44,26 +44,26 @@
 #endif
 }
 
-UserChooserUI::~UserChooserUI() {
+UserManagerUI::~UserManagerUI() {
 }
 
-content::WebUIDataSource* UserChooserUI::CreateUIDataSource(
+content::WebUIDataSource* UserManagerUI::CreateUIDataSource(
     const base::DictionaryValue& localized_strings) {
   content::WebUIDataSource* source =
-      content::WebUIDataSource::Create(chrome::kChromeUIUserChooserHost);
+      content::WebUIDataSource::Create(chrome::kChromeUIUserManagerHost);
   source->SetUseJsonJSFormatV2();
   source->AddLocalizedStrings(localized_strings);
   source->SetJsonPath(kStringsJSPath);
 
-  source->SetDefaultResource(IDR_USER_CHOOSER_HTML);
-  source->AddResourcePath(kUserChooserJSPath, IDR_USER_CHOOSER_JS);
+  source->SetDefaultResource(IDR_USER_MANAGER_HTML);
+  source->AddResourcePath(kUserManagerJSPath, IDR_USER_MANAGER_JS);
 
   return source;
 }
 
-void UserChooserUI::GetLocalizedStrings(
+void UserManagerUI::GetLocalizedStrings(
     base::DictionaryValue* localized_strings) {
-  user_chooser_screen_handler_->GetLocalizedValues(localized_strings);
+  user_manager_screen_handler_->GetLocalizedValues(localized_strings);
   webui::SetFontAndTextDirection(localized_strings);
 
 #if defined(GOOGLE_CHROME_BUILD)
diff --git a/chrome/browser/ui/webui/signin/user_manager_ui.h b/chrome/browser/ui/webui/signin/user_manager_ui.h
new file mode 100644
index 0000000..0e5ab3d
--- /dev/null
+++ b/chrome/browser/ui/webui/signin/user_manager_ui.h
@@ -0,0 +1,35 @@
+// 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_UI_WEBUI_SIGNIN_USER_MANAGER_UI_H_
+#define CHROME_BROWSER_UI_WEBUI_SIGNIN_USER_MANAGER_UI_H_
+
+#include "content/public/browser/web_ui_controller.h"
+
+class UserManagerScreenHandler;
+
+namespace base {
+class DictionaryValue;
+}
+namespace content {
+class WebUIDataSource;
+}
+
+// A WebUI dialog to display available users.
+class UserManagerUI : public content::WebUIController {
+ public:
+  explicit UserManagerUI(content::WebUI* web_ui);
+  virtual ~UserManagerUI();
+
+ private:
+  content::WebUIDataSource* CreateUIDataSource(
+      const base::DictionaryValue& localized_strings);
+  void GetLocalizedStrings(base::DictionaryValue* localized_strings);
+
+  UserManagerScreenHandler* user_manager_screen_handler_;
+
+  DISALLOW_COPY_AND_ASSIGN(UserManagerUI);
+};
+
+#endif  // CHROME_BROWSER_UI_WEBUI_SIGNIN_USER_MANAGER_UI_H_
diff --git a/chrome/browser/ui/webui/task_manager/task_manager_handler.cc b/chrome/browser/ui/webui/task_manager/task_manager_handler.cc
index 8ce0d82..8ba6cef 100644
--- a/chrome/browser/ui/webui/task_manager/task_manager_handler.cc
+++ b/chrome/browser/ui/webui/task_manager/task_manager_handler.cc
@@ -11,12 +11,9 @@
 #include "base/bind_helpers.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/values.h"
-#include "chrome/browser/chrome_notification_types.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/task_manager/task_manager.h"
 #include "chrome/browser/ui/host_desktop.h"
-#include "content/public/browser/notification_service.h"
-#include "content/public/browser/notification_source.h"
 #include "content/public/browser/render_view_host.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/browser/web_ui.h"
@@ -184,11 +181,6 @@
 
   model_->AddObserver(this);
   model_->StartUpdating();
-
-  content::NotificationService::current()->Notify(
-      chrome::NOTIFICATION_TASK_MANAGER_WINDOW_READY,
-      content::Source<TaskManagerModel>(model_),
-      content::NotificationService::NoDetails());
 }
 
 void TaskManagerHandler::OpenAboutMemory(const ListValue* indexes) {
diff --git a/chrome/browser/ui/webui/version_handler.cc b/chrome/browser/ui/webui/version_handler.cc
index 065b4f2..91c5fa3 100644
--- a/chrome/browser/ui/webui/version_handler.cc
+++ b/chrome/browser/ui/webui/version_handler.cc
@@ -14,10 +14,10 @@
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/plugin_service.h"
 #include "content/public/browser/web_ui.h"
+#include "content/public/common/content_constants.h"
 #include "grit/generated_resources.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "url/gurl.h"
-#include "webkit/plugins/plugin_constants.h"
 
 namespace {
 
@@ -133,7 +133,7 @@
   // Obtain the version of the first enabled Flash plugin.
   std::vector<content::WebPluginInfo> info_array;
   content::PluginService::GetInstance()->GetPluginInfoArray(
-      GURL(), kFlashPluginSwfMimeType, false, &info_array, NULL);
+      GURL(), content::kFlashPluginSwfMimeType, false, &info_array, NULL);
   string16 flash_version =
       l10n_util::GetStringUTF16(IDS_PLUGINS_DISABLED_PLUGIN);
   PluginPrefs* plugin_prefs =
diff --git a/chrome/browser/usb/usb_device.cc b/chrome/browser/usb/usb_device.cc
new file mode 100644
index 0000000..6041e68
--- /dev/null
+++ b/chrome/browser/usb/usb_device.cc
@@ -0,0 +1,98 @@
+// 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/usb/usb_device.h"
+
+#include <algorithm>
+
+#include "base/stl_util.h"
+#include "chrome/browser/usb/usb_context.h"
+#include "chrome/browser/usb/usb_device_handle.h"
+#include "content/public/browser/browser_thread.h"
+#include "third_party/libusb/src/libusb/libusb.h"
+
+using content::BrowserThread;
+
+UsbDevice::UsbDevice(
+    scoped_refptr<UsbContext> context,
+    PlatformUsbDevice platform_device,
+    uint16 vendor_id,
+    uint16 product_id)
+    : platform_device_(platform_device),
+      vendor_id_(vendor_id),
+      product_id_(product_id),
+      context_(context) {
+  CHECK(platform_device) << "platform_device cannot be NULL";
+  libusb_ref_device(platform_device);
+}
+
+UsbDevice::UsbDevice()
+    : platform_device_(NULL),
+      vendor_id_(0),
+      product_id_(0),
+      context_(NULL) {
+}
+
+UsbDevice::~UsbDevice() {
+  DCHECK(thread_checker_.CalledOnValidThread());
+  for (HandlesVector::iterator it = handles_.begin();
+      it != handles_.end();
+      ++it) {
+    (*it)->InternalClose();
+  }
+  STLClearObject(&handles_);
+  libusb_unref_device(platform_device_);
+}
+
+scoped_refptr<UsbDeviceHandle> UsbDevice::Open() {
+  DCHECK(thread_checker_.CalledOnValidThread());
+  PlatformUsbDeviceHandle handle;
+  int rv = libusb_open(platform_device_, &handle);
+  if (LIBUSB_SUCCESS == rv) {
+    scoped_refptr<UsbDeviceHandle> device_handle =
+        new UsbDeviceHandle(context_, this, handle);
+    handles_.push_back(device_handle);
+    return device_handle;
+  }
+  return NULL;
+}
+
+bool UsbDevice::Close(scoped_refptr<UsbDeviceHandle> handle) {
+  DCHECK(thread_checker_.CalledOnValidThread());
+
+  for (HandlesVector::iterator it = handles_.begin();
+      it != handles_.end();
+      ++it) {
+    if (*it == handle) {
+      (*it)->InternalClose();
+      handles_.erase(it);
+      return true;
+    }
+  }
+  return false;
+}
+
+bool UsbDevice::ListInterfaces(UsbConfigDescriptor* config) {
+  DCHECK(thread_checker_.CalledOnValidThread());
+
+  PlatformUsbConfigDescriptor platform_config;
+  const int list_result =
+      libusb_get_active_config_descriptor(platform_device_, &platform_config);
+  if (list_result == 0)
+    config->Reset(platform_config);
+
+  return list_result == 0;
+}
+
+void UsbDevice::OnDisconnect() {
+  DCHECK(thread_checker_.CalledOnValidThread());
+  HandlesVector handles;
+  swap(handles, handles_);
+  for (std::vector<scoped_refptr<UsbDeviceHandle> >::iterator it =
+      handles.begin();
+      it != handles.end();
+      ++it) {
+    (*it)->InternalClose();
+  }
+}
diff --git a/chrome/browser/usb/usb_device.h b/chrome/browser/usb/usb_device.h
new file mode 100644
index 0000000..524cee3
--- /dev/null
+++ b/chrome/browser/usb/usb_device.h
@@ -0,0 +1,81 @@
+// 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_USB_USB_DEVICE_H_
+#define CHROME_BROWSER_USB_USB_DEVICE_H_
+
+#include <vector>
+
+#include "base/basictypes.h"
+#include "base/memory/ref_counted.h"
+#include "base/threading/thread_checker.h"
+#include "chrome/browser/usb/usb_interface.h"
+
+struct libusb_device;
+class UsbDeviceHandle;
+class UsbContext;
+
+typedef libusb_device* PlatformUsbDevice;
+
+// A UsbDevice object represents a detected USB device, providing basic
+// information about it. For further manipulation of the device, a
+// UsbDeviceHandle must be created from Open() method.
+class UsbDevice : public base::RefCountedThreadSafe<UsbDevice> {
+ public:
+  // Accessors to basic information.
+  PlatformUsbDevice platform_device() const { return platform_device_; }
+  uint16 vendor_id() const { return vendor_id_; }
+  uint16 product_id() const { return product_id_; }
+
+  // Creates a UsbDeviceHandle for further manipulation.
+  // Blocking method. Must be called on FILE thread.
+  virtual scoped_refptr<UsbDeviceHandle> Open();
+
+  // Explicitly closes a device handle. This method will be automatically called
+  // by the destructor of a UsbDeviceHandle as well.
+  // Closing a closed handle is a safe
+  // Blocking method. Must be called on FILE thread.
+  virtual bool Close(scoped_refptr<UsbDeviceHandle> handle);
+
+  // Lists the interfaces provided by the device and fills the given
+  // UsbConfigDescriptor.
+  // Blocking method. Must be called on FILE thread.
+  virtual bool ListInterfaces(UsbConfigDescriptor* config);
+
+ protected:
+  friend class UsbService;
+  friend class base::RefCountedThreadSafe<UsbDevice>;
+
+  // Called by UsbService only;
+  UsbDevice(scoped_refptr<UsbContext> context,
+            PlatformUsbDevice platform_device,
+            uint16 vendor_id,
+            uint16 product_id);
+
+  // Constructor called in test only.
+  UsbDevice();
+  virtual ~UsbDevice();
+
+  // Called only be UsbService.
+  virtual void OnDisconnect();
+
+ private:
+  PlatformUsbDevice platform_device_;
+  uint16 vendor_id_;
+  uint16 product_id_;
+
+  // Retain the context so that it will not be released before UsbDevice.
+  scoped_refptr<UsbContext> context_;
+
+  // Opened handles.
+  typedef std::vector<scoped_refptr<UsbDeviceHandle> > HandlesVector;
+  HandlesVector handles_;
+
+  base::ThreadChecker thread_checker_;
+
+  DISALLOW_COPY_AND_ASSIGN(UsbDevice);
+};
+
+#endif  // CHROME_BROWSER_USB_USB_DEVICE_H_
diff --git a/chrome/browser/usb/usb_device_handle.cc b/chrome/browser/usb/usb_device_handle.cc
index 56c3dc7..32903ba 100644
--- a/chrome/browser/usb/usb_device_handle.cc
+++ b/chrome/browser/usb/usb_device_handle.cc
@@ -7,13 +7,20 @@
 #include <algorithm>
 #include <vector>
 
+#include "base/message_loop/message_loop.h"
 #include "base/stl_util.h"
 #include "base/strings/string16.h"
 #include "base/synchronization/lock.h"
+#include "chrome/browser/usb/usb_context.h"
+#include "chrome/browser/usb/usb_device.h"
 #include "chrome/browser/usb/usb_interface.h"
 #include "chrome/browser/usb/usb_service.h"
+#include "content/public/browser/browser_thread.h"
 #include "third_party/libusb/src/libusb/libusb.h"
 
+using content::BrowserThread;
+void HandleTransferCompletion(PlatformUsbTransferHandle transfer);
+
 namespace {
 
 static uint8 ConvertTransferDirection(
@@ -90,61 +97,139 @@
   }
 }
 
-static void LIBUSB_CALL HandleTransferCompletion(
-    struct libusb_transfer* transfer) {
-  UsbDeviceHandle* const device =
-      reinterpret_cast<UsbDeviceHandle*>(transfer->user_data);
-  device->TransferComplete(transfer);
+static void LIBUSB_CALL PlatformTransferCompletionCallback(
+    PlatformUsbTransferHandle transfer) {
+  BrowserThread::PostTask(BrowserThread::FILE,
+                          FROM_HERE,
+                          base::Bind(HandleTransferCompletion, transfer));
 }
 
 }  // namespace
 
-UsbDeviceHandle::Transfer::Transfer() : length(0) {}
+void HandleTransferCompletion(PlatformUsbTransferHandle transfer) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+  UsbDeviceHandle* const device_handle =
+      reinterpret_cast<UsbDeviceHandle*>(transfer->user_data);
+  CHECK(device_handle) << "Device handle is closed before transfer finishes.";
+  device_handle->TransferComplete(transfer);
+  libusb_free_transfer(transfer);
+}
+
+
+class UsbDeviceHandle::InterfaceClaimer
+    : public base::RefCountedThreadSafe<UsbDeviceHandle::InterfaceClaimer> {
+ public:
+  InterfaceClaimer(const scoped_refptr<UsbDeviceHandle> handle,
+                   const int interface_number);
+
+  bool Claim() const;
+
+  int alternate_setting() const { return alternate_setting_; }
+  void set_alternate_setting(const int alternate_setting) {
+    alternate_setting_ = alternate_setting;
+  }
+
+ private:
+  friend class UsbDevice;
+  friend class base::RefCountedThreadSafe<InterfaceClaimer>;
+  ~InterfaceClaimer();
+
+  const scoped_refptr<UsbDeviceHandle> handle_;
+  const int interface_number_;
+  int alternate_setting_;
+
+  DISALLOW_COPY_AND_ASSIGN(InterfaceClaimer);
+};
+
+UsbDeviceHandle::InterfaceClaimer::InterfaceClaimer(
+    const scoped_refptr<UsbDeviceHandle> handle, const int interface_number)
+    : handle_(handle),
+      interface_number_(interface_number),
+      alternate_setting_(0) {
+}
+
+UsbDeviceHandle::InterfaceClaimer::~InterfaceClaimer() {
+  libusb_release_interface(handle_->handle(), interface_number_);
+}
+
+bool UsbDeviceHandle::InterfaceClaimer::Claim() const {
+  return libusb_claim_interface(handle_->handle(), interface_number_) == 0;
+}
+
+struct UsbDeviceHandle::Transfer {
+  Transfer();
+  ~Transfer();
+
+  UsbTransferType transfer_type;
+  scoped_refptr<net::IOBuffer> buffer;
+  scoped_refptr<UsbDeviceHandle::InterfaceClaimer> claimed_interface;
+  scoped_refptr<base::MessageLoopProxy> message_loop_proxy;
+  size_t length;
+  UsbTransferCallback callback;
+};
+
+UsbDeviceHandle::Transfer::Transfer()
+    : transfer_type(USB_TRANSFER_CONTROL),
+      length(0) {
+}
 
 UsbDeviceHandle::Transfer::~Transfer() {}
 
 UsbDeviceHandle::UsbDeviceHandle(
-    UsbService* service,
+    scoped_refptr<UsbContext> context,
+    UsbDevice* device,
     PlatformUsbDeviceHandle handle)
-    : service_(service), handle_(handle) {
+    : device_(device), handle_(handle), context_(context) {
+  DCHECK(thread_checker_.CalledOnValidThread());
   DCHECK(handle) << "Cannot create device with NULL handle.";
+  interfaces_ = new UsbConfigDescriptor();
+  device->ListInterfaces(interfaces_.get());
 }
 
-UsbDeviceHandle::UsbDeviceHandle() : service_(NULL), handle_(NULL) {}
+UsbDeviceHandle::UsbDeviceHandle() : device_(NULL), handle_(NULL) {
+}
 
-UsbDeviceHandle::~UsbDeviceHandle() {}
+UsbDeviceHandle::~UsbDeviceHandle() {
+  DCHECK(thread_checker_.CalledOnValidThread());
 
-void UsbDeviceHandle::Close() {
-  CheckDevice();
-  service_->CloseDevice(this);
+  libusb_close(handle_);
   handle_ = NULL;
 }
 
-void UsbDeviceHandle::TransferComplete(PlatformUsbTransferHandle handle) {
-  base::AutoLock lock(lock_);
+scoped_refptr<UsbDevice> UsbDeviceHandle::device() const {
+  return device_;
+}
 
-  // TODO(gdk): Handle device disconnect.
+void UsbDeviceHandle::Close() {
+  DCHECK(thread_checker_.CalledOnValidThread());
+  if (device_)
+    device_->Close(this);
+}
+
+void UsbDeviceHandle::TransferComplete(PlatformUsbTransferHandle handle) {
   DCHECK(ContainsKey(transfers_, handle)) << "Missing transfer completed";
-  Transfer* const transfer = &transfers_[handle];
+
+  Transfer transfer = transfers_[handle];
+  transfers_.erase(handle);
 
   DCHECK_GE(handle->actual_length, 0) << "Negative actual length received";
   size_t actual_length =
       static_cast<size_t>(std::max(handle->actual_length, 0));
 
-  DCHECK(transfer->length >= actual_length) <<
+  DCHECK(transfer.length >= actual_length) <<
       "data too big for our buffer (libusb failure?)";
 
-  scoped_refptr<net::IOBuffer> buffer = transfer->buffer;
-  switch (transfer->transfer_type) {
+  scoped_refptr<net::IOBuffer> buffer = transfer.buffer;
+  switch (transfer.transfer_type) {
     case USB_TRANSFER_CONTROL:
       // If the transfer is a control transfer we do not expose the control
       // setup header to the caller. This logic strips off the header if
       // present before invoking the callback provided with the transfer.
       if (actual_length > 0) {
-        CHECK(transfer->length >= LIBUSB_CONTROL_SETUP_SIZE) <<
+        CHECK(transfer.length >= LIBUSB_CONTROL_SETUP_SIZE) <<
             "buffer was not correctly set: too small for the control header";
 
-        if (transfer->length >= actual_length &&
+        if (transfer.length >= actual_length &&
             actual_length >= LIBUSB_CONTROL_SETUP_SIZE) {
           // If the payload is zero bytes long, pad out the allocated buffer
           // size to one byte so that an IOBuffer of that size can be allocated.
@@ -172,7 +257,7 @@
             // all the data the packet can hold.
             if (actual_length < packet_buffer_start) {
               CHECK(packet_buffer_start + packet->actual_length <=
-                    transfer->length);
+                    transfer.length);
               memmove(buffer->data() + actual_length,
                       buffer->data() + packet_buffer_start,
                       packet->actual_length);
@@ -191,61 +276,81 @@
 
     default:
       NOTREACHED() << "Invalid usb transfer type";
+      break;
   }
 
-  transfer->callback.Run(ConvertTransferStatus(handle->status), buffer,
-                         actual_length);
+  transfer.message_loop_proxy->PostTask(
+      FROM_HERE,
+      base::Bind(transfer.callback,
+                 ConvertTransferStatus(handle->status),
+                 buffer,
+                 actual_length));
 
-  transfers_.erase(handle);
-  libusb_free_transfer(handle);
-}
-
-bool UsbDeviceHandle::ListInterfaces(UsbConfigDescriptor* config) {
-  CheckDevice();
-
-  PlatformUsbDevice device = libusb_get_device(handle_);
-
-  PlatformUsbConfigDescriptor platform_config;
-  const int list_result = libusb_get_active_config_descriptor(device,
-      &platform_config);
-  if (list_result == 0) {
-    config->Reset(platform_config);
-  }
-  return list_result == 0;
+  // Must release interface first before actually delete this.
+  transfer.claimed_interface = NULL;
 }
 
 bool UsbDeviceHandle::ClaimInterface(const int interface_number) {
-  CheckDevice();
+  DCHECK(thread_checker_.CalledOnValidThread());
+  if (!device_) return false;
+  if (ContainsKey(claimed_interfaces_, interface_number)) return true;
 
-  const int claim_result = libusb_claim_interface(handle_, interface_number);
-  return claim_result == 0;
+  scoped_refptr<InterfaceClaimer> claimer =
+      new InterfaceClaimer(this, interface_number);
+
+  if (claimer->Claim()) {
+    claimed_interfaces_[interface_number]= claimer;
+    RefreshEndpointMap();
+    return true;
+  }
+  return false;
 }
 
 bool UsbDeviceHandle::ReleaseInterface(const int interface_number) {
-  CheckDevice();
+  DCHECK(thread_checker_.CalledOnValidThread());
+  if (!device_) return false;
+  if (!ContainsKey(claimed_interfaces_, interface_number)) return false;
 
-  const int release_result = libusb_release_interface(handle_,
-                                                      interface_number);
-  return release_result == 0;
+  // Cancel all the transfers on that interface.
+  InterfaceClaimer* interface_claimer =
+      claimed_interfaces_[interface_number].get();
+  for (TransferMap::iterator it = transfers_.begin();
+      it != transfers_.end(); ++it) {
+    if (it->second.claimed_interface.get() == interface_claimer)
+      libusb_cancel_transfer(it->first);
+  }
+  claimed_interfaces_.erase(interface_number);
+
+  RefreshEndpointMap();
+  return true;
 }
 
 bool UsbDeviceHandle::SetInterfaceAlternateSetting(
     const int interface_number,
     const int alternate_setting) {
-  CheckDevice();
-
-  const int setting_result = libusb_set_interface_alt_setting(handle_,
+  DCHECK(thread_checker_.CalledOnValidThread());
+  if (!device_) return false;
+  if (!ContainsKey(claimed_interfaces_, interface_number)) return false;
+  const int rv = libusb_set_interface_alt_setting(handle_,
       interface_number, alternate_setting);
-
-  return setting_result == 0;
+  if (rv == 0) {
+    claimed_interfaces_[interface_number]->
+      set_alternate_setting(alternate_setting);
+    RefreshEndpointMap();
+    return true;
+  }
+  return false;
 }
 
 bool UsbDeviceHandle::ResetDevice() {
-  CheckDevice();
+  DCHECK(thread_checker_.CalledOnValidThread());
+  if (!device_) return false;
+
   return libusb_reset_device(handle_) == 0;
 }
 
 bool UsbDeviceHandle::GetSerial(base::string16* serial) {
+  DCHECK(thread_checker_.CalledOnValidThread());
   PlatformUsbDevice device = libusb_get_device(handle_);
   libusb_device_descriptor desc;
 
@@ -291,7 +396,10 @@
     const uint8 request, const uint16 value, const uint16 index,
     net::IOBuffer* buffer, const size_t length, const unsigned int timeout,
     const UsbTransferCallback& callback) {
-  CheckDevice();
+  if (!device_) {
+    callback.Run(USB_TRANSFER_DISCONNECT, buffer, 0);
+    return;
+  }
 
   const size_t resized_length = LIBUSB_CONTROL_SETUP_SIZE + length;
   scoped_refptr<net::IOBuffer> resized_buffer(new net::IOBufferWithSize(
@@ -299,84 +407,194 @@
   memcpy(resized_buffer->data() + LIBUSB_CONTROL_SETUP_SIZE, buffer->data(),
          length);
 
-  struct libusb_transfer* const transfer = libusb_alloc_transfer(0);
+  PlatformUsbTransferHandle const transfer = libusb_alloc_transfer(0);
   const uint8 converted_type = CreateRequestType(direction, request_type,
                                                  recipient);
   libusb_fill_control_setup(reinterpret_cast<uint8*>(resized_buffer->data()),
                             converted_type, request, value, index, length);
-  libusb_fill_control_transfer(transfer, handle_, reinterpret_cast<uint8*>(
-      resized_buffer->data()), HandleTransferCompletion, this, timeout);
-  SubmitTransfer(transfer,
+  libusb_fill_control_transfer(
+      transfer,
+      handle_,
+      reinterpret_cast<uint8*>(resized_buffer->data()),
+      PlatformTransferCompletionCallback,
+      this,
+      timeout);
+
+  BrowserThread::PostTask(
+      BrowserThread::FILE,
+      FROM_HERE,
+      base::Bind(&UsbDeviceHandle::SubmitTransfer,
+                 this,
+                 transfer,
                  USB_TRANSFER_CONTROL,
-                 resized_buffer.get(),
+                 resized_buffer,
                  resized_length,
-                 callback);
+                 base::MessageLoopProxy::current(),
+                 callback));
 }
 
 void UsbDeviceHandle::BulkTransfer(const UsbEndpointDirection direction,
     const uint8 endpoint, net::IOBuffer* buffer, const size_t length,
     const unsigned int timeout, const UsbTransferCallback& callback) {
-  CheckDevice();
+  if (!device_) {
+    callback.Run(USB_TRANSFER_DISCONNECT, buffer, 0);
+    return;
+  }
 
-  struct libusb_transfer* const transfer = libusb_alloc_transfer(0);
+  PlatformUsbTransferHandle const transfer = libusb_alloc_transfer(0);
   const uint8 new_endpoint = ConvertTransferDirection(direction) | endpoint;
   libusb_fill_bulk_transfer(transfer, handle_, new_endpoint,
       reinterpret_cast<uint8*>(buffer->data()), length,
-      HandleTransferCompletion, this, timeout);
-  SubmitTransfer(transfer, USB_TRANSFER_BULK, buffer, length, callback);
+      PlatformTransferCompletionCallback, this, timeout);
+
+  BrowserThread::PostTask(
+      BrowserThread::FILE,
+      FROM_HERE,
+      base::Bind(&UsbDeviceHandle::SubmitTransfer,
+                 this,
+                 transfer,
+                 USB_TRANSFER_BULK,
+                 make_scoped_refptr(buffer),
+                 length,
+                 base::MessageLoopProxy::current(),
+                 callback));
 }
 
 void UsbDeviceHandle::InterruptTransfer(const UsbEndpointDirection direction,
     const uint8 endpoint, net::IOBuffer* buffer, const size_t length,
     const unsigned int timeout, const UsbTransferCallback& callback) {
-  CheckDevice();
+  if (!device_) {
+    callback.Run(USB_TRANSFER_DISCONNECT, buffer, 0);
+    return;
+  }
 
-  struct libusb_transfer* const transfer = libusb_alloc_transfer(0);
+  PlatformUsbTransferHandle const transfer = libusb_alloc_transfer(0);
   const uint8 new_endpoint = ConvertTransferDirection(direction) | endpoint;
   libusb_fill_interrupt_transfer(transfer, handle_, new_endpoint,
       reinterpret_cast<uint8*>(buffer->data()), length,
-      HandleTransferCompletion, this, timeout);
-  SubmitTransfer(transfer, USB_TRANSFER_INTERRUPT, buffer, length, callback);
+      PlatformTransferCompletionCallback, this, timeout);
+  BrowserThread::PostTask(
+      BrowserThread::FILE,
+      FROM_HERE,
+      base::Bind(&UsbDeviceHandle::SubmitTransfer,
+                 this,
+                 transfer,
+                 USB_TRANSFER_INTERRUPT,
+                 make_scoped_refptr(buffer),
+                 length,
+                 base::MessageLoopProxy::current(),
+                 callback));
 }
 
 void UsbDeviceHandle::IsochronousTransfer(const UsbEndpointDirection direction,
     const uint8 endpoint, net::IOBuffer* buffer, const size_t length,
     const unsigned int packets, const unsigned int packet_length,
     const unsigned int timeout, const UsbTransferCallback& callback) {
-  CheckDevice();
+  if (!device_) {
+    callback.Run(USB_TRANSFER_DISCONNECT, buffer, 0);
+    return;
+  }
 
   const uint64 total_length = packets * packet_length;
   CHECK(packets <= length && total_length <= length) <<
       "transfer length is too small";
 
-  struct libusb_transfer* const transfer = libusb_alloc_transfer(packets);
+  PlatformUsbTransferHandle const transfer = libusb_alloc_transfer(packets);
   const uint8 new_endpoint = ConvertTransferDirection(direction) | endpoint;
   libusb_fill_iso_transfer(transfer, handle_, new_endpoint,
       reinterpret_cast<uint8*>(buffer->data()), length, packets,
-      HandleTransferCompletion, this, timeout);
+      PlatformTransferCompletionCallback, this, timeout);
   libusb_set_iso_packet_lengths(transfer, packet_length);
 
-  SubmitTransfer(transfer, USB_TRANSFER_ISOCHRONOUS, buffer, length, callback);
+  BrowserThread::PostTask(
+      BrowserThread::FILE,
+      FROM_HERE,
+      base::Bind(&UsbDeviceHandle::SubmitTransfer,
+                 this,
+                 transfer,
+                 USB_TRANSFER_ISOCHRONOUS,
+                 make_scoped_refptr(buffer),
+                 length,
+                 base::MessageLoopProxy::current(),
+                 callback));
 }
 
-void UsbDeviceHandle::CheckDevice() {
-  DCHECK(handle_) << "Device is already closed.";
+void UsbDeviceHandle::RefreshEndpointMap() {
+  DCHECK(thread_checker_.CalledOnValidThread());
+  endpoint_map_.clear();
+  for (ClaimedInterfaceMap::iterator it = claimed_interfaces_.begin();
+      it != claimed_interfaces_.end(); ++it) {
+    scoped_refptr<const UsbInterfaceDescriptor> interface_desc =
+        interfaces_->GetInterface(it->first)->GetAltSetting(
+            it->second->alternate_setting());
+    for (size_t i = 0; i < interface_desc->GetNumEndpoints(); i++) {
+      scoped_refptr<const UsbEndpointDescriptor> endpoint =
+          interface_desc->GetEndpoint(i);
+      endpoint_map_[endpoint->GetAddress()] = it->first;
+    }
+  }
 }
 
-void UsbDeviceHandle::SubmitTransfer(PlatformUsbTransferHandle handle,
-                               UsbTransferType transfer_type,
-                               net::IOBuffer* buffer,
-                               const size_t length,
-                               const UsbTransferCallback& callback) {
+scoped_refptr<UsbDeviceHandle::InterfaceClaimer>
+    UsbDeviceHandle::GetClaimedInterfaceForEndpoint(unsigned char endpoint) {
+  unsigned char address = endpoint & LIBUSB_ENDPOINT_ADDRESS_MASK;
+  if (ContainsKey(endpoint_map_, address))
+    return claimed_interfaces_[endpoint_map_[address]];
+  return NULL;
+}
+
+void UsbDeviceHandle::SubmitTransfer(
+    PlatformUsbTransferHandle handle,
+    UsbTransferType transfer_type,
+    net::IOBuffer* buffer,
+    const size_t length,
+    scoped_refptr<base::MessageLoopProxy> message_loop_proxy,
+    const UsbTransferCallback& callback) {
+  DCHECK(thread_checker_.CalledOnValidThread());
+  if (!device_) {
+    message_loop_proxy->PostTask(
+        FROM_HERE,
+        base::Bind(callback, USB_TRANSFER_DISCONNECT,
+                   make_scoped_refptr(buffer), 0));
+  }
+
   Transfer transfer;
   transfer.transfer_type = transfer_type;
   transfer.buffer = buffer;
   transfer.length = length;
   transfer.callback = callback;
+  transfer.message_loop_proxy = message_loop_proxy;
 
-  {
-    base::AutoLock lock(lock_);
+  // It's OK for this method to return NULL. libusb_submit_transfer will fail if
+  // it requires an interface we didn't claim.
+  transfer.claimed_interface = GetClaimedInterfaceForEndpoint(handle->endpoint);
+
+  if (libusb_submit_transfer(handle) == LIBUSB_SUCCESS) {
     transfers_[handle] = transfer;
-    libusb_submit_transfer(handle);
+  } else {
+    message_loop_proxy->PostTask(
+        FROM_HERE,
+        base::Bind(callback, USB_TRANSFER_ERROR,
+                   make_scoped_refptr(buffer), 0));
   }
 }
+
+void UsbDeviceHandle::InternalClose() {
+  DCHECK(thread_checker_.CalledOnValidThread());
+  if (!device_) return;
+
+  // Cancel all the transfers.
+  for (TransferMap::iterator it = transfers_.begin();
+      it != transfers_.end(); ++it) {
+    // The callback will be called some time later.
+    libusb_cancel_transfer(it->first);
+  }
+
+  // Attempt-release all the interfaces.
+  // It will be retained until the transfer cancellation is finished.
+  claimed_interfaces_.clear();
+
+  // Cannot close device handle here. Need to wait for libusb_cancel_transfer to
+  // finish.
+  device_ = NULL;
+}
diff --git a/chrome/browser/usb/usb_device_handle.h b/chrome/browser/usb/usb_device_handle.h
index 0659955..f7aa43f 100644
--- a/chrome/browser/usb/usb_device_handle.h
+++ b/chrome/browser/usb/usb_device_handle.h
@@ -11,21 +11,28 @@
 #include "base/memory/ref_counted.h"
 #include "base/strings/string16.h"
 #include "base/synchronization/lock.h"
+#include "base/threading/thread_checker.h"
 #include "chrome/browser/usb/usb_interface.h"
+#include "content/public/browser/browser_thread.h"
 #include "net/base/completion_callback.h"
 #include "net/base/io_buffer.h"
 
-struct libusb_device;
 struct libusb_device_handle;
 struct libusb_iso_packet_descriptor;
 struct libusb_transfer;
 
-typedef libusb_device* PlatformUsbDevice;
 typedef libusb_device_handle* PlatformUsbDeviceHandle;
 typedef libusb_iso_packet_descriptor* PlatformUsbIsoPacketDescriptor;
 typedef libusb_transfer* PlatformUsbTransferHandle;
 
-class UsbService;
+class UsbContext;
+class UsbConfigDescriptor;
+class UsbDevice;
+class UsbInterface;
+
+namespace base {
+  class MessageLoopProxy;
+}  // namespace base
 
 namespace net {
 class IOBuffer;
@@ -45,35 +52,33 @@
 typedef base::Callback<void(UsbTransferStatus, scoped_refptr<net::IOBuffer>,
     size_t)> UsbTransferCallback;
 
-// A UsbDevice wraps the platform's underlying representation of what a USB
-// device actually is, and provides accessors for performing many of the
-// standard USB operations.
-class UsbDeviceHandle : public base::RefCounted<UsbDeviceHandle> {
+// UsbDeviceHandle class provides basic I/O related functionalities.
+class UsbDeviceHandle : public base::RefCountedThreadSafe<UsbDeviceHandle> {
  public:
   enum TransferRequestType { STANDARD, CLASS, VENDOR, RESERVED };
   enum TransferRecipient { DEVICE, INTERFACE, ENDPOINT, OTHER };
 
-  // Usually you will not want to directly create a UsbDevice, favoring to let
-  // the UsbService take care of the logistics of getting a platform device
-  // handle and handling events for it.
-  UsbDeviceHandle(UsbService* service, PlatformUsbDeviceHandle handle);
+  scoped_refptr<UsbDevice> device() const;
+  PlatformUsbDeviceHandle handle() const { return handle_; }
 
-  PlatformUsbDeviceHandle handle() { return handle_; }
-
-  // Close the USB device and release the underlying platform device.
+  // Notifies UsbDevice to drop the reference of this object; cancels all the
+  // flying transfers.
+  // It is possible that the object has no other reference after this call. So
+  // if it is called using a raw pointer, it could be invalidated.
+  // The platform device handle will be closed when UsbDeviceHandle destructs.
   virtual void Close();
 
-  // Device manipulation operations. These methods are blocking.
-  virtual bool ListInterfaces(UsbConfigDescriptor* config);
+  // Device manipulation operations. These methods are blocking and must be
+  // called on FILE thread.
   virtual bool ClaimInterface(const int interface_number);
   virtual bool ReleaseInterface(const int interface_number);
   virtual bool SetInterfaceAlternateSetting(
       const int interface_number,
       const int alternate_setting);
   virtual bool ResetDevice();
-  bool GetSerial(base::string16* serial);
+  virtual bool GetSerial(base::string16* serial);
 
-  // Async IO.
+  // Async IO. Can be called on any thread.
   virtual void ControlTransfer(const UsbEndpointDirection direction,
                                const TransferRequestType request_type,
                                const TransferRecipient recipient,
@@ -108,32 +113,34 @@
                                    const unsigned int timeout,
                                    const UsbTransferCallback& callback);
 
-  // Normal code should not call this function. It is called by the platform's
-  // callback mechanism in such a way that it cannot be made private. Invokes
-  // the callbacks associated with a given transfer, and removes it from the
-  // in-flight transfer set.
-  void TransferComplete(PlatformUsbTransferHandle transfer);
-
  protected:
+  friend class base::RefCountedThreadSafe<UsbDeviceHandle>;
+  friend class UsbDevice;
+
+  // This constructor is called by UsbDevice.
+  UsbDeviceHandle(scoped_refptr<UsbContext> context,
+                  UsbDevice* device, PlatformUsbDeviceHandle handle);
+
   // This constructor variant is for use in testing only.
   UsbDeviceHandle();
-
-  friend class base::RefCounted<UsbDeviceHandle>;
   virtual ~UsbDeviceHandle();
 
+  UsbDevice* device_;
+
  private:
-  struct Transfer {
-    Transfer();
-    ~Transfer();
+  friend void HandleTransferCompletion(PlatformUsbTransferHandle handle);
 
-    UsbTransferType transfer_type;
-    scoped_refptr<net::IOBuffer> buffer;
-    size_t length;
-    UsbTransferCallback callback;
-  };
+  class InterfaceClaimer;
+  struct Transfer;
 
-  // Checks that the device has not yet been closed.
-  void CheckDevice();
+  // Refresh endpoint_map_ after ClaimInterface, ReleaseInterface and
+  // SetInterfaceAlternateSetting.
+  void RefreshEndpointMap();
+
+  // Look up the claimed interface by endpoint. Return NULL if the interface
+  // of the endpoint is not found.
+  scoped_refptr<InterfaceClaimer> GetClaimedInterfaceForEndpoint(
+      unsigned char endpoint);
 
   // Submits a transfer and starts tracking it. Retains the buffer and copies
   // the completion callback until the transfer finishes, whereupon it invokes
@@ -142,20 +149,35 @@
                       UsbTransferType transfer_type,
                       net::IOBuffer* buffer,
                       const size_t length,
+                      scoped_refptr<base::MessageLoopProxy> message_loop_proxy,
                       const UsbTransferCallback& callback);
 
-  // The UsbService isn't referenced here to prevent a dependency cycle between
-  // the service and the devices. Since a service owns every device, and is
-  // responsible for its destruction, there is no case where a UsbDevice can
-  // have outlived its originating UsbService.
-  UsbService* const service_;
+  // Invokes the callbacks associated with a given transfer, and removes it from
+  // the in-flight transfer set.
+  void TransferComplete(PlatformUsbTransferHandle transfer);
+
+  // Informs the object to drop internal references.
+  void InternalClose();
+
   PlatformUsbDeviceHandle handle_;
 
-  // transfers_ tracks all in-flight transfers associated with this device,
-  // allowing the device to retain the buffer and callback associated with a
-  // transfer until such time that it completes. It is protected by lock_.
-  base::Lock lock_;
-  std::map<PlatformUsbTransferHandle, Transfer> transfers_;
+  scoped_refptr<UsbConfigDescriptor> interfaces_;
+
+  typedef std::map<int, scoped_refptr<InterfaceClaimer> > ClaimedInterfaceMap;
+  ClaimedInterfaceMap claimed_interfaces_;
+
+  typedef std::map<PlatformUsbTransferHandle, Transfer> TransferMap;
+  TransferMap transfers_;
+
+  // A map from endpoints to interfaces
+  typedef std::map<int, int> EndpointMap;
+  EndpointMap endpoint_map_;
+
+  // Retain the UsbContext so that the platform context will not be destroyed
+  // before this handle.
+  scoped_refptr<UsbContext> context_;
+
+  base::ThreadChecker thread_checker_;
 
   DISALLOW_COPY_AND_ASSIGN(UsbDeviceHandle);
 };
diff --git a/chrome/browser/usb/usb_service.cc b/chrome/browser/usb/usb_service.cc
index d850488..4425d9b 100644
--- a/chrome/browser/usb/usb_service.cc
+++ b/chrome/browser/usb/usb_service.cc
@@ -4,6 +4,7 @@
 
 #include "chrome/browser/usb/usb_service.h"
 
+#include <set>
 #include <vector>
 
 #include "base/bind.h"
@@ -60,15 +61,19 @@
 
 }  // namespace
 
-UsbService::UsbService() : context_(new UsbContext()) {
+using content::BrowserThread;
+
+UsbService::UsbService()
+    : context_(new UsbContext()) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
 }
 
 UsbService::~UsbService() {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
-  // UsbDeviceHandle::Close removes itself from devices_.
-  while (devices_.size())
-    devices_.begin()->second->Close();
+  for (DeviceMap::iterator it = devices_.begin();
+      it != devices_.end(); ++it) {
+    it->second->OnDisconnect();
+  }
 }
 
 UsbService* UsbService::GetInstance() {
@@ -116,19 +121,14 @@
 #endif  // defined(OS_CHROMEOS)
 }
 
-void UsbService::EnumerateDevices(
-    vector<scoped_refptr<UsbDeviceHandle> >* devices) {
-  devices->clear();
+void UsbService::GetDevices(std::vector<scoped_refptr<UsbDevice> >* devices) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+  STLClearObject(devices);
+  RefreshDevices();
 
-  DeviceVector enumerated_devices;
-  EnumerateDevicesImpl(&enumerated_devices);
-
-  for (DeviceVector::iterator it = enumerated_devices.begin();
-       it != enumerated_devices.end(); ++it) {
-    PlatformUsbDevice device = it->device();
-    UsbDeviceHandle* const wrapper = LookupOrCreateDevice(device);
-    if (wrapper)
-      devices->push_back(wrapper);
+  for (DeviceMap::iterator it = devices_.begin();
+      it != devices_.end(); ++it) {
+    devices->push_back(it->second);
   }
 }
 
@@ -153,7 +153,8 @@
     const uint16 product_id,
     const base::Callback<void(ScopedDeviceVector vectors)>& callback,
     bool success) {
-  ScopedDeviceVector devices(new vector<scoped_refptr<UsbDeviceHandle> >());
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+  ScopedDeviceVector devices(new vector<scoped_refptr<UsbDevice> >());
 
   // If the permission broker was unable to obtain permission for the specified
   // devices then there is no point in attempting to enumerate the devices. On
@@ -163,88 +164,64 @@
     return;
   }
 
-  DeviceVector enumerated_devices;
-  EnumerateDevicesImpl(&enumerated_devices);
+  RefreshDevices();
 
-  for (DeviceVector::iterator it = enumerated_devices.begin();
-       it != enumerated_devices.end(); ++it) {
-    PlatformUsbDevice device = it->device();
-    if (DeviceMatches(device, vendor_id, product_id)) {
-      UsbDeviceHandle* const wrapper = LookupOrCreateDevice(device);
-      if (wrapper)
-        devices->push_back(make_scoped_refptr(wrapper));
-    }
+  for (DeviceMap::iterator it = devices_.begin();
+      it != devices_.end();   ++it) {
+    if (DeviceMatches(it->second, vendor_id, product_id))
+      devices->push_back(it->second);
   }
+
   callback.Run(devices.Pass());
 }
 
-void UsbService::CloseDevice(scoped_refptr<UsbDeviceHandle> device) {
-  PlatformUsbDevice platform_device = libusb_get_device(device->handle());
-  if (!ContainsKey(devices_, platform_device)) {
-    LOG(WARNING) << "CloseDevice called for device we're not tracking!";
-    return;
+void UsbService::RefreshDevices() {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+
+  libusb_device** platform_devices = NULL;
+  const ssize_t device_count =
+      libusb_get_device_list(context_->context(), &platform_devices);
+
+  std::set<UsbDevice*> connected_devices;
+  vector<PlatformUsbDevice> disconnected_devices;
+
+  // Populates new devices.
+  for (ssize_t i = 0; i < device_count; ++i) {
+    if (!ContainsKey(devices_, platform_devices[i])) {
+      libusb_device_descriptor descriptor;
+      // This test is needed. A valid vendor/produce pair is required.
+      if (0 != libusb_get_device_descriptor(platform_devices[i], &descriptor))
+        continue;
+      UsbDevice* new_device = new UsbDevice(context_,
+                                        platform_devices[i],
+                                        descriptor.idVendor,
+                                        descriptor.idProduct);
+      devices_[platform_devices[i]] = new_device;
+      connected_devices.insert(new_device);
+    } else {
+      connected_devices.insert(devices_[platform_devices[i]].get());
+    }
   }
 
-  devices_.erase(platform_device);
-  libusb_close(device->handle());
-}
-
-UsbService::RefCountedPlatformUsbDevice::RefCountedPlatformUsbDevice(
-    PlatformUsbDevice device) : device_(device) {
-  libusb_ref_device(device_);
-}
-
-UsbService::RefCountedPlatformUsbDevice::RefCountedPlatformUsbDevice(
-    const RefCountedPlatformUsbDevice& other) : device_(other.device_) {
-  libusb_ref_device(device_);
-}
-
-UsbService::RefCountedPlatformUsbDevice::~RefCountedPlatformUsbDevice() {
-  libusb_unref_device(device_);
-}
-
-PlatformUsbDevice UsbService::RefCountedPlatformUsbDevice::device() {
-  return device_;
-}
-
-void UsbService::EnumerateDevicesImpl(DeviceVector* output) {
-  STLClearObject(output);
-
-  libusb_device** devices = NULL;
-  const ssize_t device_count = libusb_get_device_list(
-      context_->context(),
-      &devices);
-  if (device_count < 0)
-    return;
-
-  for (int i = 0; i < device_count; ++i) {
-    libusb_device* device = devices[i];
-    libusb_ref_device(device);
-    output->push_back(RefCountedPlatformUsbDevice(device));
+  // Find disconnected devices.
+  for (DeviceMap::iterator it = devices_.begin(); it != devices_.end(); ++it) {
+    if (!ContainsKey(connected_devices, it->second)) {
+      disconnected_devices.push_back(it->first);
+    }
   }
 
-  libusb_free_device_list(devices, true);
+  // Remove disconnected devices from devices_.
+  for (size_t i = 0; i < disconnected_devices.size(); ++i) {
+    // UsbDevice will be destroyed after this. The corresponding
+    // PlatformUsbDevice will be unref'ed during this process.
+    devices_.erase(disconnected_devices[i]);
+  }
+
+  libusb_free_device_list(platform_devices, true);
 }
 
-bool UsbService::DeviceMatches(PlatformUsbDevice device,
+bool UsbService::DeviceMatches(scoped_refptr<UsbDevice> device,
                                const uint16 vendor_id,
                                const uint16 product_id) {
-  libusb_device_descriptor descriptor;
-  if (libusb_get_device_descriptor(device, &descriptor))
-    return false;
-  return descriptor.idVendor == vendor_id && descriptor.idProduct == product_id;
-}
-
-UsbDeviceHandle* UsbService::LookupOrCreateDevice(PlatformUsbDevice device) {
-  if (!ContainsKey(devices_, device)) {
-    libusb_device_handle* handle = NULL;
-    if (libusb_open(device, &handle)) {
-      LOG(WARNING) << "Could not open device.";
-      return NULL;
-    }
-
-    UsbDeviceHandle* wrapper = new UsbDeviceHandle(this, handle);
-    devices_[device] = wrapper;
-  }
-  return devices_[device].get();
+  return device->vendor_id() == vendor_id && device->product_id() == product_id;
 }
diff --git a/chrome/browser/usb/usb_service.h b/chrome/browser/usb/usb_service.h
index dcd6e28..e89eff9 100644
--- a/chrome/browser/usb/usb_service.h
+++ b/chrome/browser/usb/usb_service.h
@@ -11,7 +11,7 @@
 
 #include "base/basictypes.h"
 #include "base/memory/singleton.h"
-#include "chrome/browser/usb/usb_device_handle.h"
+#include "chrome/browser/usb/usb_device.h"
 
 namespace base {
 
@@ -28,54 +28,38 @@
 // competition for the same USB device.
 class UsbService {
  public:
-  typedef scoped_ptr<std::vector<scoped_refptr<UsbDeviceHandle> > >
+  typedef scoped_ptr<std::vector<scoped_refptr<UsbDevice> > >
       ScopedDeviceVector;
+
   // Must be called on FILE thread.
   static UsbService* GetInstance();
 
   // Find all of the devices attached to the system that are identified by
   // |vendor_id| and |product_id|, inserting them into |devices|. Clears
   // |devices| before use. Calls |callback| once |devices| is populated.
+  // The result will be sorted by id in increasing order. Must be called on
+  // FILE thread.
   void FindDevices(
       const uint16 vendor_id,
       const uint16 product_id,
       int interface_id,
       const base::Callback<void(ScopedDeviceVector vector)>& callback);
 
-  // Find all of the devices attached to the system, inserting them into
-  // |devices|. Clears |devices| before use.
-  void EnumerateDevices(std::vector<scoped_refptr<UsbDeviceHandle> >* devices);
-
-  // This function should not be called by normal code. It is invoked by a
-  // UsbDevice's Close function and disposes of the associated platform handle.
-  void CloseDevice(scoped_refptr<UsbDeviceHandle> device);
+  // Get all of the devices attached to the system, inserting them into
+  // |devices|. Clears |devices| before use. The result will be sorted by id
+  // in increasing order. Must be called on FILE thread.
+  void GetDevices(std::vector<scoped_refptr<UsbDevice> >* devices);
 
  private:
-  UsbService();
-  virtual ~UsbService();
   friend struct DefaultSingletonTraits<UsbService>;
   friend class base::DeleteHelper<UsbService>;
 
-  // RefCountedPlatformUsbDevice takes care of managing the underlying reference
-  // count of a single PlatformUsbDevice. This allows us to construct things
-  // like vectors of RefCountedPlatformUsbDevices and not worry about having to
-  // explicitly unreference them after use.
-  class RefCountedPlatformUsbDevice {
-   public:
-    explicit RefCountedPlatformUsbDevice(PlatformUsbDevice device);
-    RefCountedPlatformUsbDevice(const RefCountedPlatformUsbDevice& other);
-    virtual ~RefCountedPlatformUsbDevice();
-    PlatformUsbDevice device();
-
-   private:
-    PlatformUsbDevice device_;
-  };
-
-  typedef std::vector<RefCountedPlatformUsbDevice> DeviceVector;
+  UsbService();
+  virtual ~UsbService();
 
   // Return true if |device|'s vendor and product identifiers match |vendor_id|
   // and |product_id|.
-  static bool DeviceMatches(PlatformUsbDevice device,
+  static bool DeviceMatches(scoped_refptr<UsbDevice> device,
                             const uint16 vendor_id,
                             const uint16 product_id);
 
@@ -97,21 +81,13 @@
       const base::Callback<void(ScopedDeviceVector vector)>& callback,
       bool success);
 
-  // Populates |output| with the result of enumerating all attached USB devices.
-  void EnumerateDevicesImpl(DeviceVector* output);
-
-  // If a UsbDevice wrapper corresponding to |device| has already been created,
-  // returns it. Otherwise, opens the device, creates a wrapper, and associates
-  // the wrapper with the device internally.
-  UsbDeviceHandle* LookupOrCreateDevice(PlatformUsbDevice device);
+  // Enumerate USB devices from OS and Update devices_ map.
+  void RefreshDevices();
 
   scoped_refptr<UsbContext> context_;
 
-  // The devices_ map contains scoped_refptrs to all open devices, indicated by
-  // their vendor and product id. This allows for reusing an open device without
-  // creating another platform handle for it.
-  typedef std::map<PlatformUsbDevice, scoped_refptr<UsbDeviceHandle> >
-      DeviceMap;
+  // The map from PlatformUsbDevices to UsbDevices.
+  typedef std::map<PlatformUsbDevice, scoped_refptr<UsbDevice> > DeviceMap;
   DeviceMap devices_;
 
   DISALLOW_COPY_AND_ASSIGN(UsbService);
diff --git a/chrome/browser_tests.isolate b/chrome/browser_tests.isolate
index 9c9ad09..79ffdc0 100644
--- a/chrome/browser_tests.isolate
+++ b/chrome/browser_tests.isolate
@@ -39,6 +39,9 @@
     ['OS=="linux" or OS=="mac" or OS=="win"', {
       'variables': {
         'isolate_dependency_tracked': [
+          '../media/test/data/bear-320x240-multitrack.webm',
+          '../media/test/data/no_streams.webm',
+          '../media/test/data/sfx.ogg',
           '../ppapi/tests/test_case.html',
           '../ppapi/tests/test_page.css',
           '../tools/swarm_client/run_isolated.py',
diff --git a/chrome/chrome.gyp b/chrome/chrome.gyp
index f9334b1..011c65d 100644
--- a/chrome/chrome.gyp
+++ b/chrome/chrome.gyp
@@ -252,6 +252,7 @@
           'dependencies': [
             '../base/base.gyp:base',
             '../content/content.gyp:content_utility',
+            '../media/media.gyp:media',
             '../skia/skia.gyp:skia',
             '../third_party/libxml/libxml.gyp:libxml',
             'common',
diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi
index dc86b55..97546aa 100644
--- a/chrome/chrome_browser.gypi
+++ b/chrome/chrome_browser.gypi
@@ -410,6 +410,8 @@
         'browser/component_updater/pnacl/pnacl_profile_observer.h',
         'browser/component_updater/pnacl/pnacl_updater_observer.cc',
         'browser/component_updater/pnacl/pnacl_updater_observer.h',
+        'browser/component_updater/ppapi_utils.cc',
+        'browser/component_updater/ppapi_utils.h',
         'browser/component_updater/recovery_component_installer.cc',
         'browser/component_updater/recovery_component_installer.h',
         'browser/component_updater/swiftshader_component_installer.cc',
@@ -485,6 +487,8 @@
         'browser/download/download_crx_util.cc',
         'browser/download/download_crx_util.h',
         'browser/download/download_crx_util_android.cc',
+        'browser/download/download_danger_prompt.cc',
+        'browser/download/download_danger_prompt.h',
         'browser/download/download_extensions.cc',
         'browser/download/download_extensions.h',
         'browser/download/download_file_picker.cc',
@@ -493,6 +497,8 @@
         'browser/download/download_history.h',
         'browser/download/download_item_model.cc',
         'browser/download/download_item_model.h',
+        'browser/download/download_path_reservation_tracker.cc',
+        'browser/download/download_path_reservation_tracker.h',
         'browser/download/download_prefs.cc',
         'browser/download/download_prefs.h',
         'browser/download/download_query.cc',
@@ -501,21 +507,19 @@
         'browser/download/download_request_infobar_delegate.h',
         'browser/download/download_request_limiter.cc',
         'browser/download/download_request_limiter.h',
-        'browser/download/download_path_reservation_tracker.cc',
-        'browser/download/download_path_reservation_tracker.h',
+        'browser/download/download_resource_throttle.cc',
+        'browser/download/download_resource_throttle.h',
         'browser/download/download_service.cc',
         'browser/download/download_service.h',
         'browser/download/download_service_factory.cc',
         'browser/download/download_service_factory.h',
-        'browser/download/download_danger_prompt.cc',
-        'browser/download/download_danger_prompt.h',
-        'browser/download/download_shelf.h',
         'browser/download/download_shelf.cc',
+        'browser/download/download_shelf.h',
         'browser/download/download_shelf_context_menu.cc',
         'browser/download/download_shelf_context_menu.h',
         'browser/download/download_started_animation.h',
-        'browser/download/download_resource_throttle.cc',
-        'browser/download/download_resource_throttle.h',
+        'browser/download/download_stats.cc',
+        'browser/download/download_stats.h',
         'browser/download/download_status_updater.cc',
         'browser/download/download_status_updater.h',
         'browser/download/download_status_updater_gtk.cc',
@@ -987,6 +991,8 @@
         'browser/media/webrtc_logging_handler_host.h',
         'browser/media_galleries/fileapi/av_scanning_file_validator.cc',
         'browser/media_galleries/fileapi/av_scanning_file_validator.h',
+        'browser/media_galleries/fileapi/device_media_async_file_util.cc',
+        'browser/media_galleries/fileapi/device_media_async_file_util.h',
         'browser/media_galleries/fileapi/itunes_finder.cc',
         'browser/media_galleries/fileapi/itunes_finder.h',
         'browser/media_galleries/fileapi/itunes_finder_mac.h',
@@ -999,12 +1005,19 @@
         'browser/media_galleries/fileapi/media_file_validator_factory.cc',
         'browser/media_galleries/fileapi/media_path_filter.cc',
         'browser/media_galleries/fileapi/media_path_filter.h',
+        'browser/media_galleries/fileapi/mtp_device_async_delegate.h',
+        'browser/media_galleries/fileapi/mtp_device_map_service.cc',
+        'browser/media_galleries/fileapi/mtp_device_map_service.h',
         'browser/media_galleries/fileapi/native_media_file_util.cc',
         'browser/media_galleries/fileapi/native_media_file_util.h',
         'browser/media_galleries/fileapi/picasa/picasa_finder.cc',
         'browser/media_galleries/fileapi/picasa/picasa_finder.h',
+        'browser/media_galleries/fileapi/safe_audio_video_checker.cc',
+        'browser/media_galleries/fileapi/safe_audio_video_checker.h',
         'browser/media_galleries/fileapi/safe_itunes_pref_parser_win.cc',
         'browser/media_galleries/fileapi/safe_itunes_pref_parser_win.h',
+        'browser/media_galleries/fileapi/supported_audio_video_checker.cc',
+        'browser/media_galleries/fileapi/supported_audio_video_checker.h',
         'browser/media_galleries/fileapi/supported_image_type_validator.cc',
         'browser/media_galleries/fileapi/supported_image_type_validator.h',
         'browser/media_galleries/imported_media_gallery_registry.cc',
@@ -1513,6 +1526,9 @@
         'browser/prefs/scoped_user_pref_update.h',
         'browser/prefs/session_startup_pref.cc',
         'browser/prefs/session_startup_pref.h',
+        'browser/prefs/synced_pref_change_registrar.cc',
+        'browser/prefs/synced_pref_change_registrar.h',
+        'browser/prefs/synced_pref_observer.h',
         'browser/prerender/prerender_condition.h',
         'browser/prerender/prerender_config.cc',
         'browser/prerender/prerender_config.h',
@@ -2012,6 +2028,8 @@
         'browser/storage_monitor/udev_util_linux.h',
         'browser/storage_monitor/volume_mount_watcher_win.cc',
         'browser/storage_monitor/volume_mount_watcher_win.h',
+        'browser/sxs_linux.cc',
+        'browser/sxs_linux.h',
         'browser/sync/about_sync_util.cc',
         'browser/sync/about_sync_util.h',
         'browser/sync/backend_migrator.cc',
@@ -2349,6 +2367,8 @@
         'browser/upgrade_detector_impl.h',
         'browser/upload_list.cc',
         'browser/upload_list.h',
+        'browser/usb/usb_device.cc',
+        'browser/usb/usb_device.h',
         'browser/usb/usb_device_handle.cc',
         'browser/usb/usb_device_handle.h',
         'browser/usb/usb_interface.cc',
@@ -2465,7 +2485,6 @@
             '../ui/web_dialogs/web_dialogs.gyp:web_dialogs',
             '../v8/tools/gyp/v8.gyp:v8',
             '../webkit/common/webkit_common.gyp:webkit_common',
-            '../webkit/plugins/webkit_plugins.gyp:plugins_common',
             '../webkit/storage_browser.gyp:webkit_storage_browser',
             '../webkit/storage_common.gyp:webkit_storage_common',
             '../webkit/webkit_resources.gyp:webkit_resources',
@@ -2502,15 +2521,6 @@
             'xcode_settings': {'OTHER_LDFLAGS': ['-weak_framework CoreImage']},
           },
         }],
-        ['OS=="win" or OS=="mac" or OS=="linux" or chromeos==1', {
-          'sources': [
-            'browser/media_galleries/fileapi/device_media_async_file_util.cc',
-            'browser/media_galleries/fileapi/device_media_async_file_util.h',
-            'browser/media_galleries/fileapi/mtp_device_async_delegate.h',
-            'browser/media_galleries/fileapi/mtp_device_map_service.cc',
-            'browser/media_galleries/fileapi/mtp_device_map_service.h',
-          ],
-        }],
         ['OS=="win" or OS=="mac"', {
           'sources': [
             'browser/media_galleries/fileapi/itunes_data_provider.cc',
@@ -2780,6 +2790,8 @@
             'browser/storage_monitor/mtab_watcher_linux.h',
             'browser/storage_monitor/storage_monitor_linux.cc',
             'browser/storage_monitor/storage_monitor_linux.h',
+            'browser/sxs_linux.cc',
+            'browser/sxs_linux.h',
             'browser/themes/theme_service_aurax11.cc',
             'browser/themes/theme_service_aurax11.h',
             'browser/ui/webui/help/version_updater_basic.cc',
@@ -3377,6 +3389,8 @@
           'type': 'none',
           'sources': [
             'android/java/src/org/chromium/chrome/browser/ApplicationLifetime.java',
+            'android/java/src/org/chromium/chrome/browser/autofill/AutofillDialogControllerAndroid.java',
+            'android/java/src/org/chromium/chrome/browser/autofill/AutofillDialogResult.java',
             'android/java/src/org/chromium/chrome/browser/autofill/AutofillPopupGlue.java',
             'android/java/src/org/chromium/chrome/browser/autofill/PersonalDataManager.java',
             'android/java/src/org/chromium/chrome/browser/CertificateViewer.java',
diff --git a/chrome/chrome_browser_chromeos.gypi b/chrome/chrome_browser_chromeos.gypi
index cd5fba8..1a8f105 100644
--- a/chrome/chrome_browser_chromeos.gypi
+++ b/chrome/chrome_browser_chromeos.gypi
@@ -248,6 +248,8 @@
         'browser/chromeos/drive/file_system/create_file_operation.h',
         'browser/chromeos/drive/file_system/download_operation.cc',
         'browser/chromeos/drive/file_system/download_operation.h',
+        'browser/chromeos/drive/file_system/get_file_for_saving_operation.cc',
+        'browser/chromeos/drive/file_system/get_file_for_saving_operation.h',
         'browser/chromeos/drive/file_system/move_operation.cc',
         'browser/chromeos/drive/file_system/move_operation.h',
         'browser/chromeos/drive/file_system/open_file_operation.cc',
@@ -321,12 +323,16 @@
         'browser/chromeos/extensions/file_manager/desktop_notifications.h',
         'browser/chromeos/extensions/file_manager/event_router.cc',
         'browser/chromeos/extensions/file_manager/event_router.h',
+        'browser/chromeos/extensions/file_manager/file_browser_handlers.cc',
+        'browser/chromeos/extensions/file_manager/file_browser_handlers.h',
         'browser/chromeos/extensions/file_manager/file_manager_util.cc',
         'browser/chromeos/extensions/file_manager/file_manager_util.h',
         'browser/chromeos/extensions/file_manager/file_tasks.cc',
         'browser/chromeos/extensions/file_manager/file_tasks.h',
         'browser/chromeos/extensions/file_manager/file_watcher.cc',
         'browser/chromeos/extensions/file_manager/file_watcher.h',
+        'browser/chromeos/extensions/file_manager/fileapi_util.cc',
+        'browser/chromeos/extensions/file_manager/fileapi_util.h',
         'browser/chromeos/extensions/file_manager/mounted_disk_monitor.cc',
         'browser/chromeos/extensions/file_manager/mounted_disk_monitor.h',
         'browser/chromeos/extensions/file_manager/zip_file_creator.cc',
@@ -592,13 +598,6 @@
         'browser/chromeos/mobile/mobile_activator.h',
         'browser/chromeos/mobile_config.cc',
         'browser/chromeos/mobile_config.h',
-        'browser/chromeos/net/connectivity_state_helper.cc',
-        'browser/chromeos/net/connectivity_state_helper.h',
-        'browser/chromeos/net/connectivity_state_helper_observer.h',
-        'browser/chromeos/net/cros_network_change_notifier_factory.cc',
-        'browser/chromeos/net/cros_network_change_notifier_factory.h',
-        'browser/chromeos/net/network_change_notifier_network_library.cc',
-        'browser/chromeos/net/network_change_notifier_network_library.h',
         'browser/chromeos/net/network_portal_detector.cc',
         'browser/chromeos/net/network_portal_detector.h',
         'browser/chromeos/net/network_portal_detector_impl.cc',
@@ -786,6 +785,8 @@
         'browser/chromeos/system/timezone_settings.h',
         'browser/chromeos/system_key_event_listener.cc',
         'browser/chromeos/system_key_event_listener.h',
+        'browser/chromeos/system_logs/about_system_logs_fetcher.cc',
+        'browser/chromeos/system_logs/about_system_logs_fetcher.h',
         'browser/chromeos/system_logs/chrome_internal_log_source.cc',
         'browser/chromeos/system_logs/chrome_internal_log_source.h',
         'browser/chromeos/system_logs/command_line_log_source.cc',
@@ -800,8 +801,10 @@
         'browser/chromeos/system_logs/memory_details_log_source.h',
         'browser/chromeos/system_logs/network_event_log_source.cc',
         'browser/chromeos/system_logs/network_event_log_source.h',
-        'browser/chromeos/system_logs/system_logs_fetcher.cc',
-        'browser/chromeos/system_logs/system_logs_fetcher.h',
+        'browser/chromeos/system_logs/scrubbed_system_logs_fetcher.cc',
+        'browser/chromeos/system_logs/scrubbed_system_logs_fetcher.h',
+        'browser/chromeos/system_logs/system_logs_fetcher_base.cc',
+        'browser/chromeos/system_logs/system_logs_fetcher_base.h',
         'browser/chromeos/system_logs/touch_log_source.cc',
         'browser/chromeos/system_logs/touch_log_source.h',
         'browser/chromeos/ui/app_launch_view.cc',
diff --git a/chrome/chrome_browser_extensions.gypi b/chrome/chrome_browser_extensions.gypi
index 6f7425d..e61183b 100644
--- a/chrome/chrome_browser_extensions.gypi
+++ b/chrome/chrome_browser_extensions.gypi
@@ -54,6 +54,8 @@
         # All .cc, .h, .m, and .mm files under browser/extensions except for
         # tests and mocks.
         '../extensions/browser/extension_prefs_scope.h',
+        '../extensions/browser/extension_error.cc',
+        '../extensions/browser/extension_error.h',
         '../extensions/browser/file_reader.cc',
         '../extensions/browser/file_reader.h',
         '../extensions/browser/pref_names.cc',
@@ -76,11 +78,12 @@
         'browser/extensions/activity_log/activity_log.h',
         'browser/extensions/activity_log/activity_log_policy.cc',
         'browser/extensions/activity_log/activity_log_policy.h',
+        'browser/extensions/activity_log/counting_policy.cc',
+        'browser/extensions/activity_log/counting_policy.h',
+        'browser/extensions/activity_log/database_string_table.cc',
+        'browser/extensions/activity_log/database_string_table.h',
         'browser/extensions/activity_log/fullstream_ui_policy.cc',
         'browser/extensions/activity_log/fullstream_ui_policy.h',
-        'browser/extensions/activity_log/stream_noargs_ui_policy.cc',
-        'browser/extensions/activity_log/stream_noargs_ui_policy.h',
-        'browser/extensions/activity_log/api_name_constants.h',
         'browser/extensions/activity_log/web_request_constants.cc',
         'browser/extensions/activity_log/web_request_constants.h',
         'browser/extensions/admin_policy.cc',
@@ -485,7 +488,6 @@
         'browser/extensions/api/system_memory/memory_info_provider.h',
         'browser/extensions/api/system_memory/system_memory_api.cc',
         'browser/extensions/api/system_memory/system_memory_api.h',
-        'browser/extensions/api/system_storage/storage_free_space_observer.h',
         'browser/extensions/api/system_storage/storage_info_provider.cc',
         'browser/extensions/api/system_storage/storage_info_provider.h',
         'browser/extensions/api/system_storage/system_storage_api.cc',
@@ -573,8 +575,6 @@
         'browser/extensions/default_apps.h',
         'browser/extensions/error_console/error_console.cc',
         'browser/extensions/error_console/error_console.h',
-        'browser/extensions/error_console/extension_error.cc',
-        'browser/extensions/error_console/extension_error.h',
         'browser/extensions/event_listener_map.cc',
         'browser/extensions/event_listener_map.h',
         'browser/extensions/event_names.cc',
@@ -745,8 +745,6 @@
         'browser/extensions/script_bubble_controller.h',
         'browser/extensions/script_executor.cc',
         'browser/extensions/script_executor.h',
-        'browser/extensions/shell_window_registry.cc',
-        'browser/extensions/shell_window_registry.h',
         'browser/extensions/standard_management_policy_provider.cc',
         'browser/extensions/standard_management_policy_provider.h',
         'browser/extensions/startup_helper.cc',
diff --git a/chrome/chrome_browser_ui.gypi b/chrome/chrome_browser_ui.gypi
index ea97dd7..a2ccaca 100644
--- a/chrome/chrome_browser_ui.gypi
+++ b/chrome/chrome_browser_ui.gypi
@@ -71,6 +71,10 @@
         'browser/ui/alternate_error_tab_observer.h',
         'browser/ui/android/android_about_app_info.cc',
         'browser/ui/android/android_about_app_info.h',
+        'browser/ui/android/autofill/autofill_dialog_controller_android.cc',
+        'browser/ui/android/autofill/autofill_dialog_controller_android.h',
+        'browser/ui/android/autofill/autofill_dialog_result.cc',
+        'browser/ui/android/autofill/autofill_dialog_result.h',
         'browser/ui/android/autofill/autofill_popup_view_android.cc',
         'browser/ui/android/autofill/autofill_popup_view_android.h',
         'browser/ui/android/certificate_viewer_android.cc',
@@ -276,10 +280,10 @@
         'browser/ui/autofill/autocheckout_bubble.cc',
         'browser/ui/autofill/autocheckout_bubble_controller.cc',
         'browser/ui/autofill/autocheckout_bubble_controller.h',
-        'browser/ui/autofill/autofill_credit_card_bubble.cc',
-        'browser/ui/autofill/autofill_credit_card_bubble.h',
-        'browser/ui/autofill/autofill_credit_card_bubble_controller.cc',
-        'browser/ui/autofill/autofill_credit_card_bubble_controller.h',
+        'browser/ui/autofill/autofill_dialog_common.cc',
+        'browser/ui/autofill/autofill_dialog_common.h',
+        'browser/ui/autofill/autofill_dialog_controller.cc',
+        'browser/ui/autofill/autofill_dialog_controller.h',
         'browser/ui/autofill/autofill_dialog_controller_impl.cc',
         'browser/ui/autofill/autofill_dialog_controller_impl.h',
         'browser/ui/autofill/autofill_dialog_models.cc',
@@ -299,6 +303,14 @@
         'browser/ui/autofill/country_combobox_model.h',
         'browser/ui/autofill/data_model_wrapper.cc',
         'browser/ui/autofill/data_model_wrapper.h',
+        'browser/ui/autofill/generated_credit_card_bubble_view.cc',
+        'browser/ui/autofill/generated_credit_card_bubble_view.h',
+        'browser/ui/autofill/generated_credit_card_bubble_controller.cc',
+        'browser/ui/autofill/generated_credit_card_bubble_controller.h',
+        'browser/ui/autofill/new_credit_card_bubble_view.cc',
+        'browser/ui/autofill/new_credit_card_bubble_view.h',
+        'browser/ui/autofill/new_credit_card_bubble_controller.cc',
+        'browser/ui/autofill/new_credit_card_bubble_controller.h',
         'browser/ui/autofill/tab_autofill_manager_delegate.cc',
         'browser/ui/autofill/tab_autofill_manager_delegate.h',
         'browser/ui/auto_login_infobar_delegate.cc',
@@ -518,6 +530,8 @@
         'browser/ui/cocoa/bookmarks/bookmark_tree_browser_cell.mm',
         'browser/ui/cocoa/browser/avatar_button_controller.h',
         'browser/ui/cocoa/browser/avatar_button_controller.mm',
+        'browser/ui/cocoa/browser/avatar_label_button.h',
+        'browser/ui/cocoa/browser/avatar_label_button.mm',
         'browser/ui/cocoa/browser/avatar_menu_bubble_controller.h',
         'browser/ui/cocoa/browser/avatar_menu_bubble_controller.mm',
         'browser/ui/cocoa/browser/edit_search_engine_cocoa_controller.h',
@@ -779,6 +793,8 @@
         'browser/ui/cocoa/multi_key_equivalent_button.mm',
         'browser/ui/cocoa/new_tab_button.h',
         'browser/ui/cocoa/new_tab_button.mm',
+        'browser/ui/cocoa/nine_part_button_cell.h',
+        'browser/ui/cocoa/nine_part_button_cell.mm',
         'browser/ui/cocoa/notifications/balloon_collection_cocoa.mm',
         'browser/ui/cocoa/notifications/balloon_controller.h',
         'browser/ui/cocoa/notifications/balloon_controller.mm',
@@ -1302,8 +1318,6 @@
         'browser/ui/omnibox/omnibox_popup_model.cc',
         'browser/ui/omnibox/omnibox_popup_model.h',
         'browser/ui/omnibox/omnibox_popup_model_observer.h',
-        'browser/ui/omnibox/omnibox_popup_non_view.cc',
-        'browser/ui/omnibox/omnibox_popup_non_view.h',
         'browser/ui/omnibox/omnibox_popup_view.h',
         'browser/ui/omnibox/omnibox_view.cc',
         'browser/ui/omnibox/omnibox_view.h',
@@ -1539,12 +1553,14 @@
         'browser/ui/views/ash/tab_scrubber.cc',
         'browser/ui/views/autofill/autocheckout_bubble_views.cc',
         'browser/ui/views/autofill/autocheckout_bubble_views.h',
-        'browser/ui/views/autofill/autofill_credit_card_bubble_views.cc',
-        'browser/ui/views/autofill/autofill_credit_card_bubble_views.h',
         'browser/ui/views/autofill/autofill_dialog_views.cc',
         'browser/ui/views/autofill/autofill_dialog_views.h',
         'browser/ui/views/autofill/autofill_popup_view_views.cc',
         'browser/ui/views/autofill/autofill_popup_view_views.h',
+        'browser/ui/views/autofill/generated_credit_card_bubble_views.cc',
+        'browser/ui/views/autofill/generated_credit_card_bubble_views.h',
+        'browser/ui/views/autofill/new_credit_card_bubble_views.cc',
+        '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/avatar_menu_bubble_view.cc',
@@ -1779,8 +1795,8 @@
         'browser/ui/views/javascript_app_modal_dialog_views.h',
         'browser/ui/views/load_complete_listener.cc',
         'browser/ui/views/load_complete_listener.h',
-        'browser/ui/views/location_bar/autofill_credit_card_view.cc',
-        'browser/ui/views/location_bar/autofill_credit_card_view.h',
+        'browser/ui/views/location_bar/generated_credit_card_view.cc',
+        'browser/ui/views/location_bar/generated_credit_card_view.h',
         'browser/ui/views/location_bar/content_setting_image_view.cc',
         'browser/ui/views/location_bar/content_setting_image_view.h',
         'browser/ui/views/location_bar/ev_bubble_view.cc',
@@ -1797,8 +1813,6 @@
         'browser/ui/views/location_bar/location_bar_view.h',
         'browser/ui/views/location_bar/location_icon_view.cc',
         'browser/ui/views/location_bar/location_icon_view.h',
-        'browser/ui/views/location_bar/mic_search_view.cc',
-        'browser/ui/views/location_bar/mic_search_view.h',
         'browser/ui/views/location_bar/open_pdf_in_reader_view.cc',
         'browser/ui/views/location_bar/open_pdf_in_reader_view.h',
         'browser/ui/views/location_bar/page_action_image_view.cc',
@@ -1813,8 +1827,6 @@
         'browser/ui/views/location_bar/selected_keyword_view.h',
         'browser/ui/views/location_bar/star_view.cc',
         'browser/ui/views/location_bar/star_view.h',
-        'browser/ui/views/location_bar/touchable_location_bar_view.cc',
-        'browser/ui/views/location_bar/touchable_location_bar_view.h',
         'browser/ui/views/location_bar/zoom_bubble_view.cc',
         'browser/ui/views/location_bar/zoom_bubble_view.h',
         'browser/ui/views/location_bar/zoom_view.cc',
@@ -2053,6 +2065,8 @@
         'browser/ui/webui/chromeos/proxy_settings_ui.h',
         'browser/ui/webui/chromeos/sim_unlock_ui.cc',
         'browser/ui/webui/chromeos/sim_unlock_ui.h',
+        'browser/ui/webui/chromeos/slow_ui.cc',
+        'browser/ui/webui/chromeos/slow_ui.h',
         'browser/ui/webui/chromeos/system_info_ui.cc',
         'browser/ui/webui/chromeos/system_info_ui.h',
         'browser/ui/webui/chromeos/ui_account_tweaks.cc',
@@ -2335,10 +2349,10 @@
         'browser/ui/webui/signin/profile_signin_confirmation_dialog.cc',
         'browser/ui/webui/signin/profile_signin_confirmation_ui.h',
         'browser/ui/webui/signin/profile_signin_confirmation_ui.cc',
-        'browser/ui/webui/signin/user_chooser_screen_handler.h',
-        'browser/ui/webui/signin/user_chooser_screen_handler.cc',
-        'browser/ui/webui/signin/user_chooser_ui.h',
-        'browser/ui/webui/signin/user_chooser_ui.cc',
+        'browser/ui/webui/signin/user_manager_screen_handler.h',
+        'browser/ui/webui/signin/user_manager_screen_handler.cc',
+        'browser/ui/webui/signin/user_manager_ui.h',
+        'browser/ui/webui/signin/user_manager_ui.cc',
         'browser/ui/webui/signin_internals_ui.cc',
         'browser/ui/webui/signin_internals_ui.h',
         'browser/ui/webui/suggestions_internals/suggestions_internals_ui.cc',
@@ -2593,6 +2607,10 @@
             ['exclude', 'browser/ui/views/screen_capture_notification_ui_views.cc'],
             ['exclude', 'browser/ui/webui/help/version_updater_basic.cc'],
             ['exclude', 'browser/ui/webui/help/version_updater_basic.h'],
+            ['exclude', 'browser/ui/webui/signin/user_manager_screen_handler.h'],
+            ['exclude', 'browser/ui/webui/signin/user_manager_screen_handler.cc'],
+            ['exclude', 'browser/ui/webui/signin/user_manager_ui.h'],
+            ['exclude', 'browser/ui/webui/signin/user_manager_ui.cc'],
             ['exclude', 'browser/upgrade_detector_impl.cc'],
             ['exclude', 'browser/upgrade_detector_impl.h'],
           ],
@@ -2782,8 +2800,6 @@
             'chrome_browser_jni_headers',
           ],
           'sources': [
-            'browser/ui/find_bar/find_match_rects_details.cc',
-            'browser/ui/find_bar/find_match_rects_details.h',
             'browser/ui/webui/ntp/android/bookmarks_handler.cc',
             'browser/ui/webui/ntp/android/bookmarks_handler.h',
             'browser/ui/webui/ntp/android/context_menu_handler.cc',
@@ -2878,6 +2894,7 @@
             'browser/ui/window_sizer/window_sizer.h',
           ],
           'sources/': [
+            ['exclude', '^browser/ui/autofill/.*credit_card_bubble.*'],
             ['exclude', '^browser/ui/content_settings/'],
             ['exclude', '^browser/ui/omnibox/'],
             ['exclude', '^browser/ui/panels/'],
@@ -3081,6 +3098,15 @@
             ['include', '^browser/ui/app_list/app_list_service_disabled.cc'],
           ],
         }],
+        ['enable_autofill_dialog!=1 or OS=="android"', {
+          'sources!': [
+            'browser/ui/autofill/autofill_dialog_controller_impl.cc',
+            'browser/ui/autofill/autofill_dialog_controller_impl.h',
+            'browser/ui/autofill/autofill_dialog_view.h',
+            'browser/ui/autofill/autofill_dialog_view.cc',
+            'browser/ui/autofill/autofill_dialog_view_delegate.h',
+          ],
+        }],
         ['enable_google_now==0', {
           'sources!': [
             'browser/ui/webui/options/geolocation_options_handler.cc',
diff --git a/chrome/chrome_common.gypi b/chrome/chrome_common.gypi
index bf7f2ae..e5bdb52 100644
--- a/chrome/chrome_common.gypi
+++ b/chrome/chrome_common.gypi
@@ -70,6 +70,10 @@
         '../extensions/common/extension_paths.h',
         '../extensions/common/extension_resource.cc',
         '../extensions/common/extension_resource.h',
+        '../extensions/common/extensions_client.cc',
+        '../extensions/common/extensions_client.h',
+        '../extensions/common/features/feature_provider.cc',
+        '../extensions/common/features/feature_provider.h',
         '../extensions/common/id_util.cc',
         '../extensions/common/id_util.h',
         '../extensions/common/install_warning.cc',
@@ -90,6 +94,7 @@
         '../extensions/common/matcher/url_matcher_helpers.h',
         '../extensions/common/one_shot_event.cc',
         '../extensions/common/one_shot_event.h',
+        '../extensions/common/permissions/permissions_provider.h',
         '../extensions/common/switches.cc',
         '../extensions/common/switches.h',
         '../extensions/common/url_pattern.cc',
@@ -205,6 +210,8 @@
         'common/extensions/api/system_indicator/system_indicator_handler.h',
         'common/extensions/background_info.cc',
         'common/extensions/background_info.h',
+        'common/extensions/chrome_extensions_client.cc',
+        'common/extensions/chrome_extensions_client.h',
         'common/extensions/chrome_manifest_handlers.cc',
         'common/extensions/chrome_manifest_handlers.h',
         'common/extensions/command.cc',
@@ -242,7 +249,8 @@
         'common/extensions/features/complex_feature.h',
         'common/extensions/features/feature.cc',
         'common/extensions/features/feature.h',
-        'common/extensions/features/feature_provider.h',
+        'common/extensions/features/feature_channel.cc',
+        'common/extensions/features/feature_channel.h',
         'common/extensions/features/manifest_feature.cc',
         'common/extensions/features/manifest_feature.h',
         'common/extensions/features/permission_feature.cc',
diff --git a/chrome/chrome_dll.gypi b/chrome/chrome_dll.gypi
index 7c831d3..a64ad95 100644
--- a/chrome/chrome_dll.gypi
+++ b/chrome/chrome_dll.gypi
@@ -242,9 +242,12 @@
             }, {
               'dependencies': [
                 '<@(chromium_child_dependencies)',
-                '../content/content.gyp:content_app_child',
+                '../content/content.gyp:content_app_both',
                 '../content/content.gyp:content_worker',
               ],
+              'dependencies!': [
+                '../content/content.gyp:content_app_browser',
+              ],
             }],
             ['OS=="mac" and component!="shared_library"', {
               'includes': [ 'chrome_dll_bundle.gypi' ],
diff --git a/chrome/chrome_installer.gypi b/chrome/chrome_installer.gypi
index 8543946..f4c5f5d 100644
--- a/chrome/chrome_installer.gypi
+++ b/chrome/chrome_installer.gypi
@@ -279,6 +279,7 @@
             'installer/setup/install_worker.cc',
             'installer/setup/install_worker.h',
             'installer/setup/setup_main.cc',
+            'installer/setup/setup_main.h',
             'installer/setup/setup.ico',
             'installer/setup/setup.rc',
             'installer/setup/setup_constants.cc',
diff --git a/chrome/chrome_nibs.gypi b/chrome/chrome_nibs.gypi
index f327c14..7c7aa33 100644
--- a/chrome/chrome_nibs.gypi
+++ b/chrome/chrome_nibs.gypi
@@ -18,6 +18,7 @@
       'app/nibs/CollectedCookies.xib',
       'app/nibs/ContentBlockedCookies.xib',
       'app/nibs/ContentBlockedDownloads.xib',
+      'app/nibs/ContentBlockedMIDISysEx.xib',
       'app/nibs/ContentBlockedMedia.xib',
       'app/nibs/ContentBlockedMixedScript.xib',
       'app/nibs/ContentBlockedPlugins.xib',
diff --git a/chrome/chrome_renderer.gypi b/chrome/chrome_renderer.gypi
index d7f0353..ed66398 100644
--- a/chrome/chrome_renderer.gypi
+++ b/chrome/chrome_renderer.gypi
@@ -31,7 +31,6 @@
         '../webkit/support/webkit_support.gyp:glue_child',
         '../webkit/renderer/webkit_renderer.gyp:webkit_renderer',
         '../webkit/support/webkit_support.gyp:glue',
-        '../webkit/support/webkit_support.gyp:plugins',
         '../webkit/webkit_resources.gyp:webkit_resources',
       ],
       'include_dirs': [
diff --git a/chrome/chrome_tests.gypi b/chrome/chrome_tests.gypi
index 80199fe..8a257ce 100644
--- a/chrome/chrome_tests.gypi
+++ b/chrome/chrome_tests.gypi
@@ -1337,6 +1337,8 @@
         'browser/extensions/api/system_display/system_display_apitest.cc',
         'browser/extensions/api/system_memory/system_memory_apitest.cc',
         'browser/extensions/api/system_private/system_private_apitest.cc',
+        'browser/extensions/api/system_storage/storage_api_test_util.cc',
+        'browser/extensions/api/system_storage/storage_api_test_util.h',
         'browser/extensions/api/system_storage/system_storage_apitest.cc',
         'browser/extensions/api/system_storage/system_storage_eject_apitest.cc',
         'browser/extensions/api/tab_capture/tab_capture_apitest.cc',
@@ -1444,12 +1446,13 @@
         'browser/managed_mode/managed_user_service_browsertest.cc',
         'browser/media/chrome_media_stream_infobar_browsertest.cc',
         'browser/media/chrome_webrtc_browsertest.cc',
+        'browser/media/chrome_webrtc_audio_quality_browsertest.cc',
         'browser/media/chrome_webrtc_video_quality_browsertest.cc',
         'browser/media/webrtc_browsertest_base.cc',
         'browser/media/webrtc_browsertest_base.h',
         'browser/media/webrtc_browsertest_common.cc',
         'browser/media_galleries/fileapi/itunes_finder_win_browsertest.cc',
-        'browser/media_galleries/fileapi/media_file_validator_unittest.cc',
+        'browser/media_galleries/fileapi/media_file_validator_browsertest.cc',
         'browser/media_galleries/media_galleries_dialog_controller_mock.cc',
         'browser/media_galleries/media_galleries_dialog_controller_mock.h',
         'browser/metrics/metrics_service_browsertest.cc',
@@ -1482,6 +1485,7 @@
         'browser/policy/test_utils.h',
         'browser/prefs/pref_functional_browsertest.cc',
         'browser/prefs/pref_service_browsertest.cc',
+        'browser/prefs/synced_pref_change_registrar_browsertest.cc',
         'browser/prerender/prefetch_browsertest.cc',
         'browser/prerender/prerender_browsertest.cc',
         'browser/printing/cloud_print/test/cloud_print_policy_browsertest.cc',
@@ -2069,7 +2073,7 @@
           'dependencies': [
             # Runtime dependency.
             '../third_party/widevine/cdm/widevine_cdm.gyp:widevinecdmadapter',
-            '../webkit/support/webkit_support.gyp:clearkeycdmadapter',
+            '../media/media.gyp:clearkeycdmadapter',
           ],
         }],
       ],  # conditions
@@ -3295,7 +3299,7 @@
           'dependencies': [
             'browser_tests',
             'chrome',
-            '../third_party/WebKit/Tools/DumpRenderTree/DumpRenderTree.gyp/DumpRenderTree.gyp:copy_TestNetscapePlugIn',
+            '../third_party/WebKit/public/blink_test_plugin.gyp:blink_test_plugin',
           ],
           'includes': [
             '../build/isolate.gypi',
diff --git a/chrome/chrome_tests_unit.gypi b/chrome/chrome_tests_unit.gypi
index 79f7a73..c5c831c 100644
--- a/chrome/chrome_tests_unit.gypi
+++ b/chrome/chrome_tests_unit.gypi
@@ -11,7 +11,6 @@
       'dependencies': [
         # NOTE: New dependencies should generally be added in the OS!="ios"
         # dependencies block below, rather than here.
-        'app/policy/cloud_policy_codegen.gyp:policy_test_support',
         'browser',
         'chrome_resources.gyp:chrome_resources',
         'chrome_resources.gyp:chrome_strings',
@@ -33,7 +32,6 @@
         '../ui/message_center/message_center.gyp:message_center_test_support',
       ],
       'export_dependent_settings': [
-        'app/policy/cloud_policy_codegen.gyp:policy_test_support',
         '../base/base.gyp:test_support_base',
       ],
       'include_dirs': [
@@ -90,8 +88,6 @@
         'browser/chromeos/login/mock_user_image_manager.h',
         'browser/chromeos/login/mock_user_manager.cc',
         'browser/chromeos/login/mock_user_manager.h',
-        'browser/chromeos/net/mock_connectivity_state_helper.cc',
-        'browser/chromeos/net/mock_connectivity_state_helper.h',
         'browser/chromeos/policy/device_policy_builder.cc',
         'browser/chromeos/policy/device_policy_builder.h',
         'browser/chromeos/policy/stub_enterprise_install_attributes.cc',
@@ -113,8 +109,6 @@
         'browser/drive/fake_drive_service.h',
         'browser/extensions/api/messaging/native_messaging_test_util.cc',
         'browser/extensions/api/messaging/native_messaging_test_util.h',
-        'browser/extensions/api/system_storage/test_storage_info_provider.cc',
-        'browser/extensions/api/system_storage/test_storage_info_provider.h',
         'browser/extensions/extension_notification_observer.cc',
         'browser/extensions/extension_notification_observer.h',
         'browser/extensions/fake_safe_browsing_database_manager.cc',
@@ -195,8 +189,6 @@
         'common/extensions/extension_builder.h',
         'common/extensions/extension_test_util.cc',
         'common/extensions/extension_test_util.h',
-        'common/extensions/permissions/scoped_testing_permissions_info.cc',
-        'common/extensions/permissions/scoped_testing_permissions_info.h',
         'common/extensions/value_builder.cc',
         'common/extensions/value_builder.h',
         'renderer/chrome_mock_render_thread.cc',
@@ -342,6 +334,14 @@
             ['exclude', '^browser/policy'],
           ],
         }],
+        ['configuration_policy==1', {
+          'dependencies': [
+            'app/policy/cloud_policy_codegen.gyp:policy_test_support',
+          ],
+          'export_dependent_settings': [
+            'app/policy/cloud_policy_codegen.gyp:policy_test_support',
+          ],
+        }],
         ['safe_browsing!=1', {
           'sources/': [
             ['exclude', '^browser/extensions/blacklist_unittest.cc'],
@@ -618,6 +618,7 @@
         'browser/chromeos/drive/file_system/create_directory_operation_unittest.cc',
         'browser/chromeos/drive/file_system/create_file_operation_unittest.cc',
         'browser/chromeos/drive/file_system/download_operation_unittest.cc',
+        'browser/chromeos/drive/file_system/get_file_for_saving_operation_unittest.cc',
         'browser/chromeos/drive/file_system/move_operation_unittest.cc',
         'browser/chromeos/drive/file_system/open_file_operation_unittest.cc',
         'browser/chromeos/drive/file_system/operation_test_base.cc',
@@ -646,6 +647,7 @@
         'browser/chromeos/drive/webkit_file_stream_reader_impl_unittest.cc',
         'browser/chromeos/extensions/default_app_order_unittest.cc',
         'browser/chromeos/extensions/file_manager/desktop_notifications_unittest.cc',
+        'browser/chromeos/extensions/file_manager/file_tasks_unittest.cc',
         'browser/chromeos/extensions/file_manager/file_watcher_unittest.cc',
         'browser/chromeos/extensions/wallpaper_private_api_unittest.cc',
         'browser/chromeos/external_metrics_unittest.cc',
@@ -750,6 +752,7 @@
         'browser/download/download_status_updater_unittest.cc',
         'browser/download/download_target_determiner_unittest.cc',
         'browser/download/download_ui_controller_unittest.cc',
+        'browser/download/download_util_unittest.cc',
         'browser/drive/drive_api_util_unittest.cc',
         'browser/drive/drive_uploader_unittest.cc',
         'browser/drive/event_logger_unittest.cc',
@@ -758,8 +761,10 @@
         'browser/extensions/active_tab_unittest.cc',
         'browser/extensions/activity_log/activity_database_unittest.cc',
         'browser/extensions/activity_log/activity_log_unittest.cc',
+        'browser/extensions/activity_log/activity_log_policy_unittest.cc',
+        'browser/extensions/activity_log/counting_policy_unittest.cc',
+        'browser/extensions/activity_log/database_string_table_unittest.cc',
         'browser/extensions/activity_log/fullstream_ui_policy_unittest.cc',
-        'browser/extensions/activity_log/stream_noargs_ui_policy_unittest.cc',
         'browser/extensions/admin_policy_unittest.cc',
         'browser/extensions/api/activity_log_private/activity_log_private_api_unittest.cc',
         'browser/extensions/api/alarms/alarms_api_unittest.cc',
@@ -817,7 +822,6 @@
         'browser/extensions/api/storage/settings_test_util.h',
         'browser/extensions/api/streams_private/streams_private_manifest_unittest.cc',
         'browser/extensions/api/system_display/display_info_provider_chromeos_unittest.cc',
-        'browser/extensions/api/system_storage/storage_info_provider_unittest.cc',
         'browser/extensions/api/web_navigation/frame_navigation_state_unittest.cc',
         'browser/extensions/api/web_request/form_data_parser_unittest.cc',
         'browser/extensions/api/web_request/upload_data_presenter_unittest.cc',
@@ -1346,16 +1350,18 @@
         'browser/ui/ash/window_positioner_unittest.cc',
         'browser/ui/autofill/account_chooser_model_unittest.cc',
         'browser/ui/autofill/autocheckout_bubble_controller_unittest.cc',
-        'browser/ui/autofill/autofill_credit_card_bubble_controller_unittest.cc',
         'browser/ui/autofill/autofill_dialog_controller_unittest.cc',
         'browser/ui/autofill/autofill_dialog_models_unittest.cc',
         'browser/ui/autofill/autofill_dialog_types_unittest.cc',
         'browser/ui/autofill/autofill_popup_controller_unittest.cc',
         'browser/ui/autofill/data_model_wrapper_unittest.cc',
+        'browser/ui/autofill/generated_credit_card_bubble_controller_unittest.cc',
         'browser/ui/autofill/mock_autofill_dialog_view_delegate.cc',
         'browser/ui/autofill/mock_autofill_dialog_view_delegate.h',
-        'browser/ui/autofill/test_autofill_credit_card_bubble.cc',
-        'browser/ui/autofill/test_autofill_credit_card_bubble.h',
+        'browser/ui/autofill/mock_new_credit_card_bubble_controller.cc',
+        'browser/ui/autofill/mock_new_credit_card_bubble_controller.h',
+        'browser/ui/autofill/test_generated_credit_card_bubble_view.cc',
+        'browser/ui/autofill/test_generated_credit_card_bubble_view.h',
         'browser/ui/bookmarks/bookmark_context_menu_controller_unittest.cc',
         'browser/ui/bookmarks/bookmark_bubble_sign_in_delegate_unittest.cc',
         'browser/ui/bookmarks/bookmark_editor_unittest.cc',
@@ -1420,6 +1426,7 @@
         'browser/ui/cocoa/bookmarks/bookmark_sync_promo_controller_unittest.mm',
         'browser/ui/cocoa/bookmarks/bookmark_tree_browser_cell_unittest.mm',
         'browser/ui/cocoa/browser/avatar_button_controller_unittest.mm',
+        'browser/ui/cocoa/browser/avatar_label_button_unittest.mm',
         'browser/ui/cocoa/browser/avatar_menu_bubble_controller_unittest.mm',
         'browser/ui/cocoa/browser/edit_search_engine_cocoa_controller_unittest.mm',
         'browser/ui/cocoa/browser/password_generation_bubble_controller_unittest.mm',
@@ -1493,6 +1500,7 @@
         'browser/ui/cocoa/location_bar/keyword_hint_decoration_unittest.mm',
         'browser/ui/cocoa/location_bar/selected_keyword_decoration_unittest.mm',
         'browser/ui/cocoa/menu_button_unittest.mm',
+        'browser/ui/cocoa/nine_part_button_cell_unittest.mm',
         'browser/ui/cocoa/notifications/balloon_controller_unittest.mm',
         'browser/ui/cocoa/notifications/message_center_tray_bridge_unittest.mm',
         'browser/ui/cocoa/nsmenuitem_additions_unittest.mm',
@@ -2147,6 +2155,18 @@
             ['exclude', '^renderer/safe_browsing/'],
           ],
         }],
+        ['enable_autofill_dialog!=1 or OS=="android"', {
+          'sources!': [
+            'browser/ui/autofill/account_chooser_model_unittest.cc',
+            'browser/ui/autofill/autocheckout_bubble_controller_unittest.cc',
+            'browser/ui/autofill/autofill_credit_card_bubble_controller_unittest.cc',
+            'browser/ui/autofill/autofill_dialog_controller_unittest.cc',
+            'browser/ui/autofill/mock_autofill_dialog_view_delegate.cc',
+            'browser/ui/autofill/mock_autofill_dialog_view_delegate.h',
+            'browser/ui/autofill/test_autofill_credit_card_bubble.cc',
+            'browser/ui/autofill/test_autofill_credit_card_bubble.h',
+          ],
+        }],
         ['enable_automation!=1', {
           'sources/': [
             ['exclude', '^browser/automation/'],
@@ -2457,6 +2477,7 @@
             'browser/sync/profile_sync_service_session_unittest.cc',
             'browser/sync/sync_global_error_unittest.cc',
             'browser/tab_contents/render_view_context_menu_unittest.cc',
+            'browser/ui/autofill/autofill_dialog_controller_unittest.cc',
             'browser/ui/bookmarks/bookmark_bubble_sign_in_delegate_unittest.cc',
             'browser/ui/bookmarks/bookmark_context_menu_controller_unittest.cc',
             'browser/ui/bookmarks/bookmark_prompt_controller_unittest.cc',
@@ -2521,6 +2542,7 @@
             ['exclude', '^browser/sync/glue/app_'],
             ['exclude', '^browser/sync/glue/extension_'],
             ['exclude', '^browser/themes/'],
+            ['exclude', '^browser/ui/autofill/.*credit_card_bubble.*'],
             ['exclude', '^browser/ui/content_settings/'],
             ['exclude', '^browser/ui/omnibox/'],
             ['exclude', '^browser/ui/panels'],
diff --git a/chrome/common/chrome_constants.cc b/chrome/common/chrome_constants.cc
index 874a039..40621f8 100644
--- a/chrome/common/chrome_constants.cc
+++ b/chrome/common/chrome_constants.cc
@@ -253,6 +253,12 @@
 const char kProfileDirPrefix[] = "u-";
 #endif
 
+// This GUID is associated with any 'don't ask me again' settings that the
+// user can select for different file types.
+// {2676A9A2-D919-4FEE-9187-152100393AB2}
+const char kApplicationClientIDStringForAVScanning[] =
+    "2676A9A2-D919-4FEE-9187-152100393AB2";
+
 }  // namespace chrome
 
 #undef FPL
diff --git a/chrome/common/chrome_constants.h b/chrome/common/chrome_constants.h
index 6775c80..cd97f7c 100644
--- a/chrome/common/chrome_constants.h
+++ b/chrome/common/chrome_constants.h
@@ -139,6 +139,9 @@
 extern const char kProfileDirPrefix[];
 #endif
 
+// Used to identify the application to the system AV function in Windows.
+extern const char kApplicationClientIDStringForAVScanning[];
+
 }  // namespace chrome
 
 #endif  // CHROME_COMMON_CHROME_CONSTANTS_H_
diff --git a/chrome/common/chrome_content_client.cc b/chrome/common/chrome_content_client.cc
index 79ef06c..77a54fa 100644
--- a/chrome/common/chrome_content_client.cc
+++ b/chrome/common/chrome_content_client.cc
@@ -22,6 +22,7 @@
 #include "chrome/common/render_messages.h"
 #include "chrome/common/url_constants.h"
 #include "components/nacl/common/nacl_process_type.h"
+#include "content/public/common/content_constants.h"
 #include "content/public/common/content_switches.h"
 #include "content/public/common/pepper_plugin_info.h"
 #include "content/public/common/url_constants.h"
@@ -33,8 +34,6 @@
 #include "ui/base/layout.h"
 #include "ui/base/resource/resource_bundle.h"
 #include "webkit/common/user_agent/user_agent_util.h"
-#include "webkit/plugins/plugin_constants.h"
-#include "webkit/plugins/plugin_switches.h"
 
 #include "flapper_version.h"  // In SHARED_INTERMEDIATE_DIR.
 #include "widevine_cdm_version.h"  // In SHARED_INTERMEDIATE_DIR.
@@ -300,7 +299,7 @@
   // for testing purposes.
   plugin.is_out_of_process = !CommandLine::ForCurrentProcess()->HasSwitch(
       switches::kPpapiFlashInProcess);
-  plugin.name = kFlashPluginName;
+  plugin.name = content::kFlashPluginName;
   plugin.path = path;
   plugin.permissions = kPepperFlashPermissions;
 
@@ -321,13 +320,13 @@
   plugin.description = plugin.name + " " + flash_version_numbers[0] + "." +
       flash_version_numbers[1] + " r" + flash_version_numbers[2];
   plugin.version = JoinString(flash_version_numbers, '.');
-  content::WebPluginMimeType swf_mime_type(kFlashPluginSwfMimeType,
-                                           kFlashPluginSwfExtension,
-                                           kFlashPluginSwfDescription);
+  content::WebPluginMimeType swf_mime_type(content::kFlashPluginSwfMimeType,
+                                           content::kFlashPluginSwfExtension,
+                                           content::kFlashPluginSwfDescription);
   plugin.mime_types.push_back(swf_mime_type);
-  content::WebPluginMimeType spl_mime_type(kFlashPluginSplMimeType,
-                                           kFlashPluginSplExtension,
-                                           kFlashPluginSplDescription);
+  content::WebPluginMimeType spl_mime_type(content::kFlashPluginSplMimeType,
+                                           content::kFlashPluginSplExtension,
+                                           content::kFlashPluginSplDescription);
   plugin.mime_types.push_back(spl_mime_type);
 
   return plugin;
diff --git a/chrome/common/chrome_switches.cc b/chrome/common/chrome_switches.cc
index 8119470..c802fd1 100644
--- a/chrome/common/chrome_switches.cc
+++ b/chrome/common/chrome_switches.cc
@@ -145,6 +145,10 @@
 const char kAutomationReinitializeOnChannelError[] =
     "automation-reinitialize-on-channel-error";
 
+// Similar to kNoFirstRun, but also drops the First Run beacon so that first run
+// will not occur in subsequent runs either.
+const char kCancelFirstRun[]                = "cancel-first-run";
+
 // How often (in seconds) to check for updates. Should only be used for testing
 // purposes.
 const char kCheckForUpdateIntervalSec[]     = "check-for-update-interval";
@@ -809,7 +813,8 @@
 const char kForceAppMode[]                  = "force-app-mode";
 
 // Displays the First Run experience when the browser is started, regardless of
-// whether or not it's actually the First Run (this overrides kNoFirstRun).
+// whether or not it's actually the First Run (this overrides kNoFirstRun and
+// kCancelFirstRun).
 const char kForceFirstRun[]                 = "force-first-run";
 
 // Tries to load cloud policy for every signed in user, regardless of whether
diff --git a/chrome/common/chrome_switches.h b/chrome/common/chrome_switches.h
index 3272ce5..17d203c 100644
--- a/chrome/common/chrome_switches.h
+++ b/chrome/common/chrome_switches.h
@@ -56,6 +56,7 @@
 extern const char kAutoLaunchAtStartup[];
 extern const char kAutomationClientChannelID[];
 extern const char kAutomationReinitializeOnChannelError[];
+extern const char kCancelFirstRun[];
 extern const char kCheckForUpdateIntervalSec[];
 extern const char kCheckCloudPrintConnectorPolicy[];
 extern const char kChromeFrame[];
diff --git a/chrome/common/chrome_utility_messages.h b/chrome/common/chrome_utility_messages.h
index 3534f60..d14def5 100644
--- a/chrome/common/chrome_utility_messages.h
+++ b/chrome/common/chrome_utility_messages.h
@@ -189,6 +189,16 @@
                      std::vector<picasa::FolderINIContents> /* folders_inis */)
 #endif  // defined(OS_WIN) || defined(OS_MACOSX)
 
+#if !defined(OS_ANDROID) && !defined(OS_IOS)
+// Tell the utility process to attempt to validate the passed media file. The
+// file will undergo basic sanity checks and will be decoded for up to
+// |milliseconds_of_decoding| wall clock time. It is still not safe to decode
+// the file in the browser process after this check.
+IPC_MESSAGE_CONTROL2(ChromeUtilityMsg_CheckMediaFile,
+                     int64 /* milliseconds_of_decoding */,
+                     IPC::PlatformFileForTransit /* Media file to parse */)
+#endif  // !defined(OS_ANDROID) && !defined(OS_IOS)
+
 //------------------------------------------------------------------------------
 // Utility process host messages:
 // These are messages from the utility process to the browser.
@@ -312,3 +322,10 @@
 IPC_MESSAGE_CONTROL1(ChromeUtilityHostMsg_IndexPicasaAlbumsContents_Finished,
                      picasa::AlbumImagesMap /* albums_images */)
 #endif  // defined(OS_WIN) || defined(OS_MACOSX)
+
+#if !defined(OS_ANDROID) && !defined(OS_IOS)
+// Reply after checking the passed media file. A true result indicates that
+// the file appears to be a well formed media file.
+IPC_MESSAGE_CONTROL1(ChromeUtilityHostMsg_CheckMediaFile_Finished,
+                     bool /* passed_checks */)
+#endif  // !defined(OS_ANDROID) && !defined(OS_IOS)
diff --git a/chrome/common/extensions/api/_api_features.json b/chrome/common/extensions/api/_api_features.json
index d9075d7..3f1a46f 100644
--- a/chrome/common/extensions/api/_api_features.json
+++ b/chrome/common/extensions/api/_api_features.json
@@ -498,21 +498,6 @@
     "dependencies": ["permission:system.storage"],
     "contexts": ["blessed_extension"]
   },
-  "system.storage.addAvailableCapacityWatch": {
-    "channel": "dev"
-  },
-  "system.storage.removeAvailableCapacityWatch": {
-    "channel": "dev"
-  },
-  "system.storage.getAllAvailableCapacityWatches": {
-    "channel": "dev"
-  },
-  "system.storage.removeAllAvailableCapacityWatches": {
-    "channel": "dev"
-  },
-  "system.storage.onAvailableCapacityChanged": {
-    "channel": "dev"
-  },
   "systemPrivate": {
     "dependencies": ["permission:systemPrivate"],
     "contexts": ["blessed_extension"]
diff --git a/chrome/common/extensions/api/_permission_features.json b/chrome/common/extensions/api/_permission_features.json
index 1c761cc..fbaf434 100644
--- a/chrome/common/extensions/api/_permission_features.json
+++ b/chrome/common/extensions/api/_permission_features.json
@@ -188,15 +188,15 @@
     }
   ],
   "downloads": {
-    "channel": "beta",
+    "channel": "stable",
     "extension_types": ["extension"]
   },
   "downloads.open": {
-    "channel": "beta",
+    "channel": "stable",
     "extension_types": ["extension"]
   },
   "downloads.shelf": {
-    "channel": "beta",
+    "channel": "stable",
     "extension_types": ["extension"]
   },
   "dial": {
diff --git a/chrome/common/extensions/api/experimental_input_virtual_keyboard.json b/chrome/common/extensions/api/experimental_input_virtual_keyboard.json
index 4bd2c81..eb44bef 100644
--- a/chrome/common/extensions/api/experimental_input_virtual_keyboard.json
+++ b/chrome/common/extensions/api/experimental_input_virtual_keyboard.json
@@ -23,6 +23,27 @@
             "parameters": []
           }
         ]
+      },
+      {
+        "name": "moveCursor",
+        "type": "function",
+        "description": "Move cursor on the current focused textfield by swipe.",
+        "parameters": [
+          { "name": "swipe_direction",
+            "type": "integer",
+            "discription": "The direction of the cursor movement."
+	  },
+          { "name": "modifier_flags",
+            "type": "integer",
+            "description": "Bitmask representing the state of the system modifier keys."
+          },
+          { "type": "function",
+            "name": "callback",
+            "optional": true,
+            "decription": "called when the swipe movement is completed.",
+            "parameters": []
+          }
+	]
       }
     ]
   }
diff --git a/chrome/common/extensions/api/extension_api.cc b/chrome/common/extensions/api/extension_api.cc
index 56c44b5..0805b7e 100644
--- a/chrome/common/extensions/api/extension_api.cc
+++ b/chrome/common/extensions/api/extension_api.cc
@@ -18,10 +18,10 @@
 #include "base/values.h"
 #include "chrome/common/extensions/api/generated_schemas.h"
 #include "chrome/common/extensions/extension.h"
-#include "chrome/common/extensions/features/base_feature_provider.h"
-#include "chrome/common/extensions/features/simple_feature.h"
+#include "chrome/common/extensions/features/feature.h"
 #include "chrome/common/extensions/permissions/permission_set.h"
 #include "chrome/common/extensions/permissions/permissions_data.h"
+#include "extensions/common/features/feature_provider.h"
 #include "grit/common_resources.h"
 #include "grit/extensions_api_resources.h"
 #include "ui/base/resource/resource_bundle.h"
@@ -225,11 +225,11 @@
 
 void ExtensionAPI::InitDefaultConfiguration() {
   RegisterDependencyProvider(
-      "api", BaseFeatureProvider::GetByName("api"));
+      "api", FeatureProvider::GetByName("api"));
   RegisterDependencyProvider(
-      "manifest", BaseFeatureProvider::GetByName("manifest"));
+      "manifest", FeatureProvider::GetByName("manifest"));
   RegisterDependencyProvider(
-      "permission", BaseFeatureProvider::GetByName("permission"));
+      "permission", FeatureProvider::GetByName("permission"));
 
   // Schemas to be loaded from resources.
   CHECK(unloaded_schemas_.empty());
diff --git a/chrome/common/extensions/api/extension_api.h b/chrome/common/extensions/api/extension_api.h
index 2d5845b..e250419 100644
--- a/chrome/common/extensions/api/extension_api.h
+++ b/chrome/common/extensions/api/extension_api.h
@@ -16,7 +16,7 @@
 #include "base/strings/string_piece.h"
 #include "base/values.h"
 #include "chrome/common/extensions/features/feature.h"
-#include "chrome/common/extensions/features/feature_provider.h"
+#include "extensions/common/features/feature_provider.h"
 #include "extensions/common/url_pattern_set.h"
 
 namespace base {
diff --git a/chrome/common/extensions/api/metrics_private.json b/chrome/common/extensions/api/metrics_private.json
index 627687c..06e5274 100644
--- a/chrome/common/extensions/api/metrics_private.json
+++ b/chrome/common/extensions/api/metrics_private.json
@@ -57,6 +57,26 @@
         ]
       },
       {
+        "name": "getVariationParams",
+        "description": "Returns variation parameters for the named trial if available, or undefined otherwise.",
+        "type": "function",
+        "parameters": [
+          {"name": "name", "type": "string"},
+          {
+            "name": "callback",
+            "type": "function",
+            "optional": "false",
+            "parameters": [
+              {
+                "name": "params",
+                "type": "object",
+                "additionalProperties": { "type": "string" }
+              }
+            ]
+          }
+        ]
+      },
+      {
         "name": "recordUserAction",
         "type": "function",
         "description": "Records an action performed by the user.",
diff --git a/chrome/common/extensions/api/notifications.idl b/chrome/common/extensions/api/notifications.idl
index 5808bc4..2330c4d 100644
--- a/chrome/common/extensions/api/notifications.idl
+++ b/chrome/common/extensions/api/notifications.idl
@@ -61,7 +61,7 @@
     // epoch (e.g. <code>Date.now() + n</code>).
     double? eventTime;
 
-    // Text and icons of notification action buttons.
+    // Text and icons for up to two notification action buttons.
     NotificationButton[]? buttons;
 
     // Secondary notification content.
diff --git a/chrome/common/extensions/api/storage/storage_schema_manifest_handler_unittest.cc b/chrome/common/extensions/api/storage/storage_schema_manifest_handler_unittest.cc
index 4a6b4d8..088a2d5 100644
--- a/chrome/common/extensions/api/storage/storage_schema_manifest_handler_unittest.cc
+++ b/chrome/common/extensions/api/storage/storage_schema_manifest_handler_unittest.cc
@@ -14,7 +14,7 @@
 #include "chrome/common/chrome_version_info.h"
 #include "chrome/common/extensions/extension.h"
 #include "chrome/common/extensions/extension_file_util.h"
-#include "chrome/common/extensions/features/feature.h"
+#include "chrome/common/extensions/features/feature_channel.h"
 #include "chrome/common/extensions/manifest.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
@@ -67,7 +67,7 @@
   }
 
   base::ScopedTempDir temp_dir_;
-  Feature::ScopedCurrentChannel scoped_channel_;
+  ScopedCurrentChannel scoped_channel_;
   base::DictionaryValue manifest_;
 };
 
diff --git a/chrome/common/extensions/api/sync_file_system.idl b/chrome/common/extensions/api/sync_file_system.idl
index 72e2479..5eceabc 100644
--- a/chrome/common/extensions/api/sync_file_system.idl
+++ b/chrome/common/extensions/api/sync_file_system.idl
@@ -170,7 +170,7 @@
 
     // Returns each $ref:FileStatus for the given <code>fileEntry</code> array.
     // Typically called with the result from dirReader.readEntries().
-    static void getFileStatuses([instanceOf=EntryArray] object fileEntries,
+    static void getFileStatuses(object[] fileEntries,
                                 GetFileStatusesCallback callback);
   };
 
diff --git a/chrome/common/extensions/api/system_storage.idl b/chrome/common/extensions/api/system_storage.idl
index 4ec51f6..33338d4 100644
--- a/chrome/common/extensions/api/system_storage.idl
+++ b/chrome/common/extensions/api/system_storage.idl
@@ -4,7 +4,7 @@
 
 // Use the <code>chrome.system.storage</code> API to query storage device
 // information and be notified when a removable storage device is attached and
-// detached or the available capacity changes.
+// detached.
 namespace system.storage {
 
   enum StorageUnitType {
@@ -30,20 +30,6 @@
     double capacity;
   };
 
-  dictionary StorageFreeSpaceChangeInfo {
-    // The transient id of the storage unit already changed.
-    DOMString id;
-    // The new value of the available capacity.
-    double availableCapacity;
-  };
-
-  // A dictionary that describes the add particular storage device watch
-  // request results.
-  dictionary AddAvailableCapacityWatchResult {
-    DOMString id;
-    boolean success;
-  };
-
   [inline_doc] enum EjectDeviceResultCode {
     // The ejection command is successful -- the application can prompt the user
     // to remove the device.
@@ -58,12 +44,6 @@
     failure
   };
 
-  callback AddAvailableCapacityWatchCallback = void (
-      AddAvailableCapacityWatchResult info);
-
-  callback GetAllAvailableCapacityWatchesCallback = void (
-      DOMString[] storageIds);
-
   callback EjectDeviceCallback = void (EjectDeviceResultCode result);
 
   callback StorageInfoCallback = void (StorageUnitInfo[] info);
@@ -75,21 +55,6 @@
 
     // Ejects a removable storage device.
     static void ejectDevice(DOMString id, EjectDeviceCallback callback);
-
-    // Monitor a particular storage device available change capacity.
-    static void addAvailableCapacityWatch(
-        DOMString id,
-        AddAvailableCapacityWatchCallback callback);
-
-    // Remove the monitor of a particular device.
-    static void removeAvailableCapacityWatch(DOMString id);
-
-    // Get all the watched storage devices.
-    static void getAllAvailableCapacityWatches(
-        GetAllAvailableCapacityWatchesCallback callback);
-
-    // Remove all the storage devices monitors.
-    static void removeAllAvailableCapacityWatches();
   };
 
   interface Events {
@@ -98,10 +63,6 @@
 
     // Fired when a removable storage is detached from the system.
     static void onDetached(DOMString id);
-
-    // Fired when the storage device available capacity is changed.
-    // |info|: The changed information for the specified storage unit.
-    static void onAvailableCapacityChanged(StorageFreeSpaceChangeInfo info);
   };
 
 };
diff --git a/chrome/common/extensions/api/test.json b/chrome/common/extensions/api/test.json
index a06052d..94742b5 100644
--- a/chrome/common/extensions/api/test.json
+++ b/chrome/common/extensions/api/test.json
@@ -218,6 +218,22 @@
         ]
       },
       {
+        "name": "assertThrows",
+        "type": "function",
+        "nocompile": true,
+        "parameters": [
+          {"type": "function", "name": "fn"},
+          {
+            "type": "object",
+            "name": "self",
+            "additionalProperties": {"type": "any"},
+            "optional": true
+          },
+          {"type": "array", "items": {"type": "any"}, "name": "args"},
+          {"type": "string", "name": "message", "optional": true}
+        ]
+      },
+      {
         "name": "callback",
         "type": "function",
         "nocompile": true,
diff --git a/chrome/common/extensions/chrome_extensions_client.cc b/chrome/common/extensions/chrome_extensions_client.cc
new file mode 100644
index 0000000..3fa2135
--- /dev/null
+++ b/chrome/common/extensions/chrome_extensions_client.cc
@@ -0,0 +1,41 @@
+// 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/chrome_extensions_client.h"
+
+#include "chrome/common/extensions/chrome_manifest_handlers.h"
+#include "chrome/common/extensions/features/base_feature_provider.h"
+
+namespace extensions {
+
+static base::LazyInstance<ChromeExtensionsClient> g_client =
+    LAZY_INSTANCE_INITIALIZER;
+
+ChromeExtensionsClient::ChromeExtensionsClient()
+    :  chrome_api_permissions_(ChromeAPIPermissions()) {
+}
+
+ChromeExtensionsClient::~ChromeExtensionsClient() {
+}
+
+const PermissionsProvider&
+ChromeExtensionsClient::GetPermissionsProvider() const {
+  return chrome_api_permissions_;
+}
+
+FeatureProvider* ChromeExtensionsClient::GetFeatureProviderByName(
+    const std::string& name) const {
+  return BaseFeatureProvider::GetByName(name);
+}
+
+void ChromeExtensionsClient::RegisterManifestHandlers() const {
+  RegisterChromeManifestHandlers();
+}
+
+// static
+ChromeExtensionsClient* ChromeExtensionsClient::GetInstance() {
+  return g_client.Pointer();
+}
+
+}  // namespace extensions
diff --git a/chrome/common/extensions/chrome_extensions_client.h b/chrome/common/extensions/chrome_extensions_client.h
new file mode 100644
index 0000000..a74a890
--- /dev/null
+++ b/chrome/common/extensions/chrome_extensions_client.h
@@ -0,0 +1,42 @@
+// 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_CHROME_EXTENSIONS_CLIENT_H_
+#define CHROME_COMMON_EXTENSIONS_CHROME_EXTENSIONS_CLIENT_H_
+
+#include "base/basictypes.h"
+#include "base/compiler_specific.h"
+#include "base/lazy_instance.h"
+#include "chrome/common/extensions/permissions/chrome_api_permissions.h"
+#include "extensions/common/extensions_client.h"
+#include "extensions/common/permissions/permissions_provider.h"
+
+namespace extensions {
+
+// The implementation of ExtensionsClient for Chrome, which encapsulates the
+// global knowledge of features, permissions, and manifest fields.
+class ChromeExtensionsClient : public ExtensionsClient {
+ public:
+  ChromeExtensionsClient();
+  virtual ~ChromeExtensionsClient();
+
+  virtual const PermissionsProvider& GetPermissionsProvider() const OVERRIDE;
+  virtual void RegisterManifestHandlers() const OVERRIDE;
+  virtual FeatureProvider* GetFeatureProviderByName(const std::string& name)
+      const OVERRIDE;
+
+  // Get the LazyInstance for ChromeExtensionsClient.
+  static ChromeExtensionsClient* GetInstance();
+
+ private:
+  const ChromeAPIPermissions chrome_api_permissions_;
+
+  friend struct base::DefaultLazyInstanceTraits<ChromeExtensionsClient>;
+
+  DISALLOW_COPY_AND_ASSIGN(ChromeExtensionsClient);
+};
+
+}  // namespace extensions
+
+#endif  // CHROME_COMMON_EXTENSIONS_CHROME_EXTENSIONS_CLIENT_H_
diff --git a/chrome/common/extensions/docs/OWNERS b/chrome/common/extensions/docs/OWNERS
index 6ce4d20..df34150 100644
--- a/chrome/common/extensions/docs/OWNERS
+++ b/chrome/common/extensions/docs/OWNERS
@@ -2,6 +2,7 @@
 awatson@chromium.org
 mkearney@chromium.org
 mkwst@chromium.org
+scheib@chromium.org
 
 # For server related things (Python, JavaScript, templates, etc).
 kalman@chromium.org
diff --git a/chrome/common/extensions/docs/templates/articles/cloudMessaging.html b/chrome/common/extensions/docs/templates/articles/cloudMessaging.html
index ebb8402..d046041 100644
--- a/chrome/common/extensions/docs/templates/articles/cloudMessaging.html
+++ b/chrome/common/extensions/docs/templates/articles/cloudMessaging.html
@@ -12,14 +12,14 @@
 even when their calendaring app isn't open.
 </p>
 
-<p>This document describes how the service works and
-provides very basic examples on how to use the service.
-To learn more about GCM,
-read the API reference for the <a href="pushMessaging.html">pushMessaging Chrome API</a> and the
+<p>This document describes how to set up and use GCM.
+For additional information see the reference documentation
+for the <a href="pushMessaging.html">pushMessaging Chrome API</a> and the
 <a href="gcm_server.html">GCM service</a>.
+To get help with GCM or to give us feedback, see <a href="#feedback">Feedback</a>.
 </p>
 
-<h2 id="one">How it works</h2>
+<h2 id="one">How push messaging works</h2>
 
 <p>
 At a glance, push messaging works like this:
@@ -543,3 +543,10 @@
 you need to remove the key because the Store does not currently allow manifests
 with keys.
 </p>
+
+<h2 id="feedback">Feedback</h2>
+
+<p>You can provide feedback about Google Cloud Messaging
+and the pushMessaging API through the Google Group
+<a target="_blank" 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/articles/manifest/file_handlers.html b/chrome/common/extensions/docs/templates/articles/manifest/file_handlers.html
index e2ee9dc..fff645a 100644
--- a/chrome/common/extensions/docs/templates/articles/manifest/file_handlers.html
+++ b/chrome/common/extensions/docs/templates/articles/manifest/file_handlers.html
@@ -38,5 +38,5 @@
 permission. Apps can then be passed files in the $ref:app.runtime.onLaunched
 event - either from the system
 file manager (currently supported on ChromeOS only) or by providing
-a path on the <a href="../apps/first_app.html#open">command line</a>.
+a path on the <a href="../first_app.html#open">command line</a>.
 </p>
diff --git a/chrome/common/extensions/docs/templates/json/api_availabilities.json b/chrome/common/extensions/docs/templates/json/api_availabilities.json
index 3b6fc6b..9dbc4d6 100644
--- a/chrome/common/extensions/docs/templates/json/api_availabilities.json
+++ b/chrome/common/extensions/docs/templates/json/api_availabilities.json
@@ -19,6 +19,10 @@
     "channel": "stable",
     "version": 21
   },
+  "notifications": {
+    "channel": "stable",
+    "version": 28
+  },
   "storage": {
     "channel": "stable",
     "version": 20
diff --git a/chrome/common/extensions/features/base_feature_provider.h b/chrome/common/extensions/features/base_feature_provider.h
index c014852..8f7d325 100644
--- a/chrome/common/extensions/features/base_feature_provider.h
+++ b/chrome/common/extensions/features/base_feature_provider.h
@@ -11,8 +11,8 @@
 
 #include "base/memory/linked_ptr.h"
 #include "base/values.h"
-#include "chrome/common/extensions/features/feature_provider.h"
 #include "chrome/common/extensions/features/simple_feature.h"
+#include "extensions/common/features/feature_provider.h"
 
 namespace extensions {
 
@@ -30,10 +30,6 @@
   // Gets a feature provider for a specific feature type, like "permission".
   static FeatureProvider* GetByName(const std::string& name);
 
-  static FeatureProvider* GetPermissionFeatures() {
-    return GetByName("permission");
-  }
-
   // Gets the feature |feature_name|, if it exists.
   virtual Feature* GetFeature(const std::string& feature_name) OVERRIDE;
   virtual Feature* GetParent(Feature* feature) OVERRIDE;
diff --git a/chrome/common/extensions/features/base_feature_provider_unittest.cc b/chrome/common/extensions/features/base_feature_provider_unittest.cc
index d9f1b28..30f6abb 100644
--- a/chrome/common/extensions/features/base_feature_provider_unittest.cc
+++ b/chrome/common/extensions/features/base_feature_provider_unittest.cc
@@ -4,6 +4,7 @@
 
 #include "chrome/common/extensions/features/base_feature_provider.h"
 
+#include "chrome/common/extensions/features/feature_channel.h"
 #include "chrome/common/extensions/features/permission_feature.h"
 #include "chrome/common/extensions/value_builder.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -164,7 +165,7 @@
 
   // Make sure both rules are applied correctly.
   {
-    Feature::ScopedCurrentChannel current_channel(VersionInfo::CHANNEL_BETA);
+    ScopedCurrentChannel current_channel(VersionInfo::CHANNEL_BETA);
     EXPECT_EQ(Feature::IS_AVAILABLE, feature->IsAvailableToManifest(
         "1",
         Manifest::TYPE_EXTENSION,
@@ -177,7 +178,7 @@
         Feature::UNSPECIFIED_PLATFORM).result());
   }
   {
-    Feature::ScopedCurrentChannel current_channel(VersionInfo::CHANNEL_STABLE);
+    ScopedCurrentChannel current_channel(VersionInfo::CHANNEL_STABLE);
     EXPECT_NE(Feature::IS_AVAILABLE, feature->IsAvailableToManifest(
         "1",
         Manifest::TYPE_EXTENSION,
diff --git a/chrome/common/extensions/features/complex_feature.cc b/chrome/common/extensions/features/complex_feature.cc
index 09eb426..57c9ad4 100644
--- a/chrome/common/extensions/features/complex_feature.cc
+++ b/chrome/common/extensions/features/complex_feature.cc
@@ -4,8 +4,6 @@
 
 #include "chrome/common/extensions/features/complex_feature.h"
 
-#include "chrome/common/extensions/features/simple_feature.h"
-
 namespace extensions {
 
 ComplexFeature::ComplexFeature(scoped_ptr<FeatureList> features) {
diff --git a/chrome/common/extensions/features/complex_feature.h b/chrome/common/extensions/features/complex_feature.h
index b5b5e0c..8653d3d 100644
--- a/chrome/common/extensions/features/complex_feature.h
+++ b/chrome/common/extensions/features/complex_feature.h
@@ -14,8 +14,6 @@
 
 namespace extensions {
 
-class SimpleFeature;
-
 // A ComplexFeature is composed of one or many Features. A ComplexFeature
 // is available if any Feature (i.e. permission rule) that composes it is
 // available, but not if only some combination of Features is available.
diff --git a/chrome/common/extensions/features/complex_feature_unittest.cc b/chrome/common/extensions/features/complex_feature_unittest.cc
index be8fd34..6e7ed65 100644
--- a/chrome/common/extensions/features/complex_feature_unittest.cc
+++ b/chrome/common/extensions/features/complex_feature_unittest.cc
@@ -4,6 +4,7 @@
 
 #include "chrome/common/extensions/features/complex_feature.h"
 
+#include "chrome/common/extensions/features/feature_channel.h"
 #include "chrome/common/extensions/features/simple_feature.h"
 #include "chrome/common/extensions/value_builder.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -14,6 +15,7 @@
 using extensions::Feature;
 using extensions::ListBuilder;
 using extensions::Manifest;
+using extensions::ScopedCurrentChannel;
 using extensions::SimpleFeature;
 
 namespace {
@@ -25,7 +27,7 @@
   virtual ~ExtensionComplexFeatureTest() {}
 
  private:
-  Feature::ScopedCurrentChannel current_channel_;
+  ScopedCurrentChannel current_channel_;
 };
 
 TEST_F(ExtensionComplexFeatureTest, MultipleRulesWhitelist) {
@@ -108,7 +110,7 @@
 
   // Test match 1st rule.
   {
-    Feature::ScopedCurrentChannel current_channel(VersionInfo::CHANNEL_UNKNOWN);
+    ScopedCurrentChannel current_channel(VersionInfo::CHANNEL_UNKNOWN);
     EXPECT_EQ(Feature::IS_AVAILABLE, feature->IsAvailableToManifest(
         "1",
         Manifest::TYPE_EXTENSION,
@@ -119,7 +121,7 @@
 
   // Test match 2nd rule.
   {
-    Feature::ScopedCurrentChannel current_channel(VersionInfo::CHANNEL_BETA);
+    ScopedCurrentChannel current_channel(VersionInfo::CHANNEL_BETA);
     EXPECT_EQ(Feature::IS_AVAILABLE, feature->IsAvailableToManifest(
         "2",
         Manifest::TYPE_LEGACY_PACKAGED_APP,
@@ -130,7 +132,7 @@
 
   // Test feature not available to extensions above channel unknown.
   {
-    Feature::ScopedCurrentChannel current_channel(VersionInfo::CHANNEL_BETA);
+    ScopedCurrentChannel current_channel(VersionInfo::CHANNEL_BETA);
     EXPECT_NE(Feature::IS_AVAILABLE, feature->IsAvailableToManifest(
         "1",
         Manifest::TYPE_EXTENSION,
diff --git a/chrome/common/extensions/features/feature.cc b/chrome/common/extensions/features/feature.cc
index 40ea052..d1ae538 100644
--- a/chrome/common/extensions/features/feature.cc
+++ b/chrome/common/extensions/features/feature.cc
@@ -10,16 +10,6 @@
 #include "base/lazy_instance.h"
 #include "base/strings/string_util.h"
 #include "base/strings/stringprintf.h"
-#include "chrome/common/chrome_switches.h"
-
-using chrome::VersionInfo;
-
-namespace {
-
-const VersionInfo::Channel kDefaultChannel = VersionInfo::CHANNEL_STABLE;
-VersionInfo::Channel g_current_channel = kDefaultChannel;
-
-}  // namespace
 
 namespace extensions {
 
@@ -41,21 +31,6 @@
 }
 
 // static
-chrome::VersionInfo::Channel Feature::GetCurrentChannel() {
-  return g_current_channel;
-}
-
-// static
-void Feature::SetCurrentChannel(VersionInfo::Channel channel) {
-  g_current_channel = channel;
-}
-
-// static
-chrome::VersionInfo::Channel Feature::GetDefaultChannel() {
-  return kDefaultChannel;
-}
-
-// static
 Feature::Availability Feature::CreateAvailability(AvailabilityResult result,
                                                   const std::string& message) {
   return Availability(result, message);
diff --git a/chrome/common/extensions/features/feature.h b/chrome/common/extensions/features/feature.h
index b43dd06..618da57 100644
--- a/chrome/common/extensions/features/feature.h
+++ b/chrome/common/extensions/features/feature.h
@@ -9,14 +9,14 @@
 #include <string>
 
 #include "base/values.h"
-#include "chrome/common/chrome_version_info.h"
-#include "chrome/common/extensions/extension.h"
 #include "chrome/common/extensions/manifest.h"
 
 class GURL;
 
 namespace extensions {
 
+class Extension;
+
 // Represents a single feature accessible to an extension developer, such as a
 // top-level manifest key, a permission, or a programmatic API. A feature can
 // express requirements for where it can be accessed, and supports testing
@@ -95,34 +95,6 @@
   static Availability CreateAvailability(AvailabilityResult result,
                                          const std::string& message);
 
-  // Gets the current channel as seen by the Feature system.
-  static chrome::VersionInfo::Channel GetCurrentChannel();
-
-  // Sets the current channel as seen by the Feature system. In the browser
-  // process this should be chrome::VersionInfo::GetChannel(), and in the
-  // renderer this will need to come from an IPC.
-  static void SetCurrentChannel(chrome::VersionInfo::Channel channel);
-
-  // Gets the default channel as seen by the Feature system.
-  static chrome::VersionInfo::Channel GetDefaultChannel();
-
-  // Scoped channel setter. Use for tests.
-  class ScopedCurrentChannel {
-   public:
-    explicit ScopedCurrentChannel(chrome::VersionInfo::Channel channel)
-        : original_channel_(chrome::VersionInfo::CHANNEL_UNKNOWN) {
-      original_channel_ = GetCurrentChannel();
-      SetCurrentChannel(channel);
-    }
-
-    ~ScopedCurrentChannel() {
-      SetCurrentChannel(original_channel_);
-    }
-
-   private:
-    chrome::VersionInfo::Channel original_channel_;
-  };
-
   const std::string& name() const { return name_; }
   void set_name(const std::string& name) { name_ = name; }
   const std::set<std::string>& dependencies() { return dependencies_; }
diff --git a/chrome/common/extensions/features/feature_channel.cc b/chrome/common/extensions/features/feature_channel.cc
new file mode 100644
index 0000000..98a178e
--- /dev/null
+++ b/chrome/common/extensions/features/feature_channel.cc
@@ -0,0 +1,30 @@
+// 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/features/feature_channel.h"
+
+using chrome::VersionInfo;
+
+namespace {
+
+const VersionInfo::Channel kDefaultChannel = VersionInfo::CHANNEL_STABLE;
+VersionInfo::Channel g_current_channel = kDefaultChannel;
+
+}  // namespace
+
+namespace extensions {
+
+VersionInfo::Channel GetCurrentChannel() {
+  return g_current_channel;
+}
+
+void SetCurrentChannel(VersionInfo::Channel channel) {
+  g_current_channel = channel;
+}
+
+VersionInfo::Channel GetDefaultChannel() {
+  return kDefaultChannel;
+}
+
+}  // namespace extensions
diff --git a/chrome/common/extensions/features/feature_channel.h b/chrome/common/extensions/features/feature_channel.h
new file mode 100644
index 0000000..e915aac
--- /dev/null
+++ b/chrome/common/extensions/features/feature_channel.h
@@ -0,0 +1,42 @@
+// 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_FEATURES_FEATURE_CHANNEL_H_
+#define CHROME_COMMON_EXTENSIONS_FEATURES_FEATURE_CHANNEL_H_
+
+#include "chrome/common/chrome_version_info.h"
+
+namespace extensions {
+
+// Gets the current channel as seen by the Feature system.
+chrome::VersionInfo::Channel GetCurrentChannel();
+
+// Sets the current channel as seen by the Feature system. In the browser
+// process this should be chrome::VersionInfo::GetChannel(), and in the
+// renderer this will need to come from an IPC.
+void SetCurrentChannel(chrome::VersionInfo::Channel channel);
+
+// Gets the default channel as seen by the Feature system.
+chrome::VersionInfo::Channel GetDefaultChannel();
+
+// Scoped channel setter. Use for tests.
+class ScopedCurrentChannel {
+ public:
+  explicit ScopedCurrentChannel(chrome::VersionInfo::Channel channel)
+      : original_channel_(chrome::VersionInfo::CHANNEL_UNKNOWN) {
+    original_channel_ = GetCurrentChannel();
+    SetCurrentChannel(channel);
+  }
+
+  ~ScopedCurrentChannel() {
+    SetCurrentChannel(original_channel_);
+  }
+
+ private:
+  chrome::VersionInfo::Channel original_channel_;
+};
+
+}  // namespace extensions
+
+#endif  // CHROME_COMMON_EXTENSIONS_FEATURES_FEATURE_CHANNEL_H_
diff --git a/chrome/common/extensions/features/simple_feature.cc b/chrome/common/extensions/features/simple_feature.cc
index 676c0c6..e8ee3d5 100644
--- a/chrome/common/extensions/features/simple_feature.cc
+++ b/chrome/common/extensions/features/simple_feature.cc
@@ -14,6 +14,7 @@
 #include "base/strings/string_util.h"
 #include "base/strings/stringprintf.h"
 #include "chrome/common/chrome_switches.h"
+#include "chrome/common/extensions/features/feature_channel.h"
 
 using chrome::VersionInfo;
 
@@ -306,7 +307,7 @@
   if (max_manifest_version_ != 0 && manifest_version > max_manifest_version_)
     return CreateAvailability(INVALID_MAX_MANIFEST_VERSION, type);
 
-  if (channel_has_been_set_ && channel_ < Feature::GetCurrentChannel())
+  if (channel_has_been_set_ && channel_ < GetCurrentChannel())
     return CreateAvailability(UNSUPPORTED_CHANNEL, type);
 
   return CreateAvailability(IS_AVAILABLE, type);
diff --git a/chrome/common/extensions/features/simple_feature_unittest.cc b/chrome/common/extensions/features/simple_feature_unittest.cc
index b50ddb2..fc7967f 100644
--- a/chrome/common/extensions/features/simple_feature_unittest.cc
+++ b/chrome/common/extensions/features/simple_feature_unittest.cc
@@ -4,6 +4,7 @@
 
 #include "chrome/common/extensions/features/simple_feature.h"
 
+#include "chrome/common/extensions/features/feature_channel.h"
 #include "chrome/common/extensions/value_builder.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
@@ -13,6 +14,7 @@
 using extensions::Feature;
 using extensions::ListBuilder;
 using extensions::Manifest;
+using extensions::ScopedCurrentChannel;
 using extensions::SimpleFeature;
 
 namespace {
@@ -33,7 +35,7 @@
   virtual ~ExtensionSimpleFeatureTest() {}
 
  private:
-  Feature::ScopedCurrentChannel current_channel_;
+  ScopedCurrentChannel current_channel_;
 };
 
 TEST_F(ExtensionSimpleFeatureTest, IsAvailableNullCase) {
@@ -534,7 +536,7 @@
 
 Feature::AvailabilityResult IsAvailableInChannel(
     const std::string& channel, VersionInfo::Channel channel_for_testing) {
-  Feature::ScopedCurrentChannel current_channel(channel_for_testing);
+  ScopedCurrentChannel current_channel(channel_for_testing);
 
   SimpleFeature feature;
   if (!channel.empty()) {
diff --git a/chrome/common/extensions/manifest.cc b/chrome/common/extensions/manifest.cc
index c8cedf1..008912a 100644
--- a/chrome/common/extensions/manifest.cc
+++ b/chrome/common/extensions/manifest.cc
@@ -11,8 +11,9 @@
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/common/extensions/extension_manifest_constants.h"
-#include "chrome/common/extensions/features/base_feature_provider.h"
+#include "chrome/common/extensions/features/feature.h"
 #include "extensions/common/error_utils.h"
+#include "extensions/common/features/feature_provider.h"
 #include "extensions/common/install_warning.h"
 
 namespace errors = extension_manifest_errors;
@@ -141,7 +142,7 @@
   // TODO(aa): Consider having an error here in the case of strict error
   // checking to let developers know when they screw up.
 
-  FeatureProvider* provider = BaseFeatureProvider::GetByName("manifest");
+  FeatureProvider* provider = FeatureProvider::GetByName("manifest");
   const std::vector<std::string>& feature_names =
       provider->GetAllFeatureNames();
   for (std::vector<std::string>::const_iterator feature_name =
@@ -250,8 +251,7 @@
 }
 
 bool Manifest::CanAccessKey(const std::string& key) const {
-  Feature* feature =
-      BaseFeatureProvider::GetByName("manifest")->GetFeature(key);
+  Feature* feature = FeatureProvider::GetByName("manifest")->GetFeature(key);
   if (!feature)
     return true;
 
diff --git a/chrome/common/extensions/manifest_handlers/externally_connectable_unittest.cc b/chrome/common/extensions/manifest_handlers/externally_connectable_unittest.cc
index feea601..78857c2 100644
--- a/chrome/common/extensions/manifest_handlers/externally_connectable_unittest.cc
+++ b/chrome/common/extensions/manifest_handlers/externally_connectable_unittest.cc
@@ -5,7 +5,7 @@
 #include <algorithm>
 
 #include "chrome/common/extensions/extension_manifest_constants.h"
-#include "chrome/common/extensions/features/feature.h"
+#include "chrome/common/extensions/features/feature_channel.h"
 #include "chrome/common/extensions/manifest_handlers/externally_connectable.h"
 #include "chrome/common/extensions/manifest_tests/extension_manifest_test.h"
 #include "extensions/common/error_utils.h"
@@ -30,7 +30,7 @@
   }
 
  private:
-  Feature::ScopedCurrentChannel channel_;
+  ScopedCurrentChannel channel_;
 };
 
 TEST_F(ExternallyConnectableTest, IDsAndMatches) {
diff --git a/chrome/common/extensions/manifest_tests/extension_manifest_test.h b/chrome/common/extensions/manifest_tests/extension_manifest_test.h
index d91fc9f..7694e15 100644
--- a/chrome/common/extensions/manifest_tests/extension_manifest_test.h
+++ b/chrome/common/extensions/manifest_tests/extension_manifest_test.h
@@ -10,7 +10,7 @@
 #include "base/values.h"
 #include "chrome/common/extensions/extension.h"
 #include "chrome/common/extensions/extension_manifest_constants.h"
-#include "chrome/common/extensions/features/feature.h"
+#include "chrome/common/extensions/features/feature_channel.h"
 #include "chrome/common/extensions/manifest.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
@@ -149,7 +149,7 @@
   //
   // These objects nest, so if a test wants to explicitly test the behaviour
   // on stable or beta, declare it inside that test.
-  extensions::Feature::ScopedCurrentChannel current_channel_;
+  extensions::ScopedCurrentChannel current_channel_;
 };
 
 #endif  // CHROME_COMMON_EXTENSIONS_MANIFEST_TESTS_EXTENSION_MANIFEST_TEST_H_
diff --git a/chrome/common/extensions/manifest_tests/extension_manifests_background_unittest.cc b/chrome/common/extensions/manifest_tests/extension_manifests_background_unittest.cc
index 10ddbe3..d2d4fc7 100644
--- a/chrome/common/extensions/manifest_tests/extension_manifests_background_unittest.cc
+++ b/chrome/common/extensions/manifest_tests/extension_manifests_background_unittest.cc
@@ -10,8 +10,7 @@
 #include "chrome/common/extensions/background_info.h"
 #include "chrome/common/extensions/extension.h"
 #include "chrome/common/extensions/extension_manifest_constants.h"
-#include "chrome/common/extensions/features/base_feature_provider.h"
-#include "chrome/common/extensions/features/feature.h"
+#include "chrome/common/extensions/features/feature_channel.h"
 #include "extensions/common/constants.h"
 #include "extensions/common/error_utils.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -89,8 +88,7 @@
 }
 
 TEST_F(ExtensionManifestBackgroundTest, BackgroundPageWebRequest) {
-  Feature::ScopedCurrentChannel current_channel(
-      chrome::VersionInfo::CHANNEL_DEV);
+  ScopedCurrentChannel current_channel(chrome::VersionInfo::CHANNEL_DEV);
 
   std::string error;
   scoped_ptr<base::DictionaryValue> manifest(
diff --git a/chrome/common/extensions/permissions/chrome_api_permissions.cc b/chrome/common/extensions/permissions/chrome_api_permissions.cc
index 0b368f8..2850d13 100644
--- a/chrome/common/extensions/permissions/chrome_api_permissions.cc
+++ b/chrome/common/extensions/permissions/chrome_api_permissions.cc
@@ -317,13 +317,13 @@
   return permissions;
 }
 
-std::vector<PermissionsInfo::AliasInfo> ChromeAPIPermissions::GetAllAliases()
-    const {
+std::vector<PermissionsProvider::AliasInfo>
+ChromeAPIPermissions::GetAllAliases() const {
   // Register aliases.
-  std::vector<PermissionsInfo::AliasInfo> aliases;
-  aliases.push_back(PermissionsInfo::AliasInfo(
+  std::vector<PermissionsProvider::AliasInfo> aliases;
+  aliases.push_back(PermissionsProvider::AliasInfo(
       "unlimitedStorage", kOldUnlimitedStoragePermission));
-  aliases.push_back(PermissionsInfo::AliasInfo(
+  aliases.push_back(PermissionsProvider::AliasInfo(
       "tabs", kWindowsPermission));
   return aliases;
 }
diff --git a/chrome/common/extensions/permissions/chrome_api_permissions.h b/chrome/common/extensions/permissions/chrome_api_permissions.h
index ec5283c..9341a66 100644
--- a/chrome/common/extensions/permissions/chrome_api_permissions.h
+++ b/chrome/common/extensions/permissions/chrome_api_permissions.h
@@ -7,15 +7,16 @@
 
 #include <vector>
 
-#include "chrome/common/extensions/permissions/permissions_info.h"
+#include "base/compiler_specific.h"
+#include "extensions/common/permissions/permissions_provider.h"
 
 namespace extensions {
 
 // Registers the permissions used in Chrome with the PermissionsInfo global.
-class ChromeAPIPermissions : public PermissionsInfo::Delegate {
+class ChromeAPIPermissions : public PermissionsProvider {
  public:
   virtual std::vector<APIPermissionInfo*> GetAllPermissions() const OVERRIDE;
-  virtual std::vector<PermissionsInfo::AliasInfo> GetAllAliases() const
+  virtual std::vector<PermissionsProvider::AliasInfo> GetAllAliases() const
       OVERRIDE;
 };
 
diff --git a/chrome/common/extensions/permissions/permission_set_unittest.cc b/chrome/common/extensions/permissions/permission_set_unittest.cc
index f5adabd..637fb54 100644
--- a/chrome/common/extensions/permissions/permission_set_unittest.cc
+++ b/chrome/common/extensions/permissions/permission_set_unittest.cc
@@ -11,7 +11,7 @@
 #include "chrome/common/chrome_switches.h"
 #include "chrome/common/extensions/extension.h"
 #include "chrome/common/extensions/extension_test_util.h"
-#include "chrome/common/extensions/features/feature.h"
+#include "chrome/common/extensions/features/feature_channel.h"
 #include "chrome/common/extensions/permissions/permission_set.h"
 #include "chrome/common/extensions/permissions/permissions_data.h"
 #include "chrome/common/extensions/permissions/permissions_info.h"
@@ -835,7 +835,7 @@
 }
 
 TEST(PermissionsTest, GetWarningMessages_Socket_AnyHost) {
-  Feature::ScopedCurrentChannel channel(chrome::VersionInfo::CHANNEL_DEV);
+  ScopedCurrentChannel channel(chrome::VersionInfo::CHANNEL_DEV);
 
   scoped_refptr<Extension> extension =
       LoadManifest("permissions", "socket_any_host.json");
@@ -849,7 +849,7 @@
 }
 
 TEST(PermissionsTest, GetWarningMessages_Socket_OneDomainTwoHostnames) {
-  Feature::ScopedCurrentChannel channel(chrome::VersionInfo::CHANNEL_DEV);
+  ScopedCurrentChannel channel(chrome::VersionInfo::CHANNEL_DEV);
 
   scoped_refptr<Extension> extension =
       LoadManifest("permissions", "socket_one_domain_two_hostnames.json");
@@ -875,7 +875,7 @@
 }
 
 TEST(PermissionsTest, GetWarningMessages_Socket_TwoDomainsOneHostname) {
-  Feature::ScopedCurrentChannel channel(chrome::VersionInfo::CHANNEL_DEV);
+  ScopedCurrentChannel channel(chrome::VersionInfo::CHANNEL_DEV);
 
   scoped_refptr<Extension> extension =
       LoadManifest("permissions", "socket_two_domains_one_hostname.json");
diff --git a/chrome/common/extensions/permissions/permissions_data_unittest.cc b/chrome/common/extensions/permissions/permissions_data_unittest.cc
index a4d1cda..0127ce6 100644
--- a/chrome/common/extensions/permissions/permissions_data_unittest.cc
+++ b/chrome/common/extensions/permissions/permissions_data_unittest.cc
@@ -12,7 +12,7 @@
 #include "chrome/common/extensions/extension.h"
 #include "chrome/common/extensions/extension_manifest_constants.h"
 #include "chrome/common/extensions/extension_test_util.h"
-#include "chrome/common/extensions/features/feature.h"
+#include "chrome/common/extensions/features/feature_channel.h"
 #include "chrome/common/extensions/permissions/api_permission.h"
 #include "chrome/common/extensions/permissions/permission_set.h"
 #include "chrome/common/extensions/permissions/permissions_data.h"
@@ -117,8 +117,7 @@
 
 TEST(ExtensionPermissionsTest, SocketPermissions) {
   // Set feature current channel to appropriate value.
-  Feature::ScopedCurrentChannel scoped_channel(
-      chrome::VersionInfo::CHANNEL_DEV);
+  ScopedCurrentChannel scoped_channel(chrome::VersionInfo::CHANNEL_DEV);
   scoped_refptr<Extension> extension;
   std::string error;
 
diff --git a/chrome/common/extensions/permissions/permissions_info.cc b/chrome/common/extensions/permissions/permissions_info.cc
index 818bc4f..ec251e8 100644
--- a/chrome/common/extensions/permissions/permissions_info.cc
+++ b/chrome/common/extensions/permissions/permissions_info.cc
@@ -8,47 +8,22 @@
 #include "base/logging.h"
 #include "base/stl_util.h"
 #include "base/strings/string_util.h"
+#include "extensions/common/extensions_client.h"
 
 namespace extensions {
 
 static base::LazyInstance<PermissionsInfo> g_permissions_info =
     LAZY_INSTANCE_INITIALIZER;
-// ScopedTestingPermissionsInfo can override the global instance for testing.
-static PermissionsInfo* g_permissions_info_override = NULL;
 
 // static
 PermissionsInfo* PermissionsInfo::GetInstance() {
-  if (!g_permissions_info_override)
-    g_permissions_info_override = g_permissions_info.Pointer();
-  return g_permissions_info_override;
-}
-
-// static
-void PermissionsInfo::SetForTesting(PermissionsInfo* info) {
-  g_permissions_info_override = info;
+  return g_permissions_info.Pointer();
 }
 
 PermissionsInfo::~PermissionsInfo() {
   STLDeleteContainerPairSecondPointers(id_map_.begin(), id_map_.end());
 }
 
-void PermissionsInfo::InitializeWithDelegate(
-    const PermissionsInfo::Delegate& delegate) {
-  // TODO(yoz): Change into a DCHECK once StartupHelper browser tests
-  // are changed to unit tests.
-  if (initialized_)
-    return;
-  std::vector<APIPermissionInfo*> permissions = delegate.GetAllPermissions();
-  std::vector<AliasInfo> aliases = delegate.GetAllAliases();
-
-  for (size_t i = 0; i < permissions.size(); ++i)
-    RegisterPermission(permissions[i]);
-  for (size_t i = 0; i < aliases.size(); ++i)
-    RegisterAlias(aliases[i].name, aliases[i].alias);
-
-  initialized_ = true;
-}
-
 const APIPermissionInfo* PermissionsInfo::GetByID(
     APIPermission::ID id) const {
   IDMap::const_iterator i = id_map_.find(id);
@@ -88,8 +63,21 @@
 
 PermissionsInfo::PermissionsInfo()
     : hosted_app_permission_count_(0),
-      permission_count_(0),
-      initialized_(false) {
+      permission_count_(0) {
+  DCHECK(ExtensionsClient::Get());
+  InitializeWithProvider(ExtensionsClient::Get()->GetPermissionsProvider());
+}
+
+void PermissionsInfo::InitializeWithProvider(
+    const PermissionsProvider& provider) {
+  std::vector<APIPermissionInfo*> permissions = provider.GetAllPermissions();
+  std::vector<PermissionsProvider::AliasInfo> aliases =
+      provider.GetAllAliases();
+
+  for (size_t i = 0; i < permissions.size(); ++i)
+    RegisterPermission(permissions[i]);
+  for (size_t i = 0; i < aliases.size(); ++i)
+    RegisterAlias(aliases[i].name, aliases[i].alias);
 }
 
 void PermissionsInfo::RegisterAlias(
diff --git a/chrome/common/extensions/permissions/permissions_info.h b/chrome/common/extensions/permissions/permissions_info.h
index 238c8ae..6261362 100644
--- a/chrome/common/extensions/permissions/permissions_info.h
+++ b/chrome/common/extensions/permissions/permissions_info.h
@@ -14,6 +14,7 @@
 #include "chrome/common/extensions/permissions/api_permission.h"
 #include "chrome/common/extensions/permissions/api_permission_set.h"
 #include "chrome/common/extensions/permissions/permission_message.h"
+#include "extensions/common/permissions/permissions_provider.h"
 
 namespace extensions {
 
@@ -21,35 +22,10 @@
 // methods for accessing them.
 class PermissionsInfo {
  public:
-  // An alias for a given permission |name|.
-  struct AliasInfo {
-    const char* name;
-    const char* alias;
-
-    AliasInfo(const char* name, const char* alias)
-        : name(name), alias(alias) {
-    }
-  };
-
-  // The delegate creates the APIPermissions instances. It is only
-  // needed at startup time.
-  class Delegate {
-   public:
-    // Returns all the known permissions. The caller, PermissionsInfo,
-    // takes ownership of the APIPermissionInfos.
-    virtual std::vector<APIPermissionInfo*> GetAllPermissions() const = 0;
-
-    // Returns all the known permission aliases.
-    virtual std::vector<AliasInfo> GetAllAliases() const = 0;
-  };
-
   static PermissionsInfo* GetInstance();
 
   virtual ~PermissionsInfo();
 
-  // Initializes the permissions from the delegate.
-  void InitializeWithDelegate(const Delegate& delegate);
-
   // Returns the permission with the given |id|, and NULL if it doesn't exist.
   const APIPermissionInfo* GetByID(APIPermission::ID id) const;
 
@@ -72,14 +48,12 @@
   size_t get_permission_count() const { return permission_count_; }
 
  private:
-  friend class ScopedTestingPermissionsInfo;
   friend struct base::DefaultLazyInstanceTraits<PermissionsInfo>;
 
   PermissionsInfo();
 
-  // Overrides the global PermissionsInfo for unit tests. Should only be
-  // called from ScopedTestingPermissionsInfo.
-  static void SetForTesting(PermissionsInfo* info);
+  // Initializes the permissions from the provider.
+  void InitializeWithProvider(const PermissionsProvider& provider);
 
   // Registers an |alias| for a given permission |name|.
   void RegisterAlias(const char* name, const char* alias);
@@ -99,9 +73,6 @@
   size_t hosted_app_permission_count_;
   size_t permission_count_;
 
-  // Set to true after the delegate has created the known permissions.
-  bool initialized_;
-
   DISALLOW_COPY_AND_ASSIGN(PermissionsInfo);
 };
 
diff --git a/chrome/common/extensions/permissions/scoped_testing_permissions_info.cc b/chrome/common/extensions/permissions/scoped_testing_permissions_info.cc
deleted file mode 100644
index 81919e0..0000000
--- a/chrome/common/extensions/permissions/scoped_testing_permissions_info.cc
+++ /dev/null
@@ -1,27 +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/scoped_testing_permissions_info.h"
-
-namespace extensions {
-
-ScopedTestingPermissionsInfo::ScopedTestingPermissionsInfo()
-    : info_(new PermissionsInfo),
-      old_info_(PermissionsInfo::GetInstance()) {
-  PermissionsInfo::SetForTesting(info_.get());
-}
-
-ScopedTestingPermissionsInfo::ScopedTestingPermissionsInfo(
-    const PermissionsInfo::Delegate& delegate)
-    : info_(new PermissionsInfo),
-      old_info_(PermissionsInfo::GetInstance()) {
-  PermissionsInfo::SetForTesting(info_.get());
-  PermissionsInfo::GetInstance()->InitializeWithDelegate(delegate);
-}
-
-ScopedTestingPermissionsInfo::~ScopedTestingPermissionsInfo() {
-  PermissionsInfo::SetForTesting(old_info_);
-}
-
-}  // namespace extensions
diff --git a/chrome/common/extensions/permissions/scoped_testing_permissions_info.h b/chrome/common/extensions/permissions/scoped_testing_permissions_info.h
deleted file mode 100644
index a1d84cd..0000000
--- a/chrome/common/extensions/permissions/scoped_testing_permissions_info.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 CHROME_COMMON_EXTENSIONS_PERMISSIONS_SCOPED_TESTING_PERMISSIONS_INFO_H_
-#define CHROME_COMMON_EXTENSIONS_PERMISSIONS_SCOPED_TESTING_PERMISSIONS_INFO_H_
-
-#include "base/memory/scoped_ptr.h"
-#include "chrome/common/extensions/permissions/permissions_info.h"
-
-namespace extensions {
-
-// Overrides the global PermissionsInfo on construction and restores it
-// on destruction.
-class ScopedTestingPermissionsInfo {
- public:
-  ScopedTestingPermissionsInfo();
-  explicit ScopedTestingPermissionsInfo(
-      const PermissionsInfo::Delegate& delegate);
-  ~ScopedTestingPermissionsInfo();
-
- private:
-  scoped_ptr<PermissionsInfo> info_;
-  PermissionsInfo* old_info_;
-};
-
-}  // namespace extensions
-
-#endif  // CHROME_COMMON_EXTENSIONS_PERMISSIONS_SCOPED_TESTING_PERMISSIONS_INFO_H_
diff --git a/chrome/common/extensions/permissions/usb_device_permission_unittest.cc b/chrome/common/extensions/permissions/usb_device_permission_unittest.cc
index a590288..3f7e0b8 100644
--- a/chrome/common/extensions/permissions/usb_device_permission_unittest.cc
+++ b/chrome/common/extensions/permissions/usb_device_permission_unittest.cc
@@ -10,7 +10,7 @@
 #include "base/strings/utf_string_conversions.h"
 #include "base/values.h"
 #include "chrome/common/extensions/permissions/api_permission.h"
-#include "chrome/common/extensions/permissions/chrome_api_permissions.h"
+#include "chrome/common/extensions/permissions/permissions_info.h"
 #include "chrome/common/extensions/permissions/usb_device_permission.h"
 #include "chrome/common/extensions/permissions/usb_device_permission_data.h"
 #include "ipc/ipc_message.h"
diff --git a/chrome/common/metrics/proto/omnibox_event.proto b/chrome/common/metrics/proto/omnibox_event.proto
index 4bd5dd1..ebe0ab6 100644
--- a/chrome/common/metrics/proto/omnibox_event.proto
+++ b/chrome/common/metrics/proto/omnibox_event.proto
@@ -85,6 +85,10 @@
     // The new tab page in which this omnibox interaction first started
     // with the user having focus in the fakebox.
     INSTANT_NEW_TAB_PAGE_WITH_FAKEBOX_AS_STARTING_FOCUS = 8;
+    // The user is on a search result page that's not doing search term
+    // replacement, meaning the URL of the page should've appeared in the
+    // omnibox before the user started editing it, not the search terms.
+    SEARCH_RESULT_PAGE_NO_SEARCH_TERM_REPLACEMENT = 9;
   }
   optional PageClassification current_page_classification = 10;
 
diff --git a/chrome/common/metrics/variations/variation_ids.h b/chrome/common/metrics/variations/variation_ids.h
index 299f9c3..8ce3617 100644
--- a/chrome/common/metrics/variations/variation_ids.h
+++ b/chrome/common/metrics/variations/variation_ids.h
@@ -227,10 +227,14 @@
   SHOW_APP_LAUNCHER_PROMO_UNTIL_DISMISSED = 3310366,
   SHOW_APP_LAUNCHER_PROMO_RESET_PREF = 3310367,
 
+  // CookieRetentionPriorityStudy field trial.
+  COOKIE_RETENTION_PRIORITY_STUDY_EXPERIMENT_OFF = 3310869,
+  COOKIE_RETENTION_PRIORITY_STUDY_EXPERIMENT_ON = 3310870,
+
   // 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 = 3310869,
+  NEXT_ID = 3310871,
 
   // USABLE IDs END HERE.
   //
diff --git a/chrome/common/metrics/variations/variations_associated_data.cc b/chrome/common/metrics/variations/variations_associated_data.cc
index f74bc85..9a1a56e 100644
--- a/chrome/common/metrics/variations/variations_associated_data.cc
+++ b/chrome/common/metrics/variations/variations_associated_data.cc
@@ -132,6 +132,11 @@
     return true;
   }
 
+  void ClearAllParamsForTesting() {
+    base::AutoLock scoped_lock(lock_);
+    variation_params_.clear();
+  }
+
  private:
   friend struct DefaultSingletonTraits<VariationsParamAssociator>;
 
@@ -222,6 +227,10 @@
   GroupMapAccessor::GetInstance()->ClearAllMapsForTesting();
 }
 
+void ClearAllVariationParams() {
+  VariationsParamAssociator::GetInstance()->ClearAllParamsForTesting();
+}
+
 }  // namespace testing
 
 }  // namespace chrome_variations
diff --git a/chrome/common/metrics/variations/variations_associated_data.h b/chrome/common/metrics/variations/variations_associated_data.h
index 182b66b..d191d38 100644
--- a/chrome/common/metrics/variations/variations_associated_data.h
+++ b/chrome/common/metrics/variations/variations_associated_data.h
@@ -137,13 +137,15 @@
 std::string GetVariationParamValue(const std::string& trial_name,
                                    const std::string& param_name);
 
-// Expose some functions for testing. These functions just wrap functionality
-// that is implemented above.
+// Expose some functions for testing.
 namespace testing {
 
 // Clears all of the mapped associations.
 void ClearAllVariationIDs();
 
+// Clears all of the associated params.
+void ClearAllVariationParams();
+
 }  // namespace testing
 
 }  // namespace chrome_variations
diff --git a/chrome/common/net/url_util.cc b/chrome/common/net/url_util.cc
index 1047e91..442e599 100644
--- a/chrome/common/net/url_util.cc
+++ b/chrome/common/net/url_util.cc
@@ -5,7 +5,7 @@
 #include "chrome/common/net/url_util.h"
 
 #include "base/strings/utf_string_conversions.h"
-#include "chrome/common/url_constants.h"
+#include "content/public/common/url_constants.h"
 #include "net/base/escape.h"
 #include "net/base/net_util.h"
 #include "ui/base/clipboard/scoped_clipboard_writer.h"
@@ -21,7 +21,7 @@
 
   // Unescaping path and query is not a good idea because other applications
   // may not encode non-ASCII characters in UTF-8.  See crbug.com/2820.
-  string16 text = url.SchemeIs(chrome::kMailToScheme) ?
+  string16 text = url.SchemeIs(content::kMailToScheme) ?
       ASCIIToUTF16(url.path()) :
       net::FormatUrl(url, languages, net::kFormatUrlOmitNothing,
                      net::UnescapeRule::NONE, NULL, NULL, NULL);
diff --git a/chrome/common/pref_names.cc b/chrome/common/pref_names.cc
index bdbb346..65b4c93 100644
--- a/chrome/common/pref_names.cc
+++ b/chrome/common/pref_names.cc
@@ -1157,6 +1157,10 @@
 const char kAutofillGeneratedCardBubbleTimesShown[] =
     "autofill.generated_card_bubble_times_shown";
 
+// A dictionary that tracks the defaults to be set on the next invocation
+// of the requestAutocomplete/Autocheckout dialog.
+const char kAutofillDialogDefaults[] = "autofill.rac_dialog_defaults";
+
 // Modifying bookmarks is completely disabled when this is set to false.
 const char kEditBookmarksEnabled[] = "bookmarks.editing_enabled";
 
@@ -2489,6 +2493,10 @@
     "overscroll.horizontal_resist_threshold";
 const char kOverscrollVerticalResistThreshold[] =
     "overscroll.vertical_resist_threshold";
+// TODO(mohsen): Remove following pref in M32. By then, gesture prefs will have
+// been cleared for majority of the users: crbug.com/269292.
+// A temporary pref to do a one-time wipe of gesture preferences.
+const char kGestureConfigIsTrustworthy[] = "gesture.config_is_trustworthy";
 #endif
 
 // Counts how many more times the 'profile on a network share' warning should be
diff --git a/chrome/common/pref_names.h b/chrome/common/pref_names.h
index d6d79b2..d1bfbe7 100644
--- a/chrome/common/pref_names.h
+++ b/chrome/common/pref_names.h
@@ -401,6 +401,7 @@
 extern const char kAutofillDialogPayWithoutWallet[];
 extern const char kAutofillDialogShowCount[];
 extern const char kAutofillGeneratedCardBubbleTimesShown[];
+extern const char kAutofillDialogDefaults[];
 extern const char kEditBookmarksEnabled[];
 
 extern const char kEnableTranslate[];
@@ -907,6 +908,7 @@
 extern const char kOverscrollVerticalThresholdStart[];
 extern const char kOverscrollHorizontalResistThreshold[];
 extern const char kOverscrollVerticalResistThreshold[];
+extern const char kGestureConfigIsTrustworthy[];
 #endif
 
 extern const char kNetworkProfileWarningsLeft[];
diff --git a/chrome/common/render_messages.h b/chrome/common/render_messages.h
index 547057c..e75e566 100644
--- a/chrome/common/render_messages.h
+++ b/chrome/common/render_messages.h
@@ -672,6 +672,13 @@
                     int /* page_id */,
                     OmniboxFocusState /* state */)
 
+// Tells InstantExtended to paste text into the omnibox.  If text is empty,
+// the clipboard contents will be pasted. This causes the omnibox dropdown to
+// open.
+IPC_MESSAGE_ROUTED2(ChromeViewHostMsg_PasteAndOpenDropdown,
+                    int /* page_id */,
+                    string16 /* text to be pasted */)
+
 // Tells InstantExtended whether the embedded search API is supported.
 // See http://dev.chromium.org/embeddedsearch
 IPC_MESSAGE_ROUTED2(ChromeViewHostMsg_InstantSupportDetermined,
diff --git a/chrome/common/url_constants.cc b/chrome/common/url_constants.cc
index efc63bc..5f1c7a0 100644
--- a/chrome/common/url_constants.cc
+++ b/chrome/common/url_constants.cc
@@ -69,7 +69,7 @@
 const char kChromeUIPolicyURL[] = "chrome://policy/";
 const char kChromeUIProfileSigninConfirmationURL[] =
     "chrome://profile-signin-confirmation/";
-const char kChromeUIUserChooserURL[] = "chrome://user-chooser/";
+const char kChromeUIUserManagerURL[] = "chrome://user-manager/";
 const char kChromeUIPrintURL[] = "chrome://print/";
 const char kChromeUIRestartURL[] = "chrome://restart/";
 const char kChromeUISettingsURL[] = "chrome://settings/";
@@ -109,6 +109,7 @@
 const char kChromeUIProxySettingsURL[] = "chrome://proxy-settings/";
 const char kChromeUISimUnlockURL[] = "chrome://sim-unlock/";
 const char kChromeUISlideshowURL[] = "chrome://slideshow/";
+const char kChromeUISlowURL[] = "chrome://slow/";
 const char kChromeUISystemInfoURL[] = "chrome://system/";
 const char kChromeUITermsOemURL[] = "chrome://terms/oem";
 const char kChromeUIUserImageURL[] = "chrome://userimage/";
@@ -198,7 +199,7 @@
 const char kChromeUIPolicyHost[] = "policy";
 const char kChromeUIProfileSigninConfirmationHost[] =
     "profile-signin-confirmation";
-const char kChromeUIUserChooserHost[] = "user-chooser";
+const char kChromeUIUserManagerHost[] = "user-manager";
 const char kChromeUIPredictorsHost[] = "predictors";
 const char kChromeUIPrintHost[] = "print";
 const char kChromeUIProfilerHost[] = "profiler";
@@ -262,6 +263,7 @@
 const char kChromeUIRotateHost[] = "rotate";
 const char kChromeUISimUnlockHost[] = "sim-unlock";
 const char kChromeUISlideshowHost[] = "slideshow";
+const char kChromeUISlowHost[] = "slow";
 const char kChromeUISystemInfoHost[] = "system";
 const char kChromeUIUserImageHost[] = "userimage";
 
diff --git a/chrome/common/url_constants.h b/chrome/common/url_constants.h
index c3ff8fc..dc878ed 100644
--- a/chrome/common/url_constants.h
+++ b/chrome/common/url_constants.h
@@ -64,7 +64,7 @@
 extern const char kChromeUIPluginsURL[];
 extern const char kChromeUIPolicyURL[];
 extern const char kChromeUIProfileSigninConfirmationURL[];
-extern const char kChromeUIUserChooserURL[];
+extern const char kChromeUIUserManagerURL[];
 extern const char kChromeUIPrintURL[];
 extern const char kChromeUIRestartURL[];
 extern const char kChromeUISessionFaviconURL[];
@@ -103,6 +103,7 @@
 extern const char kChromeUIProxySettingsURL[];
 extern const char kChromeUISimUnlockURL[];
 extern const char kChromeUISlideshowURL[];
+extern const char kChromeUISlowURL[];
 extern const char kChromeUISystemInfoURL[];
 extern const char kChromeUITermsOemURL[];
 extern const char kChromeUIUserImageURL[];
@@ -189,7 +190,7 @@
 extern const char kChromeUIPluginsHost[];
 extern const char kChromeUIPolicyHost[];
 extern const char kChromeUIProfileSigninConfirmationHost[];
-extern const char kChromeUIUserChooserHost[];
+extern const char kChromeUIUserManagerHost[];
 extern const char kChromeUIPredictorsHost[];
 extern const char kChromeUIPrintHost[];
 extern const char kChromeUIProfilerHost[];
@@ -254,6 +255,7 @@
 extern const char kChromeUIRotateHost[];
 extern const char kChromeUISimUnlockHost[];
 extern const char kChromeUISlideshowHost[];
+extern const char kChromeUISlowHost[];
 extern const char kChromeUISystemInfoHost[];
 extern const char kChromeUIUserImageHost[];
 
diff --git a/chrome/installer/setup/setup_main.cc b/chrome/installer/setup/setup_main.cc
index dc96a5b..b02fb4e 100644
--- a/chrome/installer/setup/setup_main.cc
+++ b/chrome/installer/setup/setup_main.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/installer/setup/setup_main.h"
+
 #include <windows.h>
 #include <msi.h>
 #include <shellapi.h>
@@ -63,7 +65,6 @@
 #include "chrome/installer/util/self_cleaning_temp_dir.h"
 #include "chrome/installer/util/shell_util.h"
 #include "chrome/installer/util/user_experiment.h"
-#include "chrome/installer/util/util_constants.h"
 
 #include "installer_util_strings.h"  // NOLINT
 
@@ -686,311 +687,6 @@
   return true;
 }
 
-installer::InstallStatus InstallProductsHelper(
-    const InstallationState& original_state,
-    const CommandLine& cmd_line,
-    const MasterPreferences& prefs,
-    const InstallerState& installer_state,
-    installer::ArchiveType* archive_type,
-    bool* delegated_to_existing) {
-  DCHECK(archive_type);
-  DCHECK(delegated_to_existing);
-  const bool system_install = installer_state.system_install();
-  installer::InstallStatus install_status = installer::UNKNOWN_STATUS;
-
-  // Drop to background processing mode if the process was started below the
-  // normal process priority class.
-  bool entered_background_mode = installer::AdjustProcessPriority();
-  VLOG_IF(1, entered_background_mode) << "Entered background processing mode.";
-
-  // Create a temp folder where we will unpack Chrome archive. If it fails,
-  // then we are doomed, so return immediately and no cleanup is required.
-  installer::SelfCleaningTempDir temp_path;
-  base::FilePath unpack_path;
-  if (!CreateTemporaryAndUnpackDirectories(installer_state, &temp_path,
-                                           &unpack_path)) {
-    installer_state.WriteInstallerResult(installer::TEMP_DIR_FAILED,
-                                         IDS_INSTALL_TEMP_DIR_FAILED_BASE,
-                                         NULL);
-    return installer::TEMP_DIR_FAILED;
-  }
-
-  // Uncompress and optionally patch the archive if an uncompressed archive was
-  // not specified on the command line and a compressed archive is found.
-  *archive_type = installer::UNKNOWN_ARCHIVE_TYPE;
-  base::FilePath uncompressed_archive(cmd_line.GetSwitchValuePath(
-      installer::switches::kUncompressedArchive));
-  if (uncompressed_archive.empty()) {
-    scoped_ptr<installer::ArchivePatchHelper> archive_helper(
-        CreateChromeArchiveHelper(cmd_line, installer_state, unpack_path));
-    if (archive_helper) {
-      VLOG(1) << "Installing Chrome from compressed archive "
-              << archive_helper->compressed_archive().value();
-      if (!UncompressAndPatchChromeArchive(original_state,
-                                           installer_state,
-                                           archive_helper.get(),
-                                           archive_type,
-                                           &install_status)) {
-        DCHECK_NE(install_status, installer::UNKNOWN_STATUS);
-        return install_status;
-      }
-      uncompressed_archive = archive_helper->target();
-      DCHECK(!uncompressed_archive.empty());
-    }
-  }
-
-  // Check for an uncompressed archive alongside the current executable if one
-  // was not given or generated.
-  if (uncompressed_archive.empty()) {
-    uncompressed_archive =
-        cmd_line.GetProgram().DirName().Append(installer::kChromeArchive);
-  }
-
-  if (*archive_type == installer::UNKNOWN_ARCHIVE_TYPE) {
-    // An archive was not uncompressed or patched above.
-    if (uncompressed_archive.empty() ||
-        !base::PathExists(uncompressed_archive)) {
-      LOG(ERROR) << "Cannot install Chrome without an uncompressed archive.";
-      installer_state.WriteInstallerResult(
-          installer::INVALID_ARCHIVE, IDS_INSTALL_INVALID_ARCHIVE_BASE, NULL);
-      return installer::INVALID_ARCHIVE;
-    }
-    *archive_type = installer::FULL_ARCHIVE_TYPE;
-  }
-
-  // Unpack the uncompressed archive.
-  if (LzmaUtil::UnPackArchive(uncompressed_archive.value(),
-                              unpack_path.value(),
-                              NULL)) {
-    installer_state.WriteInstallerResult(
-        installer::UNCOMPRESSION_FAILED,
-        IDS_INSTALL_UNCOMPRESSION_FAILED_BASE,
-        NULL);
-    return installer::UNCOMPRESSION_FAILED;
-  }
-
-  VLOG(1) << "unpacked to " << unpack_path.value();
-  base::FilePath src_path(
-      unpack_path.Append(installer::kInstallSourceChromeDir));
-  scoped_ptr<Version>
-      installer_version(installer::GetMaxVersionFromArchiveDir(src_path));
-  if (!installer_version.get()) {
-    LOG(ERROR) << "Did not find any valid version in installer.";
-    install_status = installer::INVALID_ARCHIVE;
-    installer_state.WriteInstallerResult(install_status,
-        IDS_INSTALL_INVALID_ARCHIVE_BASE, NULL);
-  } else {
-    VLOG(1) << "version to install: " << installer_version->GetString();
-    bool proceed_with_installation = true;
-
-    if (installer_state.operation() == InstallerState::MULTI_INSTALL) {
-      // This is a new install of a multi-install product. Rather than give up
-      // in case a higher version of the binaries (including a single-install
-      // of Chrome, which can safely be migrated to multi-install by way of
-      // CheckMultiInstallConditions) is already installed, delegate to the
-      // installed setup.exe to install the product at hand.
-      base::FilePath setup_exe;
-      if (GetExistingHigherInstaller(original_state, system_install,
-                                     *installer_version, &setup_exe)) {
-        VLOG(1) << "Deferring to existing installer.";
-        installer_state.UpdateStage(installer::DEFERRING_TO_HIGHER_VERSION);
-        if (DeferToExistingInstall(setup_exe, cmd_line, installer_state,
-                                   temp_path.path(), &install_status)) {
-          *delegated_to_existing = true;
-          return install_status;
-        }
-      }
-    }
-
-    uint32 higher_products = 0;
-    COMPILE_ASSERT(
-        sizeof(higher_products) * 8 > BrowserDistribution::NUM_TYPES,
-        too_many_distribution_types_);
-    const Products& products = installer_state.products();
-    for (Products::const_iterator it = products.begin(); it < products.end();
-         ++it) {
-      const Product& product = **it;
-      const ProductState* product_state =
-          original_state.GetProductState(system_install,
-                                         product.distribution()->GetType());
-      if (product_state != NULL &&
-          (product_state->version().CompareTo(*installer_version) > 0)) {
-        LOG(ERROR) << "Higher version of "
-                   << product.distribution()->GetAppShortCutName()
-                   << " is already installed.";
-        higher_products |= (1 << product.distribution()->GetType());
-      }
-    }
-
-    if (higher_products != 0) {
-      COMPILE_ASSERT(BrowserDistribution::NUM_TYPES == 4,
-                     add_support_for_new_products_here_);
-      const uint32 kBrowserBit = 1 << BrowserDistribution::CHROME_BROWSER;
-      const uint32 kGCFBit = 1 << BrowserDistribution::CHROME_FRAME;
-      const uint32 kAppHostBit = 1 << BrowserDistribution::CHROME_APP_HOST;
-      int message_id = 0;
-
-      proceed_with_installation = false;
-      install_status = installer::HIGHER_VERSION_EXISTS;
-      switch (higher_products) {
-        case kBrowserBit:
-          message_id = IDS_INSTALL_HIGHER_VERSION_BASE;
-          break;
-        case kGCFBit:
-          message_id = IDS_INSTALL_HIGHER_VERSION_CF_BASE;
-          break;
-        case kGCFBit | kBrowserBit:
-          message_id = IDS_INSTALL_HIGHER_VERSION_CB_CF_BASE;
-          break;
-        default:
-          message_id = IDS_INSTALL_HIGHER_VERSION_APP_LAUNCHER_BASE;
-          break;
-      }
-
-      installer_state.WriteInstallerResult(install_status, message_id, NULL);
-    }
-
-    proceed_with_installation =
-        proceed_with_installation &&
-        CheckGroupPolicySettings(original_state, installer_state,
-                                 *installer_version, &install_status);
-
-    if (proceed_with_installation) {
-      // If Google Update is absent at user-level, install it using the
-      // Google Update installer from an existing system-level installation.
-      // This is for quick-enable App Host install from a system-level
-      // Chrome Binaries installation.
-      if (!system_install && installer_state.ensure_google_update_present()) {
-        if (!google_update::EnsureUserLevelGoogleUpdatePresent()) {
-          LOG(ERROR) << "Failed to install Google Update";
-          proceed_with_installation = false;
-          install_status = installer::INSTALL_OF_GOOGLE_UPDATE_FAILED;
-          installer_state.WriteInstallerResult(install_status, 0, NULL);
-        }
-      }
-    }
-
-    if (proceed_with_installation) {
-      base::FilePath prefs_source_path(cmd_line.GetSwitchValueNative(
-          installer::switches::kInstallerData));
-      install_status = installer::InstallOrUpdateProduct(
-          original_state, installer_state, cmd_line.GetProgram(),
-          uncompressed_archive, temp_path.path(), src_path, prefs_source_path,
-          prefs, *installer_version);
-
-      int install_msg_base = IDS_INSTALL_FAILED_BASE;
-      string16 chrome_exe;
-      string16 quoted_chrome_exe;
-      if (install_status == installer::SAME_VERSION_REPAIR_FAILED) {
-        if (installer_state.FindProduct(BrowserDistribution::CHROME_FRAME)) {
-          install_msg_base = IDS_SAME_VERSION_REPAIR_FAILED_CF_BASE;
-        } else {
-          install_msg_base = IDS_SAME_VERSION_REPAIR_FAILED_BASE;
-        }
-      } else if (install_status != installer::INSTALL_FAILED) {
-        if (installer_state.target_path().empty()) {
-          // If we failed to construct install path, it means the OS call to
-          // get %ProgramFiles% or %AppData% failed. Report this as failure.
-          install_msg_base = IDS_INSTALL_OS_ERROR_BASE;
-          install_status = installer::OS_ERROR;
-        } else {
-          chrome_exe = installer_state.target_path()
-              .Append(installer::kChromeExe).value();
-          quoted_chrome_exe = L"\"" + chrome_exe + L"\"";
-          install_msg_base = 0;
-        }
-      }
-
-      installer_state.UpdateStage(installer::FINISHING);
-
-      // Only do Chrome-specific stuff (like launching the browser) if
-      // Chrome was specifically requested (rather than being upgraded as
-      // part of a multi-install).
-      const Product* chrome_install = prefs.install_chrome() ?
-          installer_state.FindProduct(BrowserDistribution::CHROME_BROWSER) :
-          NULL;
-
-      bool do_not_register_for_update_launch = false;
-      if (chrome_install) {
-        prefs.GetBool(
-            installer::master_preferences::kDoNotRegisterForUpdateLaunch,
-            &do_not_register_for_update_launch);
-      } else {
-        do_not_register_for_update_launch = true;  // Never register.
-      }
-
-      bool write_chrome_launch_string =
-          (!do_not_register_for_update_launch &&
-           install_status != installer::IN_USE_UPDATED);
-
-      installer_state.WriteInstallerResult(install_status, install_msg_base,
-          write_chrome_launch_string ? &quoted_chrome_exe : NULL);
-
-      if (install_status == installer::FIRST_INSTALL_SUCCESS) {
-        VLOG(1) << "First install successful.";
-        if (chrome_install) {
-          // We never want to launch Chrome in system level install mode.
-          bool do_not_launch_chrome = false;
-          prefs.GetBool(
-              installer::master_preferences::kDoNotLaunchChrome,
-              &do_not_launch_chrome);
-          if (!system_install && !do_not_launch_chrome)
-            chrome_install->LaunchChrome(installer_state.target_path());
-        }
-      } else if ((install_status == installer::NEW_VERSION_UPDATED) ||
-                 (install_status == installer::IN_USE_UPDATED)) {
-        const Product* chrome = installer_state.FindProduct(
-            BrowserDistribution::CHROME_BROWSER);
-        if (chrome != NULL) {
-          DCHECK_NE(chrome_exe, string16());
-          installer::RemoveChromeLegacyRegistryKeys(chrome->distribution(),
-                                                    chrome_exe);
-        }
-      }
-
-      if (prefs.install_chrome_app_launcher() &&
-          InstallUtil::GetInstallReturnCode(install_status) == 0) {
-        std::string webstore_item(google_update::GetUntrustedDataValue(
-            installer::kInstallFromWebstore));
-        if (!webstore_item.empty()) {
-          bool success = installer::InstallFromWebstore(webstore_item);
-          VLOG_IF(1, !success) << "Failed to launch app installation.";
-        }
-      }
-    }
-  }
-
-  // There might be an experiment (for upgrade usually) that needs to happen.
-  // An experiment's outcome can include chrome's uninstallation. If that is
-  // the case we would not do that directly at this point but in another
-  // instance of setup.exe
-  //
-  // There is another way to reach this same function if this is a system
-  // level install. See HandleNonInstallCmdLineOptions().
-  {
-    // If installation failed, use the path to the currently running setup.
-    // If installation succeeded, use the path to setup in the installer dir.
-    base::FilePath setup_path(cmd_line.GetProgram());
-    if (InstallUtil::GetInstallReturnCode(install_status) == 0) {
-      setup_path = installer_state.GetInstallerDirectory(*installer_version)
-          .Append(setup_path.BaseName());
-    }
-    const Products& products = installer_state.products();
-    for (Products::const_iterator it = products.begin(); it < products.end();
-         ++it) {
-      const Product& product = **it;
-      product.LaunchUserExperiment(setup_path, install_status,
-                                   system_install);
-    }
-  }
-
-  // temp_path's dtor will take care of deleting or scheduling itself for
-  // deletion at reboot when this scope closes.
-  VLOG(1) << "Deleting temporary directory " << temp_path.path().value();
-
-  return install_status;
-}
-
 installer::InstallStatus InstallProducts(
     const InstallationState& original_state,
     const CommandLine& cmd_line,
@@ -1111,7 +807,7 @@
         // trigger Active Setup and make sure the system-level Chrome doesn't go
         // through first run.
         trigger_active_setup = true;
-        system_level_cmd.AppendSwitch(::switches::kNoFirstRun);
+        system_level_cmd.AppendSwitch(::switches::kCancelFirstRun);
       }
     }
   }
@@ -1703,6 +1399,315 @@
 
 }  // namespace
 
+namespace installer {
+
+installer::InstallStatus InstallProductsHelper(
+    const InstallationState& original_state,
+    const CommandLine& cmd_line,
+    const MasterPreferences& prefs,
+    const InstallerState& installer_state,
+    installer::ArchiveType* archive_type,
+    bool* delegated_to_existing) {
+  DCHECK(archive_type);
+  DCHECK(delegated_to_existing);
+  const bool system_install = installer_state.system_install();
+  installer::InstallStatus install_status = installer::UNKNOWN_STATUS;
+
+  // Drop to background processing mode if the process was started below the
+  // normal process priority class.
+  bool entered_background_mode = installer::AdjustProcessPriority();
+  VLOG_IF(1, entered_background_mode) << "Entered background processing mode.";
+
+  // Create a temp folder where we will unpack Chrome archive. If it fails,
+  // then we are doomed, so return immediately and no cleanup is required.
+  installer::SelfCleaningTempDir temp_path;
+  base::FilePath unpack_path;
+  if (!CreateTemporaryAndUnpackDirectories(installer_state, &temp_path,
+                                           &unpack_path)) {
+    installer_state.WriteInstallerResult(installer::TEMP_DIR_FAILED,
+                                         IDS_INSTALL_TEMP_DIR_FAILED_BASE,
+                                         NULL);
+    return installer::TEMP_DIR_FAILED;
+  }
+
+  // Uncompress and optionally patch the archive if an uncompressed archive was
+  // not specified on the command line and a compressed archive is found.
+  *archive_type = installer::UNKNOWN_ARCHIVE_TYPE;
+  base::FilePath uncompressed_archive(cmd_line.GetSwitchValuePath(
+      installer::switches::kUncompressedArchive));
+  if (uncompressed_archive.empty()) {
+    scoped_ptr<installer::ArchivePatchHelper> archive_helper(
+        CreateChromeArchiveHelper(cmd_line, installer_state, unpack_path));
+    if (archive_helper) {
+      VLOG(1) << "Installing Chrome from compressed archive "
+              << archive_helper->compressed_archive().value();
+      if (!UncompressAndPatchChromeArchive(original_state,
+                                           installer_state,
+                                           archive_helper.get(),
+                                           archive_type,
+                                           &install_status)) {
+        DCHECK_NE(install_status, installer::UNKNOWN_STATUS);
+        return install_status;
+      }
+      uncompressed_archive = archive_helper->target();
+      DCHECK(!uncompressed_archive.empty());
+    }
+  }
+
+  // Check for an uncompressed archive alongside the current executable if one
+  // was not given or generated.
+  if (uncompressed_archive.empty()) {
+    uncompressed_archive =
+        cmd_line.GetProgram().DirName().Append(installer::kChromeArchive);
+  }
+
+  if (*archive_type == installer::UNKNOWN_ARCHIVE_TYPE) {
+    // An archive was not uncompressed or patched above.
+    if (uncompressed_archive.empty() ||
+        !base::PathExists(uncompressed_archive)) {
+      LOG(ERROR) << "Cannot install Chrome without an uncompressed archive.";
+      installer_state.WriteInstallerResult(
+          installer::INVALID_ARCHIVE, IDS_INSTALL_INVALID_ARCHIVE_BASE, NULL);
+      return installer::INVALID_ARCHIVE;
+    }
+    *archive_type = installer::FULL_ARCHIVE_TYPE;
+  }
+
+  // Unpack the uncompressed archive.
+  if (LzmaUtil::UnPackArchive(uncompressed_archive.value(),
+                              unpack_path.value(),
+                              NULL)) {
+    installer_state.WriteInstallerResult(
+        installer::UNCOMPRESSION_FAILED,
+        IDS_INSTALL_UNCOMPRESSION_FAILED_BASE,
+        NULL);
+    return installer::UNCOMPRESSION_FAILED;
+  }
+
+  VLOG(1) << "unpacked to " << unpack_path.value();
+  base::FilePath src_path(
+      unpack_path.Append(installer::kInstallSourceChromeDir));
+  scoped_ptr<Version>
+      installer_version(installer::GetMaxVersionFromArchiveDir(src_path));
+  if (!installer_version.get()) {
+    LOG(ERROR) << "Did not find any valid version in installer.";
+    install_status = installer::INVALID_ARCHIVE;
+    installer_state.WriteInstallerResult(install_status,
+        IDS_INSTALL_INVALID_ARCHIVE_BASE, NULL);
+  } else {
+    VLOG(1) << "version to install: " << installer_version->GetString();
+    bool proceed_with_installation = true;
+
+    if (installer_state.operation() == InstallerState::MULTI_INSTALL) {
+      // This is a new install of a multi-install product. Rather than give up
+      // in case a higher version of the binaries (including a single-install
+      // of Chrome, which can safely be migrated to multi-install by way of
+      // CheckMultiInstallConditions) is already installed, delegate to the
+      // installed setup.exe to install the product at hand.
+      base::FilePath setup_exe;
+      if (GetExistingHigherInstaller(original_state, system_install,
+                                     *installer_version, &setup_exe)) {
+        VLOG(1) << "Deferring to existing installer.";
+        installer_state.UpdateStage(installer::DEFERRING_TO_HIGHER_VERSION);
+        if (DeferToExistingInstall(setup_exe, cmd_line, installer_state,
+                                   temp_path.path(), &install_status)) {
+          *delegated_to_existing = true;
+          return install_status;
+        }
+      }
+    }
+
+    uint32 higher_products = 0;
+    COMPILE_ASSERT(
+        sizeof(higher_products) * 8 > BrowserDistribution::NUM_TYPES,
+        too_many_distribution_types_);
+    const Products& products = installer_state.products();
+    for (Products::const_iterator it = products.begin(); it < products.end();
+         ++it) {
+      const Product& product = **it;
+      const ProductState* product_state =
+          original_state.GetProductState(system_install,
+                                         product.distribution()->GetType());
+      if (product_state != NULL &&
+          (product_state->version().CompareTo(*installer_version) > 0)) {
+        LOG(ERROR) << "Higher version of "
+                   << product.distribution()->GetAppShortCutName()
+                   << " is already installed.";
+        higher_products |= (1 << product.distribution()->GetType());
+      }
+    }
+
+    if (higher_products != 0) {
+      COMPILE_ASSERT(BrowserDistribution::NUM_TYPES == 4,
+                     add_support_for_new_products_here_);
+      const uint32 kBrowserBit = 1 << BrowserDistribution::CHROME_BROWSER;
+      const uint32 kGCFBit = 1 << BrowserDistribution::CHROME_FRAME;
+      const uint32 kAppHostBit = 1 << BrowserDistribution::CHROME_APP_HOST;
+      int message_id = 0;
+
+      proceed_with_installation = false;
+      install_status = installer::HIGHER_VERSION_EXISTS;
+      switch (higher_products) {
+        case kBrowserBit:
+          message_id = IDS_INSTALL_HIGHER_VERSION_BASE;
+          break;
+        case kGCFBit:
+          message_id = IDS_INSTALL_HIGHER_VERSION_CF_BASE;
+          break;
+        case kGCFBit | kBrowserBit:
+          message_id = IDS_INSTALL_HIGHER_VERSION_CB_CF_BASE;
+          break;
+        default:
+          message_id = IDS_INSTALL_HIGHER_VERSION_APP_LAUNCHER_BASE;
+          break;
+      }
+
+      installer_state.WriteInstallerResult(install_status, message_id, NULL);
+    }
+
+    proceed_with_installation =
+        proceed_with_installation &&
+        CheckGroupPolicySettings(original_state, installer_state,
+                                 *installer_version, &install_status);
+
+    if (proceed_with_installation) {
+      // If Google Update is absent at user-level, install it using the
+      // Google Update installer from an existing system-level installation.
+      // This is for quick-enable App Host install from a system-level
+      // Chrome Binaries installation.
+      if (!system_install && installer_state.ensure_google_update_present()) {
+        if (!google_update::EnsureUserLevelGoogleUpdatePresent()) {
+          LOG(ERROR) << "Failed to install Google Update";
+          proceed_with_installation = false;
+          install_status = installer::INSTALL_OF_GOOGLE_UPDATE_FAILED;
+          installer_state.WriteInstallerResult(install_status, 0, NULL);
+        }
+      }
+    }
+
+    if (proceed_with_installation) {
+      base::FilePath prefs_source_path(cmd_line.GetSwitchValueNative(
+          installer::switches::kInstallerData));
+      install_status = installer::InstallOrUpdateProduct(
+          original_state, installer_state, cmd_line.GetProgram(),
+          uncompressed_archive, temp_path.path(), src_path, prefs_source_path,
+          prefs, *installer_version);
+
+      int install_msg_base = IDS_INSTALL_FAILED_BASE;
+      string16 chrome_exe;
+      string16 quoted_chrome_exe;
+      if (install_status == installer::SAME_VERSION_REPAIR_FAILED) {
+        if (installer_state.FindProduct(BrowserDistribution::CHROME_FRAME)) {
+          install_msg_base = IDS_SAME_VERSION_REPAIR_FAILED_CF_BASE;
+        } else {
+          install_msg_base = IDS_SAME_VERSION_REPAIR_FAILED_BASE;
+        }
+      } else if (install_status != installer::INSTALL_FAILED) {
+        if (installer_state.target_path().empty()) {
+          // If we failed to construct install path, it means the OS call to
+          // get %ProgramFiles% or %AppData% failed. Report this as failure.
+          install_msg_base = IDS_INSTALL_OS_ERROR_BASE;
+          install_status = installer::OS_ERROR;
+        } else {
+          chrome_exe = installer_state.target_path()
+              .Append(installer::kChromeExe).value();
+          quoted_chrome_exe = L"\"" + chrome_exe + L"\"";
+          install_msg_base = 0;
+        }
+      }
+
+      installer_state.UpdateStage(installer::FINISHING);
+
+      // Only do Chrome-specific stuff (like launching the browser) if
+      // Chrome was specifically requested (rather than being upgraded as
+      // part of a multi-install).
+      const Product* chrome_install = prefs.install_chrome() ?
+          installer_state.FindProduct(BrowserDistribution::CHROME_BROWSER) :
+          NULL;
+
+      bool do_not_register_for_update_launch = false;
+      if (chrome_install) {
+        prefs.GetBool(
+            installer::master_preferences::kDoNotRegisterForUpdateLaunch,
+            &do_not_register_for_update_launch);
+      } else {
+        do_not_register_for_update_launch = true;  // Never register.
+      }
+
+      bool write_chrome_launch_string =
+          (!do_not_register_for_update_launch &&
+           install_status != installer::IN_USE_UPDATED);
+
+      installer_state.WriteInstallerResult(install_status, install_msg_base,
+          write_chrome_launch_string ? &quoted_chrome_exe : NULL);
+
+      if (install_status == installer::FIRST_INSTALL_SUCCESS) {
+        VLOG(1) << "First install successful.";
+        if (chrome_install) {
+          // We never want to launch Chrome in system level install mode.
+          bool do_not_launch_chrome = false;
+          prefs.GetBool(
+              installer::master_preferences::kDoNotLaunchChrome,
+              &do_not_launch_chrome);
+          if (!system_install && !do_not_launch_chrome)
+            chrome_install->LaunchChrome(installer_state.target_path());
+        }
+      } else if ((install_status == installer::NEW_VERSION_UPDATED) ||
+                 (install_status == installer::IN_USE_UPDATED)) {
+        const Product* chrome = installer_state.FindProduct(
+            BrowserDistribution::CHROME_BROWSER);
+        if (chrome != NULL) {
+          DCHECK_NE(chrome_exe, string16());
+          installer::RemoveChromeLegacyRegistryKeys(chrome->distribution(),
+                                                    chrome_exe);
+        }
+      }
+
+      if (prefs.install_chrome_app_launcher() &&
+          InstallUtil::GetInstallReturnCode(install_status) == 0) {
+        std::string webstore_item(google_update::GetUntrustedDataValue(
+            installer::kInstallFromWebstore));
+        if (!webstore_item.empty()) {
+          bool success = installer::InstallFromWebstore(webstore_item);
+          VLOG_IF(1, !success) << "Failed to launch app installation.";
+        }
+      }
+    }
+  }
+
+  // There might be an experiment (for upgrade usually) that needs to happen.
+  // An experiment's outcome can include chrome's uninstallation. If that is
+  // the case we would not do that directly at this point but in another
+  // instance of setup.exe
+  //
+  // There is another way to reach this same function if this is a system
+  // level install. See HandleNonInstallCmdLineOptions().
+  {
+    // If installation failed, use the path to the currently running setup.
+    // If installation succeeded, use the path to setup in the installer dir.
+    base::FilePath setup_path(cmd_line.GetProgram());
+    if (InstallUtil::GetInstallReturnCode(install_status) == 0) {
+      setup_path = installer_state.GetInstallerDirectory(*installer_version)
+          .Append(setup_path.BaseName());
+    }
+    const Products& products = installer_state.products();
+    for (Products::const_iterator it = products.begin(); it < products.end();
+         ++it) {
+      const Product& product = **it;
+      product.LaunchUserExperiment(setup_path, install_status,
+                                   system_install);
+    }
+  }
+
+  // temp_path's dtor will take care of deleting or scheduling itself for
+  // deletion at reboot when this scope closes.
+  VLOG(1) << "Deleting temporary directory " << temp_path.path().value();
+
+  return install_status;
+}
+
+}  // namespace installer
+
 int WINAPI wWinMain(HINSTANCE instance, HINSTANCE prev_instance,
                     wchar_t* command_line, int show_command) {
   // The exit manager is in charge of calling the dtors of singletons.
diff --git a/chrome/installer/setup/setup_main.h b/chrome/installer/setup/setup_main.h
new file mode 100644
index 0000000..f39e742
--- /dev/null
+++ b/chrome/installer/setup/setup_main.h
@@ -0,0 +1,32 @@
+// 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 header exists as a starting point for extracting some of the
+// logic out of setup_main.cc.
+
+#ifndef CHROME_INSTALLER_SETUP_SETUP_MAIN_H_
+#define CHROME_INSTALLER_SETUP_SETUP_MAIN_H_
+
+#include "chrome/installer/util/util_constants.h"
+
+class CommandLine;
+
+namespace installer {
+
+class InstallationState;
+class InstallerState;
+class MasterPreferences;
+
+// Helper function that performs the installation of a set of products.
+installer::InstallStatus InstallProductsHelper(
+    const installer::InstallationState& original_state,
+    const CommandLine& cmd_line,
+    const installer::MasterPreferences& prefs,
+    const installer::InstallerState& installer_state,
+    installer::ArchiveType* archive_type,
+    bool* delegated_to_existing);
+
+}  // namespace installer
+
+#endif  // CHROME_INSTALLER_SETUP_SETUP_MAIN_H_
diff --git a/chrome/installer/util/shell_util.cc b/chrome/installer/util/shell_util.cc
index 9ef0876..36f0f77 100644
--- a/chrome/installer/util/shell_util.cc
+++ b/chrome/installer/util/shell_util.cc
@@ -516,16 +516,16 @@
   // Generate work_item tasks required to create current registry entry and
   // add them to the given work item list.
   void AddToWorkItemList(HKEY root, WorkItemList *items) const {
-    items->AddCreateRegKeyWorkItem(root, _key_path);
-    if (_is_string) {
-      items->AddSetRegValueWorkItem(root, _key_path, _name, _value, true);
+    items->AddCreateRegKeyWorkItem(root, key_path_);
+    if (is_string_) {
+      items->AddSetRegValueWorkItem(root, key_path_, name_, value_, true);
     } else {
-      items->AddSetRegValueWorkItem(root, _key_path, _name, _int_value, true);
+      items->AddSetRegValueWorkItem(root, key_path_, name_, int_value_, true);
     }
   }
 
-  // Checks if the current registry entry exists in HKCU\|_key_path|\|_name|
-  // and value is |_value|. If the key does NOT exist in HKCU, checks for
+  // Checks if the current registry entry exists in HKCU\|key_path_|\|name_|
+  // and value is |value_|. If the key does NOT exist in HKCU, checks for
   // the correct name and value in HKLM.
   // |look_for_in| specifies roots (HKCU and/or HKLM) in which to look for the
   // key, unspecified roots are not looked into (i.e. the the key is assumed not
@@ -550,57 +550,57 @@
  private:
   // States this RegistryKey can be in compared to the registry.
   enum RegistryStatus {
-    // |_name| does not exist in the registry
+    // |name_| does not exist in the registry
     DOES_NOT_EXIST,
-    // |_name| exists, but its value != |_value|
+    // |name_| exists, but its value != |value_|
     DIFFERENT_VALUE,
-    // |_name| exists and its value is |_value|
+    // |name_| exists and its value is |value_|
     SAME_VALUE,
   };
 
   // Create a object that represent default value of a key
   RegistryEntry(const string16& key_path, const string16& value)
-      : _key_path(key_path), _name(),
-        _is_string(true), _value(value), _int_value(0) {
+      : key_path_(key_path), name_(),
+        is_string_(true), value_(value), int_value_(0) {
   }
 
   // Create a object that represent a key of type REG_SZ
   RegistryEntry(const string16& key_path, const string16& name,
                 const string16& value)
-      : _key_path(key_path), _name(name),
-        _is_string(true), _value(value), _int_value(0) {
+      : key_path_(key_path), name_(name),
+        is_string_(true), value_(value), int_value_(0) {
   }
 
   // Create a object that represent a key of integer type
   RegistryEntry(const string16& key_path, const string16& name,
                 DWORD value)
-      : _key_path(key_path), _name(name),
-        _is_string(false), _value(), _int_value(value) {
+      : key_path_(key_path), name_(name),
+        is_string_(false), value_(), int_value_(value) {
   }
 
-  string16 _key_path;  // key path for the registry entry
-  string16 _name;      // name of the registry entry
-  bool _is_string;     // true if current registry entry is of type REG_SZ
-  string16 _value;     // string value (useful if _is_string = true)
-  DWORD _int_value;    // integer value (useful if _is_string = false)
+  string16 key_path_;  // key path for the registry entry
+  string16 name_;      // name of the registry entry
+  bool is_string_;     // true if current registry entry is of type REG_SZ
+  string16 value_;     // string value (useful if is_string_ = true)
+  DWORD int_value_;    // integer value (useful if is_string_ = false)
 
   // Helper function for ExistsInRegistry().
   // Returns the RegistryStatus of the current registry entry in
-  // |root|\|_key_path|\|_name|.
+  // |root|\|key_path_|\|name_|.
   RegistryStatus StatusInRegistryUnderRoot(HKEY root) const {
-    RegKey key(root, _key_path.c_str(), KEY_QUERY_VALUE);
+    RegKey key(root, key_path_.c_str(), KEY_QUERY_VALUE);
     bool found = false;
     bool correct_value = false;
-    if (_is_string) {
+    if (is_string_) {
       string16 read_value;
-      found = key.ReadValue(_name.c_str(), &read_value) == ERROR_SUCCESS;
-      correct_value = read_value.size() == _value.size() &&
-          std::equal(_value.begin(), _value.end(), read_value.begin(),
+      found = key.ReadValue(name_.c_str(), &read_value) == ERROR_SUCCESS;
+      correct_value = read_value.size() == value_.size() &&
+          std::equal(value_.begin(), value_.end(), read_value.begin(),
                      base::CaseInsensitiveCompare<wchar_t>());
     } else {
       DWORD read_value;
-      found = key.ReadValueDW(_name.c_str(), &read_value) == ERROR_SUCCESS;
-      correct_value = read_value == _int_value;
+      found = key.ReadValueDW(name_.c_str(), &read_value) == ERROR_SUCCESS;
+      correct_value = read_value == int_value_;
     }
     return found ?
         (correct_value ? SAME_VALUE : DIFFERENT_VALUE) : DOES_NOT_EXIST;
diff --git a/chrome/renderer/DEPS b/chrome/renderer/DEPS
index d437fb2..3900f77 100644
--- a/chrome/renderer/DEPS
+++ b/chrome/renderer/DEPS
@@ -19,9 +19,6 @@
   "+webkit/glue",
   "+webkit/renderer",
 
-  # TODO(jam): eliminate all of these. http://crbug.com/263054
-  "!webkit/plugins/plugin_constants.h",
-
   "+third_party/npapi/bindings",
   "+third_party/re2",
   "+third_party/smhasher",
diff --git a/chrome/renderer/chrome_content_renderer_client.cc b/chrome/renderer/chrome_content_renderer_client.cc
index 9f8ef8d..5746899 100644
--- a/chrome/renderer/chrome_content_renderer_client.cc
+++ b/chrome/renderer/chrome_content_renderer_client.cc
@@ -17,13 +17,12 @@
 #include "chrome/common/chrome_paths.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/common/content_settings_pattern.h"
-#include "chrome/common/extensions/chrome_manifest_handlers.h"
+#include "chrome/common/extensions/chrome_extensions_client.h"
 #include "chrome/common/extensions/extension.h"
 #include "chrome/common/extensions/extension_constants.h"
 #include "chrome/common/extensions/extension_manifest_constants.h"
 #include "chrome/common/extensions/extension_process_policy.h"
 #include "chrome/common/extensions/extension_set.h"
-#include "chrome/common/extensions/permissions/chrome_api_permissions.h"
 #include "chrome/common/external_ipc_fuzzer.h"
 #include "chrome/common/localized_error.h"
 #include "chrome/common/pepper_permission_util.h"
@@ -344,9 +343,8 @@
   WebSecurityPolicy::registerURLSchemeAsBypassingContentSecurityPolicy(
       extension_resource_scheme);
 
-  extensions::PermissionsInfo::GetInstance()->InitializeWithDelegate(
-      extensions::ChromeAPIPermissions());
-  extensions::RegisterChromeManifestHandlers();
+  extensions::ExtensionsClient::Set(
+      extensions::ChromeExtensionsClient::GetInstance());
 }
 
 void ChromeContentRendererClient::RenderViewCreated(
@@ -1087,7 +1085,7 @@
 
 bool ChromeContentRendererClient::ShouldOverridePageVisibilityState(
     const content::RenderView* render_view,
-    WebKit::WebPageVisibilityState* override_state) const {
+    WebKit::WebPageVisibilityState* override_state) {
   if (!prerender::PrerenderHelper::IsPrerendering(render_view))
     return false;
 
@@ -1228,8 +1226,16 @@
   return NULL;
 }
 
+bool ChromeContentRendererClient::IsExternalPepperPlugin(
+    const std::string& module_name) {
+  // TODO(bbudge) remove this when the trusted NaCl plugin has been removed.
+  // We must defer certain plugin events for NaCl instances since we switch
+  // from the in-process to the out-of-process proxy after instantiating them.
+  return module_name == "Native Client";
+}
+
 bool ChromeContentRendererClient::IsPluginAllowedToCallRequestOSFileHandle(
-    WebKit::WebPluginContainer* container) const {
+    WebKit::WebPluginContainer* container) {
 #if defined(ENABLE_PLUGINS)
   if (!container)
     return false;
@@ -1252,7 +1258,7 @@
 }
 
 bool ChromeContentRendererClient::AllowBrowserPlugin(
-    WebKit::WebPluginContainer* container) const {
+    WebKit::WebPluginContainer* container) {
   if (CommandLine::ForCurrentProcess()->HasSwitch(
           switches::kEnableBrowserPluginForAllViewTypes))
     return true;
@@ -1278,7 +1284,7 @@
 }
 
 bool ChromeContentRendererClient::AllowPepperMediaStreamAPI(
-    const GURL& url) const {
+    const GURL& url) {
 #if !defined(OS_ANDROID)
   std::string host = url.host();
   // Allow only the Hangouts app to use the MediaStream APIs. It's OK to check
diff --git a/chrome/renderer/chrome_content_renderer_client.h b/chrome/renderer/chrome_content_renderer_client.h
index 94d9431..b4b7231 100644
--- a/chrome/renderer/chrome_content_renderer_client.h
+++ b/chrome/renderer/chrome_content_renderer_client.h
@@ -116,7 +116,7 @@
   virtual WebKit::WebPrescientNetworking* GetPrescientNetworking() OVERRIDE;
   virtual bool ShouldOverridePageVisibilityState(
       const content::RenderView* render_view,
-      WebKit::WebPageVisibilityState* override_state) const OVERRIDE;
+      WebKit::WebPageVisibilityState* override_state) OVERRIDE;
   virtual bool HandleGetCookieRequest(content::RenderView* sender,
                                       const GURL& url,
                                       const GURL& first_party_for_cookies,
@@ -126,16 +126,17 @@
                                       const GURL& first_party_for_cookies,
                                       const std::string& value) OVERRIDE;
   virtual bool AllowBrowserPlugin(
-      WebKit::WebPluginContainer* container) const OVERRIDE;
+      WebKit::WebPluginContainer* container) OVERRIDE;
   virtual const void* CreatePPAPIInterface(
       const std::string& interface_name) OVERRIDE;
+  virtual bool IsExternalPepperPlugin(const std::string& module_name) OVERRIDE;
   // TODO(victorhsieh): move to ChromeContentBrowserClient once we migrate
   // PPAPI FileIO host to browser.
   virtual bool IsPluginAllowedToCallRequestOSFileHandle(
-      WebKit::WebPluginContainer* container) const OVERRIDE;
+      WebKit::WebPluginContainer* container) OVERRIDE;
   virtual WebKit::WebSpeechSynthesizer* OverrideSpeechSynthesizer(
       WebKit::WebSpeechSynthesizerClient* client) OVERRIDE;
-  virtual bool AllowPepperMediaStreamAPI(const GURL& url) const OVERRIDE;
+  virtual bool AllowPepperMediaStreamAPI(const GURL& url) OVERRIDE;
 
   // For testing.
   void SetExtensionDispatcher(extensions::Dispatcher* extension_dispatcher);
diff --git a/chrome/renderer/extensions/api_definitions_natives.cc b/chrome/renderer/extensions/api_definitions_natives.cc
index 0fb03ae..6bd6af0 100644
--- a/chrome/renderer/extensions/api_definitions_natives.cc
+++ b/chrome/renderer/extensions/api_definitions_natives.cc
@@ -6,7 +6,8 @@
 
 #include <algorithm>
 
-#include "chrome/common/extensions/features/base_feature_provider.h"
+#include "chrome/common/extensions/features/feature.h"
+#include "extensions/common/features/feature_provider.h"
 
 namespace extensions {
 
@@ -22,7 +23,7 @@
 void ApiDefinitionsNatives::GetExtensionAPIDefinitionsForTest(
     const v8::FunctionCallbackInfo<v8::Value>& args) {
   std::vector<std::string> apis;
-  FeatureProvider* feature_provider = BaseFeatureProvider::GetByName("api");
+  FeatureProvider* feature_provider = FeatureProvider::GetByName("api");
   const std::vector<std::string>& feature_names =
       feature_provider->GetAllFeatureNames();
   for (std::vector<std::string>::const_iterator i = feature_names.begin();
diff --git a/chrome/renderer/extensions/dispatcher.cc b/chrome/renderer/extensions/dispatcher.cc
index 3b2c3ef..b569c0b 100644
--- a/chrome/renderer/extensions/dispatcher.cc
+++ b/chrome/renderer/extensions/dispatcher.cc
@@ -23,8 +23,8 @@
 #include "chrome/common/extensions/extension_constants.h"
 #include "chrome/common/extensions/extension_manifest_constants.h"
 #include "chrome/common/extensions/extension_messages.h"
-#include "chrome/common/extensions/features/base_feature_provider.h"
 #include "chrome/common/extensions/features/feature.h"
+#include "chrome/common/extensions/features/feature_channel.h"
 #include "chrome/common/extensions/manifest.h"
 #include "chrome/common/extensions/manifest_handlers/externally_connectable.h"
 #include "chrome/common/extensions/manifest_handlers/sandboxed_page_info.h"
@@ -78,14 +78,17 @@
 #include "content/public/renderer/render_view.h"
 #include "content/public/renderer/v8_value_converter.h"
 #include "extensions/common/constants.h"
+#include "extensions/common/features/feature_provider.h"
 #include "extensions/common/view_type.h"
 #include "grit/common_resources.h"
 #include "grit/renderer_resources.h"
 #include "third_party/WebKit/public/platform/WebString.h"
 #include "third_party/WebKit/public/platform/WebURLRequest.h"
+#include "third_party/WebKit/public/web/WebCustomElement.h"
 #include "third_party/WebKit/public/web/WebDataSource.h"
 #include "third_party/WebKit/public/web/WebDocument.h"
 #include "third_party/WebKit/public/web/WebFrame.h"
+#include "third_party/WebKit/public/web/WebRuntimeFeatures.h"
 #include "third_party/WebKit/public/web/WebScopedUserGesture.h"
 #include "third_party/WebKit/public/web/WebSecurityPolicy.h"
 #include "third_party/WebKit/public/web/WebView.h"
@@ -472,6 +475,9 @@
     InitOriginPermissions(extension);
   }
 
+  if (IsWithinPlatformApp())
+    EnableCustomElementWhiteList();
+
   is_webkit_initialized_ = true;
 }
 
@@ -507,7 +513,7 @@
 }
 
 void Dispatcher::OnSetChannel(int channel) {
-  Feature::SetCurrentChannel(
+  extensions::SetCurrentChannel(
       static_cast<chrome::VersionInfo::Channel>(channel));
 }
 
@@ -666,8 +672,6 @@
       }
       if (runtime_is_available)
         RegisterBinding("runtime", context);
-      else
-        DeregisterBinding("runtime", context);
       break;
     }
 
@@ -676,7 +680,7 @@
     case Feature::CONTENT_SCRIPT_CONTEXT: {
       // Extension context; iterate through all the APIs and bind the available
       // ones.
-      FeatureProvider* feature_provider = BaseFeatureProvider::GetByName("api");
+      FeatureProvider* feature_provider = FeatureProvider::GetByName("api");
       const std::vector<std::string>& apis =
           feature_provider->GetAllFeatureNames();
       for (std::vector<std::string>::const_iterator it = apis.begin();
@@ -741,7 +745,7 @@
   //  If app is available and app.window is not, just install app.
   //  If app.window is available and app is not, delete app and install
   //  app.window on a new object so app does not have to be loaded.
-  FeatureProvider* feature_provider = BaseFeatureProvider::GetByName("api");
+  FeatureProvider* feature_provider = FeatureProvider::GetByName("api");
   std::string ancestor_name;
   bool only_ancestor_available = false;
 
@@ -777,9 +781,29 @@
   std::string bind_name;
   v8::Handle<v8::Object> bind_object =
       GetOrCreateBindObjectIfAvailable(api_name, &bind_name, context);
+
+  // Empty if the bind object failed to be created, probably because the
+  // extension overrode chrome with a non-object, e.g. window.chrome = true.
   if (bind_object.IsEmpty())
     return;
 
+  v8::Local<v8::String> v8_api_name = v8::String::New(api_name.c_str());
+  if (bind_object->HasRealNamedProperty(v8_api_name)) {
+    // The bind object may already have the property if the API has been
+    // registered before (or if the extension has put something there already,
+    // but, whatevs).
+    //
+    // In the former case, we need to re-register the bindings for the APIs
+    // which the extension now has permissions for (if any), but not touch any
+    // others so that we don't destroy state such as event listeners.
+    //
+    // TODO(kalman): Only register available APIs to make this all moot.
+    if (bind_object->HasRealNamedCallbackProperty(v8_api_name))
+      return;  // lazy binding still there, nothing to do
+    if (bind_object->Get(v8_api_name)->IsObject())
+      return;  // binding has already been fully installed
+  }
+
   ModuleSystem* module_system = context->module_system();
   if (lazy_bindings_map_.find(api_name) != lazy_bindings_map_.end()) {
     InstallBindings(module_system, context->v8_context(), api_name);
@@ -1076,7 +1100,7 @@
 
   AddOrRemoveBindingsForContext(context);
 
-  bool is_within_platform_app = IsWithinPlatformApp(frame);
+  bool is_within_platform_app = IsWithinPlatformApp();
   // Inject custom JS into the platform app context.
   if (is_within_platform_app) {
     module_system->Require("platformApp");
@@ -1084,7 +1108,7 @@
 
   if (context_type == Feature::BLESSED_EXTENSION_CONTEXT &&
       is_within_platform_app &&
-      Feature::GetCurrentChannel() <= chrome::VersionInfo::CHANNEL_DEV &&
+      GetCurrentChannel() <= chrome::VersionInfo::CHANNEL_DEV &&
       CommandLine::ForCurrentProcess()->HasSwitch(
           switches::kEnableAppWindowControls)) {
     module_system->Require("windowControls");
@@ -1100,7 +1124,7 @@
     if (extension->HasAPIPermission(APIPermission::kWebView)) {
       module_system->Require("webView");
       bool includeExperimental =
-          Feature::GetCurrentChannel() <= chrome::VersionInfo::CHANNEL_DEV ||
+          GetCurrentChannel() <= chrome::VersionInfo::CHANNEL_DEV ||
           extension->id() == extension_misc::kIdentityApiUiAppId;
       if (!includeExperimental) {
         // TODO(asargent) We need a whitelist for webview experimental.
@@ -1149,11 +1173,14 @@
   return extensions_.GetExtensionOrAppIDByURL(frame_url);
 }
 
-bool Dispatcher::IsWithinPlatformApp(const WebFrame* frame) {
-  GURL url(UserScriptSlave::GetDataSourceURLForFrame(frame->top()));
-  const Extension* extension = extensions_.GetExtensionOrAppByURL(url);
-
-  return extension && extension->is_platform_app();
+bool Dispatcher::IsWithinPlatformApp() {
+  for (std::set<std::string>::iterator iter = active_extension_ids_.begin();
+       iter != active_extension_ids_.end(); ++iter) {
+    const Extension* extension = extensions_.GetByID(*iter);
+    if (extension && extension->is_platform_app())
+      return true;
+  }
+  return false;
 }
 
 void Dispatcher::WillReleaseScriptContext(
@@ -1171,7 +1198,7 @@
 }
 
 void Dispatcher::DidCreateDocumentElement(WebKit::WebFrame* frame) {
-  if (IsWithinPlatformApp(frame)) {
+  if (IsWithinPlatformApp()) {
     // WebKit doesn't let us define an additional user agent stylesheet, so we
     // insert the default platform app stylesheet into all documents that are
     // loaded in each app.
@@ -1222,6 +1249,9 @@
                                      extension_id,
                                      extension->url(),
                                      string16());
+
+    if (IsWithinPlatformApp())
+      EnableCustomElementWhiteList();
   }
 }
 
@@ -1269,6 +1299,14 @@
   }
 }
 
+void Dispatcher::EnableCustomElementWhiteList() {
+  WebKit::WebRuntimeFeatures::enableCustomElements(true);
+  WebKit::WebCustomElement::allowTagName("webview");
+  // TODO(fsamuel): Add <adview> to the whitelist once it has been converted
+  // into a custom element.
+  WebKit::WebCustomElement::allowTagName("browser-plugin");
+}
+
 void Dispatcher::AddOrRemoveBindings(const std::string& extension_id) {
   v8_context_set().ForEach(
       extension_id,
diff --git a/chrome/renderer/extensions/dispatcher.h b/chrome/renderer/extensions/dispatcher.h
index b43067d..b145eab 100644
--- a/chrome/renderer/extensions/dispatcher.h
+++ b/chrome/renderer/extensions/dispatcher.h
@@ -200,6 +200,9 @@
       const Extension* extension,
       const URLPatternSet& origins);
 
+  // Enable custom element whitelist in Apps.
+  void EnableCustomElementWhiteList();
+
   // Adds or removes bindings for every context belonging to |extension_id|, or
   // or all contexts if |extension_id| is empty.
   void AddOrRemoveBindings(const std::string& extension_id);
@@ -226,10 +229,8 @@
                        v8::Handle<v8::Context> v8_context,
                        const std::string& api);
 
-  // Determines whether |frame| is loading a platform app resource URL. (this
-  // evaluates to true for iframes in platform apps and sandboxed resources that
-  // are not in the same origin).
-  bool IsWithinPlatformApp(const WebKit::WebFrame* frame);
+  // Returns whether the current renderer hosts a platform app.
+  bool IsWithinPlatformApp();
 
   bool IsSandboxedPage(const GURL& url) const;
 
diff --git a/chrome/renderer/extensions/module_system.cc b/chrome/renderer/extensions/module_system.cc
index bf3dd70..8994293 100644
--- a/chrome/renderer/extensions/module_system.cc
+++ b/chrome/renderer/extensions/module_system.cc
@@ -12,6 +12,7 @@
 #include "base/strings/stringprintf.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/common/extensions/extension_messages.h"
+#include "chrome/common/extensions/features/feature_channel.h"
 #include "chrome/renderer/extensions/chrome_v8_context.h"
 #include "chrome/renderer/extensions/console.h"
 #include "chrome/renderer/extensions/safe_builtins.h"
@@ -53,7 +54,7 @@
   full_message += message;
 
   // <= dev means dev, canary, and trunk.
-  if (Feature::GetCurrentChannel() <= chrome::VersionInfo::CHANNEL_DEV)
+  if (GetCurrentChannel() <= chrome::VersionInfo::CHANNEL_DEV)
     console::Fatal(v8::Context::GetCalling(), full_message);
   else
     console::Error(v8::Context::GetCalling(), full_message);
diff --git a/chrome/renderer/extensions/runtime_custom_bindings.cc b/chrome/renderer/extensions/runtime_custom_bindings.cc
index dc43a8a..4f364a3 100644
--- a/chrome/renderer/extensions/runtime_custom_bindings.cc
+++ b/chrome/renderer/extensions/runtime_custom_bindings.cc
@@ -9,13 +9,14 @@
 #include "base/values.h"
 #include "chrome/common/extensions/extension.h"
 #include "chrome/common/extensions/extension_messages.h"
-#include "chrome/common/extensions/features/base_feature_provider.h"
+#include "chrome/common/extensions/features/feature.h"
 #include "chrome/common/extensions/manifest.h"
 #include "chrome/renderer/extensions/api_activity_logger.h"
 #include "chrome/renderer/extensions/chrome_v8_context.h"
 #include "chrome/renderer/extensions/dispatcher.h"
 #include "content/public/renderer/render_view.h"
 #include "content/public/renderer/v8_value_converter.h"
+#include "extensions/common/features/feature_provider.h"
 #include "third_party/WebKit/public/web/WebDocument.h"
 #include "third_party/WebKit/public/web/WebFrame.h"
 #include "third_party/WebKit/public/web/WebView.h"
@@ -67,7 +68,7 @@
     const v8::FunctionCallbackInfo<v8::Value>& args) {
   // Verify that the extension has permission to use native messaging.
   Feature::Availability availability =
-      BaseFeatureProvider::GetByName("permission")->
+      FeatureProvider::GetByName("permission")->
           GetFeature("nativeMessaging")->IsAvailableToContext(
               GetExtensionForRenderView(),
               context()->context_type(),
diff --git a/chrome/renderer/pepper/pepper_flash_drm_renderer_host.cc b/chrome/renderer/pepper/pepper_flash_drm_renderer_host.cc
index ca59c7e..7f2011c 100644
--- a/chrome/renderer/pepper/pepper_flash_drm_renderer_host.cc
+++ b/chrome/renderer/pepper/pepper_flash_drm_renderer_host.cc
@@ -12,7 +12,6 @@
 #include "ppapi/host/host_message_context.h"
 #include "ppapi/host/ppapi_host.h"
 #include "ppapi/proxy/ppapi_messages.h"
-#include "ppapi/proxy/ppb_file_ref_proxy.h"
 
 namespace chrome {
 
@@ -28,7 +27,8 @@
     PP_Instance instance,
     PP_Resource resource)
     : ResourceHost(host->GetPpapiHost(), instance, resource),
-      renderer_ppapi_host_(host) {
+      renderer_ppapi_host_(host),
+      weak_factory_(this) {
 }
 
 PepperFlashDRMRendererHost::~PepperFlashDRMRendererHost() {
@@ -56,13 +56,26 @@
   base::FilePath voucher_file = plugin_dir.Append(
       base::FilePath(kVoucherFilename));
 
-  ppapi::PPB_FileRef_CreateInfo create_info;
-  ppapi::proxy::PPB_FileRef_Proxy::SerializeFileRef(
-      plugin_instance->CreateExternalFileReference(voucher_file),
-      &create_info);
-  context->reply_msg =
-      PpapiPluginMsg_FlashDRM_GetVoucherFileReply(create_info);
-  return PP_OK;
+  renderer_ppapi_host_->CreateBrowserResourceHost(
+      pp_instance(),
+      PpapiHostMsg_FileRef_CreateExternal(voucher_file),
+      base::Bind(&PepperFlashDRMRendererHost::DidCreateFileRefHost,
+                 weak_factory_.GetWeakPtr(),
+                 context->MakeReplyMessageContext(),
+                 voucher_file));
+  return PP_OK_COMPLETIONPENDING;
+}
+
+void PepperFlashDRMRendererHost::DidCreateFileRefHost(
+    const ppapi::host::ReplyMessageContext& reply_context,
+    const base::FilePath& external_path,
+    int pending_resource_id) {
+  ppapi::FileRefCreateInfo create_info =
+      ppapi::MakeExternalFileRefCreateInfo(external_path,
+                                           std::string(),
+                                           pending_resource_id);
+  host()->SendReply(reply_context,
+                    PpapiPluginMsg_FlashDRM_GetVoucherFileReply(create_info));
 }
 
 }  // namespace chrome
diff --git a/chrome/renderer/pepper/pepper_flash_drm_renderer_host.h b/chrome/renderer/pepper/pepper_flash_drm_renderer_host.h
index f7247d6..a0382b6 100644
--- a/chrome/renderer/pepper/pepper_flash_drm_renderer_host.h
+++ b/chrome/renderer/pepper/pepper_flash_drm_renderer_host.h
@@ -7,8 +7,13 @@
 
 #include "base/basictypes.h"
 #include "base/compiler_specific.h"
+#include "base/memory/weak_ptr.h"
 #include "ppapi/host/resource_host.h"
 
+namespace base {
+class FilePath;
+}
+
 namespace content {
 class RendererPpapiHost;
 }
@@ -31,9 +36,16 @@
  private:
   int32_t OnGetVoucherFile(ppapi::host::HostMessageContext* context);
 
+  void DidCreateFileRefHost(
+      const ppapi::host::ReplyMessageContext& reply_context,
+      const base::FilePath& external_path,
+      int pending_resource_id);
+
   // Non-owning pointer.
   content::RendererPpapiHost* renderer_ppapi_host_;
 
+  base::WeakPtrFactory<PepperFlashDRMRendererHost> weak_factory_;
+
   DISALLOW_COPY_AND_ASSIGN(PepperFlashDRMRendererHost);
 };
 
diff --git a/chrome/renderer/plugins/plugin_placeholder.cc b/chrome/renderer/plugins/plugin_placeholder.cc
index bcc4fb2..eae3e0e 100644
--- a/chrome/renderer/plugins/plugin_placeholder.cc
+++ b/chrome/renderer/plugins/plugin_placeholder.cc
@@ -16,6 +16,7 @@
 #include "chrome/renderer/chrome_content_renderer_client.h"
 #include "chrome/renderer/custom_menu_commands.h"
 #include "chrome/renderer/plugins/plugin_uma.h"
+#include "content/public/common/content_constants.h"
 #include "content/public/common/context_menu_params.h"
 #include "content/public/renderer/render_thread.h"
 #include "content/public/renderer/render_view.h"
@@ -39,10 +40,6 @@
 #include "ui/base/resource/resource_bundle.h"
 #include "ui/webui/jstemplate_builder.h"
 
-#if defined(ENABLE_MOBILE_YOUTUBE_PLUGIN)
-#include "webkit/plugins/plugin_constants.h"
-#endif
-
 using content::RenderThread;
 using content::RenderView;
 using WebKit::WebContextMenuData;
@@ -624,6 +621,6 @@
       EndsWith(host, "youtube-nocookie.com", true);
 
   return is_youtube && IsValidYouTubeVideo(url.path()) &&
-      LowerCaseEqualsASCII(mime_type, kFlashPluginSwfMimeType);
+      LowerCaseEqualsASCII(mime_type, content::kFlashPluginSwfMimeType);
 }
 #endif
diff --git a/chrome/renderer/plugins/plugin_uma.cc b/chrome/renderer/plugins/plugin_uma.cc
index b634074..b6c8764 100644
--- a/chrome/renderer/plugins/plugin_uma.cc
+++ b/chrome/renderer/plugins/plugin_uma.cc
@@ -11,7 +11,6 @@
 #include "base/strings/string_util.h"
 #include "content/public/common/content_constants.h"
 #include "third_party/widevine/cdm/widevine_cdm_common.h"
-#include "webkit/plugins/plugin_constants.h"
 
 namespace {
 
@@ -192,8 +191,8 @@
   if (mime_type == content::kBrowserPluginMimeType)
     return BROWSER_PLUGIN;
 
-  if (mime_type == kFlashPluginSwfMimeType ||
-      mime_type == kFlashPluginSplMimeType) {
+  if (mime_type == content::kFlashPluginSwfMimeType ||
+      mime_type == content::kFlashPluginSplMimeType) {
     return SHOCKWAVE_FLASH;
   }
 
diff --git a/chrome/renderer/resources/extensions/searchbox_api.js b/chrome/renderer/resources/extensions/searchbox_api.js
index 6bdb5ea..3aa3d53 100644
--- a/chrome/renderer/resources/extensions/searchbox_api.js
+++ b/chrome/renderer/resources/extensions/searchbox_api.js
@@ -21,6 +21,7 @@
       native function GetStartMargin();
       native function IsFocused();
       native function IsKeyCaptureEnabled();
+      native function Paste();
       native function SetVoiceSearchSupported();
       native function StartCapturingKeyStrokes();
       native function StopCapturingKeyStrokes();
@@ -42,6 +43,10 @@
         return GetMostVisitedItemData(restrictedId);
       };
 
+      this.paste = function(value) {
+        Paste(value);
+      };
+
       this.setVoiceSearchSupported = function(supported) {
         SetVoiceSearchSupported(supported);
       };
diff --git a/chrome/renderer/resources/extensions/sync_file_system_custom_bindings.js b/chrome/renderer/resources/extensions/sync_file_system_custom_bindings.js
index c2df0b0..352b0a7 100644
--- a/chrome/renderer/resources/extensions/sync_file_system_custom_bindings.js
+++ b/chrome/renderer/resources/extensions/sync_file_system_custom_bindings.js
@@ -23,7 +23,7 @@
   }
   $Array.forEach(['getFileStatus'], bindFileEntryFunction);
 
-  // Functions which take in an [instanceOf=EntryArray].
+  // Functions which take in a FileEntry array.
   function bindFileEntryArrayFunction(functionName) {
     apiFunctions.setUpdateArgumentsPostValidate(
         functionName, function(entries, callback) {
diff --git a/chrome/renderer/resources/extensions/test_custom_bindings.js b/chrome/renderer/resources/extensions/test_custom_bindings.js
index 231e339..fe330d3 100644
--- a/chrome/renderer/resources/extensions/test_custom_bindings.js
+++ b/chrome/renderer/resources/extensions/test_custom_bindings.js
@@ -228,6 +228,18 @@
     chromeTest.assertEq(expectedError, chrome.runtime.lastError.message);
   });
 
+  apiFunctions.setHandleRequest('assertThrows',
+                                function(fn, self, args, message) {
+    assertTrue(typeof fn == 'function');
+    try {
+      fn.apply(self, args);
+      chromeTest.fail('Did not throw error: ' + fn);
+    } catch (e) {
+      if (message !== undefined)
+        chromeTest.assertEq(message, e.message);
+    }
+  });
+
   function safeFunctionApply(func, args) {
     try {
       if (func)
diff --git a/chrome/renderer/resources/extensions/web_view_experimental.js b/chrome/renderer/resources/extensions/web_view_experimental.js
index cfb11ed..c2bb066 100644
--- a/chrome/renderer/resources/extensions/web_view_experimental.js
+++ b/chrome/renderer/resources/extensions/web_view_experimental.js
@@ -41,7 +41,7 @@
                 self.viewInstanceId_);
       }
       return self[webRequestEvent.name + '_'];
-    }
+    };
   };
 
   // Populate the WebRequest events from the API definition.
@@ -52,7 +52,6 @@
         webRequestSchema.events[i].name,
         {
           get: webRequestEvent,
-          configuable: false,
           enumerable: true
         }
     );
@@ -61,7 +60,6 @@
         webRequestSchema.events[i].name,
         {
           get: webRequestEvent,
-          configuable: false,
           enumerable: true
         }
     );
@@ -71,7 +69,6 @@
       'request',
       {
         value: request,
-        configurable: false,
         enumerable: true,
         writable: false
       }
@@ -114,7 +111,7 @@
     if (browserPluginNode['-internal-setPermission'](requestId, false, '')) {
       showWarningMessage(dialogType);
     }
-  }
+  };
 
   browserPluginNode.addEventListener('-internal-dialog', function(e) {
     var evt = new Event('dialog', { bubbles: true, cancelable: true });
diff --git a/chrome/renderer/searchbox/searchbox.cc b/chrome/renderer/searchbox/searchbox.cc
index e184eab..05f5570 100644
--- a/chrome/renderer/searchbox/searchbox.cc
+++ b/chrome/renderer/searchbox/searchbox.cc
@@ -231,6 +231,11 @@
       url, transition, disposition, is_search_type));
 }
 
+void SearchBox::Paste(const string16& text) {
+  render_view()->Send(new ChromeViewHostMsg_PasteAndOpenDropdown(
+      render_view()->GetRoutingID(), render_view()->GetPageId(), text));
+}
+
 void SearchBox::SetVoiceSearchSupported(bool supported) {
   render_view()->Send(new ChromeViewHostMsg_SetVoiceSearchSupported(
       render_view()->GetRoutingID(), render_view()->GetPageId(), supported));
diff --git a/chrome/renderer/searchbox/searchbox.h b/chrome/renderer/searchbox/searchbox.h
index b4743c9..685c3cb 100644
--- a/chrome/renderer/searchbox/searchbox.h
+++ b/chrome/renderer/searchbox/searchbox.h
@@ -71,6 +71,9 @@
                      WindowOpenDisposition disposition,
                      bool is_search_type);
 
+  // Sends ChromeViewHostMsg_SearchBoxPaste to the browser.
+  void Paste(const string16& text);
+
   const ThemeBackgroundInfo& GetThemeBackgroundInfo();
 
   // Sends ChromeViewHostMsg_SetVoiceSearchSupported to the browser.
diff --git a/chrome/renderer/searchbox/searchbox_extension.cc b/chrome/renderer/searchbox/searchbox_extension.cc
index 3eacc3c..75663b7 100644
--- a/chrome/renderer/searchbox/searchbox_extension.cc
+++ b/chrome/renderer/searchbox/searchbox_extension.cc
@@ -362,6 +362,9 @@
   static void NavigateContentWindow(
       const v8::FunctionCallbackInfo<v8::Value>& args);
 
+  // Pastes provided value or clipboard's content into the omnibox.
+  static void Paste(const v8::FunctionCallbackInfo<v8::Value>& args);
+
   // Indicates whether the page supports voice search.
   static void SetVoiceSearchSupported(
       const v8::FunctionCallbackInfo<v8::Value>& args);
@@ -485,6 +488,8 @@
     return v8::FunctionTemplate::New(LogEvent);
   if (name->Equals(v8::String::New("NavigateContentWindow")))
     return v8::FunctionTemplate::New(NavigateContentWindow);
+  if (name->Equals(v8::String::New("Paste")))
+    return v8::FunctionTemplate::New(Paste);
   if (name->Equals(v8::String::New("SetVoiceSearchSupported")))
     return v8::FunctionTemplate::New(SetVoiceSearchSupported);
   if (name->Equals(v8::String::New("StartCapturingKeyStrokes")))
@@ -852,6 +857,20 @@
 }
 
 // static
+void SearchBoxExtensionWrapper::Paste(
+    const v8::FunctionCallbackInfo<v8::Value>& args) {
+  content::RenderView* render_view = GetRenderView();
+  if (!render_view) return;
+
+  string16 text;
+  if (!args[0]->IsUndefined())
+    text = V8ValueToUTF16(args[0]);
+
+  DVLOG(1) << render_view << " Paste: " << text;
+  SearchBox::Get(render_view)->Paste(text);
+}
+
+// static
 void SearchBoxExtensionWrapper::StartCapturingKeyStrokes(
     const v8::FunctionCallbackInfo<v8::Value>& args) {
   content::RenderView* render_view = GetRenderView();
diff --git a/chrome/test/DEPS b/chrome/test/DEPS
index 8c88f2b..5a9fdbd 100644
--- a/chrome/test/DEPS
+++ b/chrome/test/DEPS
@@ -19,6 +19,5 @@
   "+sandbox/win/src",
   "+sandbox/win/tests",
   "+webkit/glue",
-  "+webkit/plugins",
   "+win8/test",
 ]
diff --git a/chrome/test/base/chrome_test_suite.cc b/chrome/test/base/chrome_test_suite.cc
index 01668b4..cdb3378 100644
--- a/chrome/test/base/chrome_test_suite.cc
+++ b/chrome/test/base/chrome_test_suite.cc
@@ -21,8 +21,7 @@
 #include "chrome/common/chrome_constants.h"
 #include "chrome/common/chrome_content_client.h"
 #include "chrome/common/chrome_paths.h"
-#include "chrome/common/extensions/chrome_manifest_handlers.h"
-#include "chrome/common/extensions/permissions/chrome_api_permissions.h"
+#include "chrome/common/extensions/chrome_extensions_client.h"
 #include "chrome/common/url_constants.h"
 #include "chrome/test/base/testing_browser_process.h"
 #include "chrome/utility/chrome_content_utility_client.h"
@@ -234,12 +233,11 @@
 #if !defined(OS_IOS)
   extensions::RegisterPathProvider();
 
+  extensions::ExtensionsClient::Set(
+      extensions::ChromeExtensionsClient::GetInstance());
+
   // Only want to do this for unit tests.
   if (!content::GetCurrentTestLauncherDelegate()) {
-    extensions::PermissionsInfo::GetInstance()->InitializeWithDelegate(
-        extensions::ChromeAPIPermissions());
-    extensions::RegisterChromeManifestHandlers();
-
     // For browser tests, this won't create the right object since
     // TestChromeWebUIControllerFactory is used. That's created and
     // registered in ChromeBrowserMainParts as in normal startup.
diff --git a/chrome/test/base/test_location_bar.h b/chrome/test/base/test_location_bar.h
index b84e35e..22ef364b 100644
--- a/chrome/test/base/test_location_bar.h
+++ b/chrome/test/base/test_location_bar.h
@@ -38,7 +38,7 @@
   virtual void UpdatePageActions() OVERRIDE {}
   virtual void InvalidatePageActions() OVERRIDE {}
   virtual void UpdateOpenPDFInReaderPrompt() OVERRIDE {}
-  virtual void UpdateAutofillCreditCardView() OVERRIDE {}
+  virtual void UpdateGeneratedCreditCardView() OVERRIDE {}
   virtual void SaveStateToContents(content::WebContents* contents) OVERRIDE {}
   virtual void Revert() OVERRIDE {}
   virtual const OmniboxView* GetLocationEntry() const OVERRIDE;
diff --git a/chrome/test/base/testing_profile.cc b/chrome/test/base/testing_profile.cc
index 9570da0..318c14c 100644
--- a/chrome/test/base/testing_profile.cc
+++ b/chrome/test/base/testing_profile.cc
@@ -284,9 +284,9 @@
 
 void TestingProfile::Init() {
   // If threads have been initialized, we should be on the UI thread.
-  DCHECK(
-      !content::BrowserThread::IsWellKnownThread(content::BrowserThread::UI) ||
-      content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+  DCHECK(!content::BrowserThread::IsThreadInitialized(
+             content::BrowserThread::UI) ||
+         content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
 
   // Normally this would happen during browser startup, but for tests
   // we need to trigger creation of Profile-related services.
diff --git a/chrome/test/chromedriver/DEPS b/chrome/test/chromedriver/DEPS
index 0d83e87..f4ece7a 100644
--- a/chrome/test/chromedriver/DEPS
+++ b/chrome/test/chromedriver/DEPS
@@ -5,7 +5,6 @@
 
   "+chrome/test/chromedriver",
 
-  "+third_party/mongoose",
   "+third_party/webdriver",
   "+third_party/zlib",
 ]
diff --git a/chrome/test/chromedriver/README.txt b/chrome/test/chromedriver/README.txt
index ef3d959..43126c4 100644
--- a/chrome/test/chromedriver/README.txt
+++ b/chrome/test/chromedriver/README.txt
@@ -49,34 +49,39 @@
 command is finished, it will invoke a callback, which will eventually make its
 way back to the IO thread as a HTTP response for the server to send.
 
-=====Code structure=====
-1) chrome/test/chromedriver
+=====Code structure (relative to this file)=====
+1) .
 Implements chromedriver commands.
 
-2) chrome/test/chromedriver/chrome
-A basic interface for controlling Chrome via DevTools. Should not have
-knowledge about WebDriver, and thus not depend on chrome/test/chromedriver.
+2) chrome/
+A basic interface for controlling Chrome. Should not depend on or reference
+WebDriver-related code or concepts.
 
-3) chrome/test/chromedriver/js
+3) js/
 Javascript helper scripts.
 
-4) chrome/test/chromedriver/net
+4) net/
 Code to deal with network communication, such as connection to DevTools.
 
-5) chrome/test/chromedriver/client
+5) client/
 Code for a python client.
 
-6) chrome/test/chromedriver/server
+6) server/
 Code for the chromedriver server.
 A python wrapper to the chromedriver server.
 
-7) chrome/test/chromedriver/extension
+7) extension/
 An extension used for automating the desktop browser.
 
-8) chrome/test/chromedriver/third_party
+8) test/
+Integration tests.
+
+9) third_party/
 Third party libraries used by chromedriver.
 
 =====Testing=====
+See the ChromeDriver waterfall at:
+    http://build.chromium.org/p/chromium.chromedriver/waterfall
 There are 4 test suites for verifying ChromeDriver's correctness:
 
 1) chromedriver2_unittests (chrome/chrome_tests.gypi)
@@ -88,15 +93,14 @@
 This is a collection of C++ medium sized tests which can be run optionally
 on the trybots.
 
-3) python tests
-These are integration tests which can be found in run_py_tests.py. They are
-run on the chromium QA bots:
-    http://build.chromium.org/p/chromium.pyauto/waterfall
+3) python integration tests
+Run test/run_py_tests.py --help for more info. These are only run on the
+ChromeDriver waterfall.
 
 4) WebDriver Java acceptance tests
 These are integration tests from the WebDriver open source project which can
-be run via run_java_tests.py. They are also run on the chromium QA bots.
-See http://src.chromium.org/viewvc/chrome/trunk/deps/third_party/webdriver
+be run via test/run_java_tests.py. They are only run on the ChromeDriver
+bots. Run with --help for more info.
 
 =====Contributing=====
 Find an open issue and submit a patch for review by an individual listed in
diff --git a/chrome/test/chromedriver/chrome/web_view_impl.cc b/chrome/test/chromedriver/chrome/web_view_impl.cc
index 9357bbe..b463b0e 100644
--- a/chrome/test/chromedriver/chrome/web_view_impl.cc
+++ b/chrome/test/chromedriver/chrome/web_view_impl.cc
@@ -173,8 +173,9 @@
                                  scoped_ptr<base::Value>* result) {
   std::string json;
   base::JSONWriter::Write(&args, &json);
+  // TODO(zachconrad): Second null should be array of shadow host ids.
   std::string expression = base::StringPrintf(
-      "(%s).apply(null, [%s, %s])",
+      "(%s).apply(null, [null, %s, %s])",
       kCallFunctionScript,
       function.c_str(),
       json.c_str());
@@ -595,8 +596,9 @@
                              int* node_id) {
   std::string json;
   base::JSONWriter::Write(&args, &json);
+  // TODO(zachconrad): Second null should be array of shadow host ids.
   std::string expression = base::StringPrintf(
-      "(%s).apply(null, [%s, %s, true])",
+      "(%s).apply(null, [null, %s, %s, true])",
       kCallFunctionScript,
       function.c_str(),
       json.c_str());
diff --git a/chrome/test/chromedriver/chrome_paths.py b/chrome/test/chromedriver/chrome_paths.py
index a0d3812..5b9c976 100644
--- a/chrome/test/chromedriver/chrome_paths.py
+++ b/chrome/test/chromedriver/chrome_paths.py
@@ -12,7 +12,8 @@
 
 def GetSrc():
   """Returns the path to the root src directory."""
-  return os.path.join(_THIS_DIR, os.pardir, os.pardir, os.pardir)
+  return os.path.abspath(os.path.join(_THIS_DIR, os.pardir, os.pardir,
+                                      os.pardir))
 
 
 def GetTestData():
diff --git a/chrome/test/chromedriver/js/call_function.js b/chrome/test/chromedriver/js/call_function.js
index f9b1d0a..7a194b8 100644
--- a/chrome/test/chromedriver/js/call_function.js
+++ b/chrome/test/chromedriver/js/call_function.js
@@ -28,6 +28,13 @@
 var ELEMENT_KEY = 'ELEMENT';
 
 /**
+ * True if shadow dom is enabled.
+ * @const
+ * @type {boolean}
+ */
+var SHADOW_DOM_ENABLED = typeof WebKitShadowRoot === 'function';
+
+/**
  * A cache which maps IDs <-> cached objects for the purpose of identifying
  * a script object remotely.
  * @constructor
@@ -79,18 +86,41 @@
   clearStale: function() {
     for (var id in this.cache_) {
       var node = this.cache_[id];
-      while (node) {
-        if (node == document)
-          break;
-        node = node.parentNode;
-      }
-      if (!node)
+      if (!this.isNodeReachable_(node))
         delete this.cache_[id];
     }
+  },
+
+  /**
+    * @private
+    * @param {!Node} node The node to check.
+    * @return {boolean} If the nodes is reachable.
+    */
+  isNodeReachable_: function(node) {
+    var nodeRoot = getNodeRoot(node);
+    if (nodeRoot == document)
+      return true;
+    else if (SHADOW_DOM_ENABLED && nodeRoot instanceof WebKitShadowRoot)
+      return true;
+
+    return false;
   }
 };
 
 /**
+ * Returns the root element of the node.  Found by traversing parentNodes until
+ * a node with no parent is found.  This node is considered the root.
+ * @param {!Node} node The node to find the root element for.
+ * @return {!Node} The root node.
+ */
+function getNodeRoot(node) {
+  while (node.parentNode) {
+    node = node.parentNode;
+  }
+  return node;
+}
+
+/**
  * Returns the global object cache for the page.
  * @param {Document=} opt_doc The document whose cache to retrieve. Defaults to
  *     the current document.
@@ -114,9 +144,11 @@
 function wrap(value) {
   if (typeof(value) == 'object' && value != null) {
     var nodeType = value['nodeType'];
-    if (nodeType == NodeType.ELEMENT || nodeType == NodeType.DOCUMENT) {
+    if (nodeType == NodeType.ELEMENT || nodeType == NodeType.DOCUMENT
+        || (SHADOW_DOM_ENABLED && value instanceof WebKitShadowRoot)) {
       var wrapped = {};
-      wrapped[ELEMENT_KEY] = getPageCache(value.ownerDocument).storeItem(value);
+      var root = getNodeRoot(value);
+      wrapped[ELEMENT_KEY] = getPageCache(root).storeItem(value);
       return wrapped;
     }
 
@@ -157,6 +189,8 @@
  * between cached object reference IDs and actual JS objects. The cache will
  * automatically be pruned each call to remove stale references.
  *
+ * @param  {Array.<string>} shadowHostIds The host ids of the nested shadow
+ *     DOMs the function should be executed in the context of.
  * @param {function(...[*]) : *} func The function to invoke.
  * @param {!Array.<*>} args The array of arguments to supply to the function,
  *     which will be unwrapped before invoking the function.
@@ -167,9 +201,18 @@
  *     unwrapped return was specified, this will be the function's pure return
  *     value.
  */
-function callFunction(func, args, opt_unwrappedReturn) {
+function callFunction(shadowHostIds, func, args, opt_unwrappedReturn) {
   var cache = getPageCache();
   cache.clearStale();
+  if (shadowHostIds && SHADOW_DOM_ENABLED) {
+    for (var i = 0; i < shadowHostIds.length; i++) {
+      var host = cache.retrieveItem(shadowHostIds[i]);
+      // TODO(zachconrad): Use the olderShadowRoot API when available to check
+      // all of the shadow roots.
+      cache = getPageCache(host.webkitShadowRoot);
+      cache.clearStale();
+    }
+  }
 
   if (opt_unwrappedReturn)
     return func.apply(null, unwrap(args, cache));
diff --git a/chrome/test/chromedriver/js/call_function_test.html b/chrome/test/chromedriver/js/call_function_test.html
index c11bc6c..7c0a2df 100644
--- a/chrome/test/chromedriver/js/call_function_test.html
+++ b/chrome/test/chromedriver/js/call_function_test.html
@@ -11,7 +11,7 @@
 function testCallFunctionNoArgs() {
   clearCache();
 
-  var result = callFunction(function() { return 1; }, []);
+  var result = callFunction(null, function() { return 1; }, []);
   assertEquals(0, result.status);
   assertEquals(1, result.value);
 }
@@ -19,11 +19,12 @@
 function testCallFunctionThrows() {
   clearCache();
 
-  var result = callFunction(function() { throw new Error('fake error'); }, []);
+  var result = callFunction(null, function() { throw new Error('fake error'); },
+      []);
   assertEquals(StatusCode.UNKNOWN_ERROR, result.status);
   assertEquals('fake error', result.value);
 
-  result = callFunction(function() {
+  result = callFunction(null, function() {
     var e = new Error('fake error');
     e.code = 77;
     e.message = 'CUSTOM';
@@ -39,7 +40,7 @@
   function func(primitive, elem) {
     return [primitive, elem.querySelector('div')];
   }
-  var result = callFunction(func, [1, wrap(document)]);
+  var result = callFunction(null, func, [1, wrap(document)]);
   assertEquals(0, result.status);
   assertEquals(1, result.value[0]);
   var cache = getPageCache();
@@ -52,7 +53,7 @@
   function func(elem) {
     return elem.querySelector('div');
   }
-  var result = callFunction(func, [wrap(document)], true);
+  var result = callFunction(null, func, [wrap(document)], true);
   assertEquals(document.querySelector('div'), result);
 }
 
@@ -76,7 +77,7 @@
   var cache = getPageCache();
   var arr = [1, new Array(1, new Object({a: 1, b: {a: 1, b: {}, c: 3}}), 3)];
   var originalJson = JSON.stringify(arr);
-  arr[1][1].b.b[ELEMENT_KEY] = cache.idPrefix_ + ':' + cache.nextId_;
+  arr[1][1].b.b[ELEMENT_KEY] = cache.idPrefix_ + '-' + cache.nextId_;
   var wrappedJson = JSON.stringify(arr);
   arr[1][1].b.b = document;
   assertEquals(wrappedJson, JSON.stringify(wrap(arr)));
@@ -159,6 +160,105 @@
   }
 }
 
+function testCallFunctionWithShadowHost() {
+  clearCache();
+
+  // Set up something in the shadow DOM.
+  var host = document.body.appendChild(document.createElement('div'));
+  var root = host.webkitCreateShadowRoot();
+  var shadowDiv = root.appendChild(document.createElement('div'));
+
+  function func(element) {
+    return element;
+  }
+  var wrappedHost = wrap(host);
+  
+  var result = callFunction(null, func, [wrappedHost]);
+  assertEquals(0, result.status);
+  assertEquals(wrappedHost['ELEMENT'], result.value['ELEMENT']);
+  var cache = getPageCache();
+  assertEquals(host, unwrap(result.value, cache));
+  
+  document.body.removeChild(host);
+}
+
+function testCallFunctionWithShadowRoot() {
+  clearCache();
+
+  // Set up something in the shadow DOM.
+  var host = document.body.appendChild(document.createElement('div'));
+  var root = host.webkitCreateShadowRoot();
+  var shadowDiv = root.appendChild(document.createElement('div'));
+
+  function func(element) {
+    return element;
+  }
+  var wrappedHost = wrap(host);
+  var wrappedRoot = wrap(root);
+  
+  // Trying without setting the shadow_path should fail.
+  var result = callFunction(null, func, [wrappedRoot]);
+  assertEquals(StatusCode.STALE_ELEMENT_REFERENCE, result.status);
+  // Should succeed with the shadow_path.
+  result = callFunction([wrappedHost['ELEMENT']], func, [wrappedRoot]);
+  assertEquals(0, result.status);
+  assertEquals(wrappedRoot['ELEMENT'], result.value['ELEMENT']);
+  var cache = getPageCache(root);
+  assertEquals(root, unwrap(result.value, cache));
+  
+  document.body.removeChild(host);
+}
+
+function testCacheWithShadowDomAttached() {
+  clearCache();
+  var pageCache = getPageCache();
+  
+  // Set up something in the shadow DOM.
+  var host = document.body.appendChild(document.createElement('div'));
+  var root = host.webkitCreateShadowRoot();
+  var shadowDiv = root.appendChild(document.createElement('div'));
+  
+  // Test with attached element in shadow DOM.
+  var wrappedDiv = wrap(shadowDiv);
+  // It should NOT be in the page cache.
+  try {
+    unwrap(wrappedDiv, pageCache);
+    assert(false);
+  } catch (e) {
+    assertEquals(StatusCode.STALE_ELEMENT_REFERENCE, e.code);
+  }
+  // It should be in the shadow root cache.
+  var rootCache = getPageCache(root);
+  rootCache.clearStale();
+  var unwrappedDiv = unwrap(wrappedDiv, rootCache);
+  assertEquals(shadowDiv, unwrappedDiv);
+  
+  document.body.removeChild(host);
+}
+
+function testCacheWithShadowDomDetachedChild() {
+  clearCache();
+
+  // Set up something in the shadow DOM.
+  var host = document.body.appendChild(document.createElement('div'));
+  var root = host.webkitCreateShadowRoot();
+  var shadowDiv = root.appendChild(document.createElement('div'));
+
+  // Test with detached element in shadow DOM.
+  var wrappedDiv = wrap(shadowDiv);
+  root.removeChild(shadowDiv);
+  var rootCache = getPageCache(root);
+  rootCache.clearStale();
+  try {
+    unwrap(wrappedDiv, rootCache);
+    assert(false);
+  } catch (e) {
+    assertEquals(StatusCode.STALE_ELEMENT_REFERENCE, e.code);
+  }
+  
+  document.body.removeChild(host);
+}
+
 </script>
 <body>
 <div><span></span></div>
diff --git a/chrome/test/chromedriver/run_buildbot_steps.py b/chrome/test/chromedriver/run_buildbot_steps.py
index fb43b1f..af4a10b 100755
--- a/chrome/test/chromedriver/run_buildbot_steps.py
+++ b/chrome/test/chromedriver/run_buildbot_steps.py
@@ -202,7 +202,7 @@
 
   cmd = [
       sys.executable,
-      os.path.join(_THIS_DIR, 'run_all_tests.py'),
+      os.path.join(_THIS_DIR, 'test', 'run_all_tests.py'),
   ]
   if options.android_package:
     cmd.append('--android-package=' + options.android_package)
diff --git a/chrome/test/chromedriver/java_tests.txt b/chrome/test/chromedriver/test/java_tests.txt
similarity index 100%
rename from chrome/test/chromedriver/java_tests.txt
rename to chrome/test/chromedriver/test/java_tests.txt
diff --git a/chrome/test/chromedriver/run_all_tests.py b/chrome/test/chromedriver/test/run_all_tests.py
similarity index 96%
rename from chrome/test/chromedriver/run_all_tests.py
rename to chrome/test/chromedriver/test/run_all_tests.py
index 574fa92..7236c86 100755
--- a/chrome/test/chromedriver/run_all_tests.py
+++ b/chrome/test/chromedriver/test/run_all_tests.py
@@ -1,5 +1,5 @@
 #!/usr/bin/env python
-# Copyright (c) 2012 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.
 
@@ -10,12 +10,13 @@
 import platform
 import sys
 
+_THIS_DIR = os.path.abspath(os.path.dirname(__file__))
+sys.path.insert(0, os.path.join(_THIS_DIR, os.pardir))
+
 import archive
 import chrome_paths
 import util
 
-_THIS_DIR = os.path.abspath(os.path.dirname(__file__))
-
 
 def _AppendEnvironmentPath(env_name, path):
   if env_name in os.environ:
@@ -153,7 +154,8 @@
     _AddToolsToSystemPathForWindows()
 
   if options.android_package:
-    os.environ['PATH'] += os.pathsep + os.path.join(_THIS_DIR, 'chrome')
+    os.environ['PATH'] += os.pathsep + os.path.join(
+        _THIS_DIR, os.pardir, 'chrome')
     code1 = RunPythonTests(chromedriver,
                            ref_chromedriver,
                            android_package=options.android_package)
diff --git a/chrome/test/chromedriver/run_java_tests.py b/chrome/test/chromedriver/test/run_java_tests.py
similarity index 93%
rename from chrome/test/chromedriver/run_java_tests.py
rename to chrome/test/chromedriver/test/run_java_tests.py
index 495e49b..76ecaf3 100755
--- a/chrome/test/chromedriver/run_java_tests.py
+++ b/chrome/test/chromedriver/test/run_java_tests.py
@@ -1,5 +1,5 @@
 #!/usr/bin/env python
-# Copyright (c) 2012 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.
 
@@ -17,6 +17,9 @@
 import sys
 import xml.dom.minidom as minidom
 
+_THIS_DIR = os.path.abspath(os.path.dirname(__file__))
+sys.path.insert(1, os.path.join(_THIS_DIR, os.pardir))
+
 import chrome_paths
 import test_environment
 import util
@@ -279,8 +282,14 @@
                                       'java_tests')
     if (not os.path.exists(java_tests_src_dir) or
         not os.listdir(java_tests_src_dir)):
-      print ('"%s" is empty or it doesn\'t exist.' % java_tests_src_dir +
-             'Should add deps/third_party/webdriver to source checkout config')
+      java_tests_url = ('http://src.chromium.org/svn/trunk/deps/third_party'
+                        '/webdriver')
+      print ('"%s" is empty or it doesn\'t exist. ' % java_tests_src_dir +
+             'Need to map <chrome-svn>/trunk/deps/third_party/webdriver to '
+             'chrome/test/chromedriver/third_party/java_tests in .gclient.\n'
+             'Alternatively, do:\n'
+             '  $ cd chrome/test/chromedriver/third_party\n'
+             '  $ svn co %s java_tests' % java_tests_url)
       return 1
 
     results = []
diff --git a/chrome/test/chromedriver/run_py_tests.py b/chrome/test/chromedriver/test/run_py_tests.py
similarity index 98%
rename from chrome/test/chromedriver/run_py_tests.py
rename to chrome/test/chromedriver/test/run_py_tests.py
index 35d6c9d..2a19c6c 100755
--- a/chrome/test/chromedriver/run_py_tests.py
+++ b/chrome/test/chromedriver/test/run_py_tests.py
@@ -1,5 +1,5 @@
 #!/usr/bin/env python
-# Copyright (c) 2012 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.
 
@@ -14,8 +14,9 @@
 import unittest
 
 _THIS_DIR = os.path.abspath(os.path.dirname(__file__))
-sys.path.insert(0, os.path.join(_THIS_DIR, 'client'))
-sys.path.insert(0, os.path.join(_THIS_DIR, 'server'))
+sys.path.insert(1, os.path.join(_THIS_DIR, os.pardir))
+sys.path.insert(1, os.path.join(_THIS_DIR, os.pardir, 'client'))
+sys.path.insert(1, os.path.join(_THIS_DIR, os.pardir, 'server'))
 
 import chrome_paths
 import chromedriver
@@ -25,11 +26,10 @@
 from webelement import WebElement
 import webserver
 
-_TEST_DATA_DIR = os.path.join(_THIS_DIR, os.pardir, 'data', 'chromedriver')
+_TEST_DATA_DIR = os.path.join(chrome_paths.GetTestData(), 'chromedriver')
 
 if util.IsLinux():
-  sys.path.insert(0, os.path.join(_THIS_DIR, os.pardir, os.pardir, os.pardir,
-                                  'build', 'android'))
+  sys.path.insert(0, os.path.join(chrome_paths.GetSrc(), 'build', 'android'))
   from pylib import android_commands
   from pylib import forwarder
   from pylib import valgrind_tools
diff --git a/chrome/test/chromedriver/test_environment.py b/chrome/test/chromedriver/test/test_environment.py
similarity index 93%
rename from chrome/test/chromedriver/test_environment.py
rename to chrome/test/chromedriver/test/test_environment.py
index 2344ad3..de8753b 100644
--- a/chrome/test/chromedriver/test_environment.py
+++ b/chrome/test/chromedriver/test/test_environment.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2012 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.
 
@@ -11,13 +11,13 @@
 import os
 import sys
 
+import chrome_paths
 import util
 
 _THIS_DIR = os.path.abspath(os.path.dirname(__file__))
 
 if util.IsLinux():
-  sys.path.insert(0, os.path.join(_THIS_DIR, os.pardir, os.pardir, os.pardir,
-                                  'build', 'android'))
+  sys.path.insert(0, os.path.join(chrome_paths.GetSrc(), 'build', 'android'))
   from pylib import android_commands
   from pylib import forwarder
   from pylib import valgrind_tools
diff --git a/chrome/test/chromedriver/test_expectations b/chrome/test/chromedriver/test/test_expectations
similarity index 99%
rename from chrome/test/chromedriver/test_expectations
rename to chrome/test/chromedriver/test/test_expectations
index 1e17ea2..b63c41e 100644
--- a/chrome/test/chromedriver/test_expectations
+++ b/chrome/test/chromedriver/test/test_expectations
@@ -1,4 +1,4 @@
-# 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.
 
diff --git a/chrome/test/chromedriver/unittest_util.py b/chrome/test/chromedriver/test/unittest_util.py
similarity index 98%
rename from chrome/test/chromedriver/unittest_util.py
rename to chrome/test/chromedriver/test/unittest_util.py
index 9de9805..7c07312 100644
--- a/chrome/test/chromedriver/unittest_util.py
+++ b/chrome/test/chromedriver/test/unittest_util.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2012 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.
 
diff --git a/chrome/test/chromedriver/webserver.py b/chrome/test/chromedriver/test/webserver.py
similarity index 98%
rename from chrome/test/chromedriver/webserver.py
rename to chrome/test/chromedriver/test/webserver.py
index 170a48d..fb48cc5 100644
--- a/chrome/test/chromedriver/webserver.py
+++ b/chrome/test/chromedriver/test/webserver.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2012 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.
 
diff --git a/chrome/test/nacl/nacl_browsertest.cc b/chrome/test/nacl/nacl_browsertest.cc
index e24b910..356d183 100644
--- a/chrome/test/nacl/nacl_browsertest.cc
+++ b/chrome/test/nacl/nacl_browsertest.cc
@@ -52,12 +52,12 @@
   RunLoadTest(FILE_PATH_LITERAL("nacl_load_test.html"));
 })
 
-IN_PROC_BROWSER_TEST_F(NaClBrowserTestPnaclWithNewCache,
+IN_PROC_BROWSER_TEST_F(NaClBrowserTestPnaclWithOldCache,
                        MAYBE_PNACL(SimpleLoad)) {
   RunLoadTest(FILE_PATH_LITERAL("nacl_load_test.html"));
 }
 
-IN_PROC_BROWSER_TEST_F(NaClBrowserTestPnaclWithNewCache,
+IN_PROC_BROWSER_TEST_F(NaClBrowserTestPnaclWithOldCache,
                        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 c1e5655..3cd7e35 100644
--- a/chrome/test/nacl/nacl_browsertest_util.cc
+++ b/chrome/test/nacl/nacl_browsertest_util.cc
@@ -203,7 +203,6 @@
 }
 
 void NaClBrowserTestBase::SetUpCommandLine(CommandLine* command_line) {
-  command_line->AppendSwitch(switches::kNoFirstRun);
   command_line->AppendSwitch(switches::kEnableNaCl);
 }
 
@@ -321,9 +320,9 @@
   command_line->AppendSwitch(switches::kDisablePnacl);
 }
 
-NaClBrowserTestPnaclWithNewCache::NaClBrowserTestPnaclWithNewCache() {
+NaClBrowserTestPnaclWithOldCache::NaClBrowserTestPnaclWithOldCache() {
   scoped_ptr<base::Environment> env(base::Environment::Create());
-  env->SetVar("PNACL_USE_NEW_CACHE", "true");
+  env->SetVar("PNACL_USE_OLD_CACHE", "true");
 }
 
 base::FilePath::StringType NaClBrowserTestStatic::Variant() {
diff --git a/chrome/test/nacl/nacl_browsertest_util.h b/chrome/test/nacl/nacl_browsertest_util.h
index ba58e93..5400acc 100644
--- a/chrome/test/nacl/nacl_browsertest_util.h
+++ b/chrome/test/nacl/nacl_browsertest_util.h
@@ -136,11 +136,11 @@
   virtual bool IsPnaclDisabled() OVERRIDE;
 };
 
-// Temporary class for running tests with the new cache enabled. Once all the
-// pieces land, this will go away and the new cache will be on by default.
-class NaClBrowserTestPnaclWithNewCache : public NaClBrowserTestPnacl {
+// Temporary class for running tests with the old cache enabled. Once all the
+// pieces are stable and the old code is gone, this will go away.
+class NaClBrowserTestPnaclWithOldCache : public NaClBrowserTestPnacl {
  public:
-  NaClBrowserTestPnaclWithNewCache();
+  NaClBrowserTestPnaclWithOldCache();
 };
 
 // A NaCl browser test only using static files.
diff --git a/chrome/test/nacl_test_injection/buildbot_nacl_integration.py b/chrome/test/nacl_test_injection/buildbot_nacl_integration.py
index a23de63..4df51b3 100755
--- a/chrome/test/nacl_test_injection/buildbot_nacl_integration.py
+++ b/chrome/test/nacl_test_injection/buildbot_nacl_integration.py
@@ -9,10 +9,6 @@
 
 
 def Main(args):
-  if sys.platform == 'darwin':
-    print >> sys.stderr, "SKIPPING NACL INTEGRATION DUE TO BUG #261724."
-    return 0
-
   pwd = os.environ.get('PWD', '')
   is_integration_bot = 'nacl-chrome' in pwd
 
diff --git a/chrome/test/ppapi/ppapi_test.cc b/chrome/test/ppapi/ppapi_test.cc
index 5973877..1c912a1 100644
--- a/chrome/test/ppapi/ppapi_test.cc
+++ b/chrome/test/ppapi/ppapi_test.cc
@@ -36,7 +36,6 @@
 #include "net/base/test_data_directory.h"
 #include "ppapi/shared_impl/ppapi_switches.h"
 #include "ui/gl/gl_switches.h"
-#include "webkit/plugins/plugin_switches.h"
 
 #if defined(OS_WIN) && defined(USE_ASH)
 #include "base/win/windows_version.h"
diff --git a/chrome/tools/build/generate_policy_source.py b/chrome/tools/build/generate_policy_source.py
index 8998700..d88374d 100755
--- a/chrome/tools/build/generate_policy_source.py
+++ b/chrome/tools/build/generate_policy_source.py
@@ -11,6 +11,7 @@
 template is the path to a .json policy template file.'''
 
 from __future__ import with_statement
+import json
 from optparse import OptionParser
 import re
 import sys
@@ -55,25 +56,32 @@
 
     if is_chromium_os:
       expected_platform = 'chrome_os'
-      wildcard_platform = None
-    elif os == 'android':
-      expected_platform = 'android'
-      wildcard_platform = None
     else:
-      expected_platform = 'chrome.' + os.lower()
-      wildcard_platform = 'chrome.*'
-    is_supported = False
+      expected_platform = os.lower()
+
+    self.platforms = []
     for platform, version in [ p.split(':') for p in policy['supported_on'] ]:
-      if (platform == expected_platform or platform == wildcard_platform) and \
-          version.endswith('-'):
-        is_supported = True
-    self.is_supported = is_supported
+      if not version.endswith('-'):
+        continue
+
+      if platform.startswith('chrome.'):
+        platform_sub = platform[7:]
+        if platform_sub == '*':
+          self.platforms.extend(['win', 'mac', 'linux'])
+        else:
+          self.platforms.append(platform_sub)
+      else:
+        self.platforms.append(platform)
+
+    self.platforms.sort()
+    self.is_supported = expected_platform in self.platforms
 
     if not PolicyDetails.TYPE_MAP.has_key(policy['type']):
       raise NotImplementedError('Unknown policy type for %s: %s' %
                                 (policy['name'], policy['type']))
     self.policy_type, self.protobuf_type, self.policy_protobuf_type = \
         PolicyDetails.TYPE_MAP[policy['type']]
+    self.schema = policy['schema']
 
     self.desc = '\n'.join(
         map(str.strip,
@@ -397,6 +405,11 @@
     _OutputComment(f, '\nValid values:')
     for item in policy.items:
       _OutputComment(f, '  %s: %s' % (str(item.value), item.caption))
+  if policy.policy_type == 'TYPE_DICTIONARY':
+    _OutputComment(f, '\nValue schema:\n%s' %
+                   json.dumps(policy.schema, sort_keys=True, indent=4,
+                              separators=(',', ': ')))
+  _OutputComment(f, '\nSupported on: %s' % ', '.join(policy.platforms))
   f.write('message %sProto {\n' % policy.name)
   f.write('  optional PolicyOptions policy_options = 1;\n')
   f.write('  optional %s %s = 2;\n' % (policy.protobuf_type, policy.name))
diff --git a/chrome/tools/build/win/FILES.cfg b/chrome/tools/build/win/FILES.cfg
index b893451..4fba1cd 100644
--- a/chrome/tools/build/win/FILES.cfg
+++ b/chrome/tools/build/win/FILES.cfg
@@ -339,6 +339,7 @@
   # ANGLE files:
   {
     'filename': 'D3DCompiler_43.dll',
+    'arch': ['32bit'],
     'buildtype': ['dev', 'official'],
   },
   {
@@ -364,11 +365,9 @@
     'buildtype': ['dev', 'official'],
     'filegroup': ['default', 'symsrc'],
   },
-  # Windows Chrome does not have separate x86-32 and x86-64 installs.
-  # A single install supports both x86-32 and x86-64 versions of NaCl,
-  # so the 'arch' field does not seem to make much sense in this case.
   {
     'filename': 'nacl_irt_x86_32.nexe',
+    'arch': ['32bit'],
     'buildtype': ['dev', 'official'],
   },
   {
@@ -768,6 +767,7 @@
   },
   {
     'filename': 'nacl_irt_x86_32.nexe.debug',
+    'arch': ['32bit'],
     'buildtype': ['official'],
     'archive': 'chrome-win32-nacl-irt-syms.zip',
   },
diff --git a/chrome/utility/DEPS b/chrome/utility/DEPS
index deea898..c2b5436 100644
--- a/chrome/utility/DEPS
+++ b/chrome/utility/DEPS
@@ -1,10 +1,10 @@
 include_rules = [
   "+content/public/child",
   "+content/public/utility",
-  "+webkit/glue",
 
   # For generated headers.
   "+grit",
 
   "+skia/ext",
+  "+media",
 ]
diff --git a/chrome/utility/chrome_content_utility_client.cc b/chrome/utility/chrome_content_utility_client.cc
index 7b1ecca..0976190 100644
--- a/chrome/utility/chrome_content_utility_client.cc
+++ b/chrome/utility/chrome_content_utility_client.cc
@@ -7,22 +7,27 @@
 #include "base/base64.h"
 #include "base/bind.h"
 #include "base/command_line.h"
+#include "base/files/file_path.h"
 #include "base/json/json_reader.h"
 #include "base/memory/ref_counted.h"
 #include "base/memory/scoped_ptr.h"
+#include "base/path_service.h"
+#include "base/time/time.h"
 #include "chrome/common/chrome_utility_messages.h"
-#include "chrome/common/extensions/chrome_manifest_handlers.h"
+#include "chrome/common/extensions/chrome_extensions_client.h"
 #include "chrome/common/extensions/extension.h"
 #include "chrome/common/extensions/extension_l10n_util.h"
 #include "chrome/common/extensions/manifest.h"
-#include "chrome/common/extensions/permissions/chrome_api_permissions.h"
 #include "chrome/common/extensions/update_manifest.h"
 #include "chrome/common/safe_browsing/zip_analyzer.h"
 #include "chrome/utility/extensions/unpacker.h"
 #include "chrome/utility/profile_import_handler.h"
 #include "chrome/utility/web_resource_unpacker.h"
 #include "content/public/child/image_decoder_utils.h"
+#include "content/public/common/content_paths.h"
 #include "content/public/utility/utility_thread.h"
+#include "media/base/media.h"
+#include "media/base/media_file_checker.h"
 #include "printing/page_range.h"
 #include "third_party/skia/include/core/SkBitmap.h"
 #include "third_party/zlib/google/zip.h"
@@ -124,6 +129,10 @@
     IPC_MESSAGE_HANDLER(ChromeUtilityMsg_AnalyzeZipFileForDownloadProtection,
                         OnAnalyzeZipFileForDownloadProtection)
 
+#if !defined(OS_ANDROID) && !defined(OS_IOS)
+    IPC_MESSAGE_HANDLER(ChromeUtilityMsg_CheckMediaFile, OnCheckMediaFile)
+#endif  // !defined(OS_ANDROID) && !defined(OS_IOS)
+
 #if defined(OS_CHROMEOS)
     IPC_MESSAGE_HANDLER(ChromeUtilityMsg_CreateZipFile, OnCreateZipFile)
 #endif  // defined(OS_CHROMEOS)
@@ -151,10 +160,17 @@
   return handled;
 }
 
+// static
 void ChromeContentUtilityClient::PreSandboxStartup() {
 #if defined(ENABLE_MDNS)
   local_discovery::ServiceDiscoveryMessageHandler::PreSandboxStartup();
 #endif  // ENABLE_MDNS
+
+  // Load media libraries for media file validation.
+  base::FilePath media_path;
+  PathService::Get(content::DIR_MEDIA_LIBS, &media_path);
+  if (!media_path.empty())
+    media::InitializeMediaLibrary(media_path);
 }
 
 void ChromeContentUtilityClient::OnUnpackExtension(
@@ -164,9 +180,8 @@
     int creation_flags) {
   CHECK_GT(location, extensions::Manifest::INVALID_LOCATION);
   CHECK_LT(location, extensions::Manifest::NUM_LOCATIONS);
-  extensions::PermissionsInfo::GetInstance()->InitializeWithDelegate(
-      extensions::ChromeAPIPermissions());
-  extensions::RegisterChromeManifestHandlers();
+  extensions::ExtensionsClient::Set(
+      extensions::ChromeExtensionsClient::GetInstance());
   extensions::Unpacker unpacker(
       extension_path,
       extension_id,
@@ -505,7 +520,7 @@
 }
 
 void ChromeContentUtilityClient::OnAnalyzeZipFileForDownloadProtection(
-    IPC::PlatformFileForTransit zip_file) {
+    const IPC::PlatformFileForTransit& zip_file) {
   safe_browsing::zip_analyzer::Results results;
   safe_browsing::zip_analyzer::AnalyzeZipFile(
       IPC::PlatformFileForTransitToPlatformFile(zip_file), &results);
@@ -514,6 +529,19 @@
   ReleaseProcessIfNeeded();
 }
 
+#if !defined(OS_ANDROID) && !defined(OS_IOS)
+void ChromeContentUtilityClient::OnCheckMediaFile(
+    int64 milliseconds_of_decoding,
+    const IPC::PlatformFileForTransit& media_file) {
+  media::MediaFileChecker
+      checker(IPC::PlatformFileForTransitToPlatformFile(media_file));
+  const bool check_success = checker.Start(
+      base::TimeDelta::FromMilliseconds(milliseconds_of_decoding));
+  Send(new ChromeUtilityHostMsg_CheckMediaFile_Finished(check_success));
+  ReleaseProcessIfNeeded();
+}
+#endif  // !defined(OS_ANDROID) && !defined(OS_IOS)
+
 #if defined(OS_WIN)
 void ChromeContentUtilityClient::OnParseITunesPrefXml(
     const std::string& itunes_xml_data) {
@@ -526,7 +554,7 @@
 
 #if defined(OS_WIN) || defined(OS_MACOSX)
 void ChromeContentUtilityClient::OnParseITunesLibraryXmlFile(
-    IPC::PlatformFileForTransit itunes_library_file) {
+    const IPC::PlatformFileForTransit& itunes_library_file) {
   itunes::ITunesLibraryParser parser;
   base::PlatformFile file =
       IPC::PlatformFileForTransitToPlatformFile(itunes_library_file);
diff --git a/chrome/utility/chrome_content_utility_client.h b/chrome/utility/chrome_content_utility_client.h
index 419c155..4f8187e 100644
--- a/chrome/utility/chrome_content_utility_client.h
+++ b/chrome/utility/chrome_content_utility_client.h
@@ -81,7 +81,11 @@
   void OnGetPrinterCapsAndDefaults(const std::string& printer_name);
   void OnStartupPing();
   void OnAnalyzeZipFileForDownloadProtection(
-      IPC::PlatformFileForTransit zip_file);
+      const IPC::PlatformFileForTransit& zip_file);
+#if !defined(OS_ANDROID) && !defined(OS_IOS)
+  void OnCheckMediaFile(int64 milliseconds_of_decoding,
+                        const IPC::PlatformFileForTransit& media_file);
+#endif  // !defined(OS_ANDROID) && !defined(OS_IOS)
 
 #if defined(OS_WIN)
   void OnParseITunesPrefXml(const std::string& itunes_xml_data);
@@ -89,7 +93,7 @@
 
 #if defined(OS_WIN) || defined(OS_MACOSX)
   void OnParseITunesLibraryXmlFile(
-      IPC::PlatformFileForTransit itunes_library_file);
+      const IPC::PlatformFileForTransit& itunes_library_file);
 
   void OnParsePicasaPMPDatabase(
       const picasa::AlbumTableFilesForTransit& album_table_files);
diff --git a/chromeos/CHROMEOS_LKGM b/chromeos/CHROMEOS_LKGM
index 80e13f6..728cc40 100644
--- a/chromeos/CHROMEOS_LKGM
+++ b/chromeos/CHROMEOS_LKGM
@@ -1 +1 @@
-4509.0.0
\ No newline at end of file
+4521.0.0
\ No newline at end of file
diff --git a/chromeos/chromeos.gyp b/chromeos/chromeos.gyp
index 32691f1..69d2a67 100644
--- a/chromeos/chromeos.gyp
+++ b/chromeos/chromeos.gyp
@@ -17,6 +17,7 @@
       'dependencies': [
         '../base/base.gyp:base',
         '../base/base.gyp:base_prefs',
+        '../crypto/crypto.gyp:crypto',
         '../base/third_party/dynamic_annotations/dynamic_annotations.gyp:dynamic_annotations',
         '../build/linux/system.gyp:dbus',
         '../build/linux/system.gyp:ssl',
@@ -84,6 +85,8 @@
         'dbus/cros_disks_client.h',
         'dbus/cryptohome_client.cc',
         'dbus/cryptohome_client.h',
+        'dbus/cryptohome_client_stub.cc',
+        'dbus/cryptohome_client_stub.h',
         'dbus/dbus_client_implementation_type.h',
         'dbus/dbus_method_call_status.h',
         'dbus/dbus_thread_manager.cc',
diff --git a/chromeos/chromeos_switches.cc b/chromeos/chromeos_switches.cc
index 26c3752..8577279 100644
--- a/chromeos/chromeos_switches.cc
+++ b/chromeos/chromeos_switches.cc
@@ -82,10 +82,6 @@
 const char kEnableChromeCaptivePortalDetector[] =
     "enable-chrome-captive-portal-detector";
 
-// Disables the new NetworkChangeNotifier which uses NetworkStateHandler.
-const char kDisableNewNetworkChangeNotifier[] =
-    "disable-new-network-change-notifier";
-
 // Enables screensaver extensions.
 const char kEnableScreensaverExtensions[] = "enable-screensaver-extensions";
 
@@ -124,8 +120,9 @@
 const char kFileManagerEnableWebstoreIntegration[] =
     "file-manager-enable-webstore-integration";
 
-// Passed to Chrome on first boot. Not passed on restart after sign out.
-const char kFirstBoot[]                     = "first-boot";
+// Passed to Chrome the first time that it's run after the system boots.
+// Not passed on restart after sign out.
+const char kFirstExecAfterBoot[]            = "first-exec-after-boot";
 
 // Usually in browser tests the usual login manager bringup is skipped so that
 // tests can change how it's brought up. This flag disables that.
@@ -192,8 +189,5 @@
 const char kUseNewNetworkConfigurationHandlers[] =
     "use-new-network-configuration-handlers";
 
-const char kUseNewNetworkConnectionHandler[] =
-    "use-new-network-connection-handler";
-
 }  // namespace switches
 }  // namespace chromeos
diff --git a/chromeos/chromeos_switches.h b/chromeos/chromeos_switches.h
index 76a66bc..2281d03 100644
--- a/chromeos/chromeos_switches.h
+++ b/chromeos/chromeos_switches.h
@@ -31,7 +31,6 @@
 CHROMEOS_EXPORT extern const char kDisableLocalAccounts[];
 CHROMEOS_EXPORT extern const char kDisableLoginAnimations[];
 CHROMEOS_EXPORT extern const char kDisableNewChannelSwitcherUI[];
-CHROMEOS_EXPORT extern const char kDisableNewNetworkChangeNotifier[];
 CHROMEOS_EXPORT extern const char kDisableOOBEBlockingUpdate[];
 CHROMEOS_EXPORT extern const char kDisableOnlineEULA[];
 CHROMEOS_EXPORT extern const char kDisableOobeAnimation[];
@@ -52,7 +51,7 @@
 CHROMEOS_EXPORT extern const char kEnterpriseEnrollmentModulusLimit[];
 CHROMEOS_EXPORT extern const char kFileManagerShowCheckboxes[];
 CHROMEOS_EXPORT extern const char kFileManagerEnableWebstoreIntegration[];
-CHROMEOS_EXPORT extern const char kFirstBoot[];
+CHROMEOS_EXPORT extern const char kFirstExecAfterBoot[];
 CHROMEOS_EXPORT extern const char kForceLoginManagerInTests[];
 CHROMEOS_EXPORT extern const char kGuestSession[];
 CHROMEOS_EXPORT extern const char kHasChromeOSDiamondKey[];
@@ -71,7 +70,6 @@
 CHROMEOS_EXPORT extern const char kSmsTestMessages[];
 CHROMEOS_EXPORT extern const char kStubCrosSettings[];
 CHROMEOS_EXPORT extern const char kUseNewNetworkConfigurationHandlers[];
-CHROMEOS_EXPORT extern const char kUseNewNetworkConnectionHandler[];
 
 }  // namespace switches
 }  // namespace chromeos
diff --git a/chromeos/dbus/cryptohome_client.cc b/chromeos/dbus/cryptohome_client.cc
index 6ba9834..445ba0b 100644
--- a/chromeos/dbus/cryptohome_client.cc
+++ b/chromeos/dbus/cryptohome_client.cc
@@ -5,9 +5,12 @@
 #include "chromeos/dbus/cryptohome_client.h"
 
 #include "base/bind.h"
+#include "base/location.h"
+#include "base/memory/weak_ptr.h"
 #include "base/message_loop/message_loop.h"
 #include "chromeos/cryptohome/async_method_caller.h"
 #include "chromeos/dbus/blocking_method_caller.h"
+#include "chromeos/dbus/cryptohome_client_stub.h"
 #include "dbus/bus.h"
 #include "dbus/message.h"
 #include "dbus/object_path.h"
@@ -838,425 +841,6 @@
   DISALLOW_COPY_AND_ASSIGN(CryptohomeClientImpl);
 };
 
-// A stub implementaion of CryptohomeClient.
-class CryptohomeClientStubImpl : public CryptohomeClient {
- public:
-  CryptohomeClientStubImpl()
-      : async_call_id_(1),
-        tpm_is_ready_counter_(0),
-        locked_(false),
-        weak_ptr_factory_(this) {
-  }
-
-  virtual ~CryptohomeClientStubImpl() {}
-
-  // CryptohomeClient override.
-  virtual void SetAsyncCallStatusHandlers(
-      const AsyncCallStatusHandler& handler,
-      const AsyncCallStatusWithDataHandler& data_handler) OVERRIDE {
-    async_call_status_handler_ = handler;
-    async_call_status_data_handler_ = data_handler;
-  }
-
-  // CryptohomeClient override.
-  virtual void ResetAsyncCallStatusHandlers() OVERRIDE {
-    async_call_status_handler_.Reset();
-    async_call_status_data_handler_.Reset();
-  }
-
-  // CryptohomeClient override.
-  virtual void IsMounted(const BoolDBusMethodCallback& callback) OVERRIDE {
-    base::MessageLoop::current()->PostTask(
-        FROM_HERE, base::Bind(callback, DBUS_METHOD_CALL_SUCCESS, true));
-  }
-
-  // CryptohomeClient override.
-  virtual bool Unmount(bool* success) OVERRIDE {
-    *success = true;
-    return true;
-  }
-
-  // CryptohomeClient override.
-  virtual void AsyncCheckKey(const std::string& username,
-                             const std::string& key,
-                             const AsyncMethodCallback& callback) OVERRIDE {
-    ReturnAsyncMethodResult(callback, false);
-  }
-
-  // CryptohomeClient override.
-  virtual void AsyncMigrateKey(const std::string& username,
-                               const std::string& from_key,
-                               const std::string& to_key,
-                               const AsyncMethodCallback& callback) OVERRIDE {
-    ReturnAsyncMethodResult(callback, false);
-  }
-
-  // CryptohomeClient override.
-  virtual void AsyncRemove(const std::string& username,
-                           const AsyncMethodCallback& callback) OVERRIDE {
-    ReturnAsyncMethodResult(callback, false);
-  }
-
-  // CryptohomeClient override.
-  virtual bool GetSystemSalt(std::vector<uint8>* salt) OVERRIDE {
-    const char kStubSystemSalt[] = "stub_system_salt";
-    salt->assign(kStubSystemSalt,
-                 kStubSystemSalt + arraysize(kStubSystemSalt) - 1);
-    return true;
-  }
-
-  // CryptohomeClient override.
-  virtual void GetSanitizedUsername(
-      const std::string& username,
-      const StringDBusMethodCallback& callback) OVERRIDE {
-    // Even for stub implementation we have to return different values
-    // so that multi-profiles would work.
-    std::string sanitized_username = GetStubSanitizedUsername(username);
-    base::MessageLoop::current()->PostTask(
-        FROM_HERE,
-        base::Bind(callback, DBUS_METHOD_CALL_SUCCESS, sanitized_username));
-  }
-
-  // CryptohomeClient override.
-  virtual std::string BlockingGetSanitizedUsername(
-      const std::string& username) OVERRIDE {
-    return GetStubSanitizedUsername(username);
-  }
-
-  // CryptohomeClient override.
-  virtual void AsyncMount(const std::string& username,
-                          const std::string& key,
-                          int flags,
-                          const AsyncMethodCallback& callback) OVERRIDE {
-    ReturnAsyncMethodResult(callback, false);
-  }
-
-  // CryptohomeClient override.
-  virtual void AsyncAddKey(const std::string& username,
-                           const std::string& key,
-                           const std::string& new_key,
-                           const AsyncMethodCallback& callback) OVERRIDE {
-    ReturnAsyncMethodResult(callback, false);
-  }
-
-  // CryptohomeClient override.
-  virtual void AsyncMountGuest(const AsyncMethodCallback& callback) OVERRIDE {
-    ReturnAsyncMethodResult(callback, false);
-  }
-
-  // CryptohomeClient override.
-  virtual void AsyncMountPublic(const std::string& public_mount_id,
-                                int flags,
-                                const AsyncMethodCallback& callback) OVERRIDE {
-    ReturnAsyncMethodResult(callback, false);
-  }
-
-  // CryptohomeClient override.
-  virtual void TpmIsReady(const BoolDBusMethodCallback& callback) OVERRIDE {
-    base::MessageLoop::current()->PostTask(
-        FROM_HERE, base::Bind(callback, DBUS_METHOD_CALL_SUCCESS, true));
-  }
-
-  // CryptohomeClient override.
-  virtual void TpmIsEnabled(const BoolDBusMethodCallback& callback) OVERRIDE {
-    base::MessageLoop::current()->PostTask(
-        FROM_HERE, base::Bind(callback, DBUS_METHOD_CALL_SUCCESS, true));
-  }
-
-  // CryptohomeClient override.
-  virtual bool CallTpmIsEnabledAndBlock(bool* enabled) OVERRIDE {
-    *enabled = true;
-    return true;
-  }
-
-  // CryptohomeClient override.
-  virtual void TpmGetPassword(
-      const StringDBusMethodCallback& callback) OVERRIDE {
-    const char kStubTpmPassword[] = "Stub-TPM-password";
-    base::MessageLoop::current()->PostTask(
-        FROM_HERE,
-        base::Bind(callback, DBUS_METHOD_CALL_SUCCESS, kStubTpmPassword));
-  }
-
-  // CryptohomeClient override.
-  virtual void TpmIsOwned(const BoolDBusMethodCallback& callback) OVERRIDE {
-    base::MessageLoop::current()->PostTask(
-        FROM_HERE, base::Bind(callback, DBUS_METHOD_CALL_SUCCESS, true));
-  }
-
-  // CryptohomeClient override.
-  virtual bool CallTpmIsOwnedAndBlock(bool* owned) OVERRIDE {
-    *owned = true;
-    return true;
-  }
-
-  // CryptohomeClient override.
-  virtual void TpmIsBeingOwned(const BoolDBusMethodCallback& callback)
-      OVERRIDE {
-    base::MessageLoop::current()->PostTask(
-        FROM_HERE, base::Bind(callback, DBUS_METHOD_CALL_SUCCESS, true));
-  }
-
-  // CryptohomeClient override.
-  virtual bool CallTpmIsBeingOwnedAndBlock(bool* owning) OVERRIDE {
-    *owning = true;
-    return true;
-  }
-
-  // CryptohomeClient override.
-  virtual void TpmCanAttemptOwnership(
-      const VoidDBusMethodCallback& callback) OVERRIDE {
-    base::MessageLoop::current()->PostTask(
-        FROM_HERE, base::Bind(callback, DBUS_METHOD_CALL_SUCCESS));
-  }
-
-  // CryptohomeClient override.
-  virtual void TpmClearStoredPassword(const VoidDBusMethodCallback& callback)
-      OVERRIDE {
-    base::MessageLoop::current()->PostTask(
-        FROM_HERE, base::Bind(callback, DBUS_METHOD_CALL_SUCCESS));
-  }
-
-  // CryptohomeClient override.
-  virtual bool CallTpmClearStoredPasswordAndBlock() OVERRIDE { return true; }
-
-  // CryptohomeClient override.
-  virtual void Pkcs11IsTpmTokenReady(
-      const BoolDBusMethodCallback& callback) OVERRIDE {
-    base::MessageLoop::current()->PostTask(
-        FROM_HERE, base::Bind(callback, DBUS_METHOD_CALL_SUCCESS, true));
-  }
-
-  // CryptohomeClient override.
-  virtual void Pkcs11GetTpmTokenInfo(
-      const Pkcs11GetTpmTokenInfoCallback& callback) OVERRIDE {
-    const char kStubLabel[] = "Stub TPM Token";
-    const char kStubUserPin[] = "012345";
-    base::MessageLoop::current()->PostTask(
-        FROM_HERE,
-        base::Bind(callback,
-                   DBUS_METHOD_CALL_SUCCESS,
-                   std::string(kStubLabel),
-                   std::string(kStubUserPin)));
-  }
-
-  // CryptohomeClient override.
-  virtual bool InstallAttributesGet(const std::string& name,
-                                    std::vector<uint8>* value,
-                                    bool* successful) OVERRIDE {
-    if (install_attrs_.find(name) != install_attrs_.end()) {
-      *value = install_attrs_[name];
-      *successful = true;
-    } else {
-      value->clear();
-      *successful = false;
-    }
-    return true;
-  }
-
-  // CryptohomeClient override.
-  virtual bool InstallAttributesSet(const std::string& name,
-                                    const std::vector<uint8>& value,
-                                    bool* successful) OVERRIDE {
-    install_attrs_[name] = value;
-    *successful = true;
-    return true;
-  }
-
-  // CryptohomeClient override.
-  virtual bool InstallAttributesFinalize(bool* successful) OVERRIDE {
-    locked_ = true;
-    *successful = true;
-    return true;
-  }
-
-  // CryptohomeClient override.
-  virtual void InstallAttributesIsReady(const BoolDBusMethodCallback& callback)
-      OVERRIDE {
-    base::MessageLoop::current()->PostTask(
-        FROM_HERE, base::Bind(callback, DBUS_METHOD_CALL_SUCCESS, true));
-  }
-
-  // CryptohomeClient override.
-  virtual bool InstallAttributesIsInvalid(bool* is_invalid) OVERRIDE {
-    *is_invalid = false;
-    return true;
-  }
-
-  // CryptohomeClient override.
-  virtual bool InstallAttributesIsFirstInstall(
-      bool* is_first_install) OVERRIDE {
-    *is_first_install = !locked_;
-    return true;
-  }
-
-  // CryptohomeClient override.
-  virtual void TpmAttestationIsPrepared(
-        const BoolDBusMethodCallback& callback) OVERRIDE {
-    base::MessageLoop::current()->PostTask(
-        FROM_HERE, base::Bind(callback, DBUS_METHOD_CALL_SUCCESS, true));
-  }
-
-  // CryptohomeClient override.
-  virtual void TpmAttestationIsEnrolled(
-        const BoolDBusMethodCallback& callback) OVERRIDE {
-    base::MessageLoop::current()->PostTask(
-        FROM_HERE, base::Bind(callback, DBUS_METHOD_CALL_SUCCESS, true));
-  }
-
-  // CryptohomeClient override.
-  virtual void AsyncTpmAttestationCreateEnrollRequest(
-      const AsyncMethodCallback& callback) OVERRIDE {
-    ReturnAsyncMethodResult(callback, true);
-  }
-
-  // CryptohomeClient override.
-  virtual void AsyncTpmAttestationEnroll(
-      const std::string& pca_response,
-      const AsyncMethodCallback& callback) OVERRIDE {
-    ReturnAsyncMethodResult(callback, false);
-  }
-
-  // CryptohomeClient override.
-  virtual void AsyncTpmAttestationCreateCertRequest(
-      int options,
-      const AsyncMethodCallback& callback) OVERRIDE {
-    ReturnAsyncMethodResult(callback, true);
-  }
-
-  // CryptohomeClient override.
-  virtual void AsyncTpmAttestationFinishCertRequest(
-      const std::string& pca_response,
-      attestation::AttestationKeyType key_type,
-      const std::string& key_name,
-      const AsyncMethodCallback& callback) OVERRIDE {
-    ReturnAsyncMethodResult(callback, true);
-  }
-
-  // CryptohomeClient override.
-  virtual void TpmAttestationDoesKeyExist(
-      attestation::AttestationKeyType key_type,
-      const std::string& key_name,
-      const BoolDBusMethodCallback& callback) OVERRIDE {
-    base::MessageLoop::current()->PostTask(
-        FROM_HERE,
-        base::Bind(callback, DBUS_METHOD_CALL_SUCCESS, false));
-  }
-
-  // CryptohomeClient override.
-  virtual void TpmAttestationGetCertificate(
-      attestation::AttestationKeyType key_type,
-      const std::string& key_name,
-      const DataMethodCallback& callback) OVERRIDE {
-    base::MessageLoop::current()->PostTask(
-        FROM_HERE,
-        base::Bind(callback, DBUS_METHOD_CALL_SUCCESS, false, std::string()));
-  }
-
-  // CryptohomeClient override.
-  virtual void TpmAttestationGetPublicKey(
-      attestation::AttestationKeyType key_type,
-      const std::string& key_name,
-      const DataMethodCallback& callback) OVERRIDE {
-    base::MessageLoop::current()->PostTask(
-        FROM_HERE,
-        base::Bind(callback, DBUS_METHOD_CALL_SUCCESS, false, std::string()));
-  }
-
-  // CryptohomeClient override.
-  virtual void TpmAttestationRegisterKey(
-      attestation::AttestationKeyType key_type,
-      const std::string& key_name,
-      const AsyncMethodCallback& callback) OVERRIDE {
-    ReturnAsyncMethodResult(callback, true);
-  }
-
-  // CryptohomeClient override.
-  virtual void TpmAttestationSignEnterpriseChallenge(
-      attestation::AttestationKeyType key_type,
-      const std::string& key_name,
-      const std::string& domain,
-      const std::string& device_id,
-      attestation::AttestationChallengeOptions options,
-      const std::string& challenge,
-      const AsyncMethodCallback& callback) OVERRIDE {
-    ReturnAsyncMethodResult(callback, true);
-  }
-
-  // CryptohomeClient override.
-  virtual void TpmAttestationSignSimpleChallenge(
-      attestation::AttestationKeyType key_type,
-      const std::string& key_name,
-      const std::string& challenge,
-      const AsyncMethodCallback& callback) OVERRIDE {
-    ReturnAsyncMethodResult(callback, true);
-  }
-
-  virtual void TpmAttestationGetKeyPayload(
-      attestation::AttestationKeyType key_type,
-      const std::string& key_name,
-      const DataMethodCallback& callback) OVERRIDE {
-    base::MessageLoop::current()->PostTask(
-        FROM_HERE,
-        base::Bind(callback, DBUS_METHOD_CALL_SUCCESS, false, std::string()));
-  }
-
-  virtual void TpmAttestationSetKeyPayload(
-      attestation::AttestationKeyType key_type,
-      const std::string& key_name,
-      const std::string& payload,
-      const BoolDBusMethodCallback& callback) OVERRIDE {
-    base::MessageLoop::current()->PostTask(
-        FROM_HERE,
-        base::Bind(callback, DBUS_METHOD_CALL_SUCCESS, false));
-  }
-
-
- private:
-  // Posts tasks which return fake results to the UI thread.
-  void ReturnAsyncMethodResult(const AsyncMethodCallback& callback,
-                               bool returns_data) {
-    base::MessageLoop::current()->PostTask(
-        FROM_HERE,
-        base::Bind(&CryptohomeClientStubImpl::ReturnAsyncMethodResultInternal,
-                   weak_ptr_factory_.GetWeakPtr(),
-                   callback,
-                   returns_data));
-  }
-
-  // This method is used to implement ReturnAsyncMethodResult.
-  void ReturnAsyncMethodResultInternal(const AsyncMethodCallback& callback,
-                                       bool returns_data) {
-    callback.Run(async_call_id_);
-    if (!returns_data && !async_call_status_handler_.is_null()) {
-      base::MessageLoop::current()->PostTask(
-          FROM_HERE,
-          base::Bind(async_call_status_handler_,
-                     async_call_id_,
-                     true,
-                     cryptohome::MOUNT_ERROR_NONE));
-    } else if (returns_data && !async_call_status_data_handler_.is_null()) {
-      base::MessageLoop::current()->PostTask(
-          FROM_HERE,
-          base::Bind(async_call_status_data_handler_,
-                     async_call_id_,
-                     true,
-                     std::string()));
-    }
-    ++async_call_id_;
-  }
-
-  int async_call_id_;
-  AsyncCallStatusHandler async_call_status_handler_;
-  AsyncCallStatusWithDataHandler async_call_status_data_handler_;
-  int tpm_is_ready_counter_;
-  std::map<std::string, std::vector<uint8> > install_attrs_;
-  bool locked_;
-  base::WeakPtrFactory<CryptohomeClientStubImpl> weak_ptr_factory_;
-
-  DISALLOW_COPY_AND_ASSIGN(CryptohomeClientStubImpl);
-};
-
 }  // namespace
 
 ////////////////////////////////////////////////////////////////////////////////
diff --git a/chromeos/dbus/cryptohome_client_stub.cc b/chromeos/dbus/cryptohome_client_stub.cc
new file mode 100644
index 0000000..e9faeec
--- /dev/null
+++ b/chromeos/dbus/cryptohome_client_stub.cc
@@ -0,0 +1,381 @@
+// 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 "chromeos/dbus/cryptohome_client_stub.h"
+
+#include "base/bind.h"
+#include "base/location.h"
+#include "base/message_loop/message_loop.h"
+#include "third_party/cros_system_api/dbus/service_constants.h"
+
+namespace chromeos {
+
+CryptohomeClientStubImpl::CryptohomeClientStubImpl()
+    : async_call_id_(1),
+      tpm_is_ready_counter_(0),
+      locked_(false),
+      weak_ptr_factory_(this) {}
+
+CryptohomeClientStubImpl::~CryptohomeClientStubImpl() {}
+
+void CryptohomeClientStubImpl::SetAsyncCallStatusHandlers(
+    const AsyncCallStatusHandler& handler,
+    const AsyncCallStatusWithDataHandler& data_handler) {
+  async_call_status_handler_ = handler;
+  async_call_status_data_handler_ = data_handler;
+}
+
+void CryptohomeClientStubImpl::ResetAsyncCallStatusHandlers() {
+  async_call_status_handler_.Reset();
+  async_call_status_data_handler_.Reset();
+}
+
+void CryptohomeClientStubImpl::IsMounted(
+    const BoolDBusMethodCallback& callback) {
+  base::MessageLoop::current()->PostTask(
+      FROM_HERE, base::Bind(callback, DBUS_METHOD_CALL_SUCCESS, true));
+}
+
+bool CryptohomeClientStubImpl::Unmount(bool* success) {
+  *success = true;
+  return true;
+}
+
+void CryptohomeClientStubImpl::AsyncCheckKey(
+    const std::string& username,
+    const std::string& key,
+    const AsyncMethodCallback& callback) {
+  ReturnAsyncMethodResult(callback, false);
+}
+
+void CryptohomeClientStubImpl::AsyncMigrateKey(
+    const std::string& username,
+    const std::string& from_key,
+    const std::string& to_key,
+    const AsyncMethodCallback& callback) {
+  ReturnAsyncMethodResult(callback, false);
+}
+
+void CryptohomeClientStubImpl::AsyncRemove(
+    const std::string& username,
+    const AsyncMethodCallback& callback) {
+  ReturnAsyncMethodResult(callback, false);
+}
+
+bool CryptohomeClientStubImpl::GetSystemSalt(std::vector<uint8>* salt) {
+  const char kStubSystemSalt[] = "stub_system_salt";
+  salt->assign(kStubSystemSalt,
+               kStubSystemSalt + arraysize(kStubSystemSalt) - 1);
+  return true;
+}
+
+void CryptohomeClientStubImpl::GetSanitizedUsername(
+    const std::string& username,
+    const StringDBusMethodCallback& callback) {
+  // Even for stub implementation we have to return different values so that
+  // multi-profiles would work.
+  std::string sanitized_username = GetStubSanitizedUsername(username);
+  base::MessageLoop::current()->PostTask(
+      FROM_HERE,
+      base::Bind(callback, DBUS_METHOD_CALL_SUCCESS, sanitized_username));
+}
+
+std::string CryptohomeClientStubImpl::BlockingGetSanitizedUsername(
+    const std::string& username) {
+  return GetStubSanitizedUsername(username);
+}
+
+void CryptohomeClientStubImpl::AsyncMount(const std::string& username,
+                                          const std::string& key,
+                                          int flags,
+                                          const AsyncMethodCallback& callback) {
+  ReturnAsyncMethodResult(callback, false);
+}
+
+void CryptohomeClientStubImpl::AsyncAddKey(
+    const std::string& username,
+    const std::string& key,
+    const std::string& new_key,
+    const AsyncMethodCallback& callback) {
+  ReturnAsyncMethodResult(callback, false);
+}
+
+void CryptohomeClientStubImpl::AsyncMountGuest(
+    const AsyncMethodCallback& callback) {
+  ReturnAsyncMethodResult(callback, false);
+}
+
+void CryptohomeClientStubImpl::AsyncMountPublic(
+    const std::string& public_mount_id,
+    int flags,
+    const AsyncMethodCallback& callback) {
+  ReturnAsyncMethodResult(callback, false);
+}
+
+void CryptohomeClientStubImpl::TpmIsReady(
+    const BoolDBusMethodCallback& callback) {
+  base::MessageLoop::current()->PostTask(
+      FROM_HERE, base::Bind(callback, DBUS_METHOD_CALL_SUCCESS, true));
+}
+
+void CryptohomeClientStubImpl::TpmIsEnabled(
+    const BoolDBusMethodCallback& callback) {
+  base::MessageLoop::current()->PostTask(
+      FROM_HERE, base::Bind(callback, DBUS_METHOD_CALL_SUCCESS, true));
+}
+
+bool CryptohomeClientStubImpl::CallTpmIsEnabledAndBlock(bool* enabled) {
+  *enabled = true;
+  return true;
+}
+
+void CryptohomeClientStubImpl::TpmGetPassword(
+    const StringDBusMethodCallback& callback) {
+  const char kStubTpmPassword[] = "Stub-TPM-password";
+  base::MessageLoop::current()->PostTask(
+      FROM_HERE,
+      base::Bind(callback, DBUS_METHOD_CALL_SUCCESS, kStubTpmPassword));
+}
+
+void CryptohomeClientStubImpl::TpmIsOwned(
+    const BoolDBusMethodCallback& callback) {
+  base::MessageLoop::current()->PostTask(
+      FROM_HERE, base::Bind(callback, DBUS_METHOD_CALL_SUCCESS, true));
+}
+
+bool CryptohomeClientStubImpl::CallTpmIsOwnedAndBlock(bool* owned) {
+  *owned = true;
+  return true;
+}
+
+void CryptohomeClientStubImpl::TpmIsBeingOwned(
+    const BoolDBusMethodCallback& callback) {
+  base::MessageLoop::current()->PostTask(
+      FROM_HERE, base::Bind(callback, DBUS_METHOD_CALL_SUCCESS, true));
+}
+
+bool CryptohomeClientStubImpl::CallTpmIsBeingOwnedAndBlock(bool* owning) {
+  *owning = true;
+  return true;
+}
+
+void CryptohomeClientStubImpl::TpmCanAttemptOwnership(
+    const VoidDBusMethodCallback& callback) {
+  base::MessageLoop::current()->PostTask(
+      FROM_HERE, base::Bind(callback, DBUS_METHOD_CALL_SUCCESS));
+}
+
+void CryptohomeClientStubImpl::TpmClearStoredPassword(
+    const VoidDBusMethodCallback& callback) {
+  base::MessageLoop::current()->PostTask(
+      FROM_HERE, base::Bind(callback, DBUS_METHOD_CALL_SUCCESS));
+}
+
+bool CryptohomeClientStubImpl::CallTpmClearStoredPasswordAndBlock() {
+  return true;
+}
+
+void CryptohomeClientStubImpl::Pkcs11IsTpmTokenReady(
+    const BoolDBusMethodCallback& callback) {
+  base::MessageLoop::current()->PostTask(
+      FROM_HERE, base::Bind(callback, DBUS_METHOD_CALL_SUCCESS, true));
+}
+
+void CryptohomeClientStubImpl::Pkcs11GetTpmTokenInfo(
+    const Pkcs11GetTpmTokenInfoCallback& callback) {
+  const char kStubLabel[] = "Stub TPM Token";
+  const char kStubUserPin[] = "012345";
+  base::MessageLoop::current()->PostTask(FROM_HERE,
+                                         base::Bind(callback,
+                                                    DBUS_METHOD_CALL_SUCCESS,
+                                                    std::string(kStubLabel),
+                                                    std::string(kStubUserPin)));
+}
+
+bool CryptohomeClientStubImpl::InstallAttributesGet(const std::string& name,
+                                                    std::vector<uint8>* value,
+                                                    bool* successful) {
+  if (install_attrs_.find(name) != install_attrs_.end()) {
+    *value = install_attrs_[name];
+    *successful = true;
+  } else {
+    value->clear();
+    *successful = false;
+  }
+  return true;
+}
+
+bool CryptohomeClientStubImpl::InstallAttributesSet(
+    const std::string& name,
+    const std::vector<uint8>& value,
+    bool* successful) {
+  install_attrs_[name] = value;
+  *successful = true;
+  return true;
+}
+
+bool CryptohomeClientStubImpl::InstallAttributesFinalize(bool* successful) {
+  locked_ = true;
+  *successful = true;
+  return true;
+}
+
+void CryptohomeClientStubImpl::InstallAttributesIsReady(
+    const BoolDBusMethodCallback& callback) {
+  base::MessageLoop::current()->PostTask(
+      FROM_HERE, base::Bind(callback, DBUS_METHOD_CALL_SUCCESS, true));
+}
+
+bool CryptohomeClientStubImpl::InstallAttributesIsInvalid(bool* is_invalid) {
+  *is_invalid = false;
+  return true;
+}
+
+bool CryptohomeClientStubImpl::InstallAttributesIsFirstInstall(
+    bool* is_first_install) {
+  *is_first_install = !locked_;
+  return true;
+}
+
+void CryptohomeClientStubImpl::TpmAttestationIsPrepared(
+    const BoolDBusMethodCallback& callback) {
+  base::MessageLoop::current()->PostTask(
+      FROM_HERE, base::Bind(callback, DBUS_METHOD_CALL_SUCCESS, true));
+}
+
+void CryptohomeClientStubImpl::TpmAttestationIsEnrolled(
+    const BoolDBusMethodCallback& callback) {
+  base::MessageLoop::current()->PostTask(
+      FROM_HERE, base::Bind(callback, DBUS_METHOD_CALL_SUCCESS, true));
+}
+
+void CryptohomeClientStubImpl::AsyncTpmAttestationCreateEnrollRequest(
+    const AsyncMethodCallback& callback) {
+  ReturnAsyncMethodResult(callback, true);
+}
+
+void CryptohomeClientStubImpl::AsyncTpmAttestationEnroll(
+    const std::string& pca_response,
+    const AsyncMethodCallback& callback) {
+  ReturnAsyncMethodResult(callback, false);
+}
+
+void CryptohomeClientStubImpl::AsyncTpmAttestationCreateCertRequest(
+    int options,
+    const AsyncMethodCallback& callback) {
+  ReturnAsyncMethodResult(callback, true);
+}
+
+void CryptohomeClientStubImpl::AsyncTpmAttestationFinishCertRequest(
+    const std::string& pca_response,
+    attestation::AttestationKeyType key_type,
+    const std::string& key_name,
+    const AsyncMethodCallback& callback) {
+  ReturnAsyncMethodResult(callback, true);
+}
+
+void CryptohomeClientStubImpl::TpmAttestationDoesKeyExist(
+    attestation::AttestationKeyType key_type,
+    const std::string& key_name,
+    const BoolDBusMethodCallback& callback) {
+  base::MessageLoop::current()->PostTask(
+      FROM_HERE, base::Bind(callback, DBUS_METHOD_CALL_SUCCESS, false));
+}
+
+void CryptohomeClientStubImpl::TpmAttestationGetCertificate(
+    attestation::AttestationKeyType key_type,
+    const std::string& key_name,
+    const DataMethodCallback& callback) {
+  base::MessageLoop::current()->PostTask(
+      FROM_HERE,
+      base::Bind(callback, DBUS_METHOD_CALL_SUCCESS, false, std::string()));
+}
+
+void CryptohomeClientStubImpl::TpmAttestationGetPublicKey(
+    attestation::AttestationKeyType key_type,
+    const std::string& key_name,
+    const DataMethodCallback& callback) {
+  base::MessageLoop::current()->PostTask(
+      FROM_HERE,
+      base::Bind(callback, DBUS_METHOD_CALL_SUCCESS, false, std::string()));
+}
+
+void CryptohomeClientStubImpl::TpmAttestationRegisterKey(
+    attestation::AttestationKeyType key_type,
+    const std::string& key_name,
+    const AsyncMethodCallback& callback) {
+  ReturnAsyncMethodResult(callback, true);
+}
+
+void CryptohomeClientStubImpl::TpmAttestationSignEnterpriseChallenge(
+    attestation::AttestationKeyType key_type,
+    const std::string& key_name,
+    const std::string& domain,
+    const std::string& device_id,
+    attestation::AttestationChallengeOptions options,
+    const std::string& challenge,
+    const AsyncMethodCallback& callback) {
+  ReturnAsyncMethodResult(callback, true);
+}
+
+void CryptohomeClientStubImpl::TpmAttestationSignSimpleChallenge(
+    attestation::AttestationKeyType key_type,
+    const std::string& key_name,
+    const std::string& challenge,
+    const AsyncMethodCallback& callback) {
+  ReturnAsyncMethodResult(callback, true);
+}
+
+void CryptohomeClientStubImpl::TpmAttestationGetKeyPayload(
+    attestation::AttestationKeyType key_type,
+    const std::string& key_name,
+    const DataMethodCallback& callback) {
+  base::MessageLoop::current()->PostTask(
+      FROM_HERE,
+      base::Bind(callback, DBUS_METHOD_CALL_SUCCESS, false, std::string()));
+}
+
+void CryptohomeClientStubImpl::TpmAttestationSetKeyPayload(
+    attestation::AttestationKeyType key_type,
+    const std::string& key_name,
+    const std::string& payload,
+    const BoolDBusMethodCallback& callback) {
+  base::MessageLoop::current()->PostTask(
+      FROM_HERE, base::Bind(callback, DBUS_METHOD_CALL_SUCCESS, false));
+}
+
+void CryptohomeClientStubImpl::ReturnAsyncMethodResult(
+    const AsyncMethodCallback& callback,
+    bool returns_data) {
+  base::MessageLoop::current()->PostTask(
+      FROM_HERE,
+      base::Bind(&CryptohomeClientStubImpl::ReturnAsyncMethodResultInternal,
+                 weak_ptr_factory_.GetWeakPtr(),
+                 callback,
+                 returns_data));
+}
+
+void CryptohomeClientStubImpl::ReturnAsyncMethodResultInternal(
+    const AsyncMethodCallback& callback,
+    bool returns_data) {
+  callback.Run(async_call_id_);
+  if (!returns_data && !async_call_status_handler_.is_null()) {
+    base::MessageLoop::current()->PostTask(
+        FROM_HERE,
+        base::Bind(async_call_status_handler_,
+                   async_call_id_,
+                   true,
+                   cryptohome::MOUNT_ERROR_NONE));
+  } else if (returns_data && !async_call_status_data_handler_.is_null()) {
+    base::MessageLoop::current()->PostTask(
+        FROM_HERE,
+        base::Bind(async_call_status_data_handler_,
+                   async_call_id_,
+                   true,
+                   std::string()));
+  }
+  ++async_call_id_;
+}
+
+}  // namespace chromeos
diff --git a/chromeos/dbus/cryptohome_client_stub.h b/chromeos/dbus/cryptohome_client_stub.h
new file mode 100644
index 0000000..e38925a
--- /dev/null
+++ b/chromeos/dbus/cryptohome_client_stub.h
@@ -0,0 +1,164 @@
+// 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 CHROMEOS_DBUS_CRYPTOHOME_CLIENT_STUB_H_
+#define CHROMEOS_DBUS_CRYPTOHOME_CLIENT_STUB_H_
+
+#include <map>
+
+#include "base/basictypes.h"
+#include "base/memory/weak_ptr.h"
+#include "chromeos/dbus/cryptohome_client.h"
+
+namespace chromeos {
+
+class CryptohomeClientStubImpl : public CryptohomeClient {
+ public:
+  CryptohomeClientStubImpl();
+  virtual ~CryptohomeClientStubImpl();
+
+  virtual void SetAsyncCallStatusHandlers(
+      const AsyncCallStatusHandler& handler,
+      const AsyncCallStatusWithDataHandler& data_handler) OVERRIDE;
+  virtual void ResetAsyncCallStatusHandlers() OVERRIDE;
+  virtual void IsMounted(const BoolDBusMethodCallback& callback) OVERRIDE;
+  virtual bool Unmount(bool* success) OVERRIDE;
+  virtual void AsyncCheckKey(const std::string& username,
+                             const std::string& key,
+                             const AsyncMethodCallback& callback) OVERRIDE;
+  virtual void AsyncMigrateKey(const std::string& username,
+                               const std::string& from_key,
+                               const std::string& to_key,
+                               const AsyncMethodCallback& callback) OVERRIDE;
+  virtual void AsyncRemove(const std::string& username,
+                           const AsyncMethodCallback& callback) OVERRIDE;
+  virtual bool GetSystemSalt(std::vector<uint8>* salt) OVERRIDE;
+  virtual void GetSanitizedUsername(
+      const std::string& username,
+      const StringDBusMethodCallback& callback) OVERRIDE;
+  virtual std::string BlockingGetSanitizedUsername(
+      const std::string& username) OVERRIDE;
+  virtual void AsyncMount(const std::string& username,
+                          const std::string& key,
+                          int flags,
+                          const AsyncMethodCallback& callback) OVERRIDE;
+  virtual void AsyncAddKey(const std::string& username,
+                           const std::string& key,
+                           const std::string& new_key,
+                           const AsyncMethodCallback& callback) OVERRIDE;
+  virtual void AsyncMountGuest(const AsyncMethodCallback& callback) OVERRIDE;
+  virtual void AsyncMountPublic(const std::string& public_mount_id,
+                                int flags,
+                                const AsyncMethodCallback& callback) OVERRIDE;
+  virtual void TpmIsReady(const BoolDBusMethodCallback& callback) OVERRIDE;
+  virtual void TpmIsEnabled(const BoolDBusMethodCallback& callback) OVERRIDE;
+  virtual bool CallTpmIsEnabledAndBlock(bool* enabled) OVERRIDE;
+  virtual void TpmGetPassword(
+      const StringDBusMethodCallback& callback) OVERRIDE;
+  virtual void TpmIsOwned(const BoolDBusMethodCallback& callback) OVERRIDE;
+  virtual bool CallTpmIsOwnedAndBlock(bool* owned) OVERRIDE;
+  virtual void TpmIsBeingOwned(const BoolDBusMethodCallback& callback) OVERRIDE;
+  virtual bool CallTpmIsBeingOwnedAndBlock(bool* owning) OVERRIDE;
+  virtual void TpmCanAttemptOwnership(
+      const VoidDBusMethodCallback& callback) OVERRIDE;
+  virtual void TpmClearStoredPassword(
+      const VoidDBusMethodCallback& callback) OVERRIDE;
+  virtual bool CallTpmClearStoredPasswordAndBlock() OVERRIDE;
+  virtual void Pkcs11IsTpmTokenReady(
+      const BoolDBusMethodCallback& callback) OVERRIDE;
+  virtual void Pkcs11GetTpmTokenInfo(
+      const Pkcs11GetTpmTokenInfoCallback& callback) OVERRIDE;
+  virtual bool InstallAttributesGet(const std::string& name,
+                                    std::vector<uint8>* value,
+                                    bool* successful) OVERRIDE;
+  virtual bool InstallAttributesSet(const std::string& name,
+                                    const std::vector<uint8>& value,
+                                    bool* successful) OVERRIDE;
+  virtual bool InstallAttributesFinalize(bool* successful) OVERRIDE;
+  virtual void InstallAttributesIsReady(
+      const BoolDBusMethodCallback& callback) OVERRIDE;
+  virtual bool InstallAttributesIsInvalid(bool* is_invalid) OVERRIDE;
+  virtual bool InstallAttributesIsFirstInstall(bool* is_first_install) OVERRIDE;
+  virtual void TpmAttestationIsPrepared(
+      const BoolDBusMethodCallback& callback) OVERRIDE;
+  virtual void TpmAttestationIsEnrolled(
+      const BoolDBusMethodCallback& callback) OVERRIDE;
+  virtual void AsyncTpmAttestationCreateEnrollRequest(
+      const AsyncMethodCallback& callback) OVERRIDE;
+  virtual void AsyncTpmAttestationEnroll(
+      const std::string& pca_response,
+      const AsyncMethodCallback& callback) OVERRIDE;
+  virtual void AsyncTpmAttestationCreateCertRequest(
+      int options,
+      const AsyncMethodCallback& callback) OVERRIDE;
+  virtual void AsyncTpmAttestationFinishCertRequest(
+      const std::string& pca_response,
+      attestation::AttestationKeyType key_type,
+      const std::string& key_name,
+      const AsyncMethodCallback& callback) OVERRIDE;
+  virtual void TpmAttestationDoesKeyExist(
+      attestation::AttestationKeyType key_type,
+      const std::string& key_name,
+      const BoolDBusMethodCallback& callback) OVERRIDE;
+  virtual void TpmAttestationGetCertificate(
+      attestation::AttestationKeyType key_type,
+      const std::string& key_name,
+      const DataMethodCallback& callback) OVERRIDE;
+  virtual void TpmAttestationGetPublicKey(
+      attestation::AttestationKeyType key_type,
+      const std::string& key_name,
+      const DataMethodCallback& callback) OVERRIDE;
+  virtual void TpmAttestationRegisterKey(
+      attestation::AttestationKeyType key_type,
+      const std::string& key_name,
+      const AsyncMethodCallback& callback) OVERRIDE;
+  virtual void TpmAttestationSignEnterpriseChallenge(
+      attestation::AttestationKeyType key_type,
+      const std::string& key_name,
+      const std::string& domain,
+      const std::string& device_id,
+      attestation::AttestationChallengeOptions options,
+      const std::string& challenge,
+      const AsyncMethodCallback& callback) OVERRIDE;
+  virtual void TpmAttestationSignSimpleChallenge(
+      attestation::AttestationKeyType key_type,
+      const std::string& key_name,
+      const std::string& challenge,
+      const AsyncMethodCallback& callback) OVERRIDE;
+  virtual void TpmAttestationGetKeyPayload(
+      attestation::AttestationKeyType key_type,
+      const std::string& key_name,
+      const DataMethodCallback& callback) OVERRIDE;
+  virtual void TpmAttestationSetKeyPayload(
+      attestation::AttestationKeyType key_type,
+      const std::string& key_name,
+      const std::string& payload,
+      const BoolDBusMethodCallback& callback) OVERRIDE;
+
+ private:
+  // Posts tasks which return fake results to the UI thread.
+  void ReturnAsyncMethodResult(const AsyncMethodCallback& callback,
+                               bool returns_data);
+
+  // This method is used to implement ReturnAsyncMethodResult.
+  void ReturnAsyncMethodResultInternal(const AsyncMethodCallback& callback,
+                                       bool returns_data);
+
+  int async_call_id_;
+  AsyncCallStatusHandler async_call_status_handler_;
+  AsyncCallStatusWithDataHandler async_call_status_data_handler_;
+  int tpm_is_ready_counter_;
+
+  // A stub store for InstallAttributes, mapping an attribute name to the
+  // associated data blob. Used to implement InstallAttributesSet and -Get.
+  std::map<std::string, std::vector<uint8> > install_attrs_;
+  bool locked_;
+  base::WeakPtrFactory<CryptohomeClientStubImpl> weak_ptr_factory_;
+
+  DISALLOW_COPY_AND_ASSIGN(CryptohomeClientStubImpl);
+};
+
+}  // namespace chromeos
+
+#endif  // CHROMEOS_DBUS_CRYPTOHOME_CLIENT_STUB_H_
diff --git a/chromeos/dbus/debug_daemon_client.cc b/chromeos/dbus/debug_daemon_client.cc
index 50d5d4b..3efbe7d 100644
--- a/chromeos/dbus/debug_daemon_client.cc
+++ b/chromeos/dbus/debug_daemon_client.cc
@@ -269,6 +269,17 @@
                    callback));
   }
 
+  virtual void GetScrubbedLogs(const GetLogsCallback& callback) OVERRIDE {
+    dbus::MethodCall method_call(debugd::kDebugdInterface,
+                                 debugd::kGetFeedbackLogs);
+    debugdaemon_proxy_->CallMethod(
+        &method_call,
+        dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
+        base::Bind(&DebugDaemonClientImpl::OnGetAllLogs,
+                   weak_ptr_factory_.GetWeakPtr(),
+                   callback));
+  }
+
   virtual void GetAllLogs(const GetLogsCallback& callback)
       OVERRIDE {
     dbus::MethodCall method_call(debugd::kDebugdInterface,
@@ -653,12 +664,19 @@
                            const GetPerfDataCallback& callback) OVERRIDE {
     std::vector<uint8> data;
     base::MessageLoop::current()->PostTask(FROM_HERE,
-                                           base::Bind(callback, data));
+    base::Bind(callback, data));
+  }
+  virtual void GetScrubbedLogs(const GetLogsCallback& callback) OVERRIDE {
+    std::map<std::string, std::string> sample;
+    sample["Sample Scrubbed Log"] = "Your email address is xxxxxxxx";
+    base::MessageLoop::current()->PostTask(
+        FROM_HERE, base::Bind(callback, false, sample));
   }
   virtual void GetAllLogs(const GetLogsCallback& callback) OVERRIDE {
-    std::map<std::string, std::string> empty;
-    base::MessageLoop::current()->PostTask(FROM_HERE,
-                                           base::Bind(callback, false, empty));
+    std::map<std::string, std::string> sample;
+    sample["Sample Log"] = "Your email address is abc@abc.com";
+    base::MessageLoop::current()->PostTask(
+        FROM_HERE, base::Bind(callback, false, sample));
   }
   virtual void GetUserLogFiles(const GetLogsCallback& callback) OVERRIDE {
     std::map<std::string, std::string> user_logs;
diff --git a/chromeos/dbus/debug_daemon_client.h b/chromeos/dbus/debug_daemon_client.h
index 92652e3..7c09a78 100644
--- a/chromeos/dbus/debug_daemon_client.h
+++ b/chromeos/dbus/debug_daemon_client.h
@@ -95,11 +95,14 @@
   virtual void GetPerfData(uint32_t duration,
                            const GetPerfDataCallback& callback) = 0;
 
-  // Callback type for GetAllLogs() or GetUserLogFiles().
+  // Callback type for GetScrubbedLogs(), GetAllLogs() or GetUserLogFiles().
   typedef base::Callback<void(bool succeeded,
                               const std::map<std::string, std::string>& logs)>
       GetLogsCallback;
 
+  // Gets scrubbed logs from debugd.
+  virtual void GetScrubbedLogs(const GetLogsCallback& callback) = 0;
+
   // Gets all logs collected by debugd.
   virtual void GetAllLogs(const GetLogsCallback& callback) = 0;
 
diff --git a/chromeos/dbus/shill_service_client_stub.cc b/chromeos/dbus/shill_service_client_stub.cc
index 5060650..03d7b75 100644
--- a/chromeos/dbus/shill_service_client_stub.cc
+++ b/chromeos/dbus/shill_service_client_stub.cc
@@ -165,8 +165,9 @@
                                      const base::Closure& callback,
                                      const ErrorCallback& error_callback) {
   VLOG(1) << "ShillServiceClientStub::Connect: " << service_path.value();
-  base::Value* service;
-  if (!stub_services_.Get(service_path.value(), &service)) {
+  base::DictionaryValue* service_properties;
+  if (!stub_services_.GetDictionary(
+          service_path.value(), &service_properties)) {
     LOG(ERROR) << "Service not found: " << service_path.value();
     error_callback.Run("Error.InvalidService", "Invalid Service");
     return;
@@ -191,6 +192,11 @@
     delay = base::TimeDelta::FromSeconds(kConnectDelaySeconds);
   }
   base::StringValue online_value(flimflam::kStateOnline);
+  std::string passphrase;
+  service_properties->GetStringWithoutPathExpansion(
+      flimflam::kPassphraseProperty, &passphrase);
+  if (passphrase == "failure")
+    online_value = base::StringValue(flimflam::kStateFailure);
   base::MessageLoop::current()->PostDelayedTask(
       FROM_HERE,
       base::Bind(&ShillServiceClientStub::SetProperty,
@@ -202,6 +208,19 @@
                  error_callback),
       delay);
   callback.Run();
+  // On failure, also set the Error property.
+  if (passphrase == "failure") {
+    base::MessageLoop::current()->PostDelayedTask(
+        FROM_HERE,
+        base::Bind(&ShillServiceClientStub::SetProperty,
+                   weak_ptr_factory_.GetWeakPtr(),
+                   service_path,
+                   flimflam::kErrorProperty,
+                   base::StringValue(flimflam::kErrorBadPassphrase),
+                   base::Bind(&base::DoNothing),
+                   error_callback),
+        delay);
+  }
 }
 
 void ShillServiceClientStub::Disconnect(const dbus::ObjectPath& service_path,
diff --git a/chromeos/display/output_configurator.cc b/chromeos/display/output_configurator.cc
index c1d2b30..a8c1681 100644
--- a/chromeos/display/output_configurator.cc
+++ b/chromeos/display/output_configurator.cc
@@ -98,6 +98,12 @@
 
 }  // namespace
 
+OutputConfigurator::CoordinateTransformation::CoordinateTransformation()
+    : x_scale(1.0),
+      x_offset(0.0),
+      y_scale(1.0),
+      y_offset(0.0) {}
+
 OutputConfigurator::OutputSnapshot::OutputSnapshot()
     : output(None),
       crtc(None),
@@ -105,37 +111,14 @@
       native_mode(None),
       mirror_mode(None),
       selected_mode(None),
+      x(0),
       y(0),
-      height(0),
       is_internal(false),
       is_aspect_preserving_scaling(false),
       touch_device_id(0),
       display_id(0),
       has_display_id(false) {}
 
-OutputConfigurator::CoordinateTransformation::CoordinateTransformation()
-  : x_scale(1.0),
-    x_offset(0.0),
-    y_scale(1.0),
-    y_offset(0.0) {}
-
-OutputConfigurator::CrtcConfig::CrtcConfig()
-    : crtc(None),
-      x(0),
-      y(0),
-      mode(None),
-      output(None) {}
-
-OutputConfigurator::CrtcConfig::CrtcConfig(RRCrtc crtc,
-                                           int x, int y,
-                                           RRMode mode,
-                                           RROutput output)
-    : crtc(crtc),
-      x(x),
-      y(y),
-      mode(mode),
-      output(output) {}
-
 bool OutputConfigurator::TestApi::SendOutputChangeEvents(bool connected) {
   XRRScreenChangeNotifyEvent screen_event;
   memset(&screen_event, 0, sizeof(screen_event));
@@ -418,7 +401,16 @@
   int num_on_outputs = GetOutputPower(outputs, power_state, &output_power);
   VLOG(1) << "EnterState: output=" << OutputStateToString(output_state)
           << " power=" << DisplayPowerStateToString(power_state);
+
+  // Framebuffer dimensions.
+  int width = 0, height = 0;
+  std::vector<OutputSnapshot> updated_outputs = outputs;
+
   switch (output_state) {
+    case STATE_INVALID:
+      NOTREACHED() << "Ignoring request to enter invalid state with "
+                   << outputs.size() << " connected output(s)";
+      return false;
     case STATE_HEADLESS:
       if (outputs.size() != 0) {
         LOG(WARNING) << "Ignoring request to enter headless mode with "
@@ -435,28 +427,16 @@
         return false;
       }
 
-      // Determine which output to use.
-      const OutputSnapshot& output = outputs.size() == 1 ? outputs[0] :
-          (output_power[0] ? outputs[0] : outputs[1]);
-      int width = 0, height = 0;
-      if (!delegate_->GetModeDetails(
-              output.selected_mode, &width, &height, NULL))
-        return false;
+      for (size_t i = 0; i < updated_outputs.size(); ++i) {
+        OutputSnapshot* output = &updated_outputs[i];
+        output->x = 0;
+        output->y = 0;
+        output->current_mode = output_power[i] ? output->selected_mode : None;
 
-      std::vector<CrtcConfig> configs(outputs.size());
-      for (size_t i = 0; i < outputs.size(); ++i) {
-        configs[i] = CrtcConfig(
-            outputs[i].crtc, 0, 0,
-            output_power[i] ? outputs[i].selected_mode : None,
-            outputs[i].output);
-      }
-      delegate_->CreateFrameBuffer(width, height, configs);
-
-      for (size_t i = 0; i < outputs.size(); ++i) {
-        delegate_->ConfigureCrtc(&configs[i]);
-        if (outputs[i].touch_device_id) {
-          delegate_->ConfigureCTM(outputs[i].touch_device_id,
-                                  CoordinateTransformation());
+        if (output_power[i] || outputs.size() == 1) {
+          if (!delegate_->GetModeDetails(
+                  output->selected_mode, &width, &height, NULL))
+            return false;
         }
       }
       break;
@@ -469,34 +449,24 @@
         return false;
       }
 
-      int width = 0, height = 0;
       if (!delegate_->GetModeDetails(
-              outputs[0].mirror_mode, &width, &height, NULL)) {
+              outputs[0].mirror_mode, &width, &height, NULL))
         return false;
-      }
-
-      std::vector<CrtcConfig> configs(outputs.size());
-      for (size_t i = 0; i < outputs.size(); ++i) {
-        configs[i] = CrtcConfig(
-            outputs[i].crtc, 0, 0,
-            output_power[i] ? outputs[i].mirror_mode : None,
-            outputs[i].output);
-      }
-      delegate_->CreateFrameBuffer(width, height, configs);
 
       for (size_t i = 0; i < outputs.size(); ++i) {
-        delegate_->ConfigureCrtc(&configs[i]);
-        if (outputs[i].touch_device_id) {
-          CoordinateTransformation ctm;
+        OutputSnapshot* output = &updated_outputs[i];
+        output->x = 0;
+        output->y = 0;
+        output->current_mode = output_power[i] ? output->mirror_mode : None;
+        if (output->touch_device_id) {
           // CTM needs to be calculated if aspect preserving scaling is used.
           // Otherwise, assume it is full screen, and use identity CTM.
-          if (outputs[i].mirror_mode != outputs[i].native_mode &&
-              outputs[i].is_aspect_preserving_scaling) {
-            ctm = GetMirrorModeCTM(&outputs[i]);
-            mirrored_display_area_ratio_map_[outputs[i].touch_device_id] =
-              GetMirroredDisplayAreaRatio(&outputs[i]);
+          if (output->mirror_mode != output->native_mode &&
+              output->is_aspect_preserving_scaling) {
+            output->transform = GetMirrorModeCTM(output);
+            mirrored_display_area_ratio_map_[output->touch_device_id] =
+                GetMirroredDisplayAreaRatio(output);
           }
-          delegate_->ConfigureCTM(outputs[i].touch_device_id, ctm);
         }
       }
       break;
@@ -511,8 +481,6 @@
 
       // Pairs are [width, height] corresponding to the given output's mode.
       std::vector<std::pair<int, int> > mode_sizes(outputs.size());
-      std::vector<CrtcConfig> configs(outputs.size());
-      int width = 0, height = 0;
 
       for (size_t i = 0; i < outputs.size(); ++i) {
         if (!delegate_->GetModeDetails(outputs[i].selected_mode,
@@ -520,10 +488,10 @@
           return false;
         }
 
-        configs[i] = CrtcConfig(
-            outputs[i].crtc, 0, (height ? height + kVerticalGap : 0),
-            output_power[i] ? outputs[i].selected_mode : None,
-            outputs[i].output);
+        OutputSnapshot* output = &updated_outputs[i];
+        output->x = 0;
+        output->y = height ? height + kVerticalGap : 0;
+        output->current_mode = output_power[i] ? output->selected_mode : None;
 
         // Retain the full screen size even if all outputs are off so the
         // same desktop configuration can be restored when the outputs are
@@ -532,29 +500,44 @@
         height += (height ? kVerticalGap : 0) + mode_sizes[i].second;
       }
 
-      delegate_->CreateFrameBuffer(width, height, configs);
-
       for (size_t i = 0; i < outputs.size(); ++i) {
-        delegate_->ConfigureCrtc(&configs[i]);
-        if (outputs[i].touch_device_id) {
-          CoordinateTransformation ctm;
-          ctm.x_scale = static_cast<float>(mode_sizes[i].first) / width;
-          ctm.x_offset = static_cast<float>(configs[i].x) / width;
-          ctm.y_scale = static_cast<float>(mode_sizes[i].second) / height;
-          ctm.y_offset = static_cast<float>(configs[i].y) / height;
-          delegate_->ConfigureCTM(outputs[i].touch_device_id, ctm);
+        OutputSnapshot* output = &updated_outputs[i];
+        if (output->touch_device_id) {
+          CoordinateTransformation* ctm = &(output->transform);
+          ctm->x_scale = static_cast<float>(mode_sizes[i].first) / width;
+          ctm->x_offset = static_cast<float>(output->x) / width;
+          ctm->y_scale = static_cast<float>(mode_sizes[i].second) / height;
+          ctm->y_offset = static_cast<float>(output->y) / height;
         }
       }
       break;
     }
-    default:
-      NOTREACHED() << "Got request to enter output state " << output_state
-                   << " with " << outputs.size() << " output(s)";
-      return false;
+  }
+
+  // Finally, apply the desired changes.
+  DCHECK_EQ(outputs.size(), updated_outputs.size());
+  if (!outputs.empty()) {
+    delegate_->CreateFrameBuffer(width, height, updated_outputs);
+    for (size_t i = 0; i < outputs.size(); ++i) {
+      const OutputSnapshot& output = updated_outputs[i];
+      if (delegate_->ConfigureCrtc(output.crtc, output.current_mode,
+                                   output.output, output.x, output.y)) {
+        if (output.touch_device_id)
+          delegate_->ConfigureCTM(output.touch_device_id, output.transform);
+      } else {
+        LOG(WARNING) << "Unable to configure CRTC " << output.crtc << ":"
+                     << " mode=" << output.current_mode
+                     << " output=" << output.output
+                     << " x=" << output.x
+                     << " y=" << output.y;
+        updated_outputs[i] = outputs[i];
+      }
+    }
   }
 
   output_state_ = output_state;
   power_state_ = power_state;
+  cached_outputs_ = updated_outputs;
   return true;
 }
 
diff --git a/chromeos/display/output_configurator.h b/chromeos/display/output_configurator.h
index a308a45..fbc7804 100644
--- a/chromeos/display/output_configurator.h
+++ b/chromeos/display/output_configurator.h
@@ -42,36 +42,6 @@
     : public base::MessageLoop::Dispatcher,
       public base::MessagePumpObserver {
  public:
-  // Information about an output's current state.
-  struct OutputSnapshot {
-    OutputSnapshot();
-
-    RROutput output;
-
-    // CRTC that should be used for this output.  Not necessarily the CRTC
-    // that XRandR reports is currently being used.
-    RRCrtc crtc;
-
-    RRMode current_mode;
-    RRMode native_mode;
-    RRMode mirror_mode;
-    RRMode selected_mode;
-
-    int y;
-    int height;
-
-    bool is_internal;
-    bool is_aspect_preserving_scaling;
-
-    // XInput device ID or 0 if this output isn't a touchscreen.
-    int touch_device_id;
-
-    // Display id for this output.
-    int64 display_id;
-
-    bool has_display_id;
-  };
-
   struct CoordinateTransformation {
     // Initialized to the identity transformation.
     CoordinateTransformation();
@@ -82,15 +52,44 @@
     float y_offset;
   };
 
-  struct CrtcConfig {
-    CrtcConfig();
-    CrtcConfig(RRCrtc crtc, int x, int y, RRMode mode, RROutput output);
+  // Information about an output's current state.
+  struct OutputSnapshot {
+    OutputSnapshot();
 
+    RROutput output;
+
+    // CRTC that should be used for this output. Not necessarily the CRTC
+    // that XRandR reports is currently being used.
     RRCrtc crtc;
+
+    // Mode currently being used by the output.
+    RRMode current_mode;
+
+    // "Best" mode supported by the output.
+    RRMode native_mode;
+
+    // Mode used when displaying the same desktop on multiple outputs.
+    RRMode mirror_mode;
+
+    // User-selected mode for the output.
+    RRMode selected_mode;
+
+    // Output's origin on the framebuffer.
     int x;
     int y;
-    RRMode mode;
-    RROutput output;
+
+    bool is_internal;
+    bool is_aspect_preserving_scaling;
+
+    // XInput device ID or 0 if this output isn't a touchscreen.
+    int touch_device_id;
+
+    CoordinateTransformation transform;
+
+    // Display id for this output.
+    int64 display_id;
+
+    bool has_display_id;
   };
 
   class Observer {
@@ -176,16 +175,20 @@
                                 int* height,
                                 bool* interlaced) = 0;
 
-    // Calls XRRSetCrtcConfig() with the given options but some of our
-    // default output count and rotation arguments.
-    virtual void ConfigureCrtc(CrtcConfig* config) = 0;
+    // Calls XRRSetCrtcConfig() with the given options but some of our default
+    // output count and rotation arguments. Returns true on success.
+    virtual bool ConfigureCrtc(RRCrtc crtc,
+                               RRMode mode,
+                               RROutput output,
+                               int x,
+                               int y) = 0;
 
     // Called to set the frame buffer (underlying XRR "screen") size.  Has
     // a side-effect of disabling all CRTCs.
     virtual void CreateFrameBuffer(
         int width,
         int height,
-        const std::vector<OutputConfigurator::CrtcConfig>& configs) = 0;
+        const std::vector<OutputConfigurator::OutputSnapshot>& outputs) = 0;
 
     // Configures XInput's Coordinate Transformation Matrix property.
     // |touch_device_id| the ID of the touchscreen device to configure.
@@ -325,15 +328,17 @@
   // Switches to the state specified in |output_state| and |power_state|.
   // If the hardware mirroring failed and |mirroring_controller_| is set,
   // it switches to |STATE_DUAL_EXTENDED| and calls |SetSoftwareMirroring()|
-  // to enable software based mirroing.
-  // On success, updates |output_state_| and |power_state_| and returns true.
+  // to enable software based mirroring.
+  // On success, updates |output_state_|, |power_state_|, and |cached_outputs_|
+  // and returns true.
   bool EnterStateOrFallBackToSoftwareMirroring(
       OutputState output_state,
       DisplayPowerState power_state,
       const std::vector<OutputSnapshot>& outputs);
 
   // Switches to the state specified in |output_state| and |power_state|.
-  // On success, updates |output_state_| and |power_state_| and returns true.
+  // On success, updates |output_state_|, |power_state_|, and
+  // |cached_outputs_| and returns true.
   bool EnterState(OutputState output_state,
                   DisplayPowerState power_state,
                   const std::vector<OutputSnapshot>& outputs);
@@ -383,6 +388,10 @@
   // The current power state.
   DisplayPowerState power_state_;
 
+  // Most-recently-used output configuration. Note that the actual
+  // configuration changes asynchronously.
+  std::vector<OutputSnapshot> cached_outputs_;
+
   ObserverList<Observer> observers_;
 
   // The timer to delay configuring outputs. See also the comments in
diff --git a/chromeos/display/output_configurator_unittest.cc b/chromeos/display/output_configurator_unittest.cc
index 246a436..96386f5 100644
--- a/chromeos/display/output_configurator_unittest.cc
+++ b/chromeos/display/output_configurator_unittest.cc
@@ -148,19 +148,23 @@
       *interlaced = it->second.interlaced;
     return true;
   }
-  virtual void ConfigureCrtc(OutputConfigurator::CrtcConfig* config) OVERRIDE {
-    AppendAction(GetCrtcAction(config->crtc, config->x, config->y, config->mode,
-                               config->output));
+  virtual bool ConfigureCrtc(RRCrtc crtc,
+                             RRMode mode,
+                             RROutput output,
+                             int x,
+                             int y) OVERRIDE {
+    AppendAction(GetCrtcAction(crtc, x, y, mode, output));
+    return true;
   }
   virtual void CreateFrameBuffer(
       int width,
       int height,
-      const std::vector<OutputConfigurator::CrtcConfig>& configs) OVERRIDE {
+      const std::vector<OutputConfigurator::OutputSnapshot>& outputs) OVERRIDE {
     AppendAction(
         GetFramebufferAction(width,
                              height,
-                             configs.size() >= 1 ? configs[0].crtc : 0,
-                             configs.size() >= 2 ? configs[1].crtc : 0));
+                             outputs.size() >= 1 ? outputs[0].crtc : 0,
+                             outputs.size() >= 2 ? outputs[1].crtc : 0));
   }
   virtual void ConfigureCTM(
       int touch_device_id,
@@ -263,8 +267,8 @@
     o->native_mode = kSmallModeId;
     o->selected_mode = kSmallModeId;
     o->mirror_mode = kSmallModeId;
+    o->x = 0;
     o->y = 0;
-    o->height = kSmallModeHeight;
     o->is_internal = true;
     o->is_aspect_preserving_scaling = true;
     o->touch_device_id = 0;
@@ -277,8 +281,8 @@
     o->native_mode = kBigModeId;
     o->selected_mode = kBigModeId;
     o->mirror_mode = kSmallModeId;
+    o->x = 0;
     o->y = 0;
-    o->height = kBigModeHeight;
     o->is_internal = false;
     o->is_aspect_preserving_scaling = true;
     o->touch_device_id = 0;
diff --git a/chromeos/display/real_output_configurator_delegate.cc b/chromeos/display/real_output_configurator_delegate.cc
index 0ed0437..47fbd58 100644
--- a/chromeos/display/real_output_configurator_delegate.cc
+++ b/chromeos/display/real_output_configurator_delegate.cc
@@ -138,7 +138,7 @@
         XRRCrtcInfo* crtc_info = XRRGetCrtcInfo(
             display_, screen_, output_info->crtc);
         to_populate.current_mode = crtc_info->mode;
-        to_populate.height = crtc_info->height;
+        to_populate.x = crtc_info->x;
         to_populate.y = crtc_info->y;
         XRRFreeCrtcInfo(crtc_info);
       }
@@ -252,38 +252,37 @@
   return false;
 }
 
-void RealOutputConfiguratorDelegate::ConfigureCrtc(
-    OutputConfigurator::CrtcConfig* config) {
+bool RealOutputConfiguratorDelegate::ConfigureCrtc(
+    RRCrtc crtc,
+    RRMode mode,
+    RROutput output,
+    int x,
+    int y) {
   CHECK(screen_) << "Server not grabbed";
-  VLOG(1) << "ConfigureCrtc: crtc=" << config->crtc
-          << " mode=" << config->mode
-          << " output=" << config->output
-          << " x=" << config->x
-          << " y=" << config->y;
-
-  RROutput* outputs = NULL;
-  int num_outputs = 0;
-  if (config->output && config->mode) {
-    outputs = &config->output;
-    num_outputs = 1;
-  }
-
-  XRRSetCrtcConfig(display_,
-                   screen_,
-                   config->crtc,
-                   CurrentTime,
-                   config->x,
-                   config->y,
-                   config->mode,
-                   RR_Rotate_0,
-                   outputs,
-                   num_outputs);
+  VLOG(1) << "ConfigureCrtc: crtc=" << crtc
+          << " mode=" << mode
+          << " output=" << output
+          << " x=" << x
+          << " y=" << y;
+  // Xrandr.h is full of lies. XRRSetCrtcConfig() is defined as returning a
+  // Status, which is typically 0 for failure and 1 for success. In
+  // actuality it returns a RRCONFIGSTATUS, which uses 0 for success.
+  return XRRSetCrtcConfig(display_,
+                          screen_,
+                          crtc,
+                          CurrentTime,
+                          x,
+                          y,
+                          mode,
+                          RR_Rotate_0,
+                          (output && mode) ? &output : NULL,
+                          (output && mode) ? 1 : 0) == RRSetConfigSuccess;
 }
 
 void RealOutputConfiguratorDelegate::CreateFrameBuffer(
     int width,
     int height,
-    const std::vector<OutputConfigurator::CrtcConfig>& configs) {
+    const std::vector<OutputConfigurator::OutputSnapshot>& outputs) {
   CHECK(screen_) << "Server not grabbed";
   int current_width = DisplayWidth(display_, DefaultScreen(display_));
   int current_height = DisplayHeight(display_, DefaultScreen(display_));
@@ -292,7 +291,7 @@
   if (width ==  current_width && height == current_height)
     return;
 
-  DestroyUnusedCrtcs(configs);
+  DestroyUnusedCrtcs(outputs);
   int mm_width = width * kPixelsToMmScale;
   int mm_height = height * kPixelsToMmScale;
   XRRSetScreenSize(display_, window_, width, height, mm_width, mm_height);
@@ -345,7 +344,7 @@
 }
 
 void RealOutputConfiguratorDelegate::DestroyUnusedCrtcs(
-    const std::vector<OutputConfigurator::CrtcConfig>& configs) {
+    const std::vector<OutputConfigurator::OutputSnapshot>& outputs) {
   CHECK(screen_) << "Server not grabbed";
   // Setting the screen size will fail if any CRTC doesn't fit afterwards.
   // At the same time, turning CRTCs off and back on uses up a lot of time.
@@ -360,31 +359,32 @@
   // out of the way so we can rebuild the frame buffer.
   for (int i = 0; i < screen_->ncrtc; ++i) {
     // Default config is to disable the crtcs.
-    OutputConfigurator::CrtcConfig config(
-        screen_->crtcs[i], 0, 0, None, None);
-    for (std::vector<OutputConfigurator::CrtcConfig>::const_iterator it =
-         configs.begin(); it != configs.end(); ++it) {
-      if (config.crtc == it->crtc) {
-        config.mode = it->mode;
-        config.output = it->output;
+    RRCrtc crtc = screen_->crtcs[i];
+    RRMode mode = None;
+    RROutput output = None;
+    for (std::vector<OutputConfigurator::OutputSnapshot>::const_iterator it =
+         outputs.begin(); it != outputs.end(); ++it) {
+      if (crtc == it->crtc) {
+        mode = it->current_mode;
+        output = it->output;
         break;
       }
     }
 
-    if (config.mode != None) {
+    if (mode != None) {
       // In case our CRTC doesn't fit in our current framebuffer, disable it.
       // It'll get reenabled after we resize the framebuffer.
       int mode_width = 0, mode_height = 0;
-      CHECK(GetModeDetails(config.mode, &mode_width, &mode_height, NULL));
+      CHECK(GetModeDetails(mode, &mode_width, &mode_height, NULL));
       int current_width = DisplayWidth(display_, DefaultScreen(display_));
       int current_height = DisplayHeight(display_, DefaultScreen(display_));
       if (mode_width > current_width || mode_height > current_height) {
-        config.mode = None;
-        config.output = None;
+        mode = None;
+        output = None;
       }
     }
 
-    ConfigureCrtc(&config);
+    ConfigureCrtc(crtc, mode, output, 0, 0);
   }
 }
 
diff --git a/chromeos/display/real_output_configurator_delegate.h b/chromeos/display/real_output_configurator_delegate.h
index eeec2ab..9f083cf 100644
--- a/chromeos/display/real_output_configurator_delegate.h
+++ b/chromeos/display/real_output_configurator_delegate.h
@@ -44,11 +44,16 @@
       int* width,
       int* height,
       bool* interlaced) OVERRIDE;
-  virtual void ConfigureCrtc(OutputConfigurator::CrtcConfig* config) OVERRIDE;
+  virtual bool ConfigureCrtc(
+      RRCrtc crtc,
+      RRMode mode,
+      RROutput output,
+      int x,
+      int y) OVERRIDE;
   virtual void CreateFrameBuffer(
       int width,
       int height,
-      const std::vector<OutputConfigurator::CrtcConfig>& configs) OVERRIDE;
+      const std::vector<OutputConfigurator::OutputSnapshot>& outputs) OVERRIDE;
   virtual void ConfigureCTM(
       int touch_device_id,
       const OutputConfigurator::CoordinateTransformation& ctm) OVERRIDE;
@@ -59,7 +64,7 @@
   // framebuffer resize. This is faster than turning them off, resizing,
   // then turning them back on.
   void DestroyUnusedCrtcs(
-      const std::vector<OutputConfigurator::CrtcConfig>& configs);
+      const std::vector<OutputConfigurator::OutputSnapshot>& outputs);
 
   // Returns whether |id| is configured to preserve aspect when scaling.
   bool IsOutputAspectPreservingScaling(RROutput id);
diff --git a/chromeos/ime/input_methods.txt b/chromeos/ime/input_methods.txt
index 11a9f88..2b4bc91 100644
--- a/chromeos/ime/input_methods.txt
+++ b/chromeos/ime/input_methods.txt
@@ -97,10 +97,6 @@
 # a new Mozc Japanese IME for another keyboard layout is added.
 xkb:jp::jpn	jp	ja
 
-# Traditional Chinese
-mozc-chewing   us      zh-TW
-m17n:zh:quick  us      zh-TW
-
 # Russian
 xkb:ru::rus	ru	ru
 xkb:ru:phonetic:rus	ru(phonetic)	ru
diff --git a/chromeos/network/favorite_state.cc b/chromeos/network/favorite_state.cc
index 90043e9..2bc6b8e 100644
--- a/chromeos/network/favorite_state.cc
+++ b/chromeos/network/favorite_state.cc
@@ -15,32 +15,31 @@
 namespace chromeos {
 
 FavoriteState::FavoriteState(const std::string& path)
-    : ManagedState(MANAGED_TYPE_FAVORITE, path),
-      onc_source_(onc::ONC_SOURCE_NONE) {
+    : ManagedState(MANAGED_TYPE_FAVORITE, path) {
 }
 
 FavoriteState::~FavoriteState() {
 }
 
 bool FavoriteState::PropertyChanged(const std::string& key,
-                                  const base::Value& value) {
+                                    const base::Value& value) {
   if (ManagedStatePropertyChanged(key, value))
     return true;
   if (key == flimflam::kProfileProperty) {
     return GetStringValue(key, value, &profile_path_);
   } else if (key == flimflam::kUIDataProperty) {
-    if (!NetworkState::GetOncSource(value, &onc_source_)) {
+    if (!NetworkState::GetUIDataFromValue(value, &ui_data_)) {
       NET_LOG_ERROR("Failed to parse " + key, path());
       return false;
     }
     return true;
-}
+  }
   return false;
 }
 
 bool FavoriteState::IsManaged() const {
-  return onc_source_ == onc::ONC_SOURCE_DEVICE_POLICY ||
-         onc_source_ == onc::ONC_SOURCE_USER_POLICY;
+  return ui_data_.onc_source() == onc::ONC_SOURCE_DEVICE_POLICY ||
+      ui_data_.onc_source() == onc::ONC_SOURCE_USER_POLICY;
 }
 
 bool FavoriteState::IsPrivate() const {
diff --git a/chromeos/network/favorite_state.h b/chromeos/network/favorite_state.h
index 4fa03f3..53f9281 100644
--- a/chromeos/network/favorite_state.h
+++ b/chromeos/network/favorite_state.h
@@ -6,6 +6,7 @@
 #define CHROMEOS_NETWORK_FAVORITE_STATE_H_
 
 #include "chromeos/network/managed_state.h"
+#include "chromeos/network/network_ui_data.h"
 #include "chromeos/network/onc/onc_constants.h"
 
 namespace chromeos {
@@ -30,7 +31,7 @@
   // Accessors
   const std::string& profile_path() const { return profile_path_; }
   bool is_favorite() const { return !profile_path_.empty(); }
-  onc::ONCSource onc_source() const { return onc_source_; }
+  const NetworkUIData& ui_data() const { return ui_data_; }
 
   // Returns true if the ONC source is a device or user policy.
   bool IsManaged() const;
@@ -40,7 +41,7 @@
 
  private:
   std::string profile_path_;
-  onc::ONCSource onc_source_;
+  NetworkUIData ui_data_;
 
   DISALLOW_COPY_AND_ASSIGN(FavoriteState);
 };
diff --git a/chromeos/network/network_configuration_handler.cc b/chromeos/network/network_configuration_handler.cc
index f7f118e..fbd73c6 100644
--- a/chromeos/network/network_configuration_handler.cc
+++ b/chromeos/network/network_configuration_handler.cc
@@ -9,6 +9,7 @@
 
 #include "base/bind.h"
 #include "base/format_macros.h"
+#include "base/json/json_writer.h"
 #include "base/logging.h"
 #include "base/memory/ref_counted.h"
 #include "base/memory/scoped_ptr.h"
@@ -66,6 +67,43 @@
       *properties_copy.get());
 }
 
+void SetNetworkProfileErrorCallback(
+    const std::string& service_path,
+    const std::string& profile_path,
+    const network_handler::ErrorCallback& error_callback,
+    const std::string& dbus_error_name,
+    const std::string& dbus_error_message) {
+  network_handler::ShillErrorCallbackFunction(
+      "Config.SetNetworkProfile Failed: " + profile_path,
+      service_path, error_callback,
+      dbus_error_name, dbus_error_message);
+}
+
+bool IsPassphrase(const std::string& key) {
+  return key == flimflam::kEapPrivateKeyPasswordProperty ||
+      key == flimflam::kEapPasswordProperty ||
+      key == flimflam::kL2tpIpsecPasswordProperty ||
+      key == flimflam::kOpenVPNPasswordProperty ||
+      key == flimflam::kPassphraseProperty ||
+      key == flimflam::kOpenVPNOTPProperty ||
+      key == flimflam::kEapPrivateKeyProperty ||
+      key == flimflam::kEapPrivateKeyPasswordProperty ||
+      key == flimflam::kEapPinProperty ||
+      key == flimflam::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()))
+      base::JSONWriter::Write(&iter.value(), &v);
+    NET_LOG_DEBUG(desc,  path + "." + iter.key() + "=" + v);
+  }
+}
+
 }  // namespace
 
 // Helper class to request from Shill the profile entries associated with a
@@ -188,7 +226,14 @@
     const base::DictionaryValue& properties,
     const base::Closure& callback,
     const network_handler::ErrorCallback& error_callback) {
+  if (properties.empty()) {
+    if (!callback.is_null())
+      callback.Run();
+    return;
+  }
   NET_LOG_USER("SetProperties", service_path);
+  LogConfigProperties("SetProperty", service_path, properties);
+
   DBusThreadManager::Get()->GetShillServiceClient()->SetProperties(
       dbus::ObjectPath(service_path),
       properties,
@@ -203,7 +248,16 @@
     const std::vector<std::string>& names,
     const base::Closure& callback,
     const network_handler::ErrorCallback& error_callback) {
+  if (names.empty()) {
+    if (!callback.is_null())
+      callback.Run();
+    return;
+  }
   NET_LOG_USER("ClearProperties", service_path);
+  for (std::vector<std::string>::const_iterator iter = names.begin();
+       iter != names.end(); ++iter) {
+    NET_LOG_DEBUG("ClearProperty", service_path + "." + *iter);
+  }
   DBusThreadManager::Get()->GetShillServiceClient()->ClearProperties(
       dbus::ObjectPath(service_path),
       names,
@@ -219,9 +273,12 @@
     const network_handler::ErrorCallback& error_callback) {
   ShillManagerClient* manager =
       DBusThreadManager::Get()->GetShillManagerClient();
-
   std::string type;
   properties.GetStringWithoutPathExpansion(flimflam::kTypeProperty, &type);
+
+  NET_LOG_USER("CreateConfiguration", type);
+  LogConfigProperties("Configure", type, properties);
+
   // Shill supports ConfigureServiceForProfile only for network type WiFi. In
   // all other cases, we have to rely on GetService for now. This is
   // unproblematic for VPN (user profile only), but will lead to inconsistencies
@@ -265,6 +322,22 @@
   deleter->Run();
 }
 
+void NetworkConfigurationHandler::SetNetworkProfile(
+    const std::string& service_path,
+    const std::string& profile_path,
+    const base::Closure& callback,
+    const network_handler::ErrorCallback& error_callback) {
+  NET_LOG_USER("SetNetworkProfile", service_path + ": " + profile_path);
+  base::StringValue profile_path_value(profile_path);
+  DBusThreadManager::Get()->GetShillServiceClient()->SetProperty(
+      dbus::ObjectPath(service_path),
+      flimflam::kProfileProperty,
+      profile_path_value,
+      callback,
+      base::Bind(&SetNetworkProfileErrorCallback,
+                 service_path, profile_path, error_callback));
+}
+
 // NetworkConfigurationHandler Private methods
 
 NetworkConfigurationHandler::NetworkConfigurationHandler()
diff --git a/chromeos/network/network_configuration_handler.h b/chromeos/network/network_configuration_handler.h
index 9ef1131..f1ee856 100644
--- a/chromeos/network/network_configuration_handler.h
+++ b/chromeos/network/network_configuration_handler.h
@@ -99,6 +99,13 @@
       const base::Closure& callback,
       const network_handler::ErrorCallback& error_callback);
 
+  // Changes the profile for the network |service_path| to |profile_path|.
+  // See note on |callback| and |error_callback| in class description above.
+  void SetNetworkProfile(const std::string& service_path,
+                         const std::string& profile_path,
+                         const base::Closure& callback,
+                         const network_handler::ErrorCallback& error_callback);
+
   // Construct and initialize an instance for testing.
   static NetworkConfigurationHandler* InitializeForTest(
       NetworkStateHandler* network_state_handler);
diff --git a/chromeos/network/network_connection_handler.cc b/chromeos/network/network_connection_handler.cc
index 66e8d4f..25e03de 100644
--- a/chromeos/network/network_connection_handler.cc
+++ b/chromeos/network/network_connection_handler.cc
@@ -62,56 +62,40 @@
 }
 
 bool VPNIsConfigured(const std::string& service_path,
-                     const base::DictionaryValue& service_properties) {
-  // VPN Provider values are read from the "Provider" dictionary, not the
-  // "Provider.Type", etc keys (which are used only to set the values).
-  const base::DictionaryValue* provider_properties;
-  if (!service_properties.GetDictionaryWithoutPathExpansion(
-          flimflam::kProviderProperty, &provider_properties)) {
-    NET_LOG_ERROR("VPN Provider Dictionary not present", service_path);
-    return false;
-  }
-  std::string provider_type;
-  if (!provider_properties->GetStringWithoutPathExpansion(
-          flimflam::kTypeProperty, &provider_type)) {
-    NET_LOG_ERROR("VPN Provider Type not present", service_path);
-    return false;
-  }
+                     const std::string& provider_type,
+                     const base::DictionaryValue& provider_properties) {
   if (provider_type == flimflam::kProviderOpenVpn) {
     std::string hostname;
-    provider_properties->GetStringWithoutPathExpansion(
+    provider_properties.GetStringWithoutPathExpansion(
         flimflam::kHostProperty, &hostname);
     if (hostname.empty()) {
       NET_LOG_EVENT("OpenVPN: No hostname", service_path);
       return false;
     }
     std::string username;
-    provider_properties->GetStringWithoutPathExpansion(
+    provider_properties.GetStringWithoutPathExpansion(
         flimflam::kOpenVPNUserProperty, &username);
     if (username.empty()) {
       NET_LOG_EVENT("OpenVPN: No username", service_path);
       return false;
     }
     bool passphrase_required = false;
-    provider_properties->GetBooleanWithoutPathExpansion(
+    provider_properties.GetBooleanWithoutPathExpansion(
         flimflam::kPassphraseRequiredProperty, &passphrase_required);
-    std::string passphrase;
-    provider_properties->GetStringWithoutPathExpansion(
-        flimflam::kOpenVPNPasswordProperty, &passphrase);
-    if (passphrase_required && passphrase.empty()) {
-      NET_LOG_EVENT("OpenVPN: No passphrase", service_path);
+    if (passphrase_required) {
+      NET_LOG_EVENT("OpenVPN: Passphrase Required", service_path);
       return false;
     }
     NET_LOG_EVENT("OpenVPN Is Configured", service_path);
   } else {
     bool passphrase_required = false;
     std::string passphrase;
-    provider_properties->GetBooleanWithoutPathExpansion(
+    provider_properties.GetBooleanWithoutPathExpansion(
         flimflam::kL2tpIpsecPskRequiredProperty, &passphrase_required);
-    provider_properties->GetStringWithoutPathExpansion(
-        flimflam::kL2tpIpsecPskProperty, &passphrase);
-    if (passphrase_required && passphrase.empty())
+    if (passphrase_required) {
+      NET_LOG_EVENT("VPN: Passphrase Required", service_path);
       return false;
+    }
     NET_LOG_EVENT("VPN Is Configured", service_path);
   }
   return true;
@@ -135,10 +119,14 @@
     "authentication-required";
 const char NetworkConnectionHandler::kErrorShillError[] = "shill-error";
 const char NetworkConnectionHandler::kErrorConnectFailed[] = "connect-failed";
-const char NetworkConnectionHandler::kErrorDisconnectFailed[] =
-    "disconnect-failed";
-const char NetworkConnectionHandler::kErrorMissingProviderType[] =
-    "missing-provider-type";
+const char NetworkConnectionHandler::kErrorConfigureFailed[] =
+    "configure-failed";
+const char NetworkConnectionHandler::kErrorActivateFailed[] =
+    "activate-failed";
+const char NetworkConnectionHandler::kErrorMissingProvider[] =
+    "missing-provider";
+const char NetworkConnectionHandler::kErrorConnectCanceled[] =
+    "connect-canceled";
 const char NetworkConnectionHandler::kErrorUnknown[] = "unknown-error";
 
 struct NetworkConnectionHandler::ConnectRequest {
@@ -203,10 +191,6 @@
 
 void NetworkConnectionHandler::LoggedInStateChanged(
     LoginState::LoggedInState state) {
-  NET_LOG_EVENT("NewNetworkConnectionHandler",
-                CommandLine::ForCurrentProcess()->HasSwitch(
-                    chromeos::switches::kUseNewNetworkConnectionHandler) ?
-                "enabled" : "disabled");
   if (state == LoginState::LOGGED_IN_ACTIVE) {
     logged_in_ = true;
     NET_LOG_EVENT("Logged In", "");
@@ -266,6 +250,26 @@
     return;
   }
 
+  if (check_error_state) {
+    const std::string& error = network->error();
+    if (error == flimflam::kErrorConnectFailed) {
+      InvokeErrorCallback(
+          service_path, error_callback, kErrorPassphraseRequired);
+      return;
+    }
+    if (error == flimflam::kErrorBadPassphrase) {
+      InvokeErrorCallback(
+          service_path, error_callback, kErrorPassphraseRequired);
+      return;
+    }
+
+    if (IsAuthenticationError(error)) {
+      InvokeErrorCallback(
+          service_path, error_callback, kErrorAuthenticationRequired);
+      return;
+    }
+  }
+
   // All synchronous checks passed, add |service_path| to connecting list.
   pending_requests_.insert(std::make_pair(
       service_path,
@@ -316,6 +320,21 @@
   CallShillDisconnect(service_path, success_callback, error_callback);
 }
 
+void NetworkConnectionHandler::ActivateNetwork(
+    const std::string& service_path,
+    const std::string& carrier,
+    const base::Closure& success_callback,
+    const network_handler::ErrorCallback& error_callback) {
+  NET_LOG_USER("DisconnectNetwork", service_path);
+  const NetworkState* network =
+      network_state_handler_->GetNetworkState(service_path);
+  if (!network) {
+    InvokeErrorCallback(service_path, error_callback, kErrorNotFound);
+    return;
+  }
+  CallShillActivate(service_path, carrier, success_callback, error_callback);
+}
+
 bool NetworkConnectionHandler::HasConnectingNetwork(
     const std::string& service_path) {
   return pending_requests_.count(service_path) != 0;
@@ -347,30 +366,6 @@
     const base::DictionaryValue& service_properties) {
   NET_LOG_EVENT("VerifyConfiguredAndConnect", service_path);
 
-  std::string type;
-  service_properties.GetStringWithoutPathExpansion(
-      flimflam::kTypeProperty, &type);
-
-  if (check_error_state) {
-    std::string error;
-    service_properties.GetStringWithoutPathExpansion(
-        flimflam::kErrorProperty, &error);
-    if (error == flimflam::kErrorConnectFailed) {
-      ErrorCallbackForPendingRequest(service_path, kErrorPassphraseRequired);
-      return;
-    }
-    if (error == flimflam::kErrorBadPassphrase) {
-      ErrorCallbackForPendingRequest(service_path, kErrorPassphraseRequired);
-      return;
-    }
-
-    if (IsAuthenticationError(error)) {
-      ErrorCallbackForPendingRequest(service_path,
-                                     kErrorAuthenticationRequired);
-      return;
-    }
-  }
-
   // If 'passphrase_required' is still true, then the 'Passphrase' property
   // has not been set to a minimum length value.
   bool passphrase_required = false;
@@ -381,14 +376,43 @@
     return;
   }
 
-  // VPN requires a host and username to be set.
-  if (type == flimflam::kTypeVPN &&
-      !VPNIsConfigured(service_path, service_properties)) {
-    ErrorCallbackForPendingRequest(service_path, kErrorConfigurationRequired);
-    return;
+  std::string type;
+  service_properties.GetStringWithoutPathExpansion(
+      flimflam::kTypeProperty, &type);
+
+  // Get VPN provider type and host (required for configuration) and ensure
+  // that required VPN non-cert properties are set.
+  std::string vpn_provider_type, vpn_provider_host;
+  if (type == flimflam::kTypeVPN) {
+    // VPN Provider values are read from the "Provider" dictionary, not the
+    // "Provider.Type", etc keys (which are used only to set the values).
+    const base::DictionaryValue* provider_properties;
+    if (service_properties.GetDictionaryWithoutPathExpansion(
+            flimflam::kProviderProperty, &provider_properties)) {
+      provider_properties->GetStringWithoutPathExpansion(
+          flimflam::kTypeProperty, &vpn_provider_type);
+      provider_properties->GetStringWithoutPathExpansion(
+          flimflam::kHostProperty, &vpn_provider_host);
+    }
+    if (vpn_provider_type.empty() || vpn_provider_host.empty()) {
+      ErrorCallbackForPendingRequest(service_path, kErrorMissingProvider);
+      return;
+    }
+    // VPN requires a host and username to be set.
+    if (!VPNIsConfigured(
+            service_path, vpn_provider_type, *provider_properties)) {
+      NET_LOG_ERROR("VPN Not Configured", service_path);
+      ErrorCallbackForPendingRequest(service_path, kErrorConfigurationRequired);
+      return;
+    }
   }
 
-  // Check certificate properties in kUIDataProperty.
+  // These will be set if they need to be configured, otherwise they will
+  // be left empty and the properties will not be set.
+  std::string pkcs11_id, tpm_slot, tpm_pin;
+
+  // Check certificate properties in kUIDataProperty if configured.
+  // Note: Wifi/VPNConfigView set these properties explicitly.
   scoped_ptr<NetworkUIData> ui_data =
       ManagedNetworkConfigurationHandler::GetUIData(service_properties);
   if (ui_data && ui_data->certificate_type() == CLIENT_CERT_TYPE_PATTERN) {
@@ -397,6 +421,7 @@
       ErrorCallbackForPendingRequest(service_path, kErrorCertificateRequired);
       return;
     }
+
     // If certificates have not been loaded yet, queue the connect request.
     if (!certificates_loaded_) {
       ConnectRequest* request = pending_request(service_path);
@@ -408,68 +433,79 @@
       return;
     }
 
-    // Ensure the certificate is available.
-    std::string pkcs11_id;
+    // Ensure the certificate is available and configured.
     if (!CertificateIsConfigured(ui_data.get(), &pkcs11_id)) {
       ErrorCallbackForPendingRequest(service_path, kErrorCertificateRequired);
       return;
     }
+  }
 
-    // The network may not be 'Connectable' because the certificate data is
-    // not set up, so configure tpm slot/pin and pkcs11_id before connecting.
-    // TODO(stevenjb): Remove this code once NetworkConfigurationHandler
-    // handles this.
-    NET_LOG_EVENT("Configuring Network", service_path);
-    const std::string& tpm_slot = cert_loader_->tpm_token_slot();
-    const std::string& tpm_pin = cert_loader_->tpm_user_pin();
-    base::DictionaryValue config_properties;
-    // Set configuration properties required by Shill to identify the network.
-    config_properties.SetStringWithoutPathExpansion(
-        flimflam::kTypeProperty, type);
-    CopyStringFromDictionary(service_properties, flimflam::kNameProperty,
-                             &config_properties);
-    CopyStringFromDictionary(service_properties, flimflam::kSecurityProperty,
-                             &config_properties);
-    CopyStringFromDictionary(service_properties, flimflam::kGuidProperty,
-                             &config_properties);
+  // The network may not be 'Connectable' because the TPM properties are
+  // not set up, so configure tpm slot/pin before connecting.
+  if (cert_loader_) {
+    tpm_slot = cert_loader_->tpm_token_slot();
+    tpm_pin = cert_loader_->tpm_user_pin();
+  }
 
-    if (type == flimflam::kTypeVPN) {
-      // VPN Provider values are read from the "Provider" dictionary, not the
-      // "Provider.Type", etc keys (which are used only to set the values).
-      std::string provider_type;
-      const base::DictionaryValue* provider_properties;
-      if (service_properties.GetDictionaryWithoutPathExpansion(
-              flimflam::kProviderProperty, &provider_properties)) {
-        provider_properties->GetStringWithoutPathExpansion(
-            flimflam::kTypeProperty, &provider_type);
-      }
-      if (provider_type.empty()) {
-        ErrorCallbackForPendingRequest(service_path, kErrorMissingProviderType);
-        return;
-      }
-      if (provider_type == flimflam::kProviderOpenVpn) {
-        config_properties.SetStringWithoutPathExpansion(
-            flimflam::kOpenVPNClientCertSlotProperty, tpm_slot);
-        config_properties.SetStringWithoutPathExpansion(
-            flimflam::kOpenVPNPinProperty, tpm_pin);
+  base::DictionaryValue config_properties;
+
+  if (type == flimflam::kTypeVPN) {
+    if (vpn_provider_type == flimflam::kProviderOpenVpn) {
+      if (!pkcs11_id.empty()) {
         config_properties.SetStringWithoutPathExpansion(
             flimflam::kOpenVPNClientCertIdProperty, pkcs11_id);
-      } else {
+      }
+      if (!tpm_pin.empty()) {
         config_properties.SetStringWithoutPathExpansion(
-            flimflam::kL2tpIpsecClientCertSlotProperty, tpm_slot);
-        config_properties.SetStringWithoutPathExpansion(
-            flimflam::kL2tpIpsecPinProperty, tpm_pin);
+            flimflam::kOpenVPNPinProperty, tpm_pin);
+      }
+    } else {
+      if (!pkcs11_id.empty()) {
         config_properties.SetStringWithoutPathExpansion(
             flimflam::kL2tpIpsecClientCertIdProperty, pkcs11_id);
       }
-    } else if (type == flimflam::kTypeWifi) {
-      config_properties.SetStringWithoutPathExpansion(
-          flimflam::kEapPinProperty, cert_loader_->tpm_user_pin());
+      if (!tpm_slot.empty()) {
+        config_properties.SetStringWithoutPathExpansion(
+            flimflam::kL2tpIpsecClientCertSlotProperty, tpm_slot);
+      }
+      if (!tpm_pin.empty()) {
+        config_properties.SetStringWithoutPathExpansion(
+            flimflam::kL2tpIpsecPinProperty, tpm_pin);
+      }
+    }
+  } else if (type == flimflam::kTypeWifi) {
+    if (!pkcs11_id.empty()) {
       config_properties.SetStringWithoutPathExpansion(
           flimflam::kEapCertIdProperty, pkcs11_id);
       config_properties.SetStringWithoutPathExpansion(
           flimflam::kEapKeyIdProperty, pkcs11_id);
     }
+    if (!tpm_pin.empty()) {
+      config_properties.SetStringWithoutPathExpansion(
+          flimflam::kEapPinProperty, tpm_pin);
+    }
+  }
+
+  if (!config_properties.empty()) {
+    NET_LOG_EVENT("Configuring Network", service_path);
+
+    // Set configuration properties required by Shill to identify the network.
+    config_properties.SetStringWithoutPathExpansion(
+        flimflam::kTypeProperty, type);
+    CopyStringFromDictionary(service_properties, flimflam::kNameProperty,
+                             &config_properties);
+    CopyStringFromDictionary(service_properties, flimflam::kGuidProperty,
+                             &config_properties);
+    if (type == flimflam::kTypeVPN) {
+      config_properties.SetStringWithoutPathExpansion(
+          flimflam::kProviderTypeProperty, vpn_provider_type);
+      config_properties.SetStringWithoutPathExpansion(
+          flimflam::kProviderHostProperty, vpn_provider_host);
+    } else if (type == flimflam::kTypeWifi) {
+      CopyStringFromDictionary(service_properties, flimflam::kSecurityProperty,
+                               &config_properties);
+    }
+
     network_configuration_handler_->SetProperties(
         service_path,
         config_properties,
@@ -480,8 +516,14 @@
    return;
   }
 
-  // Otherwise, we need to configure the network.
-  ErrorCallbackForPendingRequest(service_path, kErrorConfigurationRequired);
+  // Otherwise, we probably still need to configure the network since
+  // 'Connectable' is false. If |check_error_state| is true, signal an
+  // error, otherwise attempt to connect to possibly gain additional error
+  // state from Shill (or in case 'Connectable' is improperly unset).
+  if (check_error_state)
+    ErrorCallbackForPendingRequest(service_path, kErrorConfigurationRequired);
+  else
+    CallShillConnect(service_path);
 }
 
 void NetworkConnectionHandler::CallShillConnect(
@@ -504,7 +546,7 @@
   network_handler::ErrorCallback error_callback = request->error_callback;
   pending_requests_.erase(service_path);
   if (!error_callback.is_null())
-    error_callback.Run(error_name, error_data.Pass());
+    error_callback.Run(kErrorConfigureFailed, error_data.Pass());
 }
 
 void NetworkConnectionHandler::HandleShillConnectSuccess(
@@ -563,13 +605,21 @@
   }
 
   // Network is neither connecting or connected; an error occurred.
-  std::string error_name = kErrorConnectFailed;
-  std::string error_detail = network->error();
-  if (error_detail.empty()) {
-    if (network->connection_state() == flimflam::kStateFailure)
-      error_detail = flimflam::kUnknownString;
-    else
-      error_detail = "Unexpected State: " + network->connection_state();
+  std::string error_name, error_detail;
+  if (network->connection_state() == flimflam::kStateIdle &&
+      pending_requests_.size() > 1) {
+    // Another connect request canceled this one.
+    error_name = kErrorConnectCanceled;
+    error_detail = "";
+  } else {
+    error_name = kErrorConnectFailed;
+    error_detail = network->error();
+    if (error_detail.empty()) {
+      if (network->connection_state() == flimflam::kStateFailure)
+        error_detail = flimflam::kUnknownString;
+      else
+        error_detail = "Unexpected State: " + network->connection_state();
+    }
   }
   std::string error_msg = error_name + ": " + error_detail;
   NET_LOG_ERROR(error_msg, service_path);
@@ -627,7 +677,7 @@
       base::Bind(&NetworkConnectionHandler::HandleShillDisconnectSuccess,
                  AsWeakPtr(), service_path, success_callback),
       base::Bind(&network_handler::ShillErrorCallbackFunction,
-                 kErrorDisconnectFailed, service_path, error_callback));
+                 kErrorShillError, service_path, error_callback));
 }
 
 void NetworkConnectionHandler::HandleShillDisconnectSuccess(
@@ -638,4 +688,29 @@
     success_callback.Run();
 }
 
+// Activate
+
+void NetworkConnectionHandler::CallShillActivate(
+    const std::string& service_path,
+    const std::string& carrier,
+    const base::Closure& success_callback,
+    const network_handler::ErrorCallback& error_callback) {
+  NET_LOG_USER("Activate Request", service_path + ": '" + carrier + "'");
+  DBusThreadManager::Get()->GetShillServiceClient()->ActivateCellularModem(
+      dbus::ObjectPath(service_path),
+      carrier,
+      base::Bind(&NetworkConnectionHandler::HandleShillActivateSuccess,
+                 AsWeakPtr(), service_path, success_callback),
+      base::Bind(&network_handler::ShillErrorCallbackFunction,
+                 kErrorShillError, service_path, error_callback));
+}
+
+void NetworkConnectionHandler::HandleShillActivateSuccess(
+    const std::string& service_path,
+    const base::Closure& success_callback) {
+  NET_LOG_EVENT("Activate Request Sent", service_path);
+  if (!success_callback.is_null())
+    success_callback.Run();
+}
+
 }  // namespace chromeos
diff --git a/chromeos/network/network_connection_handler.h b/chromeos/network/network_connection_handler.h
index 8f00a8a..90f91e2 100644
--- a/chromeos/network/network_connection_handler.h
+++ b/chromeos/network/network_connection_handler.h
@@ -58,8 +58,10 @@
   static const char kErrorConfigurationRequired[];
   static const char kErrorShillError[];
   static const char kErrorConnectFailed[];
-  static const char kErrorDisconnectFailed[];
-  static const char kErrorMissingProviderType[];
+  static const char kErrorConfigureFailed[];
+  static const char kErrorActivateFailed[];
+  static const char kErrorMissingProvider[];
+  static const char kErrorConnectCanceled[];
   static const char kErrorUnknown[];
 
   // Constants for |error_name| from |error_callback| for Disconnect.
@@ -99,6 +101,18 @@
                          const base::Closure& success_callback,
                          const network_handler::ErrorCallback& error_callback);
 
+  // ActivateNetwork() will start an asynchronous activation attempt.
+  // |carrier| may be empty or may specify a carrier to activate.
+  // On success, |success_callback| will be called.
+  // On failure, |error_callback| will be called with |error_name| one of:
+  //  kErrorNotFound if no network matching |service_path| is found.
+  //  kErrorShillError if a DBus or Shill error occurred.
+  // TODO(stevenjb/armansito): Move this to a separate NetworkActivationHandler.
+  void ActivateNetwork(const std::string& service_path,
+                       const std::string& carrier,
+                       const base::Closure& success_callback,
+                       const network_handler::ErrorCallback& error_callback);
+
   // Returns true if ConnectToNetwork has been called with |service_path| and
   // has not completed (i.e. success or error callback has been called).
   bool HasConnectingNetwork(const std::string& service_path);
@@ -163,10 +177,21 @@
       const base::Closure& success_callback,
       const network_handler::ErrorCallback& error_callback);
 
-  // Handle success or failure from Shill.Service.Disconnect.
+  // Handle success from Shill.Service.Disconnect.
   void HandleShillDisconnectSuccess(const std::string& service_path,
                                     const base::Closure& success_callback);
 
+  // Calls Shill.Manager.Activate asynchronously.
+  void CallShillActivate(
+      const std::string& service_path,
+      const std::string& carrier,
+      const base::Closure& success_callback,
+      const network_handler::ErrorCallback& error_callback);
+
+  // Handle success from Shill.Service.ActivateCellularModem.
+  void HandleShillActivateSuccess(const std::string& service_path,
+                                  const base::Closure& success_callback);
+
   // Local references to the associated handler instances.
   CertLoader* cert_loader_;
   NetworkStateHandler* network_state_handler_;
diff --git a/chromeos/network/network_handler_callbacks.h b/chromeos/network/network_handler_callbacks.h
index 8ba2f7d..92fb1d1 100644
--- a/chromeos/network/network_handler_callbacks.h
+++ b/chromeos/network/network_handler_callbacks.h
@@ -19,6 +19,11 @@
 namespace chromeos {
 namespace network_handler {
 
+CHROMEOS_EXPORT extern const char kErrorName[];
+CHROMEOS_EXPORT extern const char kErrorDetail[];
+CHROMEOS_EXPORT extern const char kDbusErrorName[];
+CHROMEOS_EXPORT extern const char kDbusErrorMessage[];
+
 // An error callback used by both the configuration handler and the state
 // handler to receive error results from the API.
 typedef base::Callback<
diff --git a/chromeos/network/network_profile_handler.cc b/chromeos/network/network_profile_handler.cc
index d209265..26b1bef 100644
--- a/chromeos/network/network_profile_handler.cc
+++ b/chromeos/network/network_profile_handler.cc
@@ -188,6 +188,16 @@
   return NULL;
 }
 
+const NetworkProfile* NetworkProfileHandler::GetDefaultUserProfile() const {
+  for (NetworkProfileHandler::ProfileList::const_iterator it =
+           profiles_.begin();
+       it != profiles_.end(); ++it) {
+    if (!it->userhash.empty())
+      return &*it;
+  }
+  return NULL;
+}
+
 NetworkProfileHandler::NetworkProfileHandler()
     : network_state_handler_(NULL),
       weak_ptr_factory_(this) {
diff --git a/chromeos/network/network_profile_handler.h b/chromeos/network/network_profile_handler.h
index d3c784e..15bb0fd 100644
--- a/chromeos/network/network_profile_handler.h
+++ b/chromeos/network/network_profile_handler.h
@@ -52,6 +52,11 @@
   const NetworkProfile* GetProfileForUserhash(
       const std::string& userhash) const;
 
+  // Returns the first profile entry with a non-empty userhash.
+  // TODO(stevenjb): Replace with GetProfileForUserhash() with the correct
+  // userhash.
+  const NetworkProfile* GetDefaultUserProfile() const;
+
   static const char kSharedProfilePath[];
 
  protected:
diff --git a/chromeos/network/network_state.cc b/chromeos/network/network_state.cc
index f0da62d..deff647 100644
--- a/chromeos/network/network_state.cc
+++ b/chromeos/network/network_state.cc
@@ -13,13 +13,14 @@
 #include "base/strings/utf_string_conversion_utils.h"
 #include "chromeos/network/network_event_log.h"
 #include "chromeos/network/network_profile_handler.h"
-#include "chromeos/network/network_ui_data.h"
 #include "chromeos/network/network_util.h"
 #include "chromeos/network/onc/onc_utils.h"
 #include "third_party/cros_system_api/dbus/service_constants.h"
 
 namespace {
 
+const char kErrorUnknown[] = "Unknown";
+
 bool ConvertListValueToStringVector(const base::ListValue& string_list,
                                     std::vector<std::string>* result) {
   for (size_t i = 0; i < string_list.GetSize(); ++i) {
@@ -51,23 +52,6 @@
   return result;
 }
 
-// Returns a new NetworkUIData* if |ui_data_value| is a valid NetworkUIData
-// dictionary string, otherwise returns NULL.
-chromeos::NetworkUIData* CreateUIDataFromValue(
-    const base::Value& ui_data_value) {
-  std::string ui_data_str;
-  if (!ui_data_value.GetAsString(&ui_data_str))
-    return NULL;
-  if (ui_data_str.empty())
-    return new chromeos::NetworkUIData();
-
-  scoped_ptr<base::DictionaryValue> ui_data_dict(
-      chromeos::onc::ReadDictionaryFromJson(ui_data_str));
-  if (!ui_data_dict)
-    return NULL;
-  return new chromeos::NetworkUIData(*ui_data_dict);
-}
-
 bool IsCaCertNssSet(const base::DictionaryValue& properties) {
   std::string ca_cert_nss;
   if (properties.GetStringWithoutPathExpansion(flimflam::kEapCaCertNssProperty,
@@ -104,7 +88,6 @@
       auto_connect_(false),
       favorite_(false),
       priority_(0),
-      onc_source_(onc::ONC_SOURCE_NONE),
       prefix_length_(0),
       signal_strength_(0),
       connectable_(false),
@@ -128,7 +111,12 @@
   } else if (key == flimflam::kConnectableProperty) {
     return GetBooleanValue(key, value, &connectable_);
   } else if (key == flimflam::kErrorProperty) {
-    return GetStringValue(key, value, &error_);
+    if (!GetStringValue(key, value, &error_))
+      return false;
+    // Shill uses "Unknown" to indicate an unset error state.
+    if (error_ == kErrorUnknown)
+      error_.clear();
+    return true;
   } else if (key == shill::kErrorDetailsProperty) {
     return GetStringValue(key, value, &error_details_);
   } else if (key == IPConfigProperty(flimflam::kAddressProperty)) {
@@ -180,7 +168,7 @@
     }
     return true;
   } else if (key == flimflam::kUIDataProperty) {
-    if (!GetOncSource(value, &onc_source_)) {
+    if (!GetUIDataFromValue(value, &ui_data_)) {
       NET_LOG_ERROR("Failed to parse " + key, path());
       return false;
     }
@@ -310,8 +298,8 @@
 }
 
 bool NetworkState::IsManaged() const {
-  return onc_source_ == onc::ONC_SOURCE_DEVICE_POLICY ||
-         onc_source_ == onc::ONC_SOURCE_USER_POLICY;
+  return ui_data_.onc_source() == onc::ONC_SOURCE_DEVICE_POLICY ||
+         ui_data_.onc_source() == onc::ONC_SOURCE_USER_POLICY;
 }
 
 bool NetworkState::IsPrivate() const {
@@ -432,12 +420,20 @@
 }
 
 // static
-bool NetworkState::GetOncSource(const base::Value& ui_data_value,
-                                onc::ONCSource* out) {
-  scoped_ptr<NetworkUIData> ui_data(CreateUIDataFromValue(ui_data_value));
-  if (!ui_data)
+bool NetworkState::GetUIDataFromValue(const base::Value& ui_data_value,
+                                      NetworkUIData* out) {
+  std::string ui_data_str;
+  if (!ui_data_value.GetAsString(&ui_data_str))
     return false;
-  *out = ui_data->onc_source();
+  if (ui_data_str.empty()) {
+    *out = NetworkUIData();
+    return true;
+  }
+  scoped_ptr<base::DictionaryValue> ui_data_dict(
+      chromeos::onc::ReadDictionaryFromJson(ui_data_str));
+  if (!ui_data_dict)
+    return false;
+  *out = NetworkUIData(*ui_data_dict);
   return true;
 }
 
diff --git a/chromeos/network/network_state.h b/chromeos/network/network_state.h
index f177794..6759082 100644
--- a/chromeos/network/network_state.h
+++ b/chromeos/network/network_state.h
@@ -10,6 +10,7 @@
 
 #include "base/values.h"
 #include "chromeos/network/managed_state.h"
+#include "chromeos/network/network_ui_data.h"
 #include "chromeos/network/onc/onc_constants.h"
 
 namespace chromeos {
@@ -50,7 +51,7 @@
   bool favorite() const { return favorite_; }
   int priority() const { return priority_; }
   const base::DictionaryValue& proxy_config() const { return proxy_config_; }
-  onc::ONCSource onc_source() const { return onc_source_; }
+  const NetworkUIData& ui_data() const { return ui_data_; }
   // IPConfig Properties
   const std::string& ip_address() const { return ip_address_; }
   const std::string& gateway() const { return gateway_; }
@@ -90,7 +91,7 @@
   // Returns a comma separated string of name servers.
   std::string GetDnsServersAsString() const;
 
-  // Converts the prefix length to a netmaks string.
+  // Converts the prefix length to a netmask string.
   std::string GetNetmask() const;
 
   // Helpers (used e.g. when a state is cached)
@@ -101,9 +102,9 @@
   // key.
   static std::string IPConfigProperty(const char* key);
 
-  // Sets |out| to the ONCSource specified by the UIData property |value|.
-  // Returns true if the source was successfully parsed.
-  static bool GetOncSource(const base::Value& value, onc::ONCSource* out);
+  // Sets |out| to the UIData specified by |value|. Returns true if successfully
+  // parsed.
+  static bool GetUIDataFromValue(const base::Value& value, NetworkUIData* out);
 
   // Generates a name from properties."Wifi.HexSSID" if present, otherwise
   // validates properties.Name and returns a valid utf8 version.
@@ -134,7 +135,7 @@
   // TODO(pneubeck): Remove ProxyConfig once NetworkConfigurationHandler
   // provides proxy configuration. crbug/241775
   base::DictionaryValue proxy_config_;
-  onc::ONCSource onc_source_;
+  NetworkUIData ui_data_;
   // IPConfig properties.
   // Note: These do not correspond to actual Shill.Service properties
   // but are derived from the service's corresponding IPConfig object.
diff --git a/chromeos/network/network_state_handler.cc b/chromeos/network/network_state_handler.cc
index e3f3dd3..04b6e28 100644
--- a/chromeos/network/network_state_handler.cc
+++ b/chromeos/network/network_state_handler.cc
@@ -368,16 +368,6 @@
   }
 }
 
-void NetworkStateHandler::SetConnectingNetwork(
-    const std::string& service_path) {
-  connecting_network_ = service_path;
-  const NetworkState* network = GetNetworkState(service_path);
-  if (network)
-    NET_LOG_EVENT("SetConnectingNetwork", GetManagedStateLogName(network));
-  else
-    NET_LOG_ERROR("SetConnectingNetwork to unknown network", service_path);
-}
-
 void NetworkStateHandler::SetCheckPortalList(
     const std::string& check_portal_list) {
   NET_LOG_EVENT("SetCheckPortalList", check_portal_list);
@@ -440,7 +430,7 @@
     }
     list_entries.insert(path);
   }
-  // Delete any remaning entries in managed_map.
+  // Delete any remaining entries in managed_map.
   STLDeleteContainerPairSecondPointers(managed_map.begin(), managed_map.end());
 }
 
@@ -524,29 +514,43 @@
   if (!network)
     return;
   std::string prev_connection_state = network->connection_state();
+  std::string prev_profile_path = network->profile_path();
   if (!network->PropertyChanged(key, value))
     return;
 
   if (key == flimflam::kStateProperty) {
-    if (ConnectionStateChanged(network, prev_connection_state))
+    if (ConnectionStateChanged(network, prev_connection_state)) {
       OnNetworkConnectionStateChanged(network);
+      // If the connection state changes, other properties such as IPConfig
+      // may have changed, so request a full update.
+      RequestUpdateForNetwork(service_path);
+    }
   } else {
-    if (network->path() == default_network_path_ &&
-        key != flimflam::kSignalStrengthProperty &&
-        key != shill::kWifiFrequencyListProperty) {
-      // WiFi SignalStrength and WifiFrequencyList updates are too noisy, so
+    bool noisy_property =
+        key == flimflam::kSignalStrengthProperty ||
+        key == shill::kWifiFrequencyListProperty;
+    if (network->path() == default_network_path_ && !noisy_property) {
+      // Wifi SignalStrength and WifiFrequencyList updates are too noisy, so
       // don't trigger default network updates for those changes.
       OnDefaultNetworkChanged();
     }
-    std::string detail = network->name() + "." + key;
-    detail += " = " + network_event_log::ValueAsString(value);
-    network_event_log::LogLevel log_level = network_event_log::LOG_LEVEL_EVENT;
-    if (key == flimflam::kErrorProperty || key == shill::kErrorDetailsProperty)
-      log_level = network_event_log::LOG_LEVEL_ERROR;
-    else if (key == flimflam::kSignalStrengthProperty ||
-             key == shill::kWifiFrequencyListProperty)
-      log_level = network_event_log::LOG_LEVEL_DEBUG;
-    NET_LOG_LEVEL(log_level, "NetworkPropertyUpdated", detail);
+    if (prev_profile_path.empty() && !network->profile_path().empty()) {
+      // If added to a Profile, request a full update so that a FavoriteState
+      // gets created.
+      RequestUpdateForNetwork(service_path);
+    }
+    if (!noisy_property) {
+      std::string detail = network->name() + "." + key;
+      detail += " = " + network_event_log::ValueAsString(value);
+      network_event_log::LogLevel log_level;
+      if (key == flimflam::kErrorProperty ||
+          key == shill::kErrorDetailsProperty) {
+        log_level = network_event_log::LOG_LEVEL_ERROR;
+      } else {
+        log_level = network_event_log::LOG_LEVEL_EVENT;
+      }
+      NET_LOG_LEVEL(log_level, "NetworkPropertyUpdated", detail);
+    }
   }
   NetworkPropertiesUpdated(network);
 }
@@ -596,8 +600,8 @@
   } else if (type == ManagedState::MANAGED_TYPE_FAVORITE) {
     NET_LOG_DEBUG("FavoriteListChanged",
                   base::StringPrintf("Size:%" PRIuS, favorite_list_.size()));
-    FOR_EACH_OBSERVER(NetworkStateHandlerObserver, observers_,
-                      NetworkListChanged());
+    // The FavoriteState list only changes when the NetworkState list changes,
+    // so no need to signal observers here again.
   } else if (type == ManagedState::MANAGED_TYPE_DEVICE) {
     NET_LOG_DEBUG("DeviceListChanged",
                   base::StringPrintf("Size:%" PRIuS, device_list_.size()));
@@ -689,16 +693,6 @@
     const NetworkState* network) {
   FOR_EACH_OBSERVER(NetworkStateHandlerObserver, observers_,
                     NetworkPropertiesUpdated(network));
-  // If |connecting_network_| transitions to a non-idle, non-connecting state,
-  // clear it *after* signalling observers.
-  if (network->path() == connecting_network_ &&
-      !network->IsConnectingState() &&
-      network->connection_state() != flimflam::kStateIdle) {
-    connecting_network_.clear();
-    NET_LOG_EVENT("ClearConnectingNetwork", base::StringPrintf(
-        "%s:%s", GetManagedStateLogName(network).c_str(),
-        network->connection_state().c_str()));
-  }
 }
 
 void NetworkStateHandler::ScanCompleted(const std::string& type) {
diff --git a/chromeos/network/network_state_handler.h b/chromeos/network/network_state_handler.h
index 161e196..ab99e33 100644
--- a/chromeos/network/network_state_handler.h
+++ b/chromeos/network/network_state_handler.h
@@ -191,13 +191,9 @@
   // existing networks.
   void RequestUpdateForAllNetworks();
 
-  // Set the user initiated connecting network.
-  void SetConnectingNetwork(const std::string& service_path);
-
   // Set the list of devices on which portal check is enabled.
   void SetCheckPortalList(const std::string& check_portal_list);
 
-  const std::string& connecting_network() const { return connecting_network_; }
   const std::string& check_portal_list() const { return check_portal_list_; }
 
   // Generates a DictionaryValue of all NetworkState properties. Currently
@@ -332,12 +328,6 @@
   // Keeps track of the default network for notifying observers when it changes.
   std::string default_network_path_;
 
-  // Convenience member to track the user initiated connecting network. Set
-  // externally when a connection is requested and cleared here when the state
-  // changes to something other than Connecting (after observers are notified).
-  // TODO(stevenjb): Move this to NetworkConfigurationHandler.
-  std::string connecting_network_;
-
   // List of interfaces on which portal check is enabled.
   std::string check_portal_list_;
 
diff --git a/cloud_print/gcp20/prototype/dns_sd_server.cc b/cloud_print/gcp20/prototype/dns_sd_server.cc
index 8a6653f..4ef9bb3 100644
--- a/cloud_print/gcp20/prototype/dns_sd_server.cc
+++ b/cloud_print/gcp20/prototype/dns_sd_server.cc
@@ -183,13 +183,13 @@
 
   VLOG(1) << "Current TTL for respond: " << current_ttl;
 
-  bool multicast_respond =
-      CommandLine::ForCurrentProcess()->HasSwitch("multicast-respond");
+  bool unicast_respond =
+      CommandLine::ForCurrentProcess()->HasSwitch("unicast-respond");
   socket_->SendTo(buffer.get(), buffer.get()->size(),
-                  multicast_respond ? multicast_address_ : recv_address_,
+                  unicast_respond ? recv_address_ : multicast_address_,
                   base::Bind(&DoNothingAfterSendToSocket));
   VLOG(1) << "Responded to "
-      << (multicast_respond ? multicast_address_ : recv_address_).ToString();
+      << (unicast_respond ? recv_address_ : multicast_address_).ToString();
 }
 
 void DnsSdServer::ProccessQuery(uint32 current_ttl, const DnsQueryRecord& query,
diff --git a/cloud_print/gcp20/prototype/gcp20_device.cc b/cloud_print/gcp20/prototype/gcp20_device.cc
index 01d34ed..2d2c1d5 100644
--- a/cloud_print/gcp20/prototype/gcp20_device.cc
+++ b/cloud_print/gcp20/prototype/gcp20_device.cc
@@ -26,8 +26,8 @@
                                 "HTTP header\n"
     "  -h, --help                prints this message\n"
     "  --no-announcement         disables DNS announcements\n"
-    "  --multicast-respond       DNS responses will be sent in multicast "
-                                "instead of unicast\n"
+    "  --unicast-respond         DNS responses will be sent in unicast "
+                                "instead of multicast\n"
     "\n"
     "options:\n"
     "  --domain-name=<name>      sets, should ends with '.local'\n"
@@ -49,17 +49,24 @@
 
 base::RunLoop* g_runner = NULL;
 Printer* g_printer = NULL;
+base::MessageLoop* g_message_loop;
+
+void StopLoop() {
+  // Always do after printer.Stop() to make sure XMPP will
+  // be disabled fully before |Quit| will be called
+  // (XMPP disables itself via MessageLoop call).
+  g_message_loop->PostTask(FROM_HERE, g_runner->QuitClosure());
+  g_message_loop = NULL;
+  g_runner = NULL;
+}
 
 void OnAbort(int val) {
-  if (g_runner) {
-    g_printer->Stop();  // TODO(maksymb): Make this call in safe place call:
-                        // |OnAbort| is called from different thread.
+  if (g_printer) {
+    g_message_loop->PostTask(
+        FROM_HERE,
+        base::Bind(&Printer::Stop, base::Unretained(g_printer)));
+    g_message_loop->PostTask(FROM_HERE, base::Bind(&StopLoop));
     g_printer = NULL;
-
-    g_runner->Quit();   // Always do after printer.Stop() to make sure XMPP will
-                        // be disabled fully before |Quit| will be called
-                        // (XMPP disables itself via MessageLoop call).
-    g_runner = NULL;
   }
 }
 
@@ -83,8 +90,8 @@
   signal(SIGINT, OnAbort);  // Handle Ctrl+C signal.
 
   base::MessageLoop loop(base::MessageLoop::TYPE_IO);
-  base::MessageLoop::current()->PostTask(FROM_HERE,
-                                         base::Bind(&StartPrinter, &printer));
+  g_message_loop = &loop;
+  g_message_loop->PostTask(FROM_HERE, base::Bind(&StartPrinter, &printer));
   base::RunLoop runner;
   g_printer = &printer;
   g_runner = &runner;
diff --git a/cloud_print/gcp20/prototype/privet_http_server.cc b/cloud_print/gcp20/prototype/privet_http_server.cc
index 0ffcfbc..0a21059 100644
--- a/cloud_print/gcp20/prototype/privet_http_server.cc
+++ b/cloud_print/gcp20/prototype/privet_http_server.cc
@@ -85,10 +85,10 @@
 
   if (server_->GetLocalAddress(&address) != net::OK) {
     NOTREACHED() << "Cannot start HTTP server";
-  } else {
-    VLOG(1) << "Address of HTTP server: " << address.ToString();
+    return false;
   }
 
+  VLOG(1) << "Address of HTTP server: " << address.ToString();
   return true;
 }
 
diff --git a/components/autofill/content/browser/DEPS b/components/autofill/content/browser/DEPS
index 0b9fb92..fb768b6 100644
--- a/components/autofill/content/browser/DEPS
+++ b/components/autofill/content/browser/DEPS
@@ -9,7 +9,6 @@
   "+sql",
   "+third_party/libjingle",
   "+third_party/libphonenumber",  # For phone number i18n.
-  "+webkit/plugins/webplugininfo.h",
 ]
 
 specific_include_rules = {
diff --git a/components/autofill/content/browser/wallet/full_wallet.cc b/components/autofill/content/browser/wallet/full_wallet.cc
index 28c47b3..f66b28a 100644
--- a/components/autofill/content/browser/wallet/full_wallet.cc
+++ b/components/autofill/content/browser/wallet/full_wallet.cc
@@ -42,6 +42,7 @@
 
 FullWallet::~FullWallet() {}
 
+// static
 scoped_ptr<FullWallet>
     FullWallet::CreateFullWallet(const DictionaryValue& dictionary) {
   const ListValue* required_actions_list;
@@ -127,6 +128,32 @@
                                                required_actions));
 }
 
+// static
+scoped_ptr<FullWallet>
+    FullWallet::CreateFullWalletFromClearText(
+        int expiration_month,
+        int expiration_year,
+        const std::string& pan,
+        const std::string& cvn,
+        scoped_ptr<Address> billing_address,
+        scoped_ptr<Address> shipping_address) {
+  DCHECK(billing_address);
+  DCHECK(!pan.empty());
+  DCHECK(!cvn.empty());
+
+  scoped_ptr<FullWallet> wallet(new FullWallet(
+      expiration_month,
+      expiration_year,
+      std::string(),  // no iin -- clear text pan/cvn are set below.
+      std::string(),  // no encrypted_rest -- clear text pan/cvn are set below.
+      billing_address.Pass(),
+      shipping_address.Pass(),
+      std::vector<RequiredAction>()));  // no required actions in clear text.
+  wallet->pan_ = pan;
+  wallet->cvn_ = cvn;
+  return wallet.Pass();
+}
+
 base::string16 FullWallet::GetInfo(const AutofillType& type) {
   switch (type.GetStorableType()) {
     case CREDIT_CARD_NUMBER:
diff --git a/components/autofill/content/browser/wallet/full_wallet.h b/components/autofill/content/browser/wallet/full_wallet.h
index 61e846a..84cc82e 100644
--- a/components/autofill/content/browser/wallet/full_wallet.h
+++ b/components/autofill/content/browser/wallet/full_wallet.h
@@ -41,6 +41,16 @@
   static scoped_ptr<FullWallet>
       CreateFullWallet(const base::DictionaryValue& dictionary);
 
+  // Returns a wallet built from the provided clear-text data.
+  // Data is not validated; |pan|, |cvn| and |billing_address| must be set.
+  static scoped_ptr<FullWallet>
+      CreateFullWalletFromClearText(int expiration_month,
+                                    int expiration_year,
+                                    const std::string& pan,
+                                    const std::string& cvn,
+                                    scoped_ptr<Address> billing_address,
+                                    scoped_ptr<Address> shipping_address);
+
   // Returns corresponding data for |type|.
   base::string16 GetInfo(const AutofillType& type);
 
@@ -80,6 +90,7 @@
   FRIEND_TEST_ALL_PREFIXES(FullWalletTest, RestLengthCorrectDecryptionTest);
   FRIEND_TEST_ALL_PREFIXES(FullWalletTest, RestLengthUnderDecryptionTest);
   FRIEND_TEST_ALL_PREFIXES(FullWalletTest, GetCreditCardInfo);
+
   FullWallet(int expiration_month,
              int expiration_year,
              const std::string& iin,
diff --git a/components/autofill/content/browser/wallet/full_wallet_unittest.cc b/components/autofill/content/browser/wallet/full_wallet_unittest.cc
index 5225bc4..6f66213 100644
--- a/components/autofill/content/browser/wallet/full_wallet_unittest.cc
+++ b/components/autofill/content/browser/wallet/full_wallet_unittest.cc
@@ -505,5 +505,26 @@
             full_wallet.GetInfo(AutofillType(CREDIT_CARD_TYPE)));
 }
 
+TEST_F(FullWalletTest, CreateFullWalletFromClearTextData) {
+  scoped_ptr<FullWallet> full_wallet =
+      FullWallet::CreateFullWalletFromClearText(
+          11, 2012,
+          "5555555555554444", "123",
+          GetTestAddress(), GetTestShippingAddress());
+  EXPECT_EQ(ASCIIToUTF16("5555555555554444"),
+            full_wallet->GetInfo(AutofillType(CREDIT_CARD_NUMBER)));
+  EXPECT_EQ(ASCIIToUTF16("MasterCard"),
+            full_wallet->GetInfo(AutofillType(CREDIT_CARD_TYPE)));
+  EXPECT_EQ(ASCIIToUTF16("123"),
+            full_wallet->GetInfo(AutofillType(CREDIT_CARD_VERIFICATION_CODE)));
+  EXPECT_EQ(ASCIIToUTF16("11/12"),
+            full_wallet->GetInfo(
+                AutofillType(CREDIT_CARD_EXP_DATE_2_DIGIT_YEAR)));
+  EXPECT_TRUE(GetTestAddress()->EqualsIgnoreID(
+      *full_wallet->billing_address()));
+  EXPECT_TRUE(GetTestShippingAddress()->EqualsIgnoreID(
+      *full_wallet->shipping_address()));
+}
+
 }  // namespace wallet
 }  // namespace autofill
diff --git a/components/autofill/content/browser/wallet/wallet_address.cc b/components/autofill/content/browser/wallet/wallet_address.cc
index 9595c3c..8ab5998 100644
--- a/components/autofill/content/browser/wallet/wallet_address.cc
+++ b/components/autofill/content/browser/wallet/wallet_address.cc
@@ -264,6 +264,16 @@
 
 string16 Address::GetInfo(const AutofillType& type,
                           const std::string& app_locale) const {
+  if (type.html_type() == HTML_TYPE_COUNTRY_CODE) {
+    DCHECK(IsStringASCII(country_name_code()));
+    return ASCIIToUTF16(country_name_code());
+  } else if (type.html_type() == HTML_TYPE_STREET_ADDRESS) {
+    base::string16 address = address_line_1();
+    if (!address_line_2().empty())
+      address += ASCIIToUTF16(", ") + address_line_2();
+    return address;
+  }
+
   switch (type.GetStorableType()) {
     case NAME_FULL:
       return recipient_name();
diff --git a/components/autofill/content/browser/wallet/wallet_address_unittest.cc b/components/autofill/content/browser/wallet/wallet_address_unittest.cc
index 6a09fa9..9135f54 100644
--- a/components/autofill/content/browser/wallet/wallet_address_unittest.cc
+++ b/components/autofill/content/browser/wallet/wallet_address_unittest.cc
@@ -409,5 +409,70 @@
   }
 }
 
+// Verifies that WalletAddress::GetInfo() can correctly return both country
+// codes and localized country names.
+TEST_F(WalletAddressTest, GetCountryInfo) {
+  Address address("FR",
+                  ASCIIToUTF16("recipient_name"),
+                  ASCIIToUTF16("address_line_1"),
+                  ASCIIToUTF16("address_line_2"),
+                  ASCIIToUTF16("locality_name"),
+                  ASCIIToUTF16("administrative_area_name"),
+                  ASCIIToUTF16("postal_code_number"),
+                  ASCIIToUTF16("phone_number"),
+                  "id1");
+
+  AutofillType type = AutofillType(HTML_TYPE_COUNTRY_CODE, HTML_MODE_NONE);
+  EXPECT_EQ(ASCIIToUTF16("FR"), address.GetInfo(type, "en-US"));
+
+  type = AutofillType(HTML_TYPE_COUNTRY_NAME, HTML_MODE_NONE);
+  EXPECT_EQ(ASCIIToUTF16("France"), address.GetInfo(type, "en-US"));
+
+  type = AutofillType(ADDRESS_HOME_COUNTRY);
+  EXPECT_EQ(ASCIIToUTF16("France"), address.GetInfo(type, "en-US"));
+}
+
+// Verifies that WalletAddress::GetInfo() can correctly return a concatenated
+// full street address.
+TEST_F(WalletAddressTest, GetStreetAddress) {
+  // Address has both lines 1 and 2.
+  Address address1("FR",
+                   ASCIIToUTF16("recipient_name"),
+                   ASCIIToUTF16("address_line_1"),
+                   ASCIIToUTF16("address_line_2"),
+                   ASCIIToUTF16("locality_name"),
+                   ASCIIToUTF16("administrative_area_name"),
+                   ASCIIToUTF16("postal_code_number"),
+                   ASCIIToUTF16("phone_number"),
+                   "id1");
+  AutofillType type = AutofillType(HTML_TYPE_STREET_ADDRESS, HTML_MODE_NONE);
+  EXPECT_EQ(ASCIIToUTF16("address_line_1, address_line_2"),
+            address1.GetInfo(type, "en-US"));
+
+  // Address has only line 1.
+  Address address2("FR",
+                   ASCIIToUTF16("recipient_name"),
+                   ASCIIToUTF16("address_line_1"),
+                   base::string16(),
+                   ASCIIToUTF16("locality_name"),
+                   ASCIIToUTF16("administrative_area_name"),
+                   ASCIIToUTF16("postal_code_number"),
+                   ASCIIToUTF16("phone_number"),
+                   "id1");
+  EXPECT_EQ(ASCIIToUTF16("address_line_1"), address2.GetInfo(type, "en-US"));
+
+  // Address has no address lines.
+  Address address3("FR",
+                   ASCIIToUTF16("recipient_name"),
+                   base::string16(),
+                   base::string16(),
+                   ASCIIToUTF16("locality_name"),
+                   ASCIIToUTF16("administrative_area_name"),
+                   ASCIIToUTF16("postal_code_number"),
+                   ASCIIToUTF16("phone_number"),
+                   "id1");
+  EXPECT_EQ(base::string16(), address3.GetInfo(type, "en-US"));
+}
+
 }  // namespace wallet
 }  // namespace autofill
diff --git a/components/autofill/content/browser/wallet/wallet_client.cc b/components/autofill/content/browser/wallet/wallet_client.cc
index 09afa60..bb5c525 100644
--- a/components/autofill/content/browser/wallet/wallet_client.cc
+++ b/components/autofill/content/browser/wallet/wallet_client.cc
@@ -105,6 +105,8 @@
                       &trimmed);
   if (LowerCaseEqualsASCII(trimmed, "buyer_account_error"))
     return WalletClient::BUYER_ACCOUNT_ERROR;
+  if (LowerCaseEqualsASCII(trimmed, "unsupported_merchant"))
+    return WalletClient::UNSUPPORTED_MERCHANT;
   if (LowerCaseEqualsASCII(trimmed, "internal_error"))
     return WalletClient::INTERNAL_ERROR;
   if (LowerCaseEqualsASCII(trimmed, "invalid_params"))
@@ -113,9 +115,26 @@
     return WalletClient::SERVICE_UNAVAILABLE;
   if (LowerCaseEqualsASCII(trimmed, "unsupported_api_version"))
     return WalletClient::UNSUPPORTED_API_VERSION;
+
   return WalletClient::UNKNOWN_ERROR;
 }
 
+// Get the more specific WalletClient::ErrorType when the error is
+// |BUYER_ACCOUNT_ERROR|.
+WalletClient::ErrorType BuyerErrorStringToErrorType(
+    const std::string& buyer_error_type) {
+  std::string trimmed;
+  TrimWhitespaceASCII(buyer_error_type,
+                      TRIM_ALL,
+                      &trimmed);
+  if (LowerCaseEqualsASCII(trimmed, "bla_country_not_supported"))
+    return WalletClient::BUYER_LEGAL_ADDRESS_NOT_SUPPORTED;
+  if (LowerCaseEqualsASCII(trimmed, "buyer_kyc_error"))
+    return WalletClient::UNVERIFIED_KNOW_YOUR_CUSTOMER_STATUS;
+
+  return WalletClient::BUYER_ACCOUNT_ERROR;
+}
+
 // Gets and parses required actions from a SaveToWallet response. Returns
 // false if any unknown required actions are seen and true otherwise.
 void GetRequiredActionsForSaveToWallet(
@@ -161,16 +180,22 @@
   switch (error_type) {
     case WalletClient::BAD_REQUEST:
       return AutofillMetrics::WALLET_BAD_REQUEST;
+    case WalletClient::BUYER_LEGAL_ADDRESS_NOT_SUPPORTED:
+      return AutofillMetrics::WALLET_BUYER_LEGAL_ADDRESS_NOT_SUPPORTED;
     case WalletClient::BUYER_ACCOUNT_ERROR:
       return AutofillMetrics::WALLET_BUYER_ACCOUNT_ERROR;
     case WalletClient::INTERNAL_ERROR:
       return AutofillMetrics::WALLET_INTERNAL_ERROR;
     case WalletClient::INVALID_PARAMS:
       return AutofillMetrics::WALLET_INVALID_PARAMS;
+    case WalletClient::UNVERIFIED_KNOW_YOUR_CUSTOMER_STATUS:
+      return AutofillMetrics::WALLET_UNVERIFIED_KNOW_YOUR_CUSTOMER_STATUS;
     case WalletClient::SERVICE_UNAVAILABLE:
       return AutofillMetrics::WALLET_SERVICE_UNAVAILABLE;
     case WalletClient::UNSUPPORTED_API_VERSION:
       return AutofillMetrics::WALLET_UNSUPPORTED_API_VERSION;
+    case WalletClient::UNSUPPORTED_MERCHANT:
+      return AutofillMetrics::WALLET_UNSUPPORTED_MERCHANT;
     case WalletClient::MALFORMED_RESPONSE:
       return AutofillMetrics::WALLET_MALFORMED_RESPONSE;
     case WalletClient::NETWORK_ERROR:
@@ -220,6 +245,7 @@
 const char kAcceptedLegalDocumentKey[] = "accepted_legal_document";
 const char kApiKeyKey[] = "api_key";
 const char kAuthResultKey[] = "auth_result";
+const char kBuyerErrorTypeKey[] = "wallet_error.buyer_error_type";
 const char kEncryptedOtpKey[] = "encrypted_otp";
 const char kErrorTypeKey[] = "wallet_error.error_type";
 const char kFeatureKey[] = "feature";
@@ -669,13 +695,24 @@
       if (response_code == net::HTTP_INTERNAL_SERVER_ERROR) {
         request_type_ = NO_PENDING_REQUEST;
 
-        std::string error_type;
-        if (!response_dict->GetString(kErrorTypeKey, &error_type)) {
+        std::string error_type_string;
+        if (!response_dict->GetString(kErrorTypeKey, &error_type_string)) {
           HandleWalletError(UNKNOWN_ERROR);
           return;
         }
+        WalletClient::ErrorType error_type =
+            StringToErrorType(error_type_string);
+        if (error_type == BUYER_ACCOUNT_ERROR) {
+          // If the error_type is |BUYER_ACCOUNT_ERROR|, then buyer_error_type
+          // field contains more specific information about the error.
+          std::string buyer_error_type_string;
+          if (response_dict->GetString(kBuyerErrorTypeKey,
+                                       &buyer_error_type_string)) {
+            error_type = BuyerErrorStringToErrorType(buyer_error_type_string);
+          }
+        }
 
-        HandleWalletError(StringToErrorType(error_type));
+        HandleWalletError(error_type);
         return;
       }
       break;
@@ -794,6 +831,9 @@
     case WalletClient::BAD_REQUEST:
       error_message = "WALLET_BAD_REQUEST";
       break;
+    case WalletClient::BUYER_LEGAL_ADDRESS_NOT_SUPPORTED:
+      error_message = "WALLET_BUYER_LEGAL_ADDRESS_NOT_SUPPORTED";
+      break;
     case WalletClient::BUYER_ACCOUNT_ERROR:
       error_message = "WALLET_BUYER_ACCOUNT_ERROR";
       break;
@@ -803,12 +843,18 @@
     case WalletClient::INVALID_PARAMS:
       error_message = "WALLET_INVALID_PARAMS";
       break;
+    case WalletClient::UNVERIFIED_KNOW_YOUR_CUSTOMER_STATUS:
+      error_message = "WALLET_UNVERIFIED_KNOW_YOUR_CUSTOMER_STATUS";
+      break;
     case WalletClient::SERVICE_UNAVAILABLE:
       error_message = "WALLET_SERVICE_UNAVAILABLE";
       break;
     case WalletClient::UNSUPPORTED_API_VERSION:
       error_message = "WALLET_UNSUPPORTED_API_VERSION";
       break;
+    case WalletClient::UNSUPPORTED_MERCHANT:
+      error_message = "WALLET_UNSUPPORTED_MERCHANT";
+      break;
     case WalletClient::MALFORMED_RESPONSE:
       error_message = "WALLET_MALFORMED_RESPONSE";
       break;
diff --git a/components/autofill/content/browser/wallet/wallet_client.h b/components/autofill/content/browser/wallet/wallet_client.h
index ecaae3d..d4f9607 100644
--- a/components/autofill/content/browser/wallet/wallet_client.h
+++ b/components/autofill/content/browser/wallet/wallet_client.h
@@ -75,8 +75,15 @@
   // The type of error returned by Online Wallet.
   enum ErrorType {
     // Errors to display to users.
-    BUYER_ACCOUNT_ERROR,      // Risk deny, unsupported country, or account
-                              // closed.
+    BUYER_ACCOUNT_ERROR,                // Risk deny, unsupported country, or
+                                        // account closed.
+    BUYER_LEGAL_ADDRESS_NOT_SUPPORTED,  // User's Buyer Legal Address is
+                                        // unsupported by Online Wallet.
+    UNVERIFIED_KNOW_YOUR_CUSTOMER_STATUS,  // User's "know your customer" KYC
+                                           // state is not verified (either
+                                           // KYC_REFER or KYC_FAIL).
+    UNSUPPORTED_MERCHANT,               // Merchant is blacklisted due to
+                                        // compliance violation.
 
     // API errors.
     BAD_REQUEST,              // Request was very malformed or sent to the
diff --git a/components/autofill/content/browser/wallet/wallet_client_unittest.cc b/components/autofill/content/browser/wallet/wallet_client_unittest.cc
index 3f20337..031e5cd 100644
--- a/components/autofill/content/browser/wallet/wallet_client_unittest.cc
+++ b/components/autofill/content/browser/wallet/wallet_client_unittest.cc
@@ -10,6 +10,7 @@
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_split.h"
 #include "base/strings/string_util.h"
+#include "base/strings/stringprintf.h"
 #include "base/values.h"
 #include "chrome/test/base/testing_profile.h"
 #include "components/autofill/content/browser/autocheckout_steps.h"
@@ -794,6 +795,58 @@
     fetcher->delegate()->OnURLFetchComplete(fetcher);
   }
 
+  void TestWalletErrorCode(
+      const std::string& error_type_string,
+      const std::string& buyer_error_type_string,
+      WalletClient::ErrorType expected_error_type,
+      AutofillMetrics::WalletErrorMetric expected_autofill_metric) {
+    static const char kResponseTemplate[] =
+        "{"
+        "  \"error_type\":\"APPLICATION_ERROR\","
+        "  \"error_detail\":\"error_detail\","
+        "  \"application_error\":\"application_error\","
+        "  \"debug_data\":"
+        "  {"
+        "    \"debug_message\":\"debug_message\","
+        "    \"stack_trace\":\"stack_trace\""
+        "  },"
+        "  \"application_error_data\":\"application_error_data\","
+        "  \"wallet_error\":"
+        "  {"
+        "    \"error_type\":\"%s\","
+        "    %s"  // Placeholder for |user_error_type|.
+        "    \"error_detail\":\"error_detail\","
+        "    \"message_for_user\":"
+        "    {"
+        "      \"text\":\"text\","
+        "      \"subtext\":\"subtext\","
+        "      \"details\":\"details\""
+        "    }"
+        "  }"
+        "}";
+    EXPECT_CALL(delegate_, OnWalletError(expected_error_type)).Times(1);
+    delegate_.ExpectLogWalletApiCallDuration(AutofillMetrics::SEND_STATUS, 1);
+    delegate_.ExpectBaselineMetrics();
+    delegate_.ExpectWalletErrorMetric(expected_autofill_metric);
+
+    std::vector<AutocheckoutStatistic> statistics;
+    wallet_client_->SendAutocheckoutStatus(autofill::SUCCESS,
+                                           GURL(kMerchantUrl),
+                                           statistics,
+                                           "google_transaction_id");
+    std::string buyer_error;
+    if (!buyer_error_type_string.empty()) {
+      buyer_error = base::StringPrintf("\"buyer_error_type\":\"%s\",",
+                                       buyer_error_type_string.c_str());
+    }
+    std::string response = base::StringPrintf(kResponseTemplate,
+                                              error_type_string.c_str(),
+                                              buyer_error.c_str());
+    VerifyAndFinishRequest(net::HTTP_INTERNAL_SERVER_ERROR,
+                           kSendAutocheckoutStatusOfSuccessValidRequest,
+                           response);
+  }
+
  protected:
   content::TestBrowserThreadBundle thread_bundle_;
   scoped_ptr<WalletClient> wallet_client_;
@@ -819,22 +872,98 @@
   net::TestURLFetcherFactory factory_;
 };
 
-TEST_F(WalletClientTest, WalletError) {
-  EXPECT_CALL(delegate_, OnWalletError(
-      WalletClient::SERVICE_UNAVAILABLE)).Times(1);
-  delegate_.ExpectLogWalletApiCallDuration(AutofillMetrics::SEND_STATUS, 1);
-  delegate_.ExpectBaselineMetrics();
-  delegate_.ExpectWalletErrorMetric(
-      AutofillMetrics::WALLET_SERVICE_UNAVAILABLE);
+TEST_F(WalletClientTest, WalletErrorCodes) {
+  struct {
+    std::string error_type_string;
+    std::string buyer_error_type_string;
+    WalletClient::ErrorType expected_error_type;
+    AutofillMetrics::WalletErrorMetric expected_autofill_metric;
+  } test_cases[] = {
+      // General |BUYER_ACCOUNT_ERROR| with no |buyer_error_type_string|.
+      {
+          "buyer_account_error",
+          "",
+          WalletClient::BUYER_ACCOUNT_ERROR,
+          AutofillMetrics::WALLET_BUYER_ACCOUNT_ERROR
+      },
+      // |BUYER_ACCOUNT_ERROR| with "buyer_legal_address_not_supported" in
+      // buyer_error_type field.
+      {
+          "buyer_account_error",
+          "bla_country_not_supported",
+          WalletClient::BUYER_LEGAL_ADDRESS_NOT_SUPPORTED,
+          AutofillMetrics::WALLET_BUYER_LEGAL_ADDRESS_NOT_SUPPORTED
+      },
+      // |BUYER_ACCOUNT_ERROR| with KYC error code in buyer_error_type field.
+      {
+          "buyer_account_error",
+          "buyer_kyc_error",
+          WalletClient::UNVERIFIED_KNOW_YOUR_CUSTOMER_STATUS,
+          AutofillMetrics::WALLET_UNVERIFIED_KNOW_YOUR_CUSTOMER_STATUS
+      },
+      // |BUYER_ACCOUNT_ERROR| with un-recognizable |buyer_error_type|.
+      {
+          "buyer_account_error",
+          "random_string",
+          WalletClient::BUYER_ACCOUNT_ERROR,
+          AutofillMetrics::WALLET_BUYER_ACCOUNT_ERROR
+      },
+      // The following are other error types we could get from Wallet.
+      {
+          "unsupported_merchant",
+          "",
+          WalletClient::UNSUPPORTED_MERCHANT,
+          AutofillMetrics::WALLET_UNSUPPORTED_MERCHANT
+      },
+      {
+          "internal_error",
+          "",
+          WalletClient::INTERNAL_ERROR,
+          AutofillMetrics::WALLET_INTERNAL_ERROR
+      },
+      {
+          "invalid_params",
+          "",
+          WalletClient::INVALID_PARAMS,
+          AutofillMetrics::WALLET_INVALID_PARAMS
+      },
+      {
+          "service_unavailable",
+          "",
+          WalletClient::SERVICE_UNAVAILABLE,
+          AutofillMetrics::WALLET_SERVICE_UNAVAILABLE
+      },
+      {
+          "unsupported_api_version",
+          "",
+          WalletClient::UNSUPPORTED_API_VERSION,
+          AutofillMetrics::WALLET_UNSUPPORTED_API_VERSION
+      },
+      // Any un-recognizable |error_type| is a |UNKNOWN_ERROR|.
+      {
+          "random_string_1",
+          "",
+          WalletClient::UNKNOWN_ERROR,
+          AutofillMetrics::WALLET_UNKNOWN_ERROR
+      },
+      {
+          "random_string_2",
+          "",
+          WalletClient::UNKNOWN_ERROR,
+          AutofillMetrics::WALLET_UNKNOWN_ERROR
+      },
+  };
 
-  std::vector<AutocheckoutStatistic> statistics;
-  wallet_client_->SendAutocheckoutStatus(autofill::SUCCESS,
-                                         GURL(kMerchantUrl),
-                                         statistics,
-                                         "google_transaction_id");
-  VerifyAndFinishRequest(net::HTTP_INTERNAL_SERVER_ERROR,
-                         kSendAutocheckoutStatusOfSuccessValidRequest,
-                         kErrorResponse);
+  for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_cases); ++i) {
+    SCOPED_TRACE(
+        base::StringPrintf("%s - %s",
+                           test_cases[i].error_type_string.c_str(),
+                           test_cases[i].buyer_error_type_string.c_str()));
+    TestWalletErrorCode(test_cases[i].error_type_string,
+                        test_cases[i].buyer_error_type_string,
+                        test_cases[i].expected_error_type,
+                        test_cases[i].expected_autofill_metric);
+  }
 }
 
 TEST_F(WalletClientTest, WalletErrorResponseMissing) {
diff --git a/components/autofill/core/browser/address.cc b/components/autofill/core/browser/address.cc
index ca522f6..6f7f2a9 100644
--- a/components/autofill/core/browser/address.cc
+++ b/components/autofill/core/browser/address.cc
@@ -62,7 +62,7 @@
       return zip_code_;
 
     case ADDRESS_HOME_COUNTRY:
-      return country_code_;
+      return ASCIIToUTF16(country_code_);
 
     default:
       return base::string16();
@@ -89,8 +89,9 @@
       break;
 
     case ADDRESS_HOME_COUNTRY:
-      DCHECK(value.empty() || value.length() == 2u);
-      country_code_ = value;
+      DCHECK(value.empty() ||
+             (value.length() == 2u && IsStringASCII(value)));
+      country_code_ = UTF16ToASCII(value);
       break;
 
     case ADDRESS_HOME_ZIP:
@@ -104,9 +105,18 @@
 
 base::string16 Address::GetInfo(const AutofillType& type,
                                 const std::string& app_locale) const {
+  if (type.html_type() == HTML_TYPE_COUNTRY_CODE) {
+    return ASCIIToUTF16(country_code_);
+  } else if (type.html_type() == HTML_TYPE_STREET_ADDRESS) {
+    base::string16 address = line1_;
+    if (!line2_.empty())
+      address += ASCIIToUTF16(", ") + line2_;
+    return address;
+  }
+
   ServerFieldType storable_type = type.GetStorableType();
   if (storable_type == ADDRESS_HOME_COUNTRY && !country_code_.empty())
-    return AutofillCountry(UTF16ToASCII(country_code_), app_locale).name();
+    return AutofillCountry(country_code_, app_locale).name();
 
   return GetRawInfo(storable_type);
 }
@@ -114,10 +124,26 @@
 bool Address::SetInfo(const AutofillType& type,
                       const base::string16& value,
                       const std::string& app_locale) {
+  if (type.html_type() == HTML_TYPE_COUNTRY_CODE) {
+    if (!value.empty() && (value.size() != 2u || !IsStringASCII(value))) {
+      country_code_ = std::string();
+      return false;
+    }
+
+    country_code_ = StringToUpperASCII(UTF16ToASCII(value));
+    return true;
+  } else if (type.html_type() == HTML_TYPE_STREET_ADDRESS) {
+    // Don't attempt to parse the address into lines, since this is potentially
+    // a user-entered address in the user's own format, so the code would have
+    // to rely on iffy heuristics at best.  Instead, just give up when importing
+    // addresses like this.
+    line1_ = line2_ = base::string16();
+    return false;
+  }
+
   ServerFieldType storable_type = type.GetStorableType();
   if (storable_type == ADDRESS_HOME_COUNTRY && !value.empty()) {
-    country_code_ =
-        ASCIIToUTF16(AutofillCountry::GetCountryCode(value, app_locale));
+    country_code_ = AutofillCountry::GetCountryCode(value, app_locale);
     return !country_code_.empty();
   }
 
@@ -132,7 +158,7 @@
 
   // Check to see if the |text| canonicalized as a country name is a match.
   std::string country_code = AutofillCountry::GetCountryCode(text, app_locale);
-  if (!country_code.empty() && country_code_ == ASCIIToUTF16(country_code))
+  if (!country_code.empty() && country_code_ == country_code)
     matching_types->insert(ADDRESS_HOME_COUNTRY);
 }
 
diff --git a/components/autofill/core/browser/address.h b/components/autofill/core/browser/address.h
index db1c731..f62c32e 100644
--- a/components/autofill/core/browser/address.h
+++ b/components/autofill/core/browser/address.h
@@ -42,13 +42,16 @@
   virtual void GetSupportedTypes(
       ServerFieldTypeSet* supported_types) const OVERRIDE;
 
-  // The address.
+  // The address, sans country info.
   base::string16 line1_;
   base::string16 line2_;
   base::string16 city_;
   base::string16 state_;
-  base::string16 country_code_;
   base::string16 zip_code_;
+
+  // The ISO 3166 2-letter country code, or an empty string if there is no
+  // country data specified for this address.
+  std::string country_code_;
 };
 
 }  // namespace autofill
diff --git a/components/autofill/core/browser/address_unittest.cc b/components/autofill/core/browser/address_unittest.cc
index 8d2e920..b5bcfaf 100644
--- a/components/autofill/core/browser/address_unittest.cc
+++ b/components/autofill/core/browser/address_unittest.cc
@@ -4,33 +4,17 @@
 
 #include <string>
 
-#include "base/message_loop/message_loop.h"
 #include "base/strings/string16.h"
 #include "base/strings/utf_string_conversions.h"
 #include "components/autofill/core/browser/address.h"
 #include "components/autofill/core/browser/autofill_type.h"
-#include "content/public/test/test_browser_thread.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
-using content::BrowserThread;
-
 namespace autofill {
 
-class AddressTest : public testing::Test {
- public:
-  // In order to access the application locale -- which the tested functions do
-  // internally -- this test must run on the UI thread.
-  AddressTest() : ui_thread_(BrowserThread::UI, &message_loop_) {}
-
- private:
-  base::MessageLoopForUI message_loop_;
-  content::TestBrowserThread ui_thread_;
-
-  DISALLOW_COPY_AND_ASSIGN(AddressTest);
-};
-
-// Test that country codes are properly decoded as country names.
-TEST_F(AddressTest, GetCountry) {
+// Test that country data can be properly returned as either a country code or a
+// localized country name.
+TEST(AddressTest, GetCountry) {
   Address address;
   EXPECT_EQ(base::string16(), address.GetRawInfo(ADDRESS_HOME_COUNTRY));
 
@@ -43,14 +27,26 @@
       AutofillType(ADDRESS_HOME_COUNTRY), ASCIIToUTF16("US"), "en-US");
   country = address.GetInfo(AutofillType(ADDRESS_HOME_COUNTRY), "en-US");
   EXPECT_EQ(ASCIIToUTF16("United States"), country);
+  country = address.GetInfo(
+      AutofillType(HTML_TYPE_COUNTRY_NAME, HTML_MODE_NONE), "en-US");
+  EXPECT_EQ(ASCIIToUTF16("United States"), country);
+  country = address.GetInfo(
+      AutofillType(HTML_TYPE_COUNTRY_CODE, HTML_MODE_NONE), "en-US");
+  EXPECT_EQ(ASCIIToUTF16("US"), country);
 
   address.SetRawInfo(ADDRESS_HOME_COUNTRY, ASCIIToUTF16("CA"));
   country = address.GetInfo(AutofillType(ADDRESS_HOME_COUNTRY), "en-US");
   EXPECT_EQ(ASCIIToUTF16("Canada"), country);
+  country = address.GetInfo(
+      AutofillType(HTML_TYPE_COUNTRY_NAME, HTML_MODE_NONE), "en-US");
+  EXPECT_EQ(ASCIIToUTF16("Canada"), country);
+  country = address.GetInfo(
+      AutofillType(HTML_TYPE_COUNTRY_CODE, HTML_MODE_NONE), "en-US");
+  EXPECT_EQ(ASCIIToUTF16("CA"), country);
 }
 
 // Test that we properly detect country codes appropriate for each country.
-TEST_F(AddressTest, SetCountry) {
+TEST(AddressTest, SetCountry) {
   Address address;
   EXPECT_EQ(base::string16(), address.GetRawInfo(ADDRESS_HOME_COUNTRY));
 
@@ -90,10 +86,31 @@
   country = address.GetInfo(AutofillType(ADDRESS_HOME_COUNTRY), "en-US");
   EXPECT_EQ(base::string16(), address.GetRawInfo(ADDRESS_HOME_COUNTRY));
   EXPECT_EQ(base::string16(), country);
+
+  // Test setting the country based on an HTML field type.
+  AutofillType html_type_country_code =
+      AutofillType(HTML_TYPE_COUNTRY_CODE, HTML_MODE_NONE);
+  address.SetInfo(html_type_country_code, ASCIIToUTF16("US"), "en-US");
+  country = address.GetInfo(AutofillType(ADDRESS_HOME_COUNTRY), "en-US");
+  EXPECT_EQ(ASCIIToUTF16("US"), address.GetRawInfo(ADDRESS_HOME_COUNTRY));
+  EXPECT_EQ(ASCIIToUTF16("United States"), country);
+
+  // Test case-insensitivity when setting the country based on an HTML field
+  // type.
+  address.SetInfo(html_type_country_code, ASCIIToUTF16("cA"), "en-US");
+  country = address.GetInfo(AutofillType(ADDRESS_HOME_COUNTRY), "en-US");
+  EXPECT_EQ(ASCIIToUTF16("CA"), address.GetRawInfo(ADDRESS_HOME_COUNTRY));
+  EXPECT_EQ(ASCIIToUTF16("Canada"), country);
+
+  // Test setting the country based on invalid data with an HTML field type.
+  address.SetInfo(html_type_country_code, ASCIIToUTF16("unknown"), "en-US");
+  country = address.GetInfo(AutofillType(ADDRESS_HOME_COUNTRY), "en-US");
+  EXPECT_EQ(base::string16(), address.GetRawInfo(ADDRESS_HOME_COUNTRY));
+  EXPECT_EQ(base::string16(), country);
 }
 
 // Test that we properly match typed values to stored country data.
-TEST_F(AddressTest, IsCountry) {
+TEST(AddressTest, IsCountry) {
   Address address;
   address.SetRawInfo(ADDRESS_HOME_COUNTRY, ASCIIToUTF16("US"));
 
@@ -132,4 +149,50 @@
   EXPECT_EQ(0U, matching_types.size());
 }
 
+// Verifies that Address::GetInfo() can correctly return a concatenated full
+// street address.
+TEST(AddressTest, GetStreetAddress) {
+  // Address has no address lines.
+  Address address;
+  EXPECT_TRUE(address.GetRawInfo(ADDRESS_HOME_LINE1).empty());
+  EXPECT_TRUE(address.GetRawInfo(ADDRESS_HOME_LINE2).empty());
+
+  AutofillType type = AutofillType(HTML_TYPE_STREET_ADDRESS, HTML_MODE_NONE);
+  EXPECT_EQ(base::string16(), address.GetInfo(type, "en-US"));
+
+  // Address has only line 1.
+  address.SetRawInfo(ADDRESS_HOME_LINE1, ASCIIToUTF16("123 Example Ave."));
+  EXPECT_FALSE(address.GetRawInfo(ADDRESS_HOME_LINE1).empty());
+  EXPECT_TRUE(address.GetRawInfo(ADDRESS_HOME_LINE2).empty());
+
+  EXPECT_EQ(ASCIIToUTF16("123 Example Ave."),
+            address.GetInfo(type, "en-US"));
+
+  // Address has lines 1 and 2.
+  address.SetRawInfo(ADDRESS_HOME_LINE2, ASCIIToUTF16("Apt. 42"));
+  EXPECT_FALSE(address.GetRawInfo(ADDRESS_HOME_LINE1).empty());
+  EXPECT_FALSE(address.GetRawInfo(ADDRESS_HOME_LINE2).empty());
+
+  EXPECT_EQ(ASCIIToUTF16("123 Example Ave., Apt. 42"),
+            address.GetInfo(type, "en-US"));
+}
+
+// Verifies that Address::SetInfo() rejects setting data for
+// HTML_TYPE_STREET_ADDRESS, as there is no good general way to parse that data
+// into the consituent address lines.
+TEST(AddressTest, SetStreetAddress) {
+  // Address has no address lines.
+  Address address;
+  address.SetRawInfo(ADDRESS_HOME_LINE1, ASCIIToUTF16("123 Example Ave."));
+  address.SetRawInfo(ADDRESS_HOME_LINE2, ASCIIToUTF16("Apt. 42"));
+  EXPECT_FALSE(address.GetRawInfo(ADDRESS_HOME_LINE1).empty());
+  EXPECT_FALSE(address.GetRawInfo(ADDRESS_HOME_LINE2).empty());
+
+  AutofillType type = AutofillType(HTML_TYPE_STREET_ADDRESS, HTML_MODE_NONE);
+  base::string16 street_address = ASCIIToUTF16("456 New St., Apt. 17");
+  EXPECT_FALSE(address.SetInfo(type, street_address, "en-US"));
+  EXPECT_TRUE(address.GetRawInfo(ADDRESS_HOME_LINE1).empty());
+  EXPECT_TRUE(address.GetRawInfo(ADDRESS_HOME_LINE2).empty());
+}
+
 }  // namespace autofill
diff --git a/components/autofill/core/browser/autofill_manager_unittest.cc b/components/autofill/core/browser/autofill_manager_unittest.cc
index e69ed0f..7aeb81e 100644
--- a/components/autofill/core/browser/autofill_manager_unittest.cc
+++ b/components/autofill/core/browser/autofill_manager_unittest.cc
@@ -2159,7 +2159,7 @@
     EXPECT_TRUE(response_data.user_submitted);
     ASSERT_EQ(11U, response_data.fields.size());
 
-    ExpectFilledField("", "country", "United States", "text",
+    ExpectFilledField("", "country", "US", "text",
                       response_data.fields[0]);
     ExpectFilledField("", "firstname", "", "text", response_data.fields[1]);
     ExpectFilledField("", "lastname", "", "text", response_data.fields[2]);
diff --git a/components/autofill/core/browser/autofill_merge_unittest.cc b/components/autofill/core/browser/autofill_merge_unittest.cc
index 21918d7..e007a59 100644
--- a/components/autofill/core/browser/autofill_merge_unittest.cc
+++ b/components/autofill/core/browser/autofill_merge_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 <map>
 #include <vector>
 
 #include "base/basictypes.h"
@@ -143,13 +144,22 @@
   // sequentially, and fills |merged_profiles| with the serialized result.
   void MergeProfiles(const std::string& profiles, std::string* merged_profiles);
 
+  // Deserializes |str| into a field type.
+  ServerFieldType StringToFieldType(const std::string& str);
+
   PersonalDataManagerMock personal_data_;
 
  private:
+  std::map<std::string, ServerFieldType> string_to_field_type_map_;
+
   DISALLOW_COPY_AND_ASSIGN(AutofillMergeTest);
 };
 
 AutofillMergeTest::AutofillMergeTest() : DataDrivenTest(GetTestDataDir()) {
+  for (size_t i = NO_SERVER_DATA; i < MAX_VALID_FIELD_TYPE; ++i) {
+    ServerFieldType field_type = static_cast<ServerFieldType>(i);
+    string_to_field_type_map_[AutofillType(field_type).ToString()] = field_type;
+  }
 }
 
 AutofillMergeTest::~AutofillMergeTest() {
@@ -209,8 +219,7 @@
         // into the field's name.
         AutofillField* field =
             const_cast<AutofillField*>(form_structure.field(i));
-        ServerFieldType type =
-            AutofillType::StringToFieldType(UTF16ToUTF8(field->name));
+        ServerFieldType type = StringToFieldType(UTF16ToUTF8(field->name));
         field->set_heuristic_type(type);
       }
 
@@ -227,6 +236,10 @@
   *merged_profiles = SerializeProfiles(personal_data_.web_profiles());
 }
 
+ServerFieldType AutofillMergeTest::StringToFieldType(const std::string& str) {
+  return string_to_field_type_map_[str];
+}
+
 TEST_F(AutofillMergeTest, DataDrivenMergeProfiles) {
   RunDataDrivenTest(GetInputDirectory(kTestName), GetOutputDirectory(kTestName),
                     kFileNamePattern);
diff --git a/components/autofill/core/browser/autofill_metrics.h b/components/autofill/core/browser/autofill_metrics.h
index 05d3a8d..d6ae790 100644
--- a/components/autofill/core/browser/autofill_metrics.h
+++ b/components/autofill/core/browser/autofill_metrics.h
@@ -329,6 +329,13 @@
     WALLET_UNSUPPORTED_API_VERSION,
     // Catch all error type.
     WALLET_UNKNOWN_ERROR,
+    // The merchant has been blacklisted for Online Wallet due to some manner
+    // of compliance violation.
+    WALLET_UNSUPPORTED_MERCHANT,
+    // Buyer Legal Address has a country which is unsupported by Wallet.
+    WALLET_BUYER_LEGAL_ADDRESS_NOT_SUPPORTED,
+    // Wallet's Know Your Customer(KYC) action is pending/failed for this user.
+    WALLET_UNVERIFIED_KNOW_YOUR_CUSTOMER_STATUS,
     NUM_WALLET_ERROR_METRICS
   };
 
diff --git a/components/autofill/core/browser/autofill_type.cc b/components/autofill/core/browser/autofill_type.cc
index c47a9df..f1e280b 100644
--- a/components/autofill/core/browser/autofill_type.cc
+++ b/components/autofill/core/browser/autofill_type.cc
@@ -137,6 +137,7 @@
     case HTML_TYPE_ORGANIZATION:
       return COMPANY;
 
+    case HTML_TYPE_STREET_ADDRESS:
     case HTML_TYPE_ADDRESS_LINE1:
     case HTML_TYPE_ADDRESS_LINE2:
     case HTML_TYPE_LOCALITY:
@@ -265,6 +266,9 @@
     case HTML_TYPE_ORGANIZATION:
       return COMPANY_NAME;
 
+    case HTML_TYPE_STREET_ADDRESS:
+      return ADDRESS_HOME_LINE1;
+
     case HTML_TYPE_ADDRESS_LINE1:
       return ADDRESS_HOME_LINE1;
 
@@ -543,6 +547,8 @@
       return "HTML_TYPE_FAMILY_NAME";
     case HTML_TYPE_ORGANIZATION:
       return "HTML_TYPE_ORGANIZATION";
+    case HTML_TYPE_STREET_ADDRESS:
+      return "HTML_TYPE_STREET_ADDRESS";
     case HTML_TYPE_ADDRESS_LINE1:
       return "HTML_TYPE_ADDRESS_LINE1";
     case HTML_TYPE_ADDRESS_LINE2:
@@ -603,101 +609,4 @@
   return std::string();
 }
 
-// static
-ServerFieldType AutofillType::StringToFieldType(const std::string& str) {
-  if (str == "NO_SERVER_DATA")
-    return NO_SERVER_DATA;
-  if (str == "UNKNOWN_TYPE")
-    return UNKNOWN_TYPE;
-  if (str == "EMPTY_TYPE")
-    return EMPTY_TYPE;
-  if (str == "NAME_FIRST")
-    return NAME_FIRST;
-  if (str == "NAME_MIDDLE")
-    return NAME_MIDDLE;
-  if (str == "NAME_LAST")
-    return NAME_LAST;
-  if (str == "NAME_MIDDLE_INITIAL")
-    return NAME_MIDDLE_INITIAL;
-  if (str == "NAME_FULL")
-    return NAME_FULL;
-  if (str == "NAME_SUFFIX")
-    return NAME_SUFFIX;
-  if (str == "NAME_BILLING_FIRST")
-    return NAME_BILLING_FIRST;
-  if (str == "NAME_BILLING_MIDDLE")
-    return NAME_BILLING_MIDDLE;
-  if (str == "NAME_BILLING_LAST")
-    return NAME_BILLING_LAST;
-  if (str == "NAME_BILLING_MIDDLE_INITIAL")
-    return NAME_BILLING_MIDDLE_INITIAL;
-  if (str == "NAME_BILLING_FULL")
-    return NAME_BILLING_FULL;
-  if (str == "NAME_BILLING_SUFFIX")
-    return NAME_BILLING_SUFFIX;
-  if (str == "EMAIL_ADDRESS")
-    return EMAIL_ADDRESS;
-  if (str == "PHONE_HOME_NUMBER")
-    return PHONE_HOME_NUMBER;
-  if (str == "PHONE_HOME_CITY_CODE")
-    return PHONE_HOME_CITY_CODE;
-  if (str == "PHONE_HOME_COUNTRY_CODE")
-    return PHONE_HOME_COUNTRY_CODE;
-  if (str == "PHONE_HOME_CITY_AND_NUMBER")
-    return PHONE_HOME_CITY_AND_NUMBER;
-  if (str == "PHONE_HOME_WHOLE_NUMBER")
-    return PHONE_HOME_WHOLE_NUMBER;
-  if (str == "ADDRESS_HOME_LINE1")
-    return ADDRESS_HOME_LINE1;
-  if (str == "ADDRESS_HOME_LINE2")
-    return ADDRESS_HOME_LINE2;
-  if (str == "ADDRESS_HOME_APT_NUM")
-    return ADDRESS_HOME_APT_NUM;
-  if (str == "ADDRESS_HOME_CITY")
-    return ADDRESS_HOME_CITY;
-  if (str == "ADDRESS_HOME_STATE")
-    return ADDRESS_HOME_STATE;
-  if (str == "ADDRESS_HOME_ZIP")
-    return ADDRESS_HOME_ZIP;
-  if (str == "ADDRESS_HOME_COUNTRY")
-    return ADDRESS_HOME_COUNTRY;
-  if (str == "ADDRESS_BILLING_LINE1")
-    return ADDRESS_BILLING_LINE1;
-  if (str == "ADDRESS_BILLING_LINE2")
-    return ADDRESS_BILLING_LINE2;
-  if (str == "ADDRESS_BILLING_APT_NUM")
-    return ADDRESS_BILLING_APT_NUM;
-  if (str == "ADDRESS_BILLING_CITY")
-    return ADDRESS_BILLING_CITY;
-  if (str == "ADDRESS_BILLING_STATE")
-    return ADDRESS_BILLING_STATE;
-  if (str == "ADDRESS_BILLING_ZIP")
-    return ADDRESS_BILLING_ZIP;
-  if (str == "ADDRESS_BILLING_COUNTRY")
-    return ADDRESS_BILLING_COUNTRY;
-  if (str == "CREDIT_CARD_NAME")
-    return CREDIT_CARD_NAME;
-  if (str == "CREDIT_CARD_NUMBER")
-    return CREDIT_CARD_NUMBER;
-  if (str == "CREDIT_CARD_EXP_MONTH")
-    return CREDIT_CARD_EXP_MONTH;
-  if (str == "CREDIT_CARD_EXP_2_DIGIT_YEAR")
-    return CREDIT_CARD_EXP_2_DIGIT_YEAR;
-  if (str == "CREDIT_CARD_EXP_4_DIGIT_YEAR")
-    return CREDIT_CARD_EXP_4_DIGIT_YEAR;
-  if (str == "CREDIT_CARD_EXP_DATE_2_DIGIT_YEAR")
-    return CREDIT_CARD_EXP_DATE_2_DIGIT_YEAR;
-  if (str == "CREDIT_CARD_EXP_DATE_4_DIGIT_YEAR")
-    return CREDIT_CARD_EXP_DATE_4_DIGIT_YEAR;
-  if (str == "CREDIT_CARD_TYPE")
-    return CREDIT_CARD_TYPE;
-  if (str == "CREDIT_CARD_VERIFICATION_CODE")
-    return CREDIT_CARD_VERIFICATION_CODE;
-  if (str == "COMPANY_NAME")
-    return COMPANY_NAME;
-
-  NOTREACHED() << "Unknown ServerFieldType " << str;
-  return UNKNOWN_TYPE;
-}
-
 }  // namespace autofill
diff --git a/components/autofill/core/browser/autofill_type.h b/components/autofill/core/browser/autofill_type.h
index 653c023..41fa613 100644
--- a/components/autofill/core/browser/autofill_type.h
+++ b/components/autofill/core/browser/autofill_type.h
@@ -20,6 +20,8 @@
   AutofillType(const AutofillType& autofill_type);
   AutofillType& operator=(const AutofillType& autofill_type);
 
+  HtmlFieldType html_type() const { return html_type_; }
+
   FieldTypeGroup group() const;
 
   // Returns true if both the |server_type_| and the |html_type_| are set to
@@ -29,24 +31,19 @@
   // Maps |this| type to a field type that can be directly stored in an Autofill
   // data model (in the sense that it makes sense to call
   // |AutofillDataModel::SetRawInfo()| with the returned field type as the first
-  // parameter).
+  // parameter).  Note that the returned type might not be exactly equivalent to
+  // |this| type.  For example, there is no exact analogue to the
+  // 'street-address' HTML type hint among the storable field types.
   ServerFieldType GetStorableType() const;
 
   // Serializes |this| type to a string.
   std::string ToString() const;
 
-  // Maps |field_type| to a field type from ADDRESS_BILLING FieldTypeGroup if
-  // field type is an Address type.
-  // TODO(isherman): This method is only used by the
-  // AutofillDialogControllerImpl class.  Consider moving it to a more focused
-  // location.
+  // Maps |field_type| to the corresponding billing field type if the field type
+  // is an address, name, or phone number type.
   static ServerFieldType GetEquivalentBillingFieldType(
       ServerFieldType field_type);
 
-  // TODO(isherman): This method is only used be a single test class.  Move the
-  // logic into there or something, eh?
-  static ServerFieldType StringToFieldType(const std::string& str);
-
  private:
   // The server-native field type, or UNKNOWN_TYPE if unset.
   ServerFieldType server_type_;
diff --git a/components/autofill/core/browser/field_types.h b/components/autofill/core/browser/field_types.h
index dc86ffd..081a7a7 100644
--- a/components/autofill/core/browser/field_types.h
+++ b/components/autofill/core/browser/field_types.h
@@ -121,6 +121,7 @@
   HTML_TYPE_ORGANIZATION,
 
   // Address types.
+  HTML_TYPE_STREET_ADDRESS,
   HTML_TYPE_ADDRESS_LINE1,
   HTML_TYPE_ADDRESS_LINE2,
   HTML_TYPE_LOCALITY,      // For U.S. addresses, corresponds to the city.
diff --git a/components/autofill/core/browser/form_structure.cc b/components/autofill/core/browser/form_structure.cc
index fd907dc..0a534f8 100644
--- a/components/autofill/core/browser/form_structure.cc
+++ b/components/autofill/core/browser/form_structure.cc
@@ -212,6 +212,9 @@
   if (autocomplete_attribute_value == "organization")
     return HTML_TYPE_ORGANIZATION;
 
+  if (autocomplete_attribute_value == "street-address")
+    return HTML_TYPE_STREET_ADDRESS;
+
   if (autocomplete_attribute_value == "address-line1")
     return HTML_TYPE_ADDRESS_LINE1;
 
diff --git a/components/autofill/core/browser/personal_data_manager.h b/components/autofill/core/browser/personal_data_manager.h
index b9ab979..9b71aa5 100644
--- a/components/autofill/core/browser/personal_data_manager.h
+++ b/components/autofill/core/browser/personal_data_manager.h
@@ -26,6 +26,7 @@
 }
 
 namespace autofill {
+class AutofillInteractiveTest;
 class AutofillMetrics;
 class AutofillTest;
 class FormStructure;
@@ -182,6 +183,7 @@
   FRIEND_TEST_ALL_PREFIXES(AutofillMetricsTest, AutofillIsEnabledAtStartup);
   FRIEND_TEST_ALL_PREFIXES(PersonalDataManagerTest,
                            AggregateExistingAuxiliaryProfile);
+  friend class autofill::AutofillInteractiveTest;
   friend class autofill::AutofillTest;
   friend class autofill::PersonalDataManagerFactory;
   friend class PersonalDataManagerTest;
diff --git a/components/autofill_content_browser.target.darwin-arm.mk b/components/autofill_content_browser.target.darwin-arm.mk
index a29898a..7e8787a 100644
--- a/components/autofill_content_browser.target.darwin-arm.mk
+++ b/components/autofill_content_browser.target.darwin-arm.mk
@@ -107,6 +107,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DFEATURE_ENABLE_SSL' \
 	'-DFEATURE_ENABLE_VOICEMAIL' \
@@ -242,6 +243,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DFEATURE_ENABLE_SSL' \
 	'-DFEATURE_ENABLE_VOICEMAIL' \
diff --git a/components/autofill_content_browser.target.darwin-mips.mk b/components/autofill_content_browser.target.darwin-mips.mk
index 8e550a8..83d058b 100644
--- a/components/autofill_content_browser.target.darwin-mips.mk
+++ b/components/autofill_content_browser.target.darwin-mips.mk
@@ -106,6 +106,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DFEATURE_ENABLE_SSL' \
 	'-DFEATURE_ENABLE_VOICEMAIL' \
@@ -240,6 +241,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DFEATURE_ENABLE_SSL' \
 	'-DFEATURE_ENABLE_VOICEMAIL' \
diff --git a/components/autofill_content_browser.target.darwin-x86.mk b/components/autofill_content_browser.target.darwin-x86.mk
index a2c9ed2..8760e97 100644
--- a/components/autofill_content_browser.target.darwin-x86.mk
+++ b/components/autofill_content_browser.target.darwin-x86.mk
@@ -109,6 +109,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DFEATURE_ENABLE_SSL' \
 	'-DFEATURE_ENABLE_VOICEMAIL' \
@@ -246,6 +247,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DFEATURE_ENABLE_SSL' \
 	'-DFEATURE_ENABLE_VOICEMAIL' \
diff --git a/components/autofill_content_browser.target.linux-arm.mk b/components/autofill_content_browser.target.linux-arm.mk
index a29898a..7e8787a 100644
--- a/components/autofill_content_browser.target.linux-arm.mk
+++ b/components/autofill_content_browser.target.linux-arm.mk
@@ -107,6 +107,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DFEATURE_ENABLE_SSL' \
 	'-DFEATURE_ENABLE_VOICEMAIL' \
@@ -242,6 +243,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DFEATURE_ENABLE_SSL' \
 	'-DFEATURE_ENABLE_VOICEMAIL' \
diff --git a/components/autofill_content_browser.target.linux-mips.mk b/components/autofill_content_browser.target.linux-mips.mk
index 8e550a8..83d058b 100644
--- a/components/autofill_content_browser.target.linux-mips.mk
+++ b/components/autofill_content_browser.target.linux-mips.mk
@@ -106,6 +106,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DFEATURE_ENABLE_SSL' \
 	'-DFEATURE_ENABLE_VOICEMAIL' \
@@ -240,6 +241,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DFEATURE_ENABLE_SSL' \
 	'-DFEATURE_ENABLE_VOICEMAIL' \
diff --git a/components/autofill_content_browser.target.linux-x86.mk b/components/autofill_content_browser.target.linux-x86.mk
index a2c9ed2..8760e97 100644
--- a/components/autofill_content_browser.target.linux-x86.mk
+++ b/components/autofill_content_browser.target.linux-x86.mk
@@ -109,6 +109,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DFEATURE_ENABLE_SSL' \
 	'-DFEATURE_ENABLE_VOICEMAIL' \
@@ -246,6 +247,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DFEATURE_ENABLE_SSL' \
 	'-DFEATURE_ENABLE_VOICEMAIL' \
diff --git a/components/autofill_content_renderer.target.darwin-arm.mk b/components/autofill_content_renderer.target.darwin-arm.mk
index c3a932b..607bd46 100644
--- a/components/autofill_content_renderer.target.darwin-arm.mk
+++ b/components/autofill_content_renderer.target.darwin-arm.mk
@@ -87,6 +87,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -192,6 +193,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=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 e09cdbc..1bb72f6 100644
--- a/components/autofill_content_renderer.target.darwin-mips.mk
+++ b/components/autofill_content_renderer.target.darwin-mips.mk
@@ -86,6 +86,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -190,6 +191,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=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 5fef75e..e9b88c5 100644
--- a/components/autofill_content_renderer.target.darwin-x86.mk
+++ b/components/autofill_content_renderer.target.darwin-x86.mk
@@ -89,6 +89,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -197,6 +198,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/components/autofill_content_renderer.target.linux-arm.mk b/components/autofill_content_renderer.target.linux-arm.mk
index c3a932b..607bd46 100644
--- a/components/autofill_content_renderer.target.linux-arm.mk
+++ b/components/autofill_content_renderer.target.linux-arm.mk
@@ -87,6 +87,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -192,6 +193,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=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 e09cdbc..1bb72f6 100644
--- a/components/autofill_content_renderer.target.linux-mips.mk
+++ b/components/autofill_content_renderer.target.linux-mips.mk
@@ -86,6 +86,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -190,6 +191,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=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 5fef75e..e9b88c5 100644
--- a/components/autofill_content_renderer.target.linux-x86.mk
+++ b/components/autofill_content_renderer.target.linux-x86.mk
@@ -89,6 +89,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -197,6 +198,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/components/autofill_core_browser.target.darwin-arm.mk b/components/autofill_core_browser.target.darwin-arm.mk
index d69fa71..b7503b7 100644
--- a/components/autofill_core_browser.target.darwin-arm.mk
+++ b/components/autofill_core_browser.target.darwin-arm.mk
@@ -128,6 +128,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DFEATURE_ENABLE_SSL' \
 	'-DFEATURE_ENABLE_VOICEMAIL' \
@@ -263,6 +264,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DFEATURE_ENABLE_SSL' \
 	'-DFEATURE_ENABLE_VOICEMAIL' \
diff --git a/components/autofill_core_browser.target.darwin-mips.mk b/components/autofill_core_browser.target.darwin-mips.mk
index 643a018..e12ca1d 100644
--- a/components/autofill_core_browser.target.darwin-mips.mk
+++ b/components/autofill_core_browser.target.darwin-mips.mk
@@ -127,6 +127,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DFEATURE_ENABLE_SSL' \
 	'-DFEATURE_ENABLE_VOICEMAIL' \
@@ -261,6 +262,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DFEATURE_ENABLE_SSL' \
 	'-DFEATURE_ENABLE_VOICEMAIL' \
diff --git a/components/autofill_core_browser.target.darwin-x86.mk b/components/autofill_core_browser.target.darwin-x86.mk
index 81fd1d1..826f78b 100644
--- a/components/autofill_core_browser.target.darwin-x86.mk
+++ b/components/autofill_core_browser.target.darwin-x86.mk
@@ -130,6 +130,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DFEATURE_ENABLE_SSL' \
 	'-DFEATURE_ENABLE_VOICEMAIL' \
@@ -267,6 +268,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DFEATURE_ENABLE_SSL' \
 	'-DFEATURE_ENABLE_VOICEMAIL' \
diff --git a/components/autofill_core_browser.target.linux-arm.mk b/components/autofill_core_browser.target.linux-arm.mk
index d69fa71..b7503b7 100644
--- a/components/autofill_core_browser.target.linux-arm.mk
+++ b/components/autofill_core_browser.target.linux-arm.mk
@@ -128,6 +128,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DFEATURE_ENABLE_SSL' \
 	'-DFEATURE_ENABLE_VOICEMAIL' \
@@ -263,6 +264,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DFEATURE_ENABLE_SSL' \
 	'-DFEATURE_ENABLE_VOICEMAIL' \
diff --git a/components/autofill_core_browser.target.linux-mips.mk b/components/autofill_core_browser.target.linux-mips.mk
index 643a018..e12ca1d 100644
--- a/components/autofill_core_browser.target.linux-mips.mk
+++ b/components/autofill_core_browser.target.linux-mips.mk
@@ -127,6 +127,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DFEATURE_ENABLE_SSL' \
 	'-DFEATURE_ENABLE_VOICEMAIL' \
@@ -261,6 +262,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DFEATURE_ENABLE_SSL' \
 	'-DFEATURE_ENABLE_VOICEMAIL' \
diff --git a/components/autofill_core_browser.target.linux-x86.mk b/components/autofill_core_browser.target.linux-x86.mk
index 81fd1d1..826f78b 100644
--- a/components/autofill_core_browser.target.linux-x86.mk
+++ b/components/autofill_core_browser.target.linux-x86.mk
@@ -130,6 +130,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DFEATURE_ENABLE_SSL' \
 	'-DFEATURE_ENABLE_VOICEMAIL' \
@@ -267,6 +268,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DFEATURE_ENABLE_SSL' \
 	'-DFEATURE_ENABLE_VOICEMAIL' \
diff --git a/components/autofill_core_common.target.darwin-arm.mk b/components/autofill_core_common.target.darwin-arm.mk
index e6d5505..49e5c78 100644
--- a/components/autofill_core_common.target.darwin-arm.mk
+++ b/components/autofill_core_common.target.darwin-arm.mk
@@ -97,6 +97,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DPOSIX_AVOID_MMAP' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-D__STDC_CONSTANT_MACROS' \
@@ -207,6 +208,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DPOSIX_AVOID_MMAP' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-D__STDC_CONSTANT_MACROS' \
diff --git a/components/autofill_core_common.target.darwin-mips.mk b/components/autofill_core_common.target.darwin-mips.mk
index 6ca808c..3cab27f 100644
--- a/components/autofill_core_common.target.darwin-mips.mk
+++ b/components/autofill_core_common.target.darwin-mips.mk
@@ -96,6 +96,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DPOSIX_AVOID_MMAP' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-D__STDC_CONSTANT_MACROS' \
@@ -205,6 +206,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DPOSIX_AVOID_MMAP' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-D__STDC_CONSTANT_MACROS' \
diff --git a/components/autofill_core_common.target.darwin-x86.mk b/components/autofill_core_common.target.darwin-x86.mk
index 3de9cad..5208989 100644
--- a/components/autofill_core_common.target.darwin-x86.mk
+++ b/components/autofill_core_common.target.darwin-x86.mk
@@ -99,6 +99,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
@@ -211,6 +212,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
diff --git a/components/autofill_core_common.target.linux-arm.mk b/components/autofill_core_common.target.linux-arm.mk
index e6d5505..49e5c78 100644
--- a/components/autofill_core_common.target.linux-arm.mk
+++ b/components/autofill_core_common.target.linux-arm.mk
@@ -97,6 +97,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DPOSIX_AVOID_MMAP' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-D__STDC_CONSTANT_MACROS' \
@@ -207,6 +208,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DPOSIX_AVOID_MMAP' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-D__STDC_CONSTANT_MACROS' \
diff --git a/components/autofill_core_common.target.linux-mips.mk b/components/autofill_core_common.target.linux-mips.mk
index 6ca808c..3cab27f 100644
--- a/components/autofill_core_common.target.linux-mips.mk
+++ b/components/autofill_core_common.target.linux-mips.mk
@@ -96,6 +96,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DPOSIX_AVOID_MMAP' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-D__STDC_CONSTANT_MACROS' \
@@ -205,6 +206,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DPOSIX_AVOID_MMAP' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-D__STDC_CONSTANT_MACROS' \
diff --git a/components/autofill_core_common.target.linux-x86.mk b/components/autofill_core_common.target.linux-x86.mk
index 3de9cad..5208989 100644
--- a/components/autofill_core_common.target.linux-x86.mk
+++ b/components/autofill_core_common.target.linux-x86.mk
@@ -99,6 +99,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
@@ -211,6 +212,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
diff --git a/components/nacl/loader/nacl_sandbox_linux.cc b/components/nacl/loader/nacl_sandbox_linux.cc
index 3041db6..c93aba7 100644
--- a/components/nacl/loader/nacl_sandbox_linux.cc
+++ b/components/nacl/loader/nacl_sandbox_linux.cc
@@ -137,11 +137,6 @@
       content::InitializeSandbox(NaClBpfSandboxPolicy);
   if (sandbox_is_initialized) {
     RunSandboxSanityChecks();
-    // TODO(jln): Find a way to fix this.
-    // The sandbox' SIGSYS handler trips NaCl, so we disable it.
-    // If SIGSYS is triggered it'll now execute the default action
-    // (CORE). This will make it hard to track down bugs and sandbox violations.
-    CHECK(signal(SIGSYS, SIG_DFL) != SIG_ERR);
     return true;
   }
   return false;
diff --git a/components/visitedlink_renderer.target.darwin-arm.mk b/components/visitedlink_renderer.target.darwin-arm.mk
index ebabeb0..4930623 100644
--- a/components/visitedlink_renderer.target.darwin-arm.mk
+++ b/components/visitedlink_renderer.target.darwin-arm.mk
@@ -81,6 +81,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
@@ -192,6 +193,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
diff --git a/components/visitedlink_renderer.target.darwin-mips.mk b/components/visitedlink_renderer.target.darwin-mips.mk
index 7ce00dd..00836e3 100644
--- a/components/visitedlink_renderer.target.darwin-mips.mk
+++ b/components/visitedlink_renderer.target.darwin-mips.mk
@@ -80,6 +80,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
@@ -190,6 +191,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
diff --git a/components/visitedlink_renderer.target.darwin-x86.mk b/components/visitedlink_renderer.target.darwin-x86.mk
index b734a55..69f3038 100644
--- a/components/visitedlink_renderer.target.darwin-x86.mk
+++ b/components/visitedlink_renderer.target.darwin-x86.mk
@@ -83,6 +83,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
@@ -197,6 +198,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
diff --git a/components/visitedlink_renderer.target.linux-arm.mk b/components/visitedlink_renderer.target.linux-arm.mk
index ebabeb0..4930623 100644
--- a/components/visitedlink_renderer.target.linux-arm.mk
+++ b/components/visitedlink_renderer.target.linux-arm.mk
@@ -81,6 +81,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
@@ -192,6 +193,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
diff --git a/components/visitedlink_renderer.target.linux-mips.mk b/components/visitedlink_renderer.target.linux-mips.mk
index 7ce00dd..00836e3 100644
--- a/components/visitedlink_renderer.target.linux-mips.mk
+++ b/components/visitedlink_renderer.target.linux-mips.mk
@@ -80,6 +80,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
@@ -190,6 +191,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
diff --git a/components/visitedlink_renderer.target.linux-x86.mk b/components/visitedlink_renderer.target.linux-x86.mk
index b734a55..69f3038 100644
--- a/components/visitedlink_renderer.target.linux-x86.mk
+++ b/components/visitedlink_renderer.target.linux-x86.mk
@@ -83,6 +83,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
@@ -197,6 +198,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
diff --git a/components/web_contents_delegate_android.target.darwin-arm.mk b/components/web_contents_delegate_android.target.darwin-arm.mk
index 1fca453..8ff1cbd 100644
--- a/components/web_contents_delegate_android.target.darwin-arm.mk
+++ b/components/web_contents_delegate_android.target.darwin-arm.mk
@@ -87,6 +87,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
@@ -196,6 +197,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
diff --git a/components/web_contents_delegate_android.target.darwin-mips.mk b/components/web_contents_delegate_android.target.darwin-mips.mk
index 2966843..953f1f2 100644
--- a/components/web_contents_delegate_android.target.darwin-mips.mk
+++ b/components/web_contents_delegate_android.target.darwin-mips.mk
@@ -86,6 +86,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
@@ -194,6 +195,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
diff --git a/components/web_contents_delegate_android.target.darwin-x86.mk b/components/web_contents_delegate_android.target.darwin-x86.mk
index e15029a..0410db5 100644
--- a/components/web_contents_delegate_android.target.darwin-x86.mk
+++ b/components/web_contents_delegate_android.target.darwin-x86.mk
@@ -88,6 +88,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
@@ -199,6 +200,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
diff --git a/components/web_contents_delegate_android.target.linux-arm.mk b/components/web_contents_delegate_android.target.linux-arm.mk
index 1fca453..8ff1cbd 100644
--- a/components/web_contents_delegate_android.target.linux-arm.mk
+++ b/components/web_contents_delegate_android.target.linux-arm.mk
@@ -87,6 +87,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
@@ -196,6 +197,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
diff --git a/components/web_contents_delegate_android.target.linux-mips.mk b/components/web_contents_delegate_android.target.linux-mips.mk
index 2966843..953f1f2 100644
--- a/components/web_contents_delegate_android.target.linux-mips.mk
+++ b/components/web_contents_delegate_android.target.linux-mips.mk
@@ -86,6 +86,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
@@ -194,6 +195,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
diff --git a/components/web_contents_delegate_android.target.linux-x86.mk b/components/web_contents_delegate_android.target.linux-x86.mk
index e15029a..0410db5 100644
--- a/components/web_contents_delegate_android.target.linux-x86.mk
+++ b/components/web_contents_delegate_android.target.linux-x86.mk
@@ -88,6 +88,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
@@ -199,6 +200,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
diff --git a/content/browser/android/in_process/synchronous_compositor_impl.cc b/content/browser/android/in_process/synchronous_compositor_impl.cc
index 041511e..74048d8 100644
--- a/content/browser/android/in_process/synchronous_compositor_impl.cc
+++ b/content/browser/android/in_process/synchronous_compositor_impl.cc
@@ -66,10 +66,16 @@
   }
 
   virtual scoped_refptr<cc::ContextProvider>
-      GetOffscreenContextProviderForMainThread() OVERRIDE {
-    NOTIMPLEMENTED()
-        << "Synchronous compositor does not support main thread context yet.";
-    return scoped_refptr<cc::ContextProvider>();
+  GetOffscreenContextProviderForMainThread() OVERRIDE {
+    if (!offscreen_context_for_main_thread_.get() ||
+        offscreen_context_for_main_thread_->DestroyedOnMainThread()) {
+      offscreen_context_for_main_thread_ =
+          webkit::gpu::ContextProviderInProcess::Create();
+      if (offscreen_context_for_main_thread_.get() &&
+          !offscreen_context_for_main_thread_->BindToCurrentThread())
+        offscreen_context_for_main_thread_ = NULL;
+    }
+    return offscreen_context_for_main_thread_;
   }
 
   // This is called on both renderer main thread (offscreen context creation
@@ -95,6 +101,7 @@
   // Only guards construction of |offscreen_context_for_compositor_thread_|,
   // not usage.
   base::Lock offscreen_context_for_compositor_thread_creation_lock_;
+  scoped_refptr<cc::ContextProvider> offscreen_context_for_main_thread_;
   scoped_refptr<cc::ContextProvider> offscreen_context_for_compositor_thread_;
 };
 
diff --git a/content/browser/aura/gpu_process_transport_factory.cc b/content/browser/aura/gpu_process_transport_factory.cc
index 8822e85..4a047c6 100644
--- a/content/browser/aura/gpu_process_transport_factory.cc
+++ b/content/browser/aura/gpu_process_transport_factory.cc
@@ -232,6 +232,11 @@
         CreateContextCommon(data->swap_client->AsWeakPtr(), data->surface_id);
   }
   if (!context) {
+    if (ui::Compositor::WasInitializedWithThread()) {
+      LOG(FATAL) << "Failed to create UI context, but can't use software "
+                 " compositing with browser threaded compositing. Aborting.";
+    }
+
     scoped_ptr<SoftwareBrowserCompositorOutputSurface> surface =
         SoftwareBrowserCompositorOutputSurface::Create(
             CreateSoftwareOutputDevice(compositor));
diff --git a/content/browser/browser_main_loop.cc b/content/browser/browser_main_loop.cc
index 1c6b1a0..c51b5c5 100644
--- a/content/browser/browser_main_loop.cc
+++ b/content/browser/browser_main_loop.cc
@@ -7,10 +7,12 @@
 #include "base/bind.h"
 #include "base/command_line.h"
 #include "base/debug/trace_event.h"
+#include "base/file_util.h"
 #include "base/logging.h"
 #include "base/message_loop/message_loop.h"
 #include "base/metrics/field_trial.h"
 #include "base/metrics/histogram.h"
+#include "base/path_service.h"
 #include "base/pending_task.h"
 #include "base/power_monitor/power_monitor.h"
 #include "base/power_monitor/power_monitor_device_source.h"
@@ -120,48 +122,54 @@
   TRACE_EVENT0("startup", "SetupSandbox");
   // TODO(evanm): move this into SandboxWrapper; I'm just trying to move this
   // code en masse out of chrome_main for now.
-  const char* sandbox_binary = NULL;
+  base::FilePath sandbox_binary;
+  bool env_chrome_devel_sandbox_set = false;
   struct stat st;
 
-  // In Chromium branded builds, developers can set an environment variable to
-  // use the development sandbox. See
-  // http://code.google.com/p/chromium/wiki/LinuxSUIDSandboxDevelopment
-  if (stat(base::kProcSelfExe, &st) == 0 && st.st_uid == getuid())
-    sandbox_binary = getenv("CHROME_DEVEL_SANDBOX");
-
-#if defined(LINUX_SANDBOX_PATH)
-  if (!sandbox_binary)
-    sandbox_binary = LINUX_SANDBOX_PATH;
-#endif
-
   const bool want_setuid_sandbox =
       !parsed_command_line.HasSwitch(switches::kNoSandbox) &&
       !parsed_command_line.HasSwitch(switches::kDisableSetuidSandbox);
 
   if (want_setuid_sandbox) {
+    base::FilePath exe_dir;
+    if (PathService::Get(base::DIR_EXE, &exe_dir)) {
+      base::FilePath sandbox_candidate = exe_dir.AppendASCII("chrome-sandbox");
+      if (base::PathExists(sandbox_candidate))
+        sandbox_binary = sandbox_candidate;
+    }
+
+    // In user-managed builds, including development builds, an environment
+    // variable is required to enable the sandbox. See
+    // http://code.google.com/p/chromium/wiki/LinuxSUIDSandboxDevelopment
+    if (sandbox_binary.empty() &&
+        stat(base::kProcSelfExe, &st) == 0 && st.st_uid == getuid()) {
+      const char* devel_sandbox_path = getenv("CHROME_DEVEL_SANDBOX");
+      if (devel_sandbox_path) {
+        env_chrome_devel_sandbox_set = true;
+        sandbox_binary = base::FilePath(devel_sandbox_path);
+      }
+    }
+
     static const char no_suid_error[] = "Running without the SUID sandbox! See "
         "https://code.google.com/p/chromium/wiki/LinuxSUIDSandboxDevelopment "
         "for more information on developing with the sandbox on.";
-    if (!sandbox_binary) {
-      // This needs to be fatal. Talk to security@chromium.org if you feel
-      // otherwise.
-      LOG(FATAL) << no_suid_error;
-    }
-    // TODO(jln): an empty CHROME_DEVEL_SANDBOX environment variable (as
-    // opposed to a non existing one) is not fatal yet. This is needed because
-    // of existing bots and scripts. Fix it (crbug.com/245376).
-    if (sandbox_binary && *sandbox_binary == '\0')
-      LOG(ERROR) << no_suid_error;
-  }
+    if (sandbox_binary.empty()) {
+      if (!env_chrome_devel_sandbox_set) {
+        // This needs to be fatal. Talk to security@chromium.org if you feel
+        // otherwise.
+        LOG(FATAL) << no_suid_error;
+      }
 
-  std::string sandbox_cmd;
-  if (want_setuid_sandbox && sandbox_binary) {
-    sandbox_cmd = sandbox_binary;
+      // TODO(jln): an empty CHROME_DEVEL_SANDBOX environment variable (as
+      // opposed to a non existing one) is not fatal yet. This is needed
+      // because of existing bots and scripts. Fix it (crbug.com/245376).
+      LOG(ERROR) << no_suid_error;
+    }
   }
 
   // Tickle the sandbox host and zygote host so they fork now.
-  RenderSandboxHostLinux::GetInstance()->Init(sandbox_cmd);
-  ZygoteHostImpl::GetInstance()->Init(sandbox_cmd);
+  RenderSandboxHostLinux::GetInstance()->Init(sandbox_binary.value());
+  ZygoteHostImpl::GetInstance()->Init(sandbox_binary.value());
 }
 #endif
 
diff --git a/content/browser/browser_thread_impl.cc b/content/browser/browser_thread_impl.cc
index 90f660a..fb6feac 100644
--- a/content/browser/browser_thread_impl.cc
+++ b/content/browser/browser_thread_impl.cc
@@ -339,14 +339,14 @@
 }
 
 // static
-bool BrowserThread::IsWellKnownThread(ID identifier) {
+bool BrowserThread::IsThreadInitialized(ID identifier) {
   if (g_globals == NULL)
     return false;
 
   BrowserThreadGlobals& globals = g_globals.Get();
   base::AutoLock lock(globals.lock);
-  return (identifier >= 0 && identifier < ID_COUNT &&
-          globals.threads[identifier]);
+  DCHECK(identifier >= 0 && identifier < ID_COUNT);
+  return globals.threads[identifier] != NULL;
 }
 
 // static
diff --git a/content/browser/device_orientation/data_fetcher_shared_memory_android.cc b/content/browser/device_orientation/data_fetcher_shared_memory_android.cc
index b051557..8f6e202 100644
--- a/content/browser/device_orientation/data_fetcher_shared_memory_android.cc
+++ b/content/browser/device_orientation/data_fetcher_shared_memory_android.cc
@@ -27,9 +27,9 @@
     DeviceMotionHardwareBuffer* buffer) {
   DCHECK(buffer);
   device_motion_buffer_ = buffer;
-  return DataFetcherImplAndroid::GetInstance()->
+  started_ = DataFetcherImplAndroid::GetInstance()->
       StartFetchingDeviceMotionData(buffer);
-  started_ = true;
+  return started_;
 }
 
 void DataFetcherSharedMemory::StopFetchingDeviceMotionData() {
diff --git a/content/browser/devtools/devtools_protocol.cc b/content/browser/devtools/devtools_protocol.cc
index d39cc33..8398084 100644
--- a/content/browser/devtools/devtools_protocol.cc
+++ b/content/browser/devtools/devtools_protocol.cc
@@ -132,7 +132,11 @@
 DevToolsProtocol::Response::Response(int id,
                                      int error_code,
                                      const std::string& error_message)
-    : id_(id), error_code_(error_code), error_message_(error_message) {}
+    : id_(id),
+      error_code_(error_code),
+      error_message_(error_message),
+      is_async_promise_(false) {
+}
 
 DevToolsProtocol::Notification::Notification(const std::string& method,
                                              base::DictionaryValue* params)
diff --git a/content/browser/devtools/render_view_devtools_agent_host.cc b/content/browser/devtools/render_view_devtools_agent_host.cc
index 0c2d323..efc5242 100644
--- a/content/browser/devtools/render_view_devtools_agent_host.cc
+++ b/content/browser/devtools/render_view_devtools_agent_host.cc
@@ -229,7 +229,7 @@
 
 void RenderViewDevToolsAgentHost::AboutToNavigateRenderView(
     RenderViewHost* dest_rvh) {
-  if (!render_view_host_)
+  if (!render_view_host_ || !IsAttached())
     return;
 
   if (render_view_host_ == dest_rvh && static_cast<RenderViewHostImpl*>(
diff --git a/content/browser/download/base_file.cc b/content/browser/download/base_file.cc
index 466be32..90ab485 100644
--- a/content/browser/download/base_file.cc
+++ b/content/browser/download/base_file.cc
@@ -211,6 +211,10 @@
   Close();
 }
 
+void BaseFile::SetClientGuid(const std::string& guid) {
+  client_guid_ = guid;
+}
+
 // OS_WIN, OS_MACOSX and OS_LINUX have specialized implementations.
 #if !defined(OS_WIN) && !defined(OS_MACOSX) && !defined(OS_LINUX)
 DownloadInterruptReason BaseFile::AnnotateWithSourceInformation() {
diff --git a/content/browser/download/base_file.h b/content/browser/download/base_file.h
index 9c1261c..f1686c8 100644
--- a/content/browser/download/base_file.h
+++ b/content/browser/download/base_file.h
@@ -69,8 +69,15 @@
   // Indicate that the download has finished. No new data will be received.
   void Finish();
 
+  // Set the client guid which will be used to identify the app to the
+  // system AV scanning function. Should be called before
+  // AnnotateWithSourceInformation() to take effect.
+  void SetClientGuid(const std::string& guid);
+
   // Informs the OS that this file came from the internet. Returns a
   // DownloadInterruptReason indicating the result of the operation.
+  // Note: SetClientGuid() should be called before this function on
+  // Windows to ensure the correct app client ID is available.
   DownloadInterruptReason AnnotateWithSourceInformation();
 
   base::FilePath full_path() const { return full_path_; }
@@ -142,6 +149,8 @@
   // The URL where the download was initiated.
   GURL referrer_url_;
 
+  std::string client_guid_;
+
   // OS file stream for writing
   scoped_ptr<net::FileStream> file_stream_;
 
diff --git a/content/browser/download/base_file_win.cc b/content/browser/download/base_file_win.cc
index 398e5fc..252f049 100644
--- a/content/browser/download/base_file_win.cc
+++ b/content/browser/download/base_file_win.cc
@@ -5,9 +5,12 @@
 #include "content/browser/download/base_file.h"
 
 #include <windows.h>
+#include <cguid.h>
+#include <objbase.h>
 #include <shellapi.h>
 
 #include "base/file_util.h"
+#include "base/guid.h"
 #include "base/metrics/histogram.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/threading/thread_restrictions.h"
@@ -326,7 +329,16 @@
 
   bound_net_log_.BeginEvent(net::NetLog::TYPE_DOWNLOAD_FILE_ANNOTATED);
   DownloadInterruptReason result = DOWNLOAD_INTERRUPT_REASON_NONE;
-  HRESULT hr = ScanAndSaveDownloadedFile(full_path_, source_url_);
+  std::string braces_guid = "{" + client_guid_ + "}";
+  GUID guid = GUID_NULL;
+  if (base::IsValidGUID(client_guid_)) {
+    HRESULT hr = CLSIDFromString(
+        base::UTF8ToUTF16(braces_guid).c_str(), &guid);
+    if (FAILED(hr))
+      guid = GUID_NULL;
+  }
+
+  HRESULT hr = AVScanFile(full_path_, source_url_.spec(), guid);
 
   // If the download file is missing after the call, then treat this as an
   // interrupted download.
diff --git a/content/browser/download/download_file.h b/content/browser/download/download_file.h
index a8e18ff..568e7ee 100644
--- a/content/browser/download/download_file.h
+++ b/content/browser/download/download_file.h
@@ -73,6 +73,11 @@
   // Returns the current (intermediate) state of the hash as a byte string.
   virtual std::string GetHashState() = 0;
 
+  // Set the application GUID to be used to identify the app to the
+  // system AV function when scanning downloaded files. Should be called
+  // before RenameAndAnnotate() to take effect.
+  virtual void SetClientGuid(const std::string& guid) = 0;
+
   // For testing.  Must be called on FILE thread.
   // TODO(rdsmith): Replace use of EnsureNoPendingDownloads()
   // on the DownloadManager with a test-specific DownloadFileFactory
diff --git a/content/browser/download/download_file_impl.cc b/content/browser/download/download_file_impl.cc
index bbe317b..67bee81 100644
--- a/content/browser/download/download_file_impl.cc
+++ b/content/browser/download/download_file_impl.cc
@@ -200,6 +200,10 @@
   return file_.GetHashState();
 }
 
+void DownloadFileImpl::SetClientGuid(const std::string& guid) {
+  file_.SetClientGuid(guid);
+}
+
 void DownloadFileImpl::StreamActive() {
   base::TimeTicks start(base::TimeTicks::Now());
   base::TimeTicks now;
diff --git a/content/browser/download/download_file_impl.h b/content/browser/download/download_file_impl.h
index 963ae9f..9a50870 100644
--- a/content/browser/download/download_file_impl.h
+++ b/content/browser/download/download_file_impl.h
@@ -63,6 +63,7 @@
   virtual int64 CurrentSpeed() const OVERRIDE;
   virtual bool GetHash(std::string* hash) OVERRIDE;
   virtual std::string GetHashState() OVERRIDE;
+  virtual void SetClientGuid(const std::string& guid) OVERRIDE;
 
  protected:
   // For test class overrides.
diff --git a/content/browser/download/download_file_unittest.cc b/content/browser/download/download_file_unittest.cc
index ebf501d..867b76f 100644
--- a/content/browser/download/download_file_unittest.cc
+++ b/content/browser/download/download_file_unittest.cc
@@ -138,6 +138,8 @@
                              net::BoundNetLog(),
                              scoped_ptr<PowerSaveBlocker>().Pass(),
                              observer_factory_.GetWeakPtr()));
+    download_file_->SetClientGuid(
+        "12345678-ABCD-1234-DCBA-123456789ABC");
 
     EXPECT_CALL(*input_stream_, Read(_, _))
         .WillOnce(Return(ByteStreamReader::STREAM_EMPTY))
diff --git a/content/browser/download/download_item_factory.h b/content/browser/download/download_item_factory.h
index 36197d5..c5e03f5 100644
--- a/content/browser/download/download_item_factory.h
+++ b/content/browser/download/download_item_factory.h
@@ -46,6 +46,8 @@
       const GURL& referrer_url,
       const base::Time& start_time,
       const base::Time& end_time,
+      const std::string& etag,
+      const std::string& last_modified,
       int64 received_bytes,
       int64 total_bytes,
       DownloadItem::DownloadState state,
diff --git a/content/browser/download/download_item_impl.cc b/content/browser/download/download_item_impl.cc
index e54ab9e..e2e86a3 100644
--- a/content/browser/download/download_item_impl.cc
+++ b/content/browser/download/download_item_impl.cc
@@ -104,6 +104,8 @@
                                    const GURL& referrer_url,
                                    const base::Time& start_time,
                                    const base::Time& end_time,
+                                   const std::string& etag,
+                                   const std::string& last_modified,
                                    int64 received_bytes,
                                    int64 total_bytes,
                                    DownloadItem::DownloadState state,
@@ -123,6 +125,8 @@
       total_bytes_(total_bytes),
       received_bytes_(received_bytes),
       bytes_per_sec_(0),
+      last_modified_time_(last_modified),
+      etag_(etag),
       last_reason_(interrupt_reason),
       start_tick_(base::TimeTicks()),
       state_(ExternalToInternalState(state)),
diff --git a/content/browser/download/download_item_impl.h b/content/browser/download/download_item_impl.h
index ac260b1..2086a54 100644
--- a/content/browser/download/download_item_impl.h
+++ b/content/browser/download/download_item_impl.h
@@ -58,6 +58,8 @@
                    const GURL& referrer_url,
                    const base::Time& start_time,
                    const base::Time& end_time,
+                   const std::string& etag,
+                   const std::string& last_modified,
                    int64 received_bytes,
                    int64 total_bytes,
                    DownloadItem::DownloadState state,
diff --git a/content/browser/download/download_manager_impl.cc b/content/browser/download/download_manager_impl.cc
index 58fe952..ccfb4cc 100644
--- a/content/browser/download/download_manager_impl.cc
+++ b/content/browser/download/download_manager_impl.cc
@@ -177,6 +177,8 @@
       const GURL& referrer_url,
       const base::Time& start_time,
       const base::Time& end_time,
+      const std::string& etag,
+      const std::string& last_modified,
       int64 received_bytes,
       int64 total_bytes,
       DownloadItem::DownloadState state,
@@ -193,6 +195,8 @@
         referrer_url,
         start_time,
         end_time,
+        etag,
+        last_modified,
         received_bytes,
         total_bytes,
         state,
@@ -418,6 +422,13 @@
           delegate_->GenerateFileHash(),
           stream.Pass(), download->GetBoundNetLog(),
           download->DestinationObserverAsWeakPtr()));
+
+  // Attach the client ID identifying the app to the AV system.
+  if (download_file.get() && delegate_) {
+    download_file->SetClientGuid(
+        delegate_->ApplicationClientIdForFileScanning());
+  }
+
   scoped_ptr<DownloadRequestHandleInterface> req_handle(
       new DownloadRequestHandle(info->request_handle));
   download->Start(download_file.Pass(), req_handle.Pass());
@@ -617,6 +628,8 @@
     const GURL& referrer_url,
     const base::Time& start_time,
     const base::Time& end_time,
+    const std::string& etag,
+    const std::string& last_modified,
     int64 received_bytes,
     int64 total_bytes,
     DownloadItem::DownloadState state,
@@ -635,6 +648,8 @@
       referrer_url,
       start_time,
       end_time,
+      etag,
+      last_modified,
       received_bytes,
       total_bytes,
       state,
diff --git a/content/browser/download/download_manager_impl.h b/content/browser/download/download_manager_impl.h
index 46d3eb7..a9384c7 100644
--- a/content/browser/download/download_manager_impl.h
+++ b/content/browser/download/download_manager_impl.h
@@ -80,6 +80,8 @@
       const GURL& referrer_url,
       const base::Time& start_time,
       const base::Time& end_time,
+      const std::string& etag,
+      const std::string& last_modified,
       int64 received_bytes,
       int64 total_bytes,
       content::DownloadItem::DownloadState state,
diff --git a/content/browser/download/download_manager_impl_unittest.cc b/content/browser/download/download_manager_impl_unittest.cc
index 2e9eff4..eba2833 100644
--- a/content/browser/download/download_manager_impl_unittest.cc
+++ b/content/browser/download/download_manager_impl_unittest.cc
@@ -78,6 +78,8 @@
           GURL(),
           base::Time(),
           base::Time(),
+          std::string(),
+          std::string(),
           0,
           0,
           DownloadItem::COMPLETE,
@@ -193,6 +195,7 @@
   MOCK_METHOD5(ChooseSavePath, void(
       WebContents*, const base::FilePath&, const base::FilePath::StringType&,
       bool, const SavePackagePathPickedCallback&));
+  MOCK_CONST_METHOD0(ApplicationClientIdForFileScanning, std::string());
 };
 
 MockDownloadManagerDelegate::MockDownloadManagerDelegate() {}
@@ -231,6 +234,8 @@
       const GURL& referrer_url,
       const base::Time& start_time,
       const base::Time& end_time,
+      const std::string& etag,
+      const std::string& last_modofied,
       int64 received_bytes,
       int64 total_bytes,
       DownloadItem::DownloadState state,
@@ -294,6 +299,8 @@
     const GURL& referrer_url,
     const base::Time& start_time,
     const base::Time& end_time,
+    const std::string& etag,
+    const std::string& last_modified,
     int64 received_bytes,
     int64 total_bytes,
     DownloadItem::DownloadState state,
@@ -357,7 +364,7 @@
   virtual ~MockDownloadFileFactory() {}
 
   // Overridden method from DownloadFileFactory
-  MOCK_METHOD8(MockCreateFile, DownloadFile*(
+  MOCK_METHOD8(MockCreateFile, MockDownloadFile*(
     const DownloadSaveInfo&,
     const base::FilePath&,
     const GURL&, const GURL&, bool,
@@ -587,9 +594,15 @@
   EXPECT_CALL(GetMockDownloadManagerDelegate(), GetSaveDir(_, _, _, _));
   EXPECT_CALL(GetMockDownloadManagerDelegate(), GenerateFileHash())
       .WillOnce(Return(true));
+  EXPECT_CALL(GetMockDownloadManagerDelegate(),
+              ApplicationClientIdForFileScanning())
+      .WillRepeatedly(Return("client-id"));
+  MockDownloadFile* mock_file = new MockDownloadFile;
+  EXPECT_CALL(*mock_file, SetClientGuid("client-id"));
   EXPECT_CALL(*mock_download_file_factory_.get(),
               MockCreateFile(Ref(*info->save_info.get()), _, _, _, true,
-                             stream.get(), _, _));
+                             stream.get(), _, _))
+      .WillOnce(Return(mock_file));
 
   download_manager_->StartDownload(
       info.Pass(), stream.Pass(), DownloadUrlParameters::OnStartedCallback());
diff --git a/content/browser/download/download_stats.cc b/content/browser/download/download_stats.cc
index f8a1e09..7831a4d 100644
--- a/content/browser/download/download_stats.cc
+++ b/content/browser/download/download_stats.cc
@@ -168,13 +168,11 @@
 }
 
 void RecordDownloadWriteSize(size_t data_len) {
-  RecordDownloadCount(WRITE_SIZE_COUNT);
   int max = 1024 * 1024;  // One Megabyte.
   UMA_HISTOGRAM_CUSTOM_COUNTS("Download.WriteSize", data_len, 1, max, 256);
 }
 
 void RecordDownloadWriteLoopCount(int count) {
-  RecordDownloadCount(WRITE_LOOP_COUNT);
   UMA_HISTOGRAM_ENUMERATION("Download.WriteLoopCount", count, 20);
 }
 
diff --git a/content/browser/download/download_stats.h b/content/browser/download/download_stats.h
index be2ae4b..ebe643e 100644
--- a/content/browser/download/download_stats.h
+++ b/content/browser/download/download_stats.h
@@ -48,11 +48,14 @@
   // Downloads that were interrupted by the OS.
   INTERRUPTED_COUNT,
 
-  // Write sizes for downloads.
-  WRITE_SIZE_COUNT,
+  // (Deprecated) Write sizes for downloads.
+  // This is equal to the number of samples in Download.WriteSize histogram.
+  DOWNLOAD_COUNT_UNUSED_10,
 
-  // Counts iterations of the BaseFile::AppendDataToFile() loop.
-  WRITE_LOOP_COUNT,
+  // (Deprecated) Counts iterations of the BaseFile::AppendDataToFile() loop.
+  // This is equal to the number of samples in Download.WriteLoopCount
+  // histogram.
+  DOWNLOAD_COUNT_UNUSED_11,
 
   // Counts interruptions that happened at the end of the download.
   INTERRUPTED_AT_END_COUNT,
diff --git a/content/browser/download/mock_download_file.h b/content/browser/download/mock_download_file.h
index 74dc75c..5d4b270 100644
--- a/content/browser/download/mock_download_file.h
+++ b/content/browser/download/mock_download_file.h
@@ -48,6 +48,7 @@
   MOCK_CONST_METHOD0(Id, int());
   MOCK_METHOD0(GetDownloadManager, DownloadManager*());
   MOCK_CONST_METHOD0(DebugString, std::string());
+  MOCK_METHOD1(SetClientGuid, void(const std::string&));
 };
 
 }  // namespace content
diff --git a/content/browser/download/save_file.cc b/content/browser/download/save_file.cc
index 80caf13..e8885e4 100644
--- a/content/browser/download/save_file.cc
+++ b/content/browser/download/save_file.cc
@@ -60,6 +60,8 @@
 }
 
 void SaveFile::AnnotateWithSourceInformation() {
+  // TODO(gbillock): If this method is called, it should set the
+  // file_.SetClientGuid() method first.
   file_.AnnotateWithSourceInformation();
 }
 
diff --git a/content/browser/gpu/gpu_data_manager_impl_private.cc b/content/browser/gpu/gpu_data_manager_impl_private.cc
index 14ed4df..bb3e5b1 100644
--- a/content/browser/gpu/gpu_data_manager_impl_private.cc
+++ b/content/browser/gpu/gpu_data_manager_impl_private.cc
@@ -34,7 +34,6 @@
 #include "ui/gl/gl_switches.h"
 #include "ui/gl/gpu_switching_manager.h"
 #include "webkit/common/webpreferences.h"
-#include "webkit/plugins/plugin_switches.h"
 
 #if defined(OS_MACOSX)
 #include <ApplicationServices/ApplicationServices.h>
diff --git a/content/browser/indexed_db/indexed_db_backing_store.cc b/content/browser/indexed_db/indexed_db_backing_store.cc
index 8267a62..5836911 100644
--- a/content/browser/indexed_db/indexed_db_backing_store.cc
+++ b/content/browser/indexed_db/indexed_db_backing_store.cc
@@ -21,6 +21,7 @@
 #include "content/common/indexed_db/indexed_db_key_path.h"
 #include "content/common/indexed_db/indexed_db_key_range.h"
 #include "third_party/WebKit/public/platform/WebIDBTypes.h"
+#include "third_party/leveldatabase/env_chromium.h"
 
 using base::StringPiece;
 
@@ -347,11 +348,12 @@
 
 class DefaultLevelDBFactory : public LevelDBFactory {
  public:
-  virtual scoped_ptr<LevelDBDatabase> OpenLevelDB(
+  virtual leveldb::Status OpenLevelDB(
       const base::FilePath& file_name,
       const LevelDBComparator* comparator,
+      scoped_ptr<LevelDBDatabase>* db,
       bool* is_disk_full) OVERRIDE {
-    return LevelDBDatabase::Open(file_name, comparator, is_disk_full);
+    return LevelDBDatabase::Open(file_name, comparator, db, is_disk_full);
   }
   virtual bool DestroyLevelDB(const base::FilePath& file_name) OVERRIDE {
     return LevelDBDatabase::Destroy(file_name);
@@ -400,9 +402,45 @@
   INDEXED_DB_LEVEL_DB_BACKING_STORE_OPEN_ATTEMPT_NON_ASCII,
   INDEXED_DB_LEVEL_DB_BACKING_STORE_OPEN_DISK_FULL,
   INDEXED_DB_LEVEL_DB_BACKING_STORE_OPEN_ORIGIN_TOO_LONG,
+  INDEXED_DB_LEVEL_DB_BACKING_STORE_OPEN_NO_RECOVERY,
   INDEXED_DB_LEVEL_DB_BACKING_STORE_OPEN_MAX,
 };
 
+bool RecoveryCouldBeFruitful(leveldb::Status status) {
+  leveldb_env::MethodID method;
+  int error = -1;
+  leveldb_env::ErrorParsingResult result = leveldb_env::ParseMethodAndError(
+      status.ToString().c_str(), &method, &error);
+  switch (result) {
+    case leveldb_env::NONE:
+      return true;
+    case leveldb_env::METHOD_AND_PFE: {
+      base::PlatformFileError pfe = static_cast<base::PlatformFileError>(error);
+      switch (pfe) {
+        case base::PLATFORM_FILE_ERROR_TOO_MANY_OPENED:
+        case base::PLATFORM_FILE_ERROR_NO_MEMORY:
+        case base::PLATFORM_FILE_ERROR_NO_SPACE:
+          return false;
+        default:
+          return true;
+      }
+    }
+    case leveldb_env::METHOD_AND_ERRNO: {
+      switch (error) {
+        case EMFILE:
+        case ENOMEM:
+        case ENOSPC:
+          return false;
+        default:
+          return true;
+      }
+    }
+    default:
+      return true;
+  }
+  return true;
+}
+
 scoped_refptr<IndexedDBBackingStore> IndexedDBBackingStore::Open(
     const std::string& origin_identifier,
     const base::FilePath& path_base,
@@ -428,7 +466,6 @@
   *data_loss = WebKit::WebIDBCallbacks::DataLossNone;
 
   scoped_ptr<LevelDBComparator> comparator(new Comparator());
-  scoped_ptr<LevelDBDatabase> db;
 
   if (!IsStringASCII(path_base.AsUTF8Unsafe())) {
     base::Histogram::FactoryGet("WebCore.IndexedDB.BackingStore.OpenStatus",
@@ -493,7 +530,9 @@
   base::FilePath file_path = path_base.Append(identifier_path);
 
   bool is_disk_full = false;
-  db = leveldb_factory->OpenLevelDB(file_path, comparator.get(), &is_disk_full);
+  scoped_ptr<LevelDBDatabase> db;
+  leveldb::Status status = leveldb_factory->OpenLevelDB(
+      file_path, comparator.get(), &db, &is_disk_full);
 
   if (db) {
     bool known = false;
@@ -539,6 +578,16 @@
                                 base::HistogramBase::kUmaTargetedHistogramFlag)
         ->Add(INDEXED_DB_LEVEL_DB_BACKING_STORE_OPEN_DISK_FULL);
     return scoped_refptr<IndexedDBBackingStore>();
+  } else if (!RecoveryCouldBeFruitful(status)) {
+    LOG(ERROR) << "Unable to open backing store, not trying to recover - "
+               << status.ToString();
+    base::Histogram::FactoryGet("WebCore.IndexedDB.BackingStore.OpenStatus",
+                                1,
+                                INDEXED_DB_LEVEL_DB_BACKING_STORE_OPEN_MAX,
+                                INDEXED_DB_LEVEL_DB_BACKING_STORE_OPEN_MAX + 1,
+                                base::HistogramBase::kUmaTargetedHistogramFlag)
+        ->Add(INDEXED_DB_LEVEL_DB_BACKING_STORE_OPEN_NO_RECOVERY);
+    return scoped_refptr<IndexedDBBackingStore>();
   } else {
     LOG(ERROR) << "IndexedDB backing store open failed, attempting cleanup";
     *data_loss = WebKit::WebIDBCallbacks::DataLossTotal;
@@ -556,7 +605,7 @@
     }
 
     LOG(ERROR) << "IndexedDB backing store cleanup succeeded, reopening";
-    db = leveldb_factory->OpenLevelDB(file_path, comparator.get(), NULL);
+    leveldb_factory->OpenLevelDB(file_path, comparator.get(), &db, NULL);
     if (!db) {
       LOG(ERROR) << "IndexedDB backing store reopen after recovery failed";
       base::Histogram::FactoryGet(
diff --git a/content/browser/indexed_db/indexed_db_backing_store.h b/content/browser/indexed_db/indexed_db_backing_store.h
index 7dbdc53..4498b08 100644
--- a/content/browser/indexed_db/indexed_db_backing_store.h
+++ b/content/browser/indexed_db/indexed_db_backing_store.h
@@ -31,9 +31,10 @@
 class LevelDBFactory {
  public:
   virtual ~LevelDBFactory() {}
-  virtual scoped_ptr<LevelDBDatabase> OpenLevelDB(
+  virtual leveldb::Status OpenLevelDB(
       const base::FilePath& file_name,
       const LevelDBComparator* comparator,
+      scoped_ptr<LevelDBDatabase>* db,
       bool* is_disk_full) = 0;
   virtual bool DestroyLevelDB(const base::FilePath& file_name) = 0;
 };
diff --git a/content/browser/indexed_db/indexed_db_cleanup_on_io_error_unittest.cc b/content/browser/indexed_db/indexed_db_cleanup_on_io_error_unittest.cc
index 1f37a12..e05ceb9 100644
--- a/content/browser/indexed_db/indexed_db_cleanup_on_io_error_unittest.cc
+++ b/content/browser/indexed_db/indexed_db_cleanup_on_io_error_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 <cerrno>
+
 #include "base/files/file_path.h"
 #include "base/files/scoped_temp_dir.h"
 #include "base/strings/string16.h"
@@ -9,6 +11,7 @@
 #include "content/browser/indexed_db/indexed_db_backing_store.h"
 #include "content/browser/indexed_db/leveldb/leveldb_database.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/leveldatabase/env_chromium.h"
 
 using base::StringPiece;
 using content::IndexedDBBackingStore;
@@ -38,11 +41,13 @@
 class MockLevelDBFactory : public LevelDBFactory {
  public:
   MockLevelDBFactory() : destroy_called_(false) {}
-  virtual scoped_ptr<LevelDBDatabase> OpenLevelDB(
+  virtual leveldb::Status OpenLevelDB(
       const base::FilePath& file_name,
       const LevelDBComparator* comparator,
+      scoped_ptr<LevelDBDatabase>* db,
       bool* is_disk_full = 0) OVERRIDE {
-    return BustedLevelDBDatabase::Open(file_name, comparator);
+    *db = BustedLevelDBDatabase::Open(file_name, comparator);
+    return leveldb::Status::OK();
   }
   virtual bool DestroyLevelDB(const base::FilePath& file_name) OVERRIDE {
     EXPECT_FALSE(destroy_called_);
@@ -72,4 +77,78 @@
                                   &mock_leveldb_factory);
 }
 
+template <class T>
+class MockErrorLevelDBFactory : public LevelDBFactory {
+ public:
+  MockErrorLevelDBFactory(T error, bool expect_destroy)
+      : error_(error),
+        expect_destroy_(expect_destroy),
+        destroy_called_(false) {}
+  virtual leveldb::Status OpenLevelDB(
+      const base::FilePath& file_name,
+      const LevelDBComparator* comparator,
+      scoped_ptr<LevelDBDatabase>* db,
+      bool* is_disk_full = 0) OVERRIDE {
+    return MakeIOError(
+        "some filename", "some message", leveldb_env::kNewLogger, error_);
+  }
+  virtual bool DestroyLevelDB(const base::FilePath& file_name) OVERRIDE {
+    EXPECT_FALSE(destroy_called_);
+    destroy_called_ = true;
+    return false;
+  }
+  virtual ~MockErrorLevelDBFactory() {
+    EXPECT_EQ(expect_destroy_, destroy_called_);
+  }
+
+ private:
+  T error_;
+  bool expect_destroy_;
+  bool destroy_called_;
+};
+
+TEST(IndexedDBNonRecoverableIOErrorTest, NuancedCleanupTest) {
+  std::string origin_identifier("http_localhost_81");
+  base::ScopedTempDir temp_directory;
+  ASSERT_TRUE(temp_directory.CreateUniqueTempDir());
+  const base::FilePath path = temp_directory.path();
+  std::string dummy_file_identifier;
+  WebKit::WebIDBCallbacks::DataLoss data_loss =
+      WebKit::WebIDBCallbacks::DataLossNone;
+
+  MockErrorLevelDBFactory<int> mock_leveldb_factory(ENOSPC, false);
+  scoped_refptr<IndexedDBBackingStore> backing_store =
+      IndexedDBBackingStore::Open(origin_identifier,
+                                  path,
+                                  dummy_file_identifier,
+                                  &data_loss,
+                                  &mock_leveldb_factory);
+
+  MockErrorLevelDBFactory<base::PlatformFileError> mock_leveldb_factory2(
+      base::PLATFORM_FILE_ERROR_NO_MEMORY, false);
+  scoped_refptr<IndexedDBBackingStore> backing_store2 =
+      IndexedDBBackingStore::Open(origin_identifier,
+                                  path,
+                                  dummy_file_identifier,
+                                  &data_loss,
+                                  &mock_leveldb_factory2);
+
+  MockErrorLevelDBFactory<int> mock_leveldb_factory3(EIO, true);
+  scoped_refptr<IndexedDBBackingStore> backing_store3 =
+      IndexedDBBackingStore::Open(origin_identifier,
+                                  path,
+                                  dummy_file_identifier,
+                                  &data_loss,
+                                  &mock_leveldb_factory3);
+
+  MockErrorLevelDBFactory<base::PlatformFileError> mock_leveldb_factory4(
+      base::PLATFORM_FILE_ERROR_FAILED, true);
+  scoped_refptr<IndexedDBBackingStore> backing_store4 =
+      IndexedDBBackingStore::Open(origin_identifier,
+                                  path,
+                                  dummy_file_identifier,
+                                  &data_loss,
+                                  &mock_leveldb_factory4);
+}
+
 }  // namespace
diff --git a/content/browser/indexed_db/leveldb/leveldb_database.cc b/content/browser/indexed_db/leveldb/leveldb_database.cc
index cb67cd9..03d8ca6 100644
--- a/content/browser/indexed_db/leveldb/leveldb_database.cc
+++ b/content/browser/indexed_db/leveldb/leveldb_database.cc
@@ -268,9 +268,10 @@
     ParseAndHistogramCorruptionDetails(histogram_name, s);
 }
 
-scoped_ptr<LevelDBDatabase> LevelDBDatabase::Open(
+leveldb::Status LevelDBDatabase::Open(
     const base::FilePath& file_name,
     const LevelDBComparator* comparator,
+    scoped_ptr<LevelDBDatabase>* result,
     bool* is_disk_full) {
   scoped_ptr<ComparatorAdapter> comparator_adapter(
       new ComparatorAdapter(comparator));
@@ -289,17 +290,17 @@
 
     LOG(ERROR) << "Failed to open LevelDB database from "
                << file_name.AsUTF8Unsafe() << "," << s.ToString();
-    return scoped_ptr<LevelDBDatabase>();
+    return s;
   }
 
   CheckFreeSpace("Success", file_name);
 
-  scoped_ptr<LevelDBDatabase> result(new LevelDBDatabase);
-  result->db_ = make_scoped_ptr(db);
-  result->comparator_adapter_ = comparator_adapter.Pass();
-  result->comparator_ = comparator;
+  (*result).reset(new LevelDBDatabase);
+  (*result)->db_ = make_scoped_ptr(db);
+  (*result)->comparator_adapter_ = comparator_adapter.Pass();
+  (*result)->comparator_ = comparator;
 
-  return result.Pass();
+  return s;
 }
 
 scoped_ptr<LevelDBDatabase> LevelDBDatabase::OpenInMemory(
diff --git a/content/browser/indexed_db/leveldb/leveldb_database.h b/content/browser/indexed_db/leveldb/leveldb_database.h
index ad1942c..1efeefa 100644
--- a/content/browser/indexed_db/leveldb/leveldb_database.h
+++ b/content/browser/indexed_db/leveldb/leveldb_database.h
@@ -13,6 +13,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/status.h"
 
 namespace leveldb {
 class Comparator;
@@ -42,9 +43,10 @@
 
 class CONTENT_EXPORT LevelDBDatabase {
  public:
-  static scoped_ptr<LevelDBDatabase> Open(const base::FilePath& file_name,
-                                          const LevelDBComparator* comparator,
-                                          bool* is_disk_full = 0);
+  static leveldb::Status Open(const base::FilePath& file_name,
+                              const LevelDBComparator* comparator,
+                              scoped_ptr<LevelDBDatabase>* db,
+                              bool* is_disk_full = 0);
   static scoped_ptr<LevelDBDatabase> OpenInMemory(
       const LevelDBComparator* comparator);
   static bool Destroy(const base::FilePath& file_name);
diff --git a/content/browser/indexed_db/leveldb/leveldb_unittest.cc b/content/browser/indexed_db/leveldb/leveldb_unittest.cc
index ac7ebe0..9ce0664 100644
--- a/content/browser/indexed_db/leveldb/leveldb_unittest.cc
+++ b/content/browser/indexed_db/leveldb/leveldb_unittest.cc
@@ -41,8 +41,8 @@
   std::string got_value;
   SimpleComparator comparator;
 
-  scoped_ptr<LevelDBDatabase> leveldb =
-      LevelDBDatabase::Open(temp_directory.path(), &comparator);
+  scoped_ptr<LevelDBDatabase> leveldb;
+  LevelDBDatabase::Open(temp_directory.path(), &comparator, &leveldb);
   EXPECT_TRUE(leveldb);
   put_value = value;
   bool success = leveldb->Put(key, &put_value);
@@ -50,7 +50,7 @@
   leveldb.Pass();
   EXPECT_FALSE(leveldb);
 
-  leveldb = LevelDBDatabase::Open(temp_directory.path(), &comparator);
+  LevelDBDatabase::Open(temp_directory.path(), &comparator, &leveldb);
   EXPECT_TRUE(leveldb);
   bool found = false;
   success = leveldb->Get(key, &got_value, &found);
@@ -69,13 +69,16 @@
   base::TruncatePlatformFile(handle, 0);
   base::ClosePlatformFile(handle);
 
-  leveldb = LevelDBDatabase::Open(temp_directory.path(), &comparator);
+  leveldb::Status status =
+      LevelDBDatabase::Open(temp_directory.path(), &comparator, &leveldb);
   EXPECT_FALSE(leveldb);
+  EXPECT_FALSE(status.ok());
 
   bool destroyed = LevelDBDatabase::Destroy(temp_directory.path());
   EXPECT_TRUE(destroyed);
 
-  leveldb = LevelDBDatabase::Open(temp_directory.path(), &comparator);
+  status = LevelDBDatabase::Open(temp_directory.path(), &comparator, &leveldb);
+  EXPECT_TRUE(status.ok());
   EXPECT_TRUE(leveldb);
   success = leveldb->Get(key, &got_value, &found);
   EXPECT_TRUE(success);
@@ -91,8 +94,8 @@
   std::string put_value;
   SimpleComparator comparator;
 
-  scoped_ptr<LevelDBDatabase> leveldb =
-      LevelDBDatabase::Open(temp_directory.path(), &comparator);
+  scoped_ptr<LevelDBDatabase> leveldb;
+  LevelDBDatabase::Open(temp_directory.path(), &comparator, &leveldb);
   EXPECT_TRUE(leveldb);
 
   const std::string old_value("value");
@@ -158,8 +161,8 @@
   SimpleComparator comparator;
   bool success;
 
-  scoped_ptr<LevelDBDatabase> leveldb =
-      LevelDBDatabase::Open(temp_directory.path(), &comparator);
+  scoped_ptr<LevelDBDatabase> leveldb;
+  LevelDBDatabase::Open(temp_directory.path(), &comparator, &leveldb);
   EXPECT_TRUE(leveldb);
 
   put_value = value1;
diff --git a/content/browser/loader/resource_loader.cc b/content/browser/loader/resource_loader.cc
index b7b1e9d..b43d5d6 100644
--- a/content/browser/loader/resource_loader.cc
+++ b/content/browser/loader/resource_loader.cc
@@ -6,6 +6,7 @@
 
 #include "base/command_line.h"
 #include "base/message_loop/message_loop.h"
+#include "base/metrics/histogram.h"
 #include "base/time/time.h"
 #include "content/browser/child_process_security_policy_impl.h"
 #include "content/browser/loader/doomed_resource_handler.h"
@@ -560,6 +561,7 @@
           info->GetRequestID(), response.get(), &defer)) {
     Cancel();
   } else if (defer) {
+    read_deferral_start_time_ = base::TimeTicks::Now();
     deferred_stage_ = DEFERRED_READ;  // Read first chunk when resumed.
   }
 }
@@ -589,6 +591,11 @@
 void ResourceLoader::ResumeReading() {
   DCHECK(!is_deferred());
 
+  if (!read_deferral_start_time_.is_null()) {
+    UMA_HISTOGRAM_TIMES("Net.ResourceLoader.ReadDeferral",
+                        base::TimeTicks::Now() - read_deferral_start_time_);
+    read_deferral_start_time_ = base::TimeTicks();
+  }
   if (request_->status().is_success()) {
     StartReading(false);  // Read the next chunk (OK to complete synchronously).
   } else {
diff --git a/content/browser/loader/resource_loader.h b/content/browser/loader/resource_loader.h
index 03667e3..9687c3b 100644
--- a/content/browser/loader/resource_loader.h
+++ b/content/browser/loader/resource_loader.h
@@ -127,6 +127,7 @@
   uint64 last_upload_position_;
   bool waiting_for_upload_progress_ack_;
   base::TimeTicks last_upload_ticks_;
+  base::TimeTicks read_deferral_start_time_;
 
   // Indicates that we are in a state of being transferred to a new downstream
   // consumer.  We are waiting for a notification to complete the transfer, at
diff --git a/content/browser/media/webrtc_identity_store.cc b/content/browser/media/webrtc_identity_store.cc
index ee19f1e..1c77862 100644
--- a/content/browser/media/webrtc_identity_store.cc
+++ b/content/browser/media/webrtc_identity_store.cc
@@ -4,11 +4,14 @@
 
 #include "content/browser/media/webrtc_identity_store.h"
 
+#include <map>
+
 #include "base/bind.h"
 #include "base/callback_helpers.h"
 #include "base/logging.h"
 #include "base/rand_util.h"
 #include "base/threading/worker_pool.h"
+#include "content/browser/media/webrtc_identity_store_backend.h"
 #include "content/public/browser/browser_thread.h"
 #include "crypto/rsa_private_key.h"
 #include "net/base/net_errors.h"
@@ -18,11 +21,18 @@
 namespace content {
 
 struct WebRTCIdentityRequestResult {
+  WebRTCIdentityRequestResult(int error,
+                              const std::string& certificate,
+                              const std::string& private_key)
+      : error(error), certificate(certificate), private_key(private_key) {}
+
   int error;
   std::string certificate;
   std::string private_key;
 };
 
+// Generates a new identity using |common_name| and returns the result in
+// |result|.
 static void GenerateIdentityWorker(const std::string& common_name,
                                    WebRTCIdentityRequestResult* result) {
   result->error = net::OK;
@@ -60,33 +70,57 @@
       std::string(private_key_info.begin(), private_key_info.end());
 }
 
+class WebRTCIdentityRequestHandle;
+
 // The class represents an identity request internal to WebRTCIdentityStore.
-// It has a one-to-one mapping to the external version of the request
-// WebRTCIdentityRequestHandle, which is the target of the
-// WebRTCIdentityRequest's completion callback.
+// It has a one-to-many mapping to the external version of the request,
+// WebRTCIdentityRequestHandle, i.e. multiple identical external requests are
+// combined into one internal request.
 // It's deleted automatically when the request is completed.
 class WebRTCIdentityRequest {
  public:
-  WebRTCIdentityRequest(const WebRTCIdentityStore::CompletionCallback& callback)
-      : callback_(callback) {}
+  WebRTCIdentityRequest(const GURL& origin,
+                        const std::string& identity_name,
+                        const std::string& common_name)
+      : origin_(origin),
+        identity_name_(identity_name),
+        common_name_(common_name) {}
 
-  void Cancel() {
+  void Cancel(WebRTCIdentityRequestHandle* handle) {
     DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
-    callback_.Reset();
+    if (callbacks_.find(handle) == callbacks_.end())
+      return;
+    callbacks_.erase(handle);
   }
 
  private:
   friend class WebRTCIdentityStore;
 
-  void Post(WebRTCIdentityRequestResult* result) {
-    DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
-    if (callback_.is_null())
-      return;
-    callback_.Run(result->error, result->certificate, result->private_key);
-    // "this" will be deleted after this point.
+  void AddCallback(WebRTCIdentityRequestHandle* handle,
+                   const WebRTCIdentityStore::CompletionCallback& callback) {
+    DCHECK(callbacks_.find(handle) == callbacks_.end());
+    callbacks_[handle] = callback;
   }
 
-  WebRTCIdentityStore::CompletionCallback callback_;
+  // This method deletes "this" and no one should access it after the request
+  // completes.
+  // We do not use base::Owned to tie its lifetime to the callback for
+  // WebRTCIdentityStoreBackend::FindIdentity, because it needs to live longer
+  // than that if the identity does not exist in DB.
+  void Post(const WebRTCIdentityRequestResult& result) {
+    DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+    for (CallbackMap::iterator it = callbacks_.begin(); it != callbacks_.end();
+         ++it)
+      it->second.Run(result.error, result.certificate, result.private_key);
+    delete this;
+  }
+
+  GURL origin_;
+  std::string identity_name_;
+  std::string common_name_;
+  typedef std::map<WebRTCIdentityRequestHandle*,
+                   WebRTCIdentityStore::CompletionCallback> CallbackMap;
+  CallbackMap callbacks_;
 };
 
 // The class represents an identity request which calls back to the external
@@ -115,7 +149,7 @@
     request_ = NULL;
     // "this" will be deleted after the following call, because "this" is
     // owned by the Callback held by |request|.
-    request->Cancel();
+    request->Cancel(this);
   }
 
   void OnRequestStarted(WebRTCIdentityRequest* request) {
@@ -140,10 +174,12 @@
   DISALLOW_COPY_AND_ASSIGN(WebRTCIdentityRequestHandle);
 };
 
-WebRTCIdentityStore::WebRTCIdentityStore()
-    : task_runner_(base::WorkerPool::GetTaskRunner(true)) {}
+WebRTCIdentityStore::WebRTCIdentityStore(const base::FilePath& path,
+                                         quota::SpecialStoragePolicy* policy)
+    : task_runner_(base::WorkerPool::GetTaskRunner(true)),
+      backend_(new WebRTCIdentityStoreBackend(path, policy)) {}
 
-WebRTCIdentityStore::~WebRTCIdentityStore() {}
+WebRTCIdentityStore::~WebRTCIdentityStore() { backend_->Close(); }
 
 base::Closure WebRTCIdentityStore::RequestIdentity(
     const GURL& origin,
@@ -155,26 +191,118 @@
   WebRTCIdentityRequestHandle* handle =
       new WebRTCIdentityRequestHandle(this, callback);
 
-  WebRTCIdentityRequest* request = new WebRTCIdentityRequest(base::Bind(
-      &WebRTCIdentityRequestHandle::OnRequestComplete, base::Owned(handle)));
+  WebRTCIdentityRequest* request =
+      FindRequest(origin, identity_name, common_name);
+
+  // If there is no identical request in flight, create a new one, queue it,
+  // and make the backend request.
+  if (!request) {
+    request = new WebRTCIdentityRequest(origin, identity_name, common_name);
+
+    if (!backend_->FindIdentity(
+            origin,
+            identity_name,
+            common_name,
+            base::Bind(
+                &WebRTCIdentityStore::BackendFindCallback, this, request))) {
+      delete request;
+      return base::Closure();
+    }
+    in_flight_requests_.push_back(request);
+  }
+
+  request->AddCallback(
+      handle,
+      base::Bind(&WebRTCIdentityRequestHandle::OnRequestComplete,
+                 base::Owned(handle)));
   handle->OnRequestStarted(request);
-
-  WebRTCIdentityRequestResult* result = new WebRTCIdentityRequestResult();
-  if (!task_runner_->PostTaskAndReply(
-          FROM_HERE,
-          base::Bind(&GenerateIdentityWorker, common_name, result),
-          base::Bind(&WebRTCIdentityRequest::Post,
-                     base::Owned(request),
-                     base::Owned(result))))
-    return base::Closure();
-
   return base::Bind(&WebRTCIdentityRequestHandle::Cancel,
                     base::Unretained(handle));
 }
 
+void WebRTCIdentityStore::DeleteBetween(base::Time delete_begin,
+                                        base::Time delete_end,
+                                        const base::Closure& callback) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  backend_->DeleteBetween(delete_begin, delete_end, callback);
+}
+
 void WebRTCIdentityStore::SetTaskRunnerForTesting(
     const scoped_refptr<base::TaskRunner>& task_runner) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
   task_runner_ = task_runner;
 }
 
+void WebRTCIdentityStore::BackendFindCallback(WebRTCIdentityRequest* request,
+                                              int error,
+                                              const std::string& certificate,
+                                              const std::string& private_key) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  if (error == net::OK) {
+    DVLOG(2) << "Identity found in DB.";
+    WebRTCIdentityRequestResult result(error, certificate, private_key);
+    PostRequestResult(request, result);
+    return;
+  }
+  // Generate a new identity if not found in the DB.
+  WebRTCIdentityRequestResult* result =
+      new WebRTCIdentityRequestResult(0, "", "");
+  if (!task_runner_->PostTaskAndReply(
+          FROM_HERE,
+          base::Bind(&GenerateIdentityWorker, request->common_name_, result),
+          base::Bind(&WebRTCIdentityStore::GenerateIdentityCallback,
+                     this,
+                     request,
+                     base::Owned(result)))) {
+    // Completes the request with error if failed to post the task.
+    WebRTCIdentityRequestResult result(net::ERR_UNEXPECTED, "", "");
+    PostRequestResult(request, result);
+  }
+}
+
+void WebRTCIdentityStore::GenerateIdentityCallback(
+    WebRTCIdentityRequest* request,
+    WebRTCIdentityRequestResult* result) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  if (result->error == net::OK) {
+    DVLOG(2) << "New identity generated and added to the backend.";
+    backend_->AddIdentity(request->origin_,
+                          request->identity_name_,
+                          request->common_name_,
+                          result->certificate,
+                          result->private_key);
+  }
+  PostRequestResult(request, *result);
+}
+
+void WebRTCIdentityStore::PostRequestResult(
+    WebRTCIdentityRequest* request,
+    const WebRTCIdentityRequestResult& result) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  // Removes the in flight request from the queue.
+  for (size_t i = 0; i < in_flight_requests_.size(); ++i) {
+    if (in_flight_requests_[i] == request) {
+      in_flight_requests_.erase(in_flight_requests_.begin() + i);
+      break;
+    }
+  }
+  // |request| will be deleted after this call.
+  request->Post(result);
+}
+
+// Find an identical request from the in flight requests.
+WebRTCIdentityRequest* WebRTCIdentityStore::FindRequest(
+    const GURL& origin,
+    const std::string& identity_name,
+    const std::string& common_name) {
+  for (size_t i = 0; i < in_flight_requests_.size(); ++i) {
+    if (in_flight_requests_[i]->origin_ == origin &&
+        in_flight_requests_[i]->identity_name_ == identity_name &&
+        in_flight_requests_[i]->common_name_ == common_name) {
+      return in_flight_requests_[i];
+    }
+  }
+  return NULL;
+}
+
 }  // namespace content
diff --git a/content/browser/media/webrtc_identity_store.h b/content/browser/media/webrtc_identity_store.h
index 1649384..c2b523e 100644
--- a/content/browser/media/webrtc_identity_store.h
+++ b/content/browser/media/webrtc_identity_store.h
@@ -6,32 +6,44 @@
 #define CONTENT_BROWSER_MEDIA_WEBRTC_IDENTITY_STORE_H_
 
 #include <string>
+#include <vector>
 
 #include "base/callback.h"
+#include "base/time/time.h"
 #include "content/common/content_export.h"
 
 class GURL;
 
 namespace base {
+class FilePath;
 class TaskRunner;
 }  // namespace base
 
-namespace content {
+namespace quota {
+class SpecialStoragePolicy;
+}  // namespace quota
 
+namespace content {
+class WebRTCIdentityRequest;
+struct WebRTCIdentityRequestResult;
+class WebRTCIdentityStoreBackend;
 class WebRTCIdentityStoreTest;
 
 // A class for creating and fetching DTLS identities, i.e. the private key and
 // the self-signed certificate.
-class CONTENT_EXPORT WebRTCIdentityStore {
+// It can be created/destroyed on any thread, but the public methods must be
+// called on the IO thread.
+class CONTENT_EXPORT WebRTCIdentityStore
+    : public base::RefCountedThreadSafe<WebRTCIdentityStore> {
  public:
   typedef base::Callback<void(int error,
                               const std::string& certificate,
                               const std::string& private_key)>
       CompletionCallback;
 
-  WebRTCIdentityStore();
-  // Only virtual to allow subclassing for test mock.
-  virtual ~WebRTCIdentityStore();
+  // If |path| is empty, nothing will be saved to disk.
+  WebRTCIdentityStore(const base::FilePath& path,
+                      quota::SpecialStoragePolicy* policy);
 
   // Retrieve the cached DTLS private key and certificate, i.e. identity, for
   // the |origin| and |identity_name| pair, or generate a new identity using
@@ -39,7 +51,6 @@
   // If the given |common_name| is different from the common name in the cached
   // identity that has the same origin and identity_name, a new private key and
   // a new certificate will be generated, overwriting the old one.
-  // TODO(jiayl): implement identity caching through a persistent storage.
   //
   // |origin| is the origin of the DTLS connection;
   // |identity_name| is used to identify an identity within an origin; it is
@@ -49,7 +60,7 @@
   // be shared with the peer of the DTLS connection. Identities created for
   // different origins or different identity names may have the same common
   // name.
-  // |callback| is the callback to return the result.
+  // |callback| is the callback to return the result as DER strings.
   //
   // Returns the Closure used to cancel the request if the request is accepted.
   // The Closure can only be called before the request completes.
@@ -58,14 +69,42 @@
                                         const std::string& common_name,
                                         const CompletionCallback& callback);
 
+  // Delete the identities created between |delete_begin| and |delete_end|.
+  // |callback| will be called when the operation is done.
+  void DeleteBetween(base::Time delete_begin,
+                     base::Time delete_end,
+                     const base::Closure& callback);
+
+ protected:
+  // Only virtual to allow subclassing for test mock.
+  virtual ~WebRTCIdentityStore();
+
  private:
+  friend class base::RefCountedThreadSafe<WebRTCIdentityStore>;
   friend class WebRTCIdentityStoreTest;
 
   void SetTaskRunnerForTesting(
       const scoped_refptr<base::TaskRunner>& task_runner);
 
+  void BackendFindCallback(WebRTCIdentityRequest* request,
+                           int error,
+                           const std::string& certificate,
+                           const std::string& private_key);
+  void GenerateIdentityCallback(WebRTCIdentityRequest* request,
+                                WebRTCIdentityRequestResult* result);
+  WebRTCIdentityRequest* FindRequest(const GURL& origin,
+                                     const std::string& identity_name,
+                                     const std::string& common_name);
+  void PostRequestResult(WebRTCIdentityRequest* request,
+                         const WebRTCIdentityRequestResult& result);
+
   // The TaskRunner for doing work on a worker thread.
   scoped_refptr<base::TaskRunner> task_runner_;
+  // Weak references of the in flight requests. Used to join identical external
+  // requests.
+  std::vector<WebRTCIdentityRequest*> in_flight_requests_;
+
+  scoped_refptr<WebRTCIdentityStoreBackend> backend_;
 
   DISALLOW_COPY_AND_ASSIGN(WebRTCIdentityStore);
 };
diff --git a/content/browser/media/webrtc_identity_store_backend.cc b/content/browser/media/webrtc_identity_store_backend.cc
new file mode 100644
index 0000000..a86cc20
--- /dev/null
+++ b/content/browser/media/webrtc_identity_store_backend.cc
@@ -0,0 +1,543 @@
+// 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/browser/media/webrtc_identity_store_backend.h"
+
+#include "base/file_util.h"
+#include "base/files/file_path.h"
+#include "content/public/browser/browser_thread.h"
+#include "net/base/net_errors.h"
+#include "sql/error_delegate_util.h"
+#include "sql/statement.h"
+#include "sql/transaction.h"
+#include "url/gurl.h"
+#include "webkit/browser/quota/special_storage_policy.h"
+
+namespace content {
+
+static const char* kWebRTCIdentityStoreDBName = "webrtc_identity_store";
+
+static const base::FilePath::CharType kWebRTCIdentityStoreDirectory[] =
+    FILE_PATH_LITERAL("WebRTCIdentityStore");
+
+// Initializes the identity table, returning true on success.
+static bool InitDB(sql::Connection* db) {
+  if (db->DoesTableExist(kWebRTCIdentityStoreDBName)) {
+    if (db->DoesColumnExist(kWebRTCIdentityStoreDBName, "origin") &&
+        db->DoesColumnExist(kWebRTCIdentityStoreDBName, "identity_name") &&
+        db->DoesColumnExist(kWebRTCIdentityStoreDBName, "common_name") &&
+        db->DoesColumnExist(kWebRTCIdentityStoreDBName, "certificate") &&
+        db->DoesColumnExist(kWebRTCIdentityStoreDBName, "private_key") &&
+        db->DoesColumnExist(kWebRTCIdentityStoreDBName, "creation_time"))
+      return true;
+    if (!db->Execute("DROP TABLE webrtc_identity_store"))
+      return false;
+  }
+
+  return db->Execute(
+      "CREATE TABLE webrtc_identity_store"
+      " ("
+      "origin TEXT NOT NULL,"
+      "identity_name TEXT NOT NULL,"
+      "common_name TEXT NOT NULL,"
+      "certificate BLOB NOT NULL,"
+      "private_key BLOB NOT NULL,"
+      "creation_time INTEGER)");
+}
+
+struct WebRTCIdentityStoreBackend::IdentityKey {
+  IdentityKey(const GURL& origin, const std::string& identity_name)
+      : origin(origin), identity_name(identity_name) {}
+
+  bool operator<(const IdentityKey& other) const {
+    return origin < other.origin ||
+           (origin == other.origin && identity_name < other.identity_name);
+  }
+
+  GURL origin;
+  std::string identity_name;
+};
+
+struct WebRTCIdentityStoreBackend::Identity {
+  Identity(const std::string& common_name,
+           const std::string& certificate,
+           const std::string& private_key)
+      : common_name(common_name),
+        certificate(certificate),
+        private_key(private_key),
+        creation_time(base::Time::Now().ToInternalValue()) {}
+
+  Identity(const std::string& common_name,
+           const std::string& certificate,
+           const std::string& private_key,
+           int64 creation_time)
+      : common_name(common_name),
+        certificate(certificate),
+        private_key(private_key),
+        creation_time(creation_time) {}
+
+  std::string common_name;
+  std::string certificate;
+  std::string private_key;
+  int64 creation_time;
+};
+
+struct WebRTCIdentityStoreBackend::PendingFindRequest {
+  PendingFindRequest(const GURL& origin,
+                     const std::string& identity_name,
+                     const std::string& common_name,
+                     const FindIdentityCallback& callback)
+      : origin(origin),
+        identity_name(identity_name),
+        common_name(common_name),
+        callback(callback) {}
+
+  ~PendingFindRequest() {}
+
+  GURL origin;
+  std::string identity_name;
+  std::string common_name;
+  FindIdentityCallback callback;
+};
+
+// The class encapsulates the database operations. All members except ctor and
+// dtor should be accessed on the DB thread.
+// It can be created/destroyed on any thread.
+class WebRTCIdentityStoreBackend::SqlLiteStorage
+    : public base::RefCountedThreadSafe<SqlLiteStorage> {
+ public:
+  SqlLiteStorage(const base::FilePath& path,
+                 quota::SpecialStoragePolicy* policy)
+      : special_storage_policy_(policy) {
+    if (!path.empty())
+      path_ = path.Append(kWebRTCIdentityStoreDirectory);
+  }
+
+  void Load(IdentityMap* out_map);
+  void Close();
+  void AddIdentity(const GURL& origin,
+                   const std::string& identity_name,
+                   const Identity& identity);
+  void DeleteIdentity(const GURL& origin,
+                      const std::string& identity_name,
+                      const Identity& identity);
+  void DeleteBetween(base::Time delete_begin,
+                     base::Time delete_end,
+                     const base::Closure& callback);
+
+ private:
+  friend class base::RefCountedThreadSafe<SqlLiteStorage>;
+
+  enum OperationType {
+    ADD_IDENTITY,
+    DELETE_IDENTITY
+  };
+  struct PendingOperation {
+    PendingOperation(OperationType type,
+                     const GURL& origin,
+                     const std::string& identity_name,
+                     const Identity& identity)
+        : type(type),
+          origin(origin),
+          identity_name(identity_name),
+          identity(identity) {}
+
+    OperationType type;
+    GURL origin;
+    std::string identity_name;
+    Identity identity;
+  };
+  typedef std::vector<PendingOperation*> PendingOperationList;
+
+  virtual ~SqlLiteStorage() {}
+  void OnDatabaseError(int error, sql::Statement* stmt);
+  void BatchOperation(OperationType type,
+                      const GURL& origin,
+                      const std::string& identity_name,
+                      const Identity& identity);
+  void Commit();
+
+  // The file path of the DB. Empty if temporary.
+  base::FilePath path_;
+  scoped_refptr<quota::SpecialStoragePolicy> special_storage_policy_;
+  scoped_ptr<sql::Connection> db_;
+  // Batched DB operations pending to commit.
+  PendingOperationList pending_operations_;
+
+  DISALLOW_COPY_AND_ASSIGN(SqlLiteStorage);
+};
+
+WebRTCIdentityStoreBackend::WebRTCIdentityStoreBackend(
+    const base::FilePath& path,
+    quota::SpecialStoragePolicy* policy)
+    : state_(NOT_STARTED),
+      sql_lite_storage_(new SqlLiteStorage(path, policy)) {}
+
+bool WebRTCIdentityStoreBackend::FindIdentity(
+    const GURL& origin,
+    const std::string& identity_name,
+    const std::string& common_name,
+    const FindIdentityCallback& callback) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  if (state_ == CLOSED)
+    return false;
+
+  if (state_ != LOADED) {
+    // Queues the request to wait for the DB to load.
+    pending_find_requests_.push_back(
+        new PendingFindRequest(origin, identity_name, common_name, callback));
+    if (state_ == LOADING)
+      return true;
+
+    DCHECK_EQ(state_, NOT_STARTED);
+
+    // Kick off loading the DB.
+    scoped_ptr<IdentityMap> out_map(new IdentityMap());
+    if (BrowserThread::PostTaskAndReply(
+            BrowserThread::DB,
+            FROM_HERE,
+            base::Bind(&SqlLiteStorage::Load, sql_lite_storage_, out_map.get()),
+            base::Bind(&WebRTCIdentityStoreBackend::OnLoaded,
+                       this,
+                       base::Passed(&out_map)))) {
+      state_ = LOADING;
+      return true;
+    }
+    // If it fails to post task, falls back to ERR_FILE_NOT_FOUND.
+  }
+
+  IdentityKey key(origin, identity_name);
+  IdentityMap::iterator iter = identities_.find(key);
+  if (iter != identities_.end() && iter->second.common_name == common_name) {
+    // Identity found.
+    return BrowserThread::PostTask(BrowserThread::IO,
+                                   FROM_HERE,
+                                   base::Bind(callback,
+                                              net::OK,
+                                              iter->second.certificate,
+                                              iter->second.private_key));
+  }
+
+  return BrowserThread::PostTask(
+      BrowserThread::IO,
+      FROM_HERE,
+      base::Bind(callback, net::ERR_FILE_NOT_FOUND, "", ""));
+}
+
+void WebRTCIdentityStoreBackend::AddIdentity(const GURL& origin,
+                                             const std::string& identity_name,
+                                             const std::string& common_name,
+                                             const std::string& certificate,
+                                             const std::string& private_key) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  if (state_ == CLOSED)
+    return;
+
+  // If there is an existing identity for the same origin and identity_name,
+  // delete it.
+  IdentityKey key(origin, identity_name);
+  Identity identity(common_name, certificate, private_key);
+
+  if (identities_.find(key) != identities_.end()) {
+    if (!BrowserThread::PostTask(BrowserThread::DB,
+                                 FROM_HERE,
+                                 base::Bind(&SqlLiteStorage::DeleteIdentity,
+                                            sql_lite_storage_,
+                                            origin,
+                                            identity_name,
+                                            identities_.find(key)->second)))
+      return;
+  }
+  identities_.insert(std::pair<IdentityKey, Identity>(key, identity));
+
+  BrowserThread::PostTask(BrowserThread::DB,
+                          FROM_HERE,
+                          base::Bind(&SqlLiteStorage::AddIdentity,
+                                     sql_lite_storage_,
+                                     origin,
+                                     identity_name,
+                                     identity));
+}
+
+void WebRTCIdentityStoreBackend::Close() {
+  if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
+    BrowserThread::PostTask(
+        BrowserThread::IO,
+        FROM_HERE,
+        base::Bind(&WebRTCIdentityStoreBackend::Close, this));
+    return;
+  }
+
+  if (state_ == CLOSED)
+    return;
+
+  state_ = CLOSED;
+  BrowserThread::PostTask(
+      BrowserThread::DB,
+      FROM_HERE,
+      base::Bind(&SqlLiteStorage::Close, sql_lite_storage_));
+}
+
+void WebRTCIdentityStoreBackend::DeleteBetween(base::Time delete_begin,
+                                               base::Time delete_end,
+                                               const base::Closure& callback) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  // Delete the in-memory cache.
+  IdentityMap::iterator it = identities_.begin();
+  while (it != identities_.end()) {
+    if (it->second.creation_time >= delete_begin.ToInternalValue() &&
+        it->second.creation_time <= delete_end.ToInternalValue())
+      identities_.erase(it++);
+    else
+      it++;
+  }
+
+  BrowserThread::PostTaskAndReply(BrowserThread::DB,
+                                  FROM_HERE,
+                                  base::Bind(&SqlLiteStorage::DeleteBetween,
+                                             sql_lite_storage_,
+                                             delete_begin,
+                                             delete_end,
+                                             callback),
+                                  callback);
+}
+
+WebRTCIdentityStoreBackend::~WebRTCIdentityStoreBackend() {}
+
+void WebRTCIdentityStoreBackend::OnLoaded(scoped_ptr<IdentityMap> out_map) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  state_ = LOADED;
+  identities_.swap(*out_map);
+
+  for (size_t i = 0; i < pending_find_requests_.size(); ++i) {
+    FindIdentity(pending_find_requests_[i]->origin,
+                 pending_find_requests_[i]->identity_name,
+                 pending_find_requests_[i]->common_name,
+                 pending_find_requests_[i]->callback);
+    delete pending_find_requests_[i];
+  }
+  pending_find_requests_.clear();
+}
+
+//
+// Implementation of SqlLiteStorage.
+//
+
+void WebRTCIdentityStoreBackend::SqlLiteStorage::Load(IdentityMap* out_map) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
+  DCHECK(!db_.get());
+
+  // Ensure the parent directory for storing certs is created before reading
+  // from it.
+  const base::FilePath dir = path_.DirName();
+  if (!base::PathExists(dir) && !file_util::CreateDirectory(dir)) {
+    DLOG(ERROR) << "Unable to open DB file path.";
+    return;
+  }
+
+  db_.reset(new sql::Connection());
+
+  db_->set_error_callback(base::Bind(&SqlLiteStorage::OnDatabaseError, this));
+
+  if (!db_->Open(path_)) {
+    DLOG(ERROR) << "Unable to open DB.";
+    db_.reset();
+    return;
+  }
+
+  if (!InitDB(db_.get())) {
+    DLOG(ERROR) << "Unable to init DB.";
+    db_.reset();
+    return;
+  }
+
+  db_->Preload();
+
+  // Slurp all the identities into the out_map.
+  sql::Statement stmt(db_->GetUniqueStatement(
+      "SELECT origin, identity_name, common_name, "
+      "certificate, private_key, creation_time "
+      "FROM webrtc_identity_store"));
+  CHECK(stmt.is_valid());
+
+  while (stmt.Step()) {
+    IdentityKey key(GURL(stmt.ColumnString(0)), stmt.ColumnString(1));
+    std::string common_name(stmt.ColumnString(2));
+    std::string cert, private_key;
+    stmt.ColumnBlobAsString(3, &cert);
+    stmt.ColumnBlobAsString(4, &private_key);
+    int64 creation_time = stmt.ColumnInt64(5);
+    std::pair<IdentityMap::iterator, bool> result =
+        out_map->insert(std::pair<IdentityKey, Identity>(
+            key, Identity(common_name, cert, private_key, creation_time)));
+    DCHECK(result.second);
+  }
+}
+
+void WebRTCIdentityStoreBackend::SqlLiteStorage::Close() {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
+  Commit();
+  db_.reset();
+}
+
+void WebRTCIdentityStoreBackend::SqlLiteStorage::AddIdentity(
+    const GURL& origin,
+    const std::string& identity_name,
+    const Identity& identity) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
+  if (!db_.get())
+    return;
+
+  // Do not add for session only origins.
+  if (special_storage_policy_.get() &&
+      !special_storage_policy_->IsStorageProtected(origin) &&
+      special_storage_policy_->IsStorageSessionOnly(origin)) {
+    return;
+  }
+  BatchOperation(ADD_IDENTITY, origin, identity_name, identity);
+}
+
+void WebRTCIdentityStoreBackend::SqlLiteStorage::DeleteIdentity(
+    const GURL& origin,
+    const std::string& identity_name,
+    const Identity& identity) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
+  if (!db_.get())
+    return;
+  BatchOperation(DELETE_IDENTITY, origin, identity_name, identity);
+}
+
+void WebRTCIdentityStoreBackend::SqlLiteStorage::OnDatabaseError(
+    int error,
+    sql::Statement* stmt) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
+  if (!sql::IsErrorCatastrophic(error))
+    return;
+  db_->RazeAndClose();
+}
+
+void WebRTCIdentityStoreBackend::SqlLiteStorage::BatchOperation(
+    OperationType type,
+    const GURL& origin,
+    const std::string& identity_name,
+    const Identity& identity) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
+  // Commit every 30 seconds.
+  static const base::TimeDelta kCommitInterval(
+      base::TimeDelta::FromSeconds(30));
+  // Commit right away if we have more than 512 outstanding operations.
+  static const size_t kCommitAfterBatchSize = 512;
+
+  // We do a full copy of the cert here, and hopefully just here.
+  scoped_ptr<PendingOperation> operation(
+      new PendingOperation(type, origin, identity_name, identity));
+
+  pending_operations_.push_back(operation.release());
+
+  if (pending_operations_.size() == 1) {
+    // We've gotten our first entry for this batch, fire off the timer.
+    BrowserThread::PostDelayedTask(BrowserThread::DB,
+                                   FROM_HERE,
+                                   base::Bind(&SqlLiteStorage::Commit, this),
+                                   kCommitInterval);
+  } else if (pending_operations_.size() >= kCommitAfterBatchSize) {
+    // We've reached a big enough batch, fire off a commit now.
+    BrowserThread::PostTask(BrowserThread::DB,
+                            FROM_HERE,
+                            base::Bind(&SqlLiteStorage::Commit, this));
+  }
+}
+
+void WebRTCIdentityStoreBackend::SqlLiteStorage::Commit() {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
+  // Maybe an old timer fired or we are already Close()'ed.
+  if (!db_.get() || pending_operations_.empty())
+    return;
+
+  sql::Statement add_stmt(db_->GetCachedStatement(
+      SQL_FROM_HERE,
+      "INSERT INTO webrtc_identity_store "
+      "(origin, identity_name, common_name, certificate,"
+      " private_key, creation_time) VALUES"
+      " (?,?,?,?,?,?)"));
+
+  CHECK(add_stmt.is_valid());
+
+  sql::Statement del_stmt(db_->GetCachedStatement(
+      SQL_FROM_HERE,
+      "DELETE FROM webrtc_identity_store WHERE origin=? AND identity_name=?"));
+
+  CHECK(del_stmt.is_valid());
+
+  sql::Transaction transaction(db_.get());
+  if (!transaction.Begin()) {
+    DLOG(ERROR) << "Failed to begin the transaction.";
+    return;
+  }
+
+  for (PendingOperationList::iterator it = pending_operations_.begin();
+       it != pending_operations_.end();
+       ++it) {
+    scoped_ptr<PendingOperation> po(*it);
+    switch (po->type) {
+      case ADD_IDENTITY: {
+        add_stmt.Reset(true);
+        add_stmt.BindString(0, po->origin.spec());
+        add_stmt.BindString(1, po->identity_name);
+        add_stmt.BindString(2, po->identity.common_name);
+        const std::string& cert = po->identity.certificate;
+        add_stmt.BindBlob(3, cert.data(), cert.size());
+        const std::string& private_key = po->identity.private_key;
+        add_stmt.BindBlob(4, private_key.data(), private_key.size());
+        add_stmt.BindInt64(5, po->identity.creation_time);
+        CHECK(add_stmt.Run());
+        break;
+      }
+      case DELETE_IDENTITY:
+        del_stmt.Reset(true);
+        del_stmt.BindString(0, po->origin.spec());
+        add_stmt.BindString(1, po->identity_name);
+        CHECK(del_stmt.Run());
+        break;
+
+      default:
+        NOTREACHED();
+        break;
+    }
+  }
+  transaction.Commit();
+  pending_operations_.clear();
+}
+
+void WebRTCIdentityStoreBackend::SqlLiteStorage::DeleteBetween(
+    base::Time delete_begin,
+    base::Time delete_end,
+    const base::Closure& callback) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
+  if (!db_.get())
+    return;
+
+  // Commit pending operations first.
+  Commit();
+
+  sql::Statement del_stmt(db_->GetCachedStatement(
+      SQL_FROM_HERE,
+      "DELETE FROM webrtc_identity_store"
+      " WHERE creation_time >= ? AND creation_time <= ?"));
+  CHECK(del_stmt.is_valid());
+
+  del_stmt.BindInt64(0, delete_begin.ToInternalValue());
+  del_stmt.BindInt64(1, delete_end.ToInternalValue());
+
+  sql::Transaction transaction(db_.get());
+  if (!transaction.Begin()) {
+    DLOG(ERROR) << "Failed to begin the transaction.";
+    return;
+  }
+
+  CHECK(del_stmt.Run());
+  transaction.Commit();
+}
+
+}  // namespace content
diff --git a/content/browser/media/webrtc_identity_store_backend.h b/content/browser/media/webrtc_identity_store_backend.h
new file mode 100644
index 0000000..ab4e1ed
--- /dev/null
+++ b/content/browser/media/webrtc_identity_store_backend.h
@@ -0,0 +1,111 @@
+// 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_MEDIA_WEBRTC_IDENTITY_STORE_BACKEND_H_
+#define CONTENT_BROWSER_MEDIA_WEBRTC_IDENTITY_STORE_BACKEND_H_
+
+#include <map>
+#include <string>
+
+#include "base/time/time.h"
+#include "sql/connection.h"
+#include "sql/meta_table.h"
+
+class GURL;
+
+namespace base {
+class FilePath;
+}  // namespace base
+
+namespace quota {
+class SpecialStoragePolicy;
+}  // namespace quota
+
+namespace content {
+
+// This class represents a persistent cache of WebRTC identities.
+// It can be created/destroyed/Close() on any thread. All other members should
+// be accessed on the IO thread.
+class WebRTCIdentityStoreBackend
+    : public base::RefCountedThreadSafe<WebRTCIdentityStoreBackend> {
+ public:
+  typedef base::Callback<void(int error,
+                              const std::string& certificate,
+                              const std::string& private_key)>
+      FindIdentityCallback;
+
+  // No data is saved on disk if |path| is empty.
+  WebRTCIdentityStoreBackend(const base::FilePath& path,
+                             quota::SpecialStoragePolicy* policy);
+
+  // Finds the identity with |origin|, |identity_name|, and |common_name| from
+  // the DB.
+  // |origin| is the origin of the identity;
+  // |identity_name| is used to identify an identity within an origin;
+  // |common_name| is the common name used to generate the certificate;
+  // |callback| is the callback to return the find result.
+  // Returns true if |callback| will be called.
+  // Should be called on the IO thread.
+  bool FindIdentity(const GURL& origin,
+                    const std::string& identity_name,
+                    const std::string& common_name,
+                    const FindIdentityCallback& callback);
+
+  // Adds the identity to the DB and overwrites any existing identity having the
+  // same origin and identity_name.
+  // |origin| is the origin of the identity;
+  // |identity_name| is used to identify an identity within an origin;
+  // |common_name| is the common name used to generate the certificate;
+  // |certificate| is the DER string of the certificate;
+  // |private_key| is the DER string of the private key.
+  // Should be called on the IO thread.
+  void AddIdentity(const GURL& origin,
+                   const std::string& identity_name,
+                   const std::string& common_name,
+                   const std::string& certificate,
+                   const std::string& private_key);
+
+  // Commits all pending DB operations and closes the DB connection. Any API
+  // call after this will fail.
+  // Can be called on any thread.
+  void Close();
+
+  // Delete the data created between |delete_begin| and |delete_end|.
+  // Should be called on the IO thread.
+  void DeleteBetween(base::Time delete_begin,
+                     base::Time delete_end,
+                     const base::Closure& callback);
+
+ private:
+  friend class base::RefCountedThreadSafe<WebRTCIdentityStoreBackend>;
+  class SqlLiteStorage;
+  enum LoadingState {
+    NOT_STARTED,
+    LOADING,
+    LOADED,
+    CLOSED,
+  };
+  struct PendingFindRequest;
+  struct IdentityKey;
+  struct Identity;
+  typedef std::map<IdentityKey, Identity> IdentityMap;
+
+  ~WebRTCIdentityStoreBackend();
+
+  void OnLoaded(scoped_ptr<IdentityMap> out_map);
+
+  // In-memory copy of the identities.
+  IdentityMap identities_;
+  // "Find identity" requests waiting for the DB to load.
+  std::vector<PendingFindRequest*> pending_find_requests_;
+  // The persistent storage loading state.
+  LoadingState state_;
+  // The persistent storage of identities.
+  scoped_refptr<SqlLiteStorage> sql_lite_storage_;
+
+  DISALLOW_COPY_AND_ASSIGN(WebRTCIdentityStoreBackend);
+};
+}
+
+#endif  // CONTENT_BROWSER_MEDIA_WEBRTC_IDENTITY_STORE_BACKEND_H_
diff --git a/content/browser/media/webrtc_identity_store_unittest.cc b/content/browser/media/webrtc_identity_store_unittest.cc
index a975dd4..81c25d7 100644
--- a/content/browser/media/webrtc_identity_store_unittest.cc
+++ b/content/browser/media/webrtc_identity_store_unittest.cc
@@ -17,15 +17,37 @@
 // TODO(jiayl): the tests fail on Android since the openssl version of
 // CreateSelfSignedCert is not implemented. We should mock out this dependency
 // and remove the if-defined.
-
 #if !defined(OS_ANDROID)
+
+static const char* kFakeOrigin = "http://foo.com";
+static const char* kFakeIdentityName1 = "name1";
+static const char* kFakeIdentityName2 = "name2";
+static const char* kFakeCommonName1 = "cname1";
+static const char* kFakeCommonName2 = "cname2";
+
+static void OnRequestCompleted(bool* completed,
+                               std::string* out_cert,
+                               std::string* out_key,
+                               int error,
+                               const std::string& certificate,
+                               const std::string& private_key) {
+  ASSERT_EQ(net::OK, error);
+  ASSERT_NE("", certificate);
+  ASSERT_NE("", private_key);
+  *completed = true;
+  *out_cert = certificate;
+  *out_key = private_key;
+}
+
 class WebRTCIdentityStoreTest : public testing::Test {
  public:
   WebRTCIdentityStoreTest()
-      : browser_thread_bundle_(TestBrowserThreadBundle::IO_MAINLOOP),
+      : browser_thread_bundle_(TestBrowserThreadBundle::IO_MAINLOOP |
+                               TestBrowserThreadBundle::REAL_DB_THREAD),
         pool_owner_(
             new base::SequencedWorkerPoolOwner(3, "WebRTCIdentityStoreTest")),
-        webrtc_identity_store_(new WebRTCIdentityStore()) {
+        webrtc_identity_store_(
+            new WebRTCIdentityStore(base::FilePath(), NULL)) {
     webrtc_identity_store_->SetTaskRunnerForTesting(pool_owner_->pool());
   }
 
@@ -33,74 +55,224 @@
     pool_owner_->pool()->Shutdown();
   }
 
+  void RunUntilIdle() {
+    RunAllPendingInMessageLoop(BrowserThread::DB);
+    RunAllPendingInMessageLoop(BrowserThread::IO);
+    pool_owner_->pool()->FlushForTesting();
+    base::RunLoop().RunUntilIdle();
+  }
+
+  base::Closure RequestIdentityAndRunUtilIdle(const std::string& origin,
+                                              const std::string& identity_name,
+                                              const std::string& common_name,
+                                              bool* completed,
+                                              std::string* certificate,
+                                              std::string* private_key) {
+    base::Closure cancel_callback = webrtc_identity_store_->RequestIdentity(
+        GURL(origin),
+        identity_name,
+        common_name,
+        base::Bind(&OnRequestCompleted, completed, certificate, private_key));
+    EXPECT_FALSE(cancel_callback.is_null());
+    RunUntilIdle();
+    return cancel_callback;
+  }
+
  protected:
   TestBrowserThreadBundle browser_thread_bundle_;
   scoped_ptr<base::SequencedWorkerPoolOwner> pool_owner_;
-  scoped_ptr<WebRTCIdentityStore> webrtc_identity_store_;
+  scoped_refptr<WebRTCIdentityStore> webrtc_identity_store_;
 };
 
-static void OnRequestCompleted(bool* completed,
-                        int error,
-                        const std::string& certificate,
-                        const std::string& private_key) {
-  ASSERT_EQ(net::OK, error);
-  ASSERT_NE("", certificate);
-  ASSERT_NE("", private_key);
-  *completed = true;
-}
-
 TEST_F(WebRTCIdentityStoreTest, RequestIdentity) {
   bool completed = false;
+  std::string dummy;
   base::Closure cancel_callback =
-      webrtc_identity_store_->RequestIdentity(
-          GURL("http://google.com"),
-          "a",
-          "b",
-          base::Bind(&OnRequestCompleted, &completed));
-  ASSERT_FALSE(cancel_callback.is_null());
-  pool_owner_->pool()->FlushForTesting();
-  base::RunLoop().RunUntilIdle();
+      RequestIdentityAndRunUtilIdle(kFakeOrigin,
+                                    kFakeIdentityName1,
+                                    kFakeCommonName1,
+                                    &completed,
+                                    &dummy,
+                                    &dummy);
   EXPECT_TRUE(completed);
 }
 
 TEST_F(WebRTCIdentityStoreTest, CancelRequest) {
   bool completed = false;
-  base::Closure cancel_callback =
-      webrtc_identity_store_->RequestIdentity(
-          GURL("http://google.com"),
-          "a",
-          "b",
-          base::Bind(&OnRequestCompleted, &completed));
+  std::string dummy;
+  base::Closure cancel_callback = webrtc_identity_store_->RequestIdentity(
+      GURL(kFakeOrigin),
+      kFakeIdentityName1,
+      kFakeCommonName1,
+      base::Bind(&OnRequestCompleted, &completed, &dummy, &dummy));
   ASSERT_FALSE(cancel_callback.is_null());
   cancel_callback.Run();
-  pool_owner_->pool()->FlushForTesting();
-  base::RunLoop().RunUntilIdle();
+
+  RunUntilIdle();
   EXPECT_FALSE(completed);
 }
 
-TEST_F(WebRTCIdentityStoreTest, MultipleRequests) {
+TEST_F(WebRTCIdentityStoreTest, ConcurrentUniqueRequests) {
   bool completed_1 = false;
   bool completed_2 = false;
-  base::Closure cancel_callback_1 =
-    webrtc_identity_store_->RequestIdentity(
-        GURL("http://foo.com"),
-        "a",
-        "b",
-        base::Bind(&OnRequestCompleted, &completed_1));
+  std::string dummy;
+  base::Closure cancel_callback_1 = webrtc_identity_store_->RequestIdentity(
+      GURL(kFakeOrigin),
+      kFakeIdentityName1,
+      kFakeCommonName1,
+      base::Bind(&OnRequestCompleted, &completed_1, &dummy, &dummy));
   ASSERT_FALSE(cancel_callback_1.is_null());
 
-  base::Closure cancel_callback_2 =
-    webrtc_identity_store_->RequestIdentity(
-        GURL("http://bar.com"),
-        "a",
-        "b",
-        base::Bind(&OnRequestCompleted, &completed_2));
+  base::Closure cancel_callback_2 = webrtc_identity_store_->RequestIdentity(
+      GURL(kFakeOrigin),
+      kFakeIdentityName2,
+      kFakeCommonName1,
+      base::Bind(&OnRequestCompleted, &completed_2, &dummy, &dummy));
   ASSERT_FALSE(cancel_callback_2.is_null());
 
-  pool_owner_->pool()->FlushForTesting();
-  base::RunLoop().RunUntilIdle();
+  RunUntilIdle();
   EXPECT_TRUE(completed_1);
   EXPECT_TRUE(completed_2);
 }
+
+TEST_F(WebRTCIdentityStoreTest, DifferentCommonNameReturnNewIdentity) {
+  bool completed_1 = false;
+  bool completed_2 = false;
+  std::string cert_1, cert_2, key_1, key_2;
+
+  base::Closure cancel_callback_1 =
+      RequestIdentityAndRunUtilIdle(kFakeOrigin,
+                                    kFakeIdentityName1,
+                                    kFakeCommonName1,
+                                    &completed_1,
+                                    &cert_1,
+                                    &key_1);
+
+  base::Closure cancel_callback_2 =
+      RequestIdentityAndRunUtilIdle(kFakeOrigin,
+                                    kFakeIdentityName1,
+                                    kFakeCommonName2,
+                                    &completed_2,
+                                    &cert_2,
+                                    &key_2);
+
+  EXPECT_TRUE(completed_1);
+  EXPECT_TRUE(completed_2);
+  EXPECT_NE(cert_1, cert_2);
+  EXPECT_NE(key_1, key_2);
+}
+
+TEST_F(WebRTCIdentityStoreTest, SerialIdenticalRequests) {
+  bool completed_1 = false;
+  bool completed_2 = false;
+  std::string cert_1, cert_2, key_1, key_2;
+
+  base::Closure cancel_callback_1 =
+      RequestIdentityAndRunUtilIdle(kFakeOrigin,
+                                    kFakeIdentityName1,
+                                    kFakeCommonName1,
+                                    &completed_1,
+                                    &cert_1,
+                                    &key_1);
+
+  base::Closure cancel_callback_2 =
+      RequestIdentityAndRunUtilIdle(kFakeOrigin,
+                                    kFakeIdentityName1,
+                                    kFakeCommonName1,
+                                    &completed_2,
+                                    &cert_2,
+                                    &key_2);
+
+  EXPECT_TRUE(completed_1);
+  EXPECT_TRUE(completed_2);
+  EXPECT_EQ(cert_1, cert_2);
+  EXPECT_EQ(key_1, key_2);
+}
+
+TEST_F(WebRTCIdentityStoreTest, ConcurrentIdenticalRequestsJoined) {
+  bool completed_1 = false;
+  bool completed_2 = false;
+  std::string cert_1, cert_2, key_1, key_2;
+
+  base::Closure cancel_callback_1 = webrtc_identity_store_->RequestIdentity(
+      GURL(kFakeOrigin),
+      kFakeIdentityName1,
+      kFakeCommonName1,
+      base::Bind(&OnRequestCompleted, &completed_1, &cert_1, &key_1));
+  ASSERT_FALSE(cancel_callback_1.is_null());
+
+  base::Closure cancel_callback_2 = webrtc_identity_store_->RequestIdentity(
+      GURL(kFakeOrigin),
+      kFakeIdentityName1,
+      kFakeCommonName1,
+      base::Bind(&OnRequestCompleted, &completed_2, &cert_2, &key_2));
+  ASSERT_FALSE(cancel_callback_2.is_null());
+
+  RunUntilIdle();
+  EXPECT_TRUE(completed_1);
+  EXPECT_TRUE(completed_2);
+  EXPECT_EQ(cert_1, cert_2);
+  EXPECT_EQ(key_1, key_2);
+}
+
+TEST_F(WebRTCIdentityStoreTest, CancelOneOfIdenticalRequests) {
+  bool completed_1 = false;
+  bool completed_2 = false;
+  std::string cert_1, cert_2, key_1, key_2;
+
+  base::Closure cancel_callback_1 = webrtc_identity_store_->RequestIdentity(
+      GURL(kFakeOrigin),
+      kFakeIdentityName1,
+      kFakeCommonName1,
+      base::Bind(&OnRequestCompleted, &completed_1, &cert_1, &key_1));
+  ASSERT_FALSE(cancel_callback_1.is_null());
+
+  base::Closure cancel_callback_2 = webrtc_identity_store_->RequestIdentity(
+      GURL(kFakeOrigin),
+      kFakeIdentityName1,
+      kFakeCommonName1,
+      base::Bind(&OnRequestCompleted, &completed_2, &cert_2, &key_2));
+  ASSERT_FALSE(cancel_callback_2.is_null());
+
+  cancel_callback_1.Run();
+
+  RunUntilIdle();
+  EXPECT_FALSE(completed_1);
+  EXPECT_TRUE(completed_2);
+}
+
+TEST_F(WebRTCIdentityStoreTest, DeleteDataAndGenerateNewIdentity) {
+  bool completed_1 = false;
+  bool completed_2 = false;
+  std::string cert_1, cert_2, key_1, key_2;
+
+  // Generate the first identity.
+  base::Closure cancel_callback_1 =
+      RequestIdentityAndRunUtilIdle(kFakeOrigin,
+                                    kFakeIdentityName1,
+                                    kFakeCommonName1,
+                                    &completed_1,
+                                    &cert_1,
+                                    &key_1);
+
+  // Clear the data and the second request should return a new identity.
+  webrtc_identity_store_->DeleteBetween(
+      base::Time(), base::Time::Now(), base::Bind(&base::DoNothing));
+  RunUntilIdle();
+
+  base::Closure cancel_callback_2 =
+      RequestIdentityAndRunUtilIdle(kFakeOrigin,
+                                    kFakeIdentityName1,
+                                    kFakeCommonName1,
+                                    &completed_2,
+                                    &cert_2,
+                                    &key_2);
+
+  EXPECT_TRUE(completed_1);
+  EXPECT_TRUE(completed_2);
+  EXPECT_NE(cert_1, cert_2);
+  EXPECT_NE(key_1, key_2);
+}
+
 #endif
 }  // namespace content
diff --git a/content/browser/plugin_browsertest.cc b/content/browser/plugin_browsertest.cc
index ddb5683..c1dfa1f 100644
--- a/content/browser/plugin_browsertest.cc
+++ b/content/browser/plugin_browsertest.cc
@@ -15,7 +15,6 @@
 #include "content/test/content_browser_test_utils.h"
 #include "content/test/net/url_request_mock_http_job.h"
 #include "ui/gfx/rect.h"
-#include "webkit/plugins/plugin_switches.h"
 
 #if defined(OS_WIN)
 #include "base/win/registry.h"
diff --git a/content/browser/plugin_data_remover_impl.cc b/content/browser/plugin_data_remover_impl.cc
index d711f80..670d80d 100644
--- a/content/browser/plugin_data_remover_impl.cc
+++ b/content/browser/plugin_data_remover_impl.cc
@@ -19,9 +19,9 @@
 #include "content/common/plugin_process_messages.h"
 #include "content/public/browser/browser_context.h"
 #include "content/public/browser/browser_thread.h"
+#include "content/public/common/content_constants.h"
 #include "content/public/common/pepper_plugin_info.h"
 #include "ppapi/proxy/ppapi_messages.h"
-#include "webkit/plugins/plugin_constants.h"
 
 namespace content {
 
diff --git a/content/browser/plugin_service_impl.cc b/content/browser/plugin_service_impl.cc
index f596977..6682a4d 100644
--- a/content/browser/plugin_service_impl.cc
+++ b/content/browser/plugin_service_impl.cc
@@ -26,10 +26,10 @@
 #include "content/public/browser/content_browser_client.h"
 #include "content/public/browser/plugin_service_filter.h"
 #include "content/public/browser/resource_context.h"
+#include "content/public/common/content_constants.h"
 #include "content/public/common/content_switches.h"
 #include "content/public/common/process_type.h"
 #include "content/public/common/webplugininfo.h"
-#include "webkit/plugins/plugin_constants.h"
 
 #if defined(OS_WIN)
 #include "content/common/plugin_constants_win.h"
diff --git a/content/browser/power_monitor_message_broadcaster_unittest.cc b/content/browser/power_monitor_message_broadcaster_unittest.cc
index 6eb0cb4..5155082 100644
--- a/content/browser/power_monitor_message_broadcaster_unittest.cc
+++ b/content/browser/power_monitor_message_broadcaster_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 "base/power_monitor/power_monitor_test_base.h"
+#include "base/test/power_monitor_test_base.h"
 #include "content/browser/power_monitor_message_broadcaster.h"
 #include "content/common/power_monitor_messages.h"
 #include "ipc/ipc_sender.h"
diff --git a/content/browser/power_save_blocker_android.cc b/content/browser/power_save_blocker_android.cc
index 45dda18..720fbb2 100644
--- a/content/browser/power_save_blocker_android.cc
+++ b/content/browser/power_save_blocker_android.cc
@@ -5,23 +5,26 @@
 #include "content/browser/power_save_blocker_android.h"
 
 #include "base/android/jni_android.h"
+#include "base/android/jni_helper.h"
 #include "base/logging.h"
 #include "content/browser/power_save_blocker_impl.h"
+#include "content/public/browser/android/content_view_core.h"
 #include "content/public/browser/browser_thread.h"
 #include "jni/PowerSaveBlocker_jni.h"
-#include "ui/android/window_android.h"
+#include "ui/android/view_android.h"
 
 using base::android::AttachCurrentThread;
 using base::android::ScopedJavaLocalRef;
+using gfx::NativeView;
 
 namespace content {
 
 class PowerSaveBlockerImpl::Delegate
     : public base::RefCountedThreadSafe<PowerSaveBlockerImpl::Delegate> {
  public:
-  explicit Delegate(gfx::NativeWindow native_window) {
-    j_window_android_ = JavaObjectWeakGlobalRef(AttachCurrentThread(),
-        static_cast<ui::WindowAndroid*>(native_window)->GetJavaObject().obj());
+  explicit Delegate(NativeView view_android) {
+    j_view_android_ = JavaObjectWeakGlobalRef(
+        AttachCurrentThread(), view_android->GetJavaObject().obj());
   }
 
   // Does the actual work to apply or remove the desired power save block.
@@ -32,7 +35,7 @@
   friend class base::RefCountedThreadSafe<Delegate>;
   ~Delegate() {}
 
-  JavaObjectWeakGlobalRef j_window_android_;
+  JavaObjectWeakGlobalRef j_view_android_;
 
   DISALLOW_COPY_AND_ASSIGN(Delegate);
 };
@@ -40,7 +43,7 @@
 void PowerSaveBlockerImpl::Delegate::ApplyBlock() {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
   JNIEnv* env = AttachCurrentThread();
-  ScopedJavaLocalRef<jobject> j_object = j_window_android_.get(env);
+  ScopedJavaLocalRef<jobject> j_object = j_view_android_.get(env);
   if (j_object.obj())
     Java_PowerSaveBlocker_applyBlock(env, j_object.obj());
 }
@@ -48,7 +51,7 @@
 void PowerSaveBlockerImpl::Delegate::RemoveBlock() {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
   JNIEnv* env = AttachCurrentThread();
-  ScopedJavaLocalRef<jobject> j_object = j_window_android_.get(env);
+  ScopedJavaLocalRef<jobject> j_object = j_view_android_.get(env);
   if (j_object.obj())
     Java_PowerSaveBlocker_removeBlock(env, j_object.obj());
 }
@@ -66,9 +69,11 @@
   }
 }
 
-void PowerSaveBlockerImpl::InitDisplaySleepBlocker(
-    gfx::NativeWindow native_window) {
-  delegate_ = new Delegate(native_window);
+void PowerSaveBlockerImpl::InitDisplaySleepBlocker(NativeView view_android) {
+  if (!view_android)
+    return;
+
+  delegate_ = new Delegate(view_android);
   // This may be called on any thread.
   BrowserThread::PostTask(
       BrowserThread::UI, FROM_HERE,
diff --git a/content/browser/power_save_blocker_impl.h b/content/browser/power_save_blocker_impl.h
index c3a105d..948aced 100644
--- a/content/browser/power_save_blocker_impl.h
+++ b/content/browser/power_save_blocker_impl.h
@@ -17,11 +17,10 @@
   virtual ~PowerSaveBlockerImpl();
 
 #if defined(OS_ANDROID)
-  // In Android platform, the |native_window| is needed to create the
-  // kPowerSaveBlockPreventDisplaySleep type of PowerSaveBlocker
-  // so the blocker could be removed by platform if the window isn't in the
-  // foreground.
-  void InitDisplaySleepBlocker(gfx::NativeWindow native_window);
+  // In Android platform, the kPowerSaveBlockPreventDisplaySleep type of
+  // PowerSaveBlocker should associated with the ViewAndroid,
+  // so the blocker could be removed by platform if the view isn't visble
+  void InitDisplaySleepBlocker(gfx::NativeView view_android);
 #endif
 
  private:
diff --git a/content/browser/ppapi_plugin_process_host.cc b/content/browser/ppapi_plugin_process_host.cc
index f440be4..c9aa699 100644
--- a/content/browser/ppapi_plugin_process_host.cc
+++ b/content/browser/ppapi_plugin_process_host.cc
@@ -25,7 +25,6 @@
 #include "net/base/network_change_notifier.h"
 #include "ppapi/proxy/ppapi_messages.h"
 #include "ui/base/ui_base_switches.h"
-#include "webkit/plugins/plugin_switches.h"
 
 #if defined(OS_WIN)
 #include "content/common/sandbox_win.h"
diff --git a/content/browser/renderer_host/compositing_iosurface_mac.h b/content/browser/renderer_host/compositing_iosurface_mac.h
index 1b3ece3..674e4e5 100644
--- a/content/browser/renderer_host/compositing_iosurface_mac.h
+++ b/content/browser/renderer_host/compositing_iosurface_mac.h
@@ -203,6 +203,7 @@
     void PrepareForAsynchronousReadback();
 
     const scoped_ptr<CompositingIOSurfaceTransformer> transformer;
+    GLenum output_readback_format;
     int num_outputs;
     GLuint output_textures[3];  // Not owned.
     // Note: For YUV, the |output_texture_sizes| widths are in terms of 4-byte
diff --git a/content/browser/renderer_host/compositing_iosurface_mac.mm b/content/browser/renderer_host/compositing_iosurface_mac.mm
index be99891..a9ca707 100644
--- a/content/browser/renderer_host/compositing_iosurface_mac.mm
+++ b/content/browser/renderer_host/compositing_iosurface_mac.mm
@@ -173,6 +173,7 @@
     const scoped_refptr<CompositingIOSurfaceContext>& context)
   : transformer(new CompositingIOSurfaceTransformer(
         GL_TEXTURE_RECTANGLE_ARB, true, context->shader_program_cache())),
+    output_readback_format(GL_BGRA),
     num_outputs(0),
     fence(0),
     cycles_elapsed(0) {
@@ -744,7 +745,13 @@
   DCHECK_NE(bitmap_output != NULL, video_frame_output.get() != NULL);
   DCHECK(!done_callback.is_null());
 
-  const bool async_copy = IsAsynchronousReadbackSupported();
+  // SWIZZLE_RGBA_FOR_ASYNC_READPIXELS workaround: Fall-back to synchronous
+  // readback for SkBitmap output since the Blit shader program doesn't support
+  // switchable output formats.
+  const bool require_sync_copy_for_workaround = bitmap_output &&
+      context_->shader_program_cache()->rgb_to_yv12_output_format() == GL_RGBA;
+  const bool async_copy = !require_sync_copy_for_workaround &&
+      IsAsynchronousReadbackSupported();
   TRACE_EVENT2(
       "browser", "CompositingIOSurfaceMac::CopyToSelectedOutputWithinContext",
       "output", bitmap_output ? "SkBitmap (ARGB)" : "VideoFrame (YV12)",
@@ -780,6 +787,7 @@
     if (copy_context->transformer->ResizeBilinear(
             texture_, src_rect, dst_pixel_rect.size(),
             &copy_context->output_textures[0])) {
+      copy_context->output_readback_format = GL_BGRA;
       copy_context->num_outputs = 1;
       copy_context->output_texture_sizes[0] = dst_pixel_rect.size();
     }
@@ -791,6 +799,8 @@
             &copy_context->output_textures[2],
             &copy_context->output_texture_sizes[0],
             &copy_context->output_texture_sizes[1])) {
+      copy_context->output_readback_format =
+          context_->shader_program_cache()->rgb_to_yv12_output_format();
       copy_context->num_outputs = 3;
       copy_context->output_texture_sizes[2] =
           copy_context->output_texture_sizes[1];
@@ -851,7 +861,8 @@
     glReadPixels(0, 0,
                  copy_context->output_texture_sizes[i].width(),
                  copy_context->output_texture_sizes[i].height(),
-                 GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, 0);
+                 copy_context->output_readback_format,
+                 GL_UNSIGNED_INT_8_8_8_8_REV, 0);
     CHECK_AND_SAVE_GL_ERROR();
   }
 
@@ -993,8 +1004,9 @@
     glReadPixels(0, 0,
                  copy_context->output_texture_sizes[i].width(),
                  copy_context->output_texture_sizes[i].height(),
-                 GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV,
-                 buf); CHECK_AND_SAVE_GL_ERROR();
+                 copy_context->output_readback_format,
+                 GL_UNSIGNED_INT_8_8_8_8_REV, buf);
+    CHECK_AND_SAVE_GL_ERROR();
     if (video_frame_output.get()) {
       if (!temp_readback_buffer) {
         // Apply letterbox black-out around view region.
diff --git a/content/browser/renderer_host/compositing_iosurface_shader_programs_mac.cc b/content/browser/renderer_host/compositing_iosurface_shader_programs_mac.cc
index 12988a1..87f0f34 100644
--- a/content/browser/renderer_host/compositing_iosurface_shader_programs_mac.cc
+++ b/content/browser/renderer_host/compositing_iosurface_shader_programs_mac.cc
@@ -11,18 +11,27 @@
 #include "base/debug/trace_event.h"
 #include "base/logging.h"
 #include "base/memory/scoped_ptr.h"
+#include "base/values.h"
+#include "content/browser/gpu/gpu_data_manager_impl.h"
+#include "gpu/config/gpu_driver_bug_workaround_type.h"
 
 namespace content {
 
 namespace {
 
 // Convenience macro allowing GLSL programs to be specified inline, and to be
-// automatically converted into string form by the C preprocessor.  As required
-// by the spec, add the version directive to the beginning of each program to
-// activate the expected syntax and built-in features.  GLSL version 1.2 is the
-// latest version supported by MacOS 10.6.
-#define GLSL_PROGRAM_AS_STRING(shader_code) "#version 120\n" #shader_code
+// automatically converted into string form by the C preprocessor.
+#define GLSL_PROGRAM_AS_STRING(shader_code) #shader_code
 
+// As required by the spec, add the version directive to the beginning of each
+// program to activate the expected syntax and built-in features.  GLSL version
+// 1.2 is the latest version supported by MacOS 10.6.
+const char kVersionDirective[] = "#version 120\n";
+
+// Allow switchable output swizzling from RGBToYV12 fragment shaders (needed for
+// workaround; see comments in CompositingIOSurfaceShaderPrograms ctor).
+const char kOutputSwizzleMacroNormal[] = "#define OUTPUT_PIXEL_ORDERING bgra\n";
+const char kOutputSwizzleMacroSwapRB[] = "#define OUTPUT_PIXEL_ORDERING rgba\n";
 
 // Only the bare-bones calculations here for speed.
 const char kvsBlit[] = GLSL_PROGRAM_AS_STRING(
@@ -144,8 +153,7 @@
       vec2 vv = vec2(dot(blended_pixel0, rgb_to_v),
                      dot(blended_pixel1, rgb_to_v)) / 2.0;
 
-      // Note: Packaging the result to account for BGRA byte ordering.
-      gl_FragData[0] = yyyy.bgra;
+      gl_FragData[0] = yyyy.OUTPUT_PIXEL_ORDERING;
       gl_FragData[1] = vec4(uu, vv) + uv_bias;
     }
 );
@@ -178,9 +186,8 @@
       // sampler takes care of that.
       vec4 lo_uuvv = texture2DRect(texture_, texture_coord0);
       vec4 hi_uuvv = texture2DRect(texture_, texture_coord1);
-      // Note: Packaging the result to account for BGRA byte ordering.
-      gl_FragData[0] = vec4(lo_uuvv.rg, hi_uuvv.rg).bgra;
-      gl_FragData[1] = vec4(lo_uuvv.ba, hi_uuvv.ba).bgra;
+      gl_FragData[0] = vec4(lo_uuvv.rg, hi_uuvv.rg).OUTPUT_PIXEL_ORDERING;
+      gl_FragData[1] = vec4(lo_uuvv.ba, hi_uuvv.ba).OUTPUT_PIXEL_ORDERING;
     }
 );
 
@@ -219,7 +226,8 @@
   kRGBtoYV12_fsConvertUV44toU2V2,
 };
 
-GLuint CompileShaderGLSL(ShaderProgram shader_program, GLenum shader_type) {
+GLuint CompileShaderGLSL(ShaderProgram shader_program, GLenum shader_type,
+                         bool output_swap_rb) {
   TRACE_EVENT2("gpu", "CompileShaderGLSL",
                "program", shader_program,
                "type", shader_type == GL_VERTEX_SHADER ? "vertex" : "fragment");
@@ -231,11 +239,21 @@
   DCHECK_NE(shader, 0u);
 
   // Select and compile the shader program source code.
-  glShaderSource(shader,
-                 1,
-                 (shader_type == GL_VERTEX_SHADER ? kVertexShaderSourceCodeMap :
-                      kFragmentShaderSourceCodeMap) + shader_program,
-                 NULL);
+  if (shader_type == GL_VERTEX_SHADER) {
+    const GLchar* source_snippets[] = {
+      kVersionDirective,
+      kVertexShaderSourceCodeMap[shader_program],
+    };
+    glShaderSource(shader, arraysize(source_snippets), source_snippets, NULL);
+  } else {
+    DCHECK(shader_type == GL_FRAGMENT_SHADER);
+    const GLchar* source_snippets[] = {
+      kVersionDirective,
+      output_swap_rb ? kOutputSwizzleMacroSwapRB : kOutputSwizzleMacroNormal,
+      kFragmentShaderSourceCodeMap[shader_program],
+    };
+    glShaderSource(shader, arraysize(source_snippets), source_snippets, NULL);
+  }
   glCompileShader(shader);
 
   // Check for successful compilation.  On error in debug builds, pull the info
@@ -265,12 +283,14 @@
   return shader;
 }
 
-GLuint CompileAndLinkProgram(ShaderProgram which) {
+GLuint CompileAndLinkProgram(ShaderProgram which, bool output_swap_rb) {
   TRACE_EVENT1("gpu", "CompileAndLinkProgram", "program", which);
 
   // Compile and link a new shader program.
-  const GLuint vertex_shader = CompileShaderGLSL(which, GL_VERTEX_SHADER);
-  const GLuint fragment_shader = CompileShaderGLSL(which, GL_FRAGMENT_SHADER);
+  const GLuint vertex_shader =
+      CompileShaderGLSL(which, GL_VERTEX_SHADER, false);
+  const GLuint fragment_shader =
+      CompileShaderGLSL(which, GL_FRAGMENT_SHADER, output_swap_rb);
   const GLuint program = glCreateProgram();
   DCHECK_NE(program, 0u);
   glAttachShader(program, vertex_shader);
@@ -295,7 +315,8 @@
 }  // namespace
 
 
-CompositingIOSurfaceShaderPrograms::CompositingIOSurfaceShaderPrograms() {
+CompositingIOSurfaceShaderPrograms::CompositingIOSurfaceShaderPrograms()
+    : rgb_to_yv12_output_format_(GL_BGRA) {
   COMPILE_ASSERT(kNumShaderPrograms == NUM_SHADER_PROGRAMS,
                  header_constant_disagrees_with_enum);
   COMPILE_ASSERT(arraysize(kVertexShaderSourceCodeMap) == NUM_SHADER_PROGRAMS,
@@ -308,6 +329,22 @@
     texture_var_locations_[i] = -1;
   for (size_t i = 0; i < arraysize(texel_scale_x_var_locations_); ++i)
     texel_scale_x_var_locations_[i] = -1;
+
+  // Look for the swizzle_rgba_for_async_readpixels driver bug workaround and
+  // modify rgb_to_yv12_output_format_ if necessary.
+  // See: http://crbug.com/265115
+  GpuDataManagerImpl* const manager = GpuDataManagerImpl::GetInstance();
+  if (manager) {
+    base::ListValue workarounds;
+    manager->GetDriverBugWorkarounds(&workarounds);
+    base::ListValue::const_iterator it = workarounds.Find(
+        base::StringValue(gpu::GpuDriverBugWorkaroundTypeToString(
+            gpu::SWIZZLE_RGBA_FOR_ASYNC_READPIXELS)));
+    if (it != workarounds.end())
+      rgb_to_yv12_output_format_ = GL_RGBA;
+  }
+  DVLOG(1) << "Using RGBToYV12 fragment shader output format: "
+           << (rgb_to_yv12_output_format_ == GL_BGRA ? "BGRA" : "RGBA");
 }
 
 CompositingIOSurfaceShaderPrograms::~CompositingIOSurfaceShaderPrograms() {
@@ -371,10 +408,17 @@
   return true;
 }
 
+void CompositingIOSurfaceShaderPrograms::SetOutputFormatForTesting(
+    GLenum format) {
+  rgb_to_yv12_output_format_ = format;
+  Reset();
+}
+
 GLuint CompositingIOSurfaceShaderPrograms::GetShaderProgram(int which) {
   if (shader_programs_[which] == 0u) {
     shader_programs_[which] =
-        CompileAndLinkProgram(static_cast<ShaderProgram>(which));
+        CompileAndLinkProgram(static_cast<ShaderProgram>(which),
+                              rgb_to_yv12_output_format_ == GL_RGBA);
     DCHECK_NE(shader_programs_[which], 0u)
         << "Failed to create ShaderProgram " << which;
   }
diff --git a/content/browser/renderer_host/compositing_iosurface_shader_programs_mac.h b/content/browser/renderer_host/compositing_iosurface_shader_programs_mac.h
index 152858c..de1987f 100644
--- a/content/browser/renderer_host/compositing_iosurface_shader_programs_mac.h
+++ b/content/browser/renderer_host/compositing_iosurface_shader_programs_mac.h
@@ -8,13 +8,16 @@
 #include <OpenGL/gl.h>
 
 #include "base/basictypes.h"
+#include "base/gtest_prod_util.h"
 
 namespace content {
 
 // Provides caching of the compile-and-link step for shader programs at runtime
 // since, once compiled and linked, the programs can be shared.  Callers invoke
-// one of the UseXXX() methods within a GL context to glUseProgram() the program
-// and have its uniform variables bound with the given parameters.
+// one of the UseXXX() methods to glUseProgram() the program and have its
+// uniform variables bound with the given parameters.
+//
+// Note: All public methods must be invoked within the the same GL context!
 class CompositingIOSurfaceShaderPrograms {
  public:
   CompositingIOSurfaceShaderPrograms();
@@ -39,6 +42,19 @@
   // Returns false on error.
   bool UseRGBToYV12Program(int pass_number, float texel_scale_x);
 
+  // |format| argument to use for glReadPixels() when reading back textures
+  // generated by the RGBToYV12 program.
+  GLenum rgb_to_yv12_output_format() const {
+    return rgb_to_yv12_output_format_;
+  }
+
+ protected:
+  FRIEND_TEST_ALL_PREFIXES(CompositingIOSurfaceTransformerTest,
+                           TransformsRGBToYV12);
+
+  // Side effect: Calls Reset(), deleting any cached programs.
+  void SetOutputFormatForTesting(GLenum format);
+
  private:
   enum { kNumShaderPrograms = 4 };
 
@@ -53,6 +69,10 @@
   GLint texture_var_locations_[kNumShaderPrograms];
   GLint texel_scale_x_var_locations_[kNumShaderPrograms];
 
+  // Byte order of the quads generated by the RGBToYV12 shader program.  Must
+  // always be GL_BGRA (default) or GL_RGBA (workaround case).
+  GLenum rgb_to_yv12_output_format_;
+
   DISALLOW_COPY_AND_ASSIGN(CompositingIOSurfaceShaderPrograms);
 };
 
diff --git a/content/browser/renderer_host/compositing_iosurface_transformer_mac_unittest.cc b/content/browser/renderer_host/compositing_iosurface_transformer_mac_unittest.cc
index 6f2562c..7d9452f 100644
--- a/content/browser/renderer_host/compositing_iosurface_transformer_mac_unittest.cc
+++ b/content/browser/renderer_host/compositing_iosurface_transformer_mac_unittest.cc
@@ -144,7 +144,7 @@
 }
 
 // Read back a texture from the GPU, returning the image data as an SkBitmap.
-SkBitmap ReadBackTexture(GLuint texture, const gfx::Size& size) {
+SkBitmap ReadBackTexture(GLuint texture, const gfx::Size& size, GLenum format) {
   SkBitmap result;
   result.setConfig(SkBitmap::kARGB_8888_Config, size.width(), size.height());
   CHECK(result.allocPixels());
@@ -162,7 +162,7 @@
   {
     SkAutoLockPixels lock_result(result);
     EXPECT_NO_GL_ERROR(glReadPixels(
-        0, 0, size.width(), size.height(), GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV,
+        0, 0, size.width(), size.height(), format, GL_UNSIGNED_INT_8_8_8_8_REV,
         result.getPixels()));
   }
 
@@ -303,7 +303,8 @@
         original_texture, src_rect, dst_size, &scaled_texture));
     EXPECT_NE(0u, scaled_texture);
     CGLFlushDrawable(context_);  // Account for some buggy driver impls.
-    const SkBitmap result_bitmap = ReadBackTexture(scaled_texture, dst_size);
+    const SkBitmap result_bitmap =
+        ReadBackTexture(scaled_texture, dst_size, GL_BGRA);
     EXPECT_NO_GL_ERROR(glDeleteTextures(1, &original_texture));
 
     // Compare the image read back to the version produced by a known-working
@@ -344,9 +345,13 @@
 
     // Read-back the texture for each plane.
     CGLFlushDrawable(context_);  // Account for some buggy driver impls.
-    const SkBitmap result_y_bitmap = ReadBackTexture(texture_y, packed_y_size);
-    const SkBitmap result_u_bitmap = ReadBackTexture(texture_u, packed_uv_size);
-    const SkBitmap result_v_bitmap = ReadBackTexture(texture_v, packed_uv_size);
+    const GLenum format = shader_program_cache_->rgb_to_yv12_output_format();
+    const SkBitmap result_y_bitmap =
+        ReadBackTexture(texture_y, packed_y_size, format);
+    const SkBitmap result_u_bitmap =
+        ReadBackTexture(texture_u, packed_uv_size, format);
+    const SkBitmap result_v_bitmap =
+        ReadBackTexture(texture_v, packed_uv_size, format);
 
     // Compare the Y, U, and V planes read-back to the version produced by a
     // known-working software implementation.  Allow up to 2 lines of mismatch
@@ -485,35 +490,43 @@
 }
 
 TEST_F(CompositingIOSurfaceTransformerTest, TransformsRGBToYV12) {
-  for (size_t i = 0; i < arraysize(kTestParameters); ++i) {
-    SCOPED_TRACE(::testing::Message() << "kTestParameters[" << i << ']');
+  static const GLenum kOutputFormats[] = { GL_BGRA, GL_RGBA };
 
-    const TestParameters& params = kTestParameters[i];
-    const gfx::Size src_size(params.src_width, params.src_height);
-    const gfx::Size dst_size(params.scaled_width, params.scaled_height);
-    const SkBitmap src_bitmap = GenerateTestPatternBitmap(src_size);
+  for (size_t i = 0; i < arraysize(kOutputFormats); ++i) {
+    SCOPED_TRACE(::testing::Message() << "kOutputFormats[" << i << ']');
 
-    // Full texture resize test.
-    RunTransformRGBToYV12Test(src_bitmap, gfx::Rect(src_size), dst_size);
-    // Subrect resize test: missing top row in source.
-    RunTransformRGBToYV12Test(
-        src_bitmap, gfx::Rect(0, 1, params.src_width, params.src_height - 1),
-        dst_size);
-    // Subrect resize test: missing left column in source.
-    RunTransformRGBToYV12Test(
-        src_bitmap, gfx::Rect(1, 0, params.src_width - 1, params.src_height),
-        dst_size);
-    // Subrect resize test: missing top+bottom rows, and left column in
-    // source.
-    RunTransformRGBToYV12Test(
-        src_bitmap,
-        gfx::Rect(1, 1, params.src_width - 1, params.src_height - 2),
-        dst_size);
-    // Subrect resize test: missing top row, and left+right columns in source.
-    RunTransformRGBToYV12Test(
-        src_bitmap,
-        gfx::Rect(1, 1, params.src_width - 2, params.src_height - 1),
-        dst_size);
+    shader_program_cache()->SetOutputFormatForTesting(kOutputFormats[i]);
+
+    for (size_t j = 0; j < arraysize(kTestParameters); ++j) {
+      SCOPED_TRACE(::testing::Message() << "kTestParameters[" << j << ']');
+
+      const TestParameters& params = kTestParameters[j];
+      const gfx::Size src_size(params.src_width, params.src_height);
+      const gfx::Size dst_size(params.scaled_width, params.scaled_height);
+      const SkBitmap src_bitmap = GenerateTestPatternBitmap(src_size);
+
+      // Full texture resize test.
+      RunTransformRGBToYV12Test(src_bitmap, gfx::Rect(src_size), dst_size);
+      // Subrect resize test: missing top row in source.
+      RunTransformRGBToYV12Test(
+          src_bitmap, gfx::Rect(0, 1, params.src_width, params.src_height - 1),
+          dst_size);
+      // Subrect resize test: missing left column in source.
+      RunTransformRGBToYV12Test(
+          src_bitmap, gfx::Rect(1, 0, params.src_width - 1, params.src_height),
+          dst_size);
+      // Subrect resize test: missing top+bottom rows, and left column in
+      // source.
+      RunTransformRGBToYV12Test(
+          src_bitmap,
+          gfx::Rect(1, 1, params.src_width - 1, params.src_height - 2),
+          dst_size);
+      // Subrect resize test: missing top row, and left+right columns in source.
+      RunTransformRGBToYV12Test(
+          src_bitmap,
+          gfx::Rect(1, 1, params.src_width - 2, params.src_height - 1),
+          dst_size);
+    }
   }
 }
 
diff --git a/content/browser/renderer_host/input/gesture_event_filter.cc b/content/browser/renderer_host/input/gesture_event_filter.cc
index bbc01db..c2ff887 100644
--- a/content/browser/renderer_host/input/gesture_event_filter.cc
+++ b/content/browser/renderer_host/input/gesture_event_filter.cc
@@ -75,10 +75,10 @@
 GestureEventFilter::~GestureEventFilter() { }
 
 bool GestureEventFilter::ShouldDiscardFlingCancelEvent(
-    const GestureEventWithLatencyInfo& gesture_event) {
+    const GestureEventWithLatencyInfo& gesture_event) const {
   if (coalesced_gesture_events_.empty() && fling_in_progress_)
     return false;
-  GestureEventQueue::reverse_iterator it =
+  GestureEventQueue::const_reverse_iterator it =
       coalesced_gesture_events_.rbegin();
   while (it != coalesced_gesture_events_.rend()) {
     if (it->event.type == WebInputEvent::GestureFlingStart)
@@ -138,7 +138,7 @@
 }
 
 bool GestureEventFilter::ShouldForwardForZeroVelocityFlingStart(
-    const GestureEventWithLatencyInfo& gesture_event) {
+    const GestureEventWithLatencyInfo& gesture_event) const {
   return gesture_event.event.type != WebInputEvent::GestureFlingStart ||
       gesture_event.event.sourceDevice != WebGestureEvent::Touchpad ||
       gesture_event.event.data.flingStart.velocityX != 0 ||
@@ -146,7 +146,7 @@
 }
 
 bool GestureEventFilter::ShouldForwardForGFCFiltering(
-    const GestureEventWithLatencyInfo& gesture_event) {
+    const GestureEventWithLatencyInfo& gesture_event) const {
   return gesture_event.event.type != WebInputEvent::GestureFlingCancel ||
       !ShouldDiscardFlingCancelEvent(gesture_event);
 }
@@ -301,7 +301,7 @@
   fling_in_progress_ = false;
 }
 
-bool GestureEventFilter::ShouldHandleEventNow() {
+bool GestureEventFilter::ShouldHandleEventNow() const {
   return coalesced_gesture_events_.size() == 1;
 }
 
@@ -328,7 +328,7 @@
 
 void GestureEventFilter::SendScrollEndingEventsNow() {
   scrolling_in_progress_ = false;
-  for (GestureEventQueue::iterator it =
+  for (GestureEventQueue::const_iterator it =
       debouncing_deferral_queue_.begin();
       it != debouncing_deferral_queue_.end(); it++) {
     if (ShouldForwardForGFCFiltering(*it) &&
@@ -407,7 +407,7 @@
 
 bool GestureEventFilter::ShouldTryMerging(
     const GestureEventWithLatencyInfo& new_event,
-    const GestureEventWithLatencyInfo& event_in_queue) {
+    const GestureEventWithLatencyInfo& event_in_queue) const {
   DLOG_IF(WARNING,
           new_event.event.timeStampSeconds <
           event_in_queue.event.timeStampSeconds)
@@ -418,7 +418,7 @@
 }
 
 gfx::Transform GestureEventFilter::GetTransformForEvent(
-    const GestureEventWithLatencyInfo& gesture_event) {
+    const GestureEventWithLatencyInfo& gesture_event) const {
   gfx::Transform gesture_transform = gfx::Transform();
   if (gesture_event.event.type == WebInputEvent::GestureScrollUpdate) {
     gesture_transform.Translate(gesture_event.event.data.scrollUpdate.deltaX,
diff --git a/content/browser/renderer_host/input/gesture_event_filter.h b/content/browser/renderer_host/input/gesture_event_filter.h
index c4dd911..b0c3782 100644
--- a/content/browser/renderer_host/input/gesture_event_filter.h
+++ b/content/browser/renderer_host/input/gesture_event_filter.h
@@ -96,11 +96,11 @@
   // Returns |true| if the given GestureFlingCancel should be discarded
   // as unnecessary.
   bool ShouldDiscardFlingCancelEvent(
-      const GestureEventWithLatencyInfo& gesture_event);
+      const GestureEventWithLatencyInfo& gesture_event) const;
 
   // Returns |true| if the only event in the queue is the current event and
   // hence that event should be handled now.
-  bool ShouldHandleEventNow();
+  bool ShouldHandleEventNow() const;
 
   // Merge or append a GestureScrollUpdate or GesturePinchUpdate into
   // the coalescing queue.
@@ -109,7 +109,7 @@
 
   // Sub-filter for removing zero-velocity fling-starts from touchpad.
   bool ShouldForwardForZeroVelocityFlingStart(
-      const GestureEventWithLatencyInfo& gesture_event);
+      const GestureEventWithLatencyInfo& gesture_event) const;
 
   // Sub-filter for removing bounces from in-progress scrolls.
   bool ShouldForwardForBounceReduction(
@@ -117,7 +117,7 @@
 
   // Sub-filter for removing unnecessary GestureFlingCancels.
   bool ShouldForwardForGFCFiltering(
-      const GestureEventWithLatencyInfo& gesture_event);
+      const GestureEventWithLatencyInfo& gesture_event) const;
 
   // Sub-filter for suppressing taps immediately after a GestureFlingCancel.
   bool ShouldForwardForTapSuppression(
@@ -136,14 +136,15 @@
   // Whether the event_in_queue is GesturePinchUpdate or
   // GestureScrollUpdate and it has the same modifiers as the
   // new event.
-  bool ShouldTryMerging(const GestureEventWithLatencyInfo& new_event,
-                        const GestureEventWithLatencyInfo& event_in_queue);
+  bool ShouldTryMerging(
+      const GestureEventWithLatencyInfo& new_event,
+      const GestureEventWithLatencyInfo& event_in_queue)const;
 
   // Returns the transform matrix corresponding to the gesture event.
   // Assumes the gesture event sent is either GestureScrollUpdate or
   // GesturePinchUpdate. Returns the identity matrix otherwise.
   gfx::Transform GetTransformForEvent(
-      const GestureEventWithLatencyInfo& gesture_event);
+      const GestureEventWithLatencyInfo& gesture_event) const;
 
   // The receiver of all forwarded gesture events.
   InputRouter* input_router_;
diff --git a/content/browser/renderer_host/media/OWNERS b/content/browser/renderer_host/media/OWNERS
index 084677c..45ac661 100644
--- a/content/browser/renderer_host/media/OWNERS
+++ b/content/browser/renderer_host/media/OWNERS
@@ -22,5 +22,5 @@
 per-file video_capture_oracle*=nick@chromium.org
 
 # Screen capture OWNERS.
-per-file screen_capture_*=sergeyu@chromium.org
-per-file screen_capture_*=wez@chromium.org
\ No newline at end of file
+per-file desktop_capture_*=sergeyu@chromium.org
+per-file desktop_capture_*=wez@chromium.org
diff --git a/content/browser/renderer_host/media/screen_capture_device.cc b/content/browser/renderer_host/media/desktop_capture_device.cc
similarity index 68%
rename from content/browser/renderer_host/media/screen_capture_device.cc
rename to content/browser/renderer_host/media/desktop_capture_device.cc
index 3edd6cc..5a03e46 100644
--- a/content/browser/renderer_host/media/screen_capture_device.cc
+++ b/content/browser/renderer_host/media/desktop_capture_device.cc
@@ -2,18 +2,23 @@
 // 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/media/screen_capture_device.h"
+#include "content/browser/renderer_host/media/desktop_capture_device.h"
 
 #include "base/bind.h"
 #include "base/location.h"
 #include "base/logging.h"
 #include "base/sequenced_task_runner.h"
+#include "base/strings/string_number_conversions.h"
 #include "base/synchronization/lock.h"
+#include "base/threading/sequenced_worker_pool.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/common/desktop_media_id.h"
 #include "media/base/video_util.h"
 #include "third_party/libyuv/include/libyuv/scale_argb.h"
+#include "third_party/webrtc/modules/desktop_capture/desktop_capturer.h"
 #include "third_party/webrtc/modules/desktop_capture/desktop_frame.h"
-#include "third_party/webrtc/modules/desktop_capture/mouse_cursor_shape.h"
 #include "third_party/webrtc/modules/desktop_capture/screen_capturer.h"
+#include "third_party/webrtc/modules/desktop_capture/window_capturer.h"
 
 namespace content {
 
@@ -21,16 +26,12 @@
 const int kBytesPerPixel = 4;
 }  // namespace
 
-class ScreenCaptureDevice::Core
+class DesktopCaptureDevice::Core
     : public base::RefCountedThreadSafe<Core>,
       public webrtc::DesktopCapturer::Callback {
  public:
-  explicit Core(scoped_refptr<base::SequencedTaskRunner> task_runner);
-
-  // Helper used in tests to supply a fake capturer.
-  void SetScreenCapturerForTest(scoped_ptr<webrtc::ScreenCapturer> capturer) {
-    screen_capturer_ = capturer.Pass();
-  }
+  Core(scoped_refptr<base::SequencedTaskRunner> task_runner,
+       scoped_ptr<webrtc::DesktopCapturer> capturer);
 
   // Implementation of VideoCaptureDevice methods.
   void Allocate(int width, int height,
@@ -59,15 +60,18 @@
   void ScheduleCaptureTimer();
 
   // Method that is scheduled on |task_runner_| to be called on regular interval
-  // to capture the screen.
+  // to capture a frame.
   void OnCaptureTimer();
 
   // Captures a single frame.
   void DoCapture();
 
-  // Task runner used for screen capturing operations.
+  // Task runner used for capturing operations.
   scoped_refptr<base::SequencedTaskRunner> task_runner_;
 
+  // The underlying DesktopCapturer instance used to capture frames.
+  scoped_ptr<webrtc::DesktopCapturer> desktop_capturer_;
+
   // |event_handler_lock_| must be locked whenever |event_handler_| is used.
   // It's necessary because DeAllocate() needs to reset it on the calling thread
   // to ensure that the event handler is not called once DeAllocate() returns.
@@ -80,9 +84,6 @@
   // Frame rate specified to Allocate().
   int frame_rate_;
 
-  // The underlying ScreenCapturer instance used to capture frames.
-  scoped_ptr<webrtc::ScreenCapturer> screen_capturer_;
-
   // Empty until the first frame has been captured, and the output dimensions
   // chosen based on the capture frame's size, and any caller-supplied
   // size constraints.
@@ -104,25 +105,27 @@
   // |task_runner_|.
   bool capture_task_posted_;
 
-  // True when waiting for |screen_capturer_| to capture current frame.
+  // True when waiting for |desktop_capturer_| to capture current frame.
   bool capture_in_progress_;
 
   DISALLOW_COPY_AND_ASSIGN(Core);
 };
 
-ScreenCaptureDevice::Core::Core(
-    scoped_refptr<base::SequencedTaskRunner> task_runner)
+DesktopCaptureDevice::Core::Core(
+    scoped_refptr<base::SequencedTaskRunner> task_runner,
+    scoped_ptr<webrtc::DesktopCapturer> capturer)
     : task_runner_(task_runner),
+      desktop_capturer_(capturer.Pass()),
       event_handler_(NULL),
       started_(false),
       capture_task_posted_(false),
       capture_in_progress_(false) {
 }
 
-ScreenCaptureDevice::Core::~Core() {
+DesktopCaptureDevice::Core::~Core() {
 }
 
-void ScreenCaptureDevice::Core::Allocate(int width, int height,
+void DesktopCaptureDevice::Core::Allocate(int width, int height,
                                          int frame_rate,
                                          EventHandler* event_handler) {
   DCHECK_GT(width, 0);
@@ -139,17 +142,17 @@
       base::Bind(&Core::DoAllocate, this, width, height, frame_rate));
 }
 
-void ScreenCaptureDevice::Core::Start() {
+void DesktopCaptureDevice::Core::Start() {
   task_runner_->PostTask(
       FROM_HERE, base::Bind(&Core::DoStart, this));
 }
 
-void ScreenCaptureDevice::Core::Stop() {
+void DesktopCaptureDevice::Core::Stop() {
   task_runner_->PostTask(
       FROM_HERE, base::Bind(&Core::DoStop, this));
 }
 
-void ScreenCaptureDevice::Core::DeAllocate() {
+void DesktopCaptureDevice::Core::DeAllocate() {
   {
     base::AutoLock auto_lock(event_handler_lock_);
     event_handler_ = NULL;
@@ -158,11 +161,11 @@
 }
 
 webrtc::SharedMemory*
-ScreenCaptureDevice::Core::CreateSharedMemory(size_t size) {
+DesktopCaptureDevice::Core::CreateSharedMemory(size_t size) {
   return NULL;
 }
 
-void ScreenCaptureDevice::Core::OnCaptureCompleted(
+void DesktopCaptureDevice::Core::OnCaptureCompleted(
     webrtc::DesktopFrame* frame) {
   DCHECK(task_runner_->RunsTasksOnCurrentThread());
   DCHECK(capture_in_progress_);
@@ -257,41 +260,23 @@
   }
 }
 
-void ScreenCaptureDevice::Core::DoAllocate(int width,
-                                           int height,
-                                           int frame_rate) {
+void DesktopCaptureDevice::Core::DoAllocate(int width,
+                                            int height,
+                                            int frame_rate) {
   DCHECK(task_runner_->RunsTasksOnCurrentThread());
+  DCHECK(desktop_capturer_);
 
   requested_size_.set(width, height);
   output_size_.set(0, 0);
   frame_rate_ = frame_rate;
 
-  // Create and start frame capturer.
-  if (!screen_capturer_) {
-#if defined(OS_CHROMEOS) && !defined(ARCH_CPU_ARMEL) && defined(USE_X11)
-    // ScreenCapturerX11 polls by default, due to poor driver support for
-    // DAMAGE. ChromeOS' drivers [can be patched to] support DAMAGE properly, so
-    // use it. However ARM driver seems to not support this properly, so disable
-    // it for ARM. See http://crbug.com/230105.
-    screen_capturer_.reset(webrtc::ScreenCapturer::CreateWithXDamage(true));
-#elif defined(OS_WIN)
-    // ScreenCapturerWin disables Aero by default. We don't want it disabled for
-    // WebRTC screen capture, though.
-    screen_capturer_.reset(
-        webrtc::ScreenCapturer::CreateWithDisableAero(false));
-#else
-    screen_capturer_.reset(webrtc::ScreenCapturer::Create());
-#endif
-  }
-
-  if (screen_capturer_)
-    screen_capturer_->Start(this);
+  desktop_capturer_->Start(this);
 
   // Capture first frame, so that we can call OnFrameInfo() callback.
   DoCapture();
 }
 
-void ScreenCaptureDevice::Core::DoStart() {
+void DesktopCaptureDevice::Core::DoStart() {
   DCHECK(task_runner_->RunsTasksOnCurrentThread());
   started_ = true;
   if (!capture_task_posted_) {
@@ -300,20 +285,20 @@
   }
 }
 
-void ScreenCaptureDevice::Core::DoStop() {
+void DesktopCaptureDevice::Core::DoStop() {
   DCHECK(task_runner_->RunsTasksOnCurrentThread());
   started_ = false;
   scaled_frame_.reset();
 }
 
-void ScreenCaptureDevice::Core::DoDeAllocate() {
+void DesktopCaptureDevice::Core::DoDeAllocate() {
   DCHECK(task_runner_->RunsTasksOnCurrentThread());
   DoStop();
-  screen_capturer_.reset();
+  desktop_capturer_.reset();
   output_size_.set(0, 0);
 }
 
-void ScreenCaptureDevice::Core::ScheduleCaptureTimer() {
+void DesktopCaptureDevice::Core::ScheduleCaptureTimer() {
   DCHECK(!capture_task_posted_);
   capture_task_posted_ = true;
   task_runner_->PostDelayedTask(
@@ -321,7 +306,7 @@
       base::TimeDelta::FromSeconds(1) / frame_rate_);
 }
 
-void ScreenCaptureDevice::Core::OnCaptureTimer() {
+void DesktopCaptureDevice::Core::OnCaptureTimer() {
   DCHECK(capture_task_posted_);
   capture_task_posted_ = false;
 
@@ -333,33 +318,81 @@
   DoCapture();
 }
 
-void ScreenCaptureDevice::Core::DoCapture() {
+void DesktopCaptureDevice::Core::DoCapture() {
   DCHECK(task_runner_->RunsTasksOnCurrentThread());
   DCHECK(!capture_in_progress_);
 
   capture_in_progress_ = true;
-  screen_capturer_->Capture(webrtc::DesktopRegion());
+  desktop_capturer_->Capture(webrtc::DesktopRegion());
 
   // Currently only synchronous implementations of DesktopCapturer are
   // supported.
   DCHECK(!capture_in_progress_);
 }
 
-ScreenCaptureDevice::ScreenCaptureDevice(
-    scoped_refptr<base::SequencedTaskRunner> task_runner)
-    : core_(new Core(task_runner)), name_("Screen", "Screen") {
+// static
+scoped_ptr<media::VideoCaptureDevice> DesktopCaptureDevice::Create(
+    const DesktopMediaID& source) {
+  scoped_refptr<base::SequencedWorkerPool> blocking_pool =
+      BrowserThread::GetBlockingPool();
+  scoped_refptr<base::SequencedTaskRunner> task_runner =
+      blocking_pool->GetSequencedTaskRunner(
+          blocking_pool->GetSequenceToken());
+
+  switch (source.type) {
+    case DesktopMediaID::TYPE_SCREEN: {
+      scoped_ptr<webrtc::DesktopCapturer> capturer;
+
+#if defined(OS_CHROMEOS) && !defined(ARCH_CPU_ARMEL) && defined(USE_X11)
+      // ScreenCapturerX11 polls by default, due to poor driver support for
+      // DAMAGE. ChromeOS' drivers [can be patched to] support DAMAGE properly,
+      // so use it. However ARM driver seems to not support this properly, so
+      // disable it for ARM. See http://crbug.com/230105 .
+      capturer.reset(webrtc::ScreenCapturer::CreateWithXDamage(true));
+#elif defined(OS_WIN)
+      // ScreenCapturerWin disables Aero by default. We don't want it disabled
+      // for WebRTC screen capture, though.
+      capturer.reset(
+          webrtc::ScreenCapturer::CreateWithDisableAero(false));
+#else
+      capturer.reset(webrtc::ScreenCapturer::Create());
+#endif
+
+      return scoped_ptr<media::VideoCaptureDevice>(new DesktopCaptureDevice(
+          task_runner, capturer.Pass()));
+    }
+
+    case DesktopMediaID::TYPE_WINDOW: {
+      scoped_ptr<webrtc::WindowCapturer> capturer(
+          webrtc::WindowCapturer::Create());
+
+      if (!capturer || !capturer->SelectWindow(source.id)) {
+        return scoped_ptr<media::VideoCaptureDevice>();
+      }
+
+      return scoped_ptr<media::VideoCaptureDevice>(new DesktopCaptureDevice(
+          task_runner, capturer.PassAs<webrtc::DesktopCapturer>()));
+    }
+
+    default: {
+      NOTREACHED();
+      return scoped_ptr<media::VideoCaptureDevice>();
+    }
+  }
 }
 
-ScreenCaptureDevice::~ScreenCaptureDevice() {
+DesktopCaptureDevice::DesktopCaptureDevice(
+    scoped_refptr<base::SequencedTaskRunner> task_runner,
+    scoped_ptr<webrtc::DesktopCapturer> capturer)
+    : core_(new Core(task_runner, capturer.Pass())),
+      name_("", "") {
+}
+
+DesktopCaptureDevice::~DesktopCaptureDevice() {
   DeAllocate();
 }
 
-void ScreenCaptureDevice::SetScreenCapturerForTest(
-    scoped_ptr<webrtc::ScreenCapturer> capturer) {
-  core_->SetScreenCapturerForTest(capturer.Pass());
-}
-
-void ScreenCaptureDevice::Allocate(
+void DesktopCaptureDevice::Allocate(
     const media::VideoCaptureCapability& capture_format,
     EventHandler* observer) {
   core_->Allocate(capture_format.width,
@@ -368,19 +401,19 @@
                   observer);
 }
 
-void ScreenCaptureDevice::Start() {
+void DesktopCaptureDevice::Start() {
   core_->Start();
 }
 
-void ScreenCaptureDevice::Stop() {
+void DesktopCaptureDevice::Stop() {
   core_->Stop();
 }
 
-void ScreenCaptureDevice::DeAllocate() {
+void DesktopCaptureDevice::DeAllocate() {
   core_->DeAllocate();
 }
 
-const media::VideoCaptureDevice::Name& ScreenCaptureDevice::device_name() {
+const media::VideoCaptureDevice::Name& DesktopCaptureDevice::device_name() {
   return name_;
 }
 
diff --git a/content/browser/renderer_host/media/desktop_capture_device.h b/content/browser/renderer_host/media/desktop_capture_device.h
new file mode 100644
index 0000000..84422d3
--- /dev/null
+++ b/content/browser/renderer_host/media/desktop_capture_device.h
@@ -0,0 +1,58 @@
+// 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 CONTENT_BROWSER_RENDERER_HOST_MEDIA_DESKTOP_CAPTURE_DEVICE_H_
+#define CONTENT_BROWSER_RENDERER_HOST_MEDIA_DESKTOP_CAPTURE_DEVICE_H_
+
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
+#include "content/common/content_export.h"
+#include "media/video/capture/video_capture_device.h"
+
+namespace base {
+class SequencedTaskRunner;
+}  // namespace base
+
+namespace webrtc {
+class DesktopCapturer;
+}  // namespace webrtc
+
+namespace content {
+
+struct DesktopMediaID;
+
+// DesktopCaptureDevice implements VideoCaptureDevice for screens and windows.
+// It's essentially an adapter between webrtc::DesktopCapturer and
+// VideoCaptureDevice.
+class CONTENT_EXPORT DesktopCaptureDevice : public media::VideoCaptureDevice {
+ public:
+  // Creates capturer for the specified |source| and then creates
+  // DesktopCaptureDevice for it. May return NULL in case of a failure (e.g. if
+  // requested window was destroyed).
+  static scoped_ptr<media::VideoCaptureDevice> Create(
+      const DesktopMediaID& source);
+
+  DesktopCaptureDevice(scoped_refptr<base::SequencedTaskRunner> task_runner,
+                       scoped_ptr<webrtc::DesktopCapturer> desktop_capturer);
+  virtual ~DesktopCaptureDevice();
+
+  // VideoCaptureDevice interface.
+  virtual void Allocate(const media::VideoCaptureCapability& capture_format,
+                        EventHandler* observer) OVERRIDE;
+  virtual void Start() OVERRIDE;
+  virtual void Stop() OVERRIDE;
+  virtual void DeAllocate() OVERRIDE;
+  virtual const Name& device_name() OVERRIDE;
+
+ private:
+  class Core;
+  scoped_refptr<Core> core_;
+  Name name_;
+
+  DISALLOW_COPY_AND_ASSIGN(DesktopCaptureDevice);
+};
+
+}  // namespace content
+
+#endif  // CONTENT_BROWSER_RENDERER_HOST_MEDIA_DESKTOP_CAPTURE_DEVICE_H_
diff --git a/content/browser/renderer_host/media/screen_capture_device_unittest.cc b/content/browser/renderer_host/media/desktop_capture_device_unittest.cc
similarity index 91%
rename from content/browser/renderer_host/media/screen_capture_device_unittest.cc
rename to content/browser/renderer_host/media/desktop_capture_device_unittest.cc
index c3ca06f..0f14585 100644
--- a/content/browser/renderer_host/media/screen_capture_device_unittest.cc
+++ b/content/browser/renderer_host/media/desktop_capture_device_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/renderer_host/media/screen_capture_device.h"
+#include "content/browser/renderer_host/media/desktop_capture_device.h"
 
 #include "base/basictypes.h"
 #include "base/sequenced_task_runner.h"
@@ -83,7 +83,7 @@
   int frame_index_;
 };
 
-class ScreenCaptureDeviceTest : public testing::Test {
+class DesktopCaptureDeviceTest : public testing::Test {
  public:
   virtual void SetUp() OVERRIDE {
     worker_pool_ = new base::SequencedWorkerPool(3, "TestCaptureThread");
@@ -103,9 +103,12 @@
 #else
 #define MAYBE_Capture Capture
 #endif
-TEST_F(ScreenCaptureDeviceTest, MAYBE_Capture) {
-  ScreenCaptureDevice capture_device(
-      worker_pool_->GetSequencedTaskRunner(worker_pool_->GetSequenceToken()));
+TEST_F(DesktopCaptureDeviceTest, MAYBE_Capture) {
+  scoped_ptr<webrtc::DesktopCapturer> capturer(
+      webrtc::ScreenCapturer::Create());
+  DesktopCaptureDevice capture_device(
+      worker_pool_->GetSequencedTaskRunner(worker_pool_->GetSequenceToken()),
+      capturer.Pass());
   media::VideoCaptureCapability caps;
   base::WaitableEvent done_event(false, false);
   int frame_size;
@@ -121,12 +124,7 @@
           InvokeWithoutArgs(&done_event, &base::WaitableEvent::Signal)));
 
   media::VideoCaptureCapability capture_format(
-      640,
-      480,
-      kFrameRate,
-      media::VideoCaptureCapability::kI420,
-      0,
-      false,
+      640, 480, kFrameRate, media::VideoCaptureCapability::kI420, 0, false,
       media::ConstantResolutionVideoCaptureDevice);
   capture_device.Allocate(capture_format, &frame_observer);
   capture_device.Start();
@@ -144,13 +142,12 @@
 }
 
 // Test that screen capturer can handle resolution change without crashing.
-TEST_F(ScreenCaptureDeviceTest, ScreenResolutionChange) {
+TEST_F(DesktopCaptureDeviceTest, ScreenResolutionChange) {
   FakeScreenCapturer* mock_capturer = new FakeScreenCapturer();
 
-  ScreenCaptureDevice capture_device(
-      worker_pool_->GetSequencedTaskRunner(worker_pool_->GetSequenceToken()));
-  capture_device.SetScreenCapturerForTest(
-      scoped_ptr<webrtc::ScreenCapturer>(mock_capturer));
+  DesktopCaptureDevice capture_device(
+      worker_pool_->GetSequencedTaskRunner(worker_pool_->GetSequenceToken()),
+      scoped_ptr<webrtc::DesktopCapturer>(mock_capturer));
 
   media::VideoCaptureCapability caps;
   base::WaitableEvent done_event(false, false);
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 fba074b..770e800 100644
--- a/content/browser/renderer_host/media/device_request_message_filter.cc
+++ b/content/browser/renderer_host/media/device_request_message_filter.cc
@@ -71,6 +71,11 @@
   NOTIMPLEMENTED();
 }
 
+void DeviceRequestMessageFilter::StopGeneratedStream(
+    const std::string& label) {
+  NOTIMPLEMENTED();
+}
+
 void DeviceRequestMessageFilter::DevicesEnumerated(
     const std::string& label,
     const StreamDeviceInfoArray& new_devices) {
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 2ae1e77..048e215 100644
--- a/content/browser/renderer_host/media/device_request_message_filter.h
+++ b/content/browser/renderer_host/media/device_request_message_filter.h
@@ -34,6 +34,7 @@
       const std::string& label, const StreamDeviceInfoArray& audio_devices,
       const StreamDeviceInfoArray& video_devices) OVERRIDE;
   virtual void StreamGenerationFailed(const std::string& label) OVERRIDE;
+  virtual void StopGeneratedStream(const std::string& label) OVERRIDE;
   virtual void DeviceOpened(const std::string& label,
                             const StreamDeviceInfo& video_device) OVERRIDE;
   // DevicesEnumerated() is the only callback we're interested in.
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 abd4cd3..ebc4d89 100644
--- a/content/browser/renderer_host/media/media_stream_dispatcher_host.cc
+++ b/content/browser/renderer_host/media/media_stream_dispatcher_host.cc
@@ -62,6 +62,20 @@
                                                  request.page_request_id));
 }
 
+void MediaStreamDispatcherHost::StopGeneratedStream(
+    const std::string& label) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DVLOG(1) << "MediaStreamDispatcherHost::StopGeneratedStream("
+           << ", {label = " << label <<  "})";
+
+  StreamMap::iterator it = streams_.find(label);
+  DCHECK(it != streams_.end());
+  StreamRequest request = it->second;
+  streams_.erase(it);
+
+  Send(new MediaStreamMsg_StopGeneratedStream(request.render_view_id, label));
+}
+
 void MediaStreamDispatcherHost::DevicesEnumerated(
     const std::string& label,
     const StreamDeviceInfoArray& devices) {
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 4b94496..ec1dd15 100644
--- a/content/browser/renderer_host/media/media_stream_dispatcher_host.h
+++ b/content/browser/renderer_host/media/media_stream_dispatcher_host.h
@@ -33,6 +33,7 @@
       const StreamDeviceInfoArray& audio_devices,
       const StreamDeviceInfoArray& video_devices) OVERRIDE;
   virtual void StreamGenerationFailed(const std::string& label) OVERRIDE;
+  virtual void StopGeneratedStream(const std::string& label) OVERRIDE;
   virtual void DevicesEnumerated(const std::string& label,
                                  const StreamDeviceInfoArray& devices) OVERRIDE;
   virtual void DeviceOpened(const std::string& label,
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 5325155..05804266 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
@@ -52,6 +52,8 @@
                void(int routing_id, int request_id, int audio_array_size,
                     int video_array_size));
   MOCK_METHOD2(OnStreamGenerationFailed, void(int routing_id, int request_id));
+  MOCK_METHOD1(OnStopGeneratedStreamFromBrowser,
+               void(int routing_id));
 
   // Accessor to private functions.
   void OnGenerateStream(int page_request_id,
@@ -91,6 +93,8 @@
       IPC_MESSAGE_HANDLER(MediaStreamMsg_StreamGenerated, OnStreamGenerated)
       IPC_MESSAGE_HANDLER(MediaStreamMsg_StreamGenerationFailed,
                           OnStreamGenerationFailed)
+      IPC_MESSAGE_HANDLER(MediaStreamMsg_StopGeneratedStream,
+                          OnStopGeneratedStreamFromBrowser)
       IPC_MESSAGE_UNHANDLED(handled = false)
     IPC_END_MESSAGE_MAP()
     EXPECT_TRUE(handled);
@@ -122,6 +126,15 @@
     label_= "";
   }
 
+  void OnStopGeneratedStreamFromBrowser(const IPC::Message& msg,
+                                        const std::string& label) {
+    OnStopGeneratedStreamFromBrowser(msg.routing_id());
+    // Notify that the event have occured.
+    if (!quit_closure_.is_null())
+      message_loop_->PostTask(FROM_HERE, base::ResetAndReturn(&quit_closure_));
+    label_ = "";
+  }
+
   scoped_refptr<base::MessageLoopProxy> message_loop_;
   base::Closure quit_closure_;
 };
@@ -323,8 +336,7 @@
   media_stream_manager_->UseFakeUI(stream_ui.PassAs<FakeMediaStreamUIProxy>());
 
   EXPECT_CALL(*host_.get(), OnStreamGenerated(kRenderId, kPageRequestId, 0, 1));
-  EXPECT_CALL(*host_.get(),
-              OnStreamGenerationFailed(kRenderId, kPageRequestId));
+  EXPECT_CALL(*host_.get(), OnStopGeneratedStreamFromBrowser(kRenderId));
   GenerateStreamAndWaitForResult(kPageRequestId, options);
 
   EXPECT_EQ(host_->audio_devices_.size(), 0u);
diff --git a/content/browser/renderer_host/media/media_stream_manager.cc b/content/browser/renderer_host/media/media_stream_manager.cc
index b5151bc..4493311 100644
--- a/content/browser/renderer_host/media/media_stream_manager.cc
+++ b/content/browser/renderer_host/media/media_stream_manager.cc
@@ -263,18 +263,19 @@
     DCHECK(found_match || translated_video_device_id.empty());
   }
 
-  if (options.video_type == MEDIA_SCREEN_VIDEO_CAPTURE ||
+  if (options.video_type == MEDIA_DESKTOP_VIDEO_CAPTURE ||
       options.audio_type == MEDIA_SYSTEM_AUDIO_CAPTURE) {
     // For screen capture we only support two valid combinations:
     // (1) screen video capture only, or
     // (2) screen video capture with system audio capture.
-    if (options.video_type != MEDIA_SCREEN_VIDEO_CAPTURE ||
+    if (options.video_type != MEDIA_DESKTOP_VIDEO_CAPTURE ||
         (options.audio_type != MEDIA_NO_SERVICE &&
          options.audio_type != MEDIA_SYSTEM_AUDIO_CAPTURE)) {
       // TODO(sergeyu): Surface error message to the calling JS code.
       LOG(ERROR) << "Invalid screen capture request.";
       return std::string();
     }
+    translated_video_device_id = options.video_device_id;
   }
 
   // Create a new request based on options.
@@ -624,11 +625,11 @@
       audio_type == MEDIA_TAB_AUDIO_CAPTURE ||
       video_type == MEDIA_TAB_VIDEO_CAPTURE;
 
-  bool is_screen_capure =
-      video_type == MEDIA_SCREEN_VIDEO_CAPTURE;
+  bool is_screen_capture =
+      video_type == MEDIA_DESKTOP_VIDEO_CAPTURE;
 
   if (!is_web_contents_capture &&
-      !is_screen_capure &&
+      !is_screen_capture &&
       ((IsAudioMediaType(audio_type) && !audio_enumeration_cache_.valid) ||
        (IsVideoMediaType(video_type) && !video_enumeration_cache_.valid))) {
     // Enumerate the devices if there is no valid device lists to be used.
@@ -987,7 +988,7 @@
 
   // Notify renderers that the stream has been stopped.
   if (it->second->requester)
-    it->second->requester->StreamGenerationFailed(label);
+    it->second->requester->StopGeneratedStream(label);
 
   StopGeneratedStream(label);
 }
diff --git a/content/browser/renderer_host/media/media_stream_requester.h b/content/browser/renderer_host/media/media_stream_requester.h
index 6d8736e..50858fa 100644
--- a/content/browser/renderer_host/media/media_stream_requester.h
+++ b/content/browser/renderer_host/media/media_stream_requester.h
@@ -21,11 +21,12 @@
   virtual void StreamGenerated(const std::string& label,
                                const StreamDeviceInfoArray& audio_devices,
                                const StreamDeviceInfoArray& video_devices) = 0;
-  // Called if GenerateStream failed or if stream has been stopped by the user.
-  // TODO(sergeyu): Rename this method and corresponding IPC message or maybe
-  // add a separate IPC message.
+  // Called if GenerateStream failed.
   virtual void StreamGenerationFailed(const std::string& label) = 0;
 
+  // Called if stream has been stopped by user request.
+  virtual void StopGeneratedStream(const std::string& label) = 0;
+
   // Called as a reply of a successful call to EnumerateDevices.
   virtual void DevicesEnumerated(const std::string& label,
                                  const StreamDeviceInfoArray& devices) = 0;
diff --git a/content/browser/renderer_host/media/screen_capture_device.h b/content/browser/renderer_host/media/screen_capture_device.h
deleted file mode 100644
index df338d7..0000000
--- a/content/browser/renderer_host/media/screen_capture_device.h
+++ /dev/null
@@ -1,53 +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 CONTENT_BROWSER_RENDERER_HOST_MEDIA_SCREEN_CAPTURE_DEVICE_H_
-#define CONTENT_BROWSER_RENDERER_HOST_MEDIA_SCREEN_CAPTURE_DEVICE_H_
-
-#include "base/memory/ref_counted.h"
-#include "base/memory/scoped_ptr.h"
-#include "content/common/content_export.h"
-#include "media/video/capture/video_capture_device.h"
-
-namespace base {
-class SequencedTaskRunner;
-}  // namespace base
-
-namespace webrtc {
-class ScreenCapturer;
-}  // namespace webrtc
-
-namespace content {
-
-// ScreenCaptureDevice implements VideoCaptureDevice for the screen. It's
-// essentially an adapter between ScreenCapturer and VideoCaptureDevice.
-class CONTENT_EXPORT ScreenCaptureDevice : public media::VideoCaptureDevice {
- public:
-  explicit ScreenCaptureDevice(
-      scoped_refptr<base::SequencedTaskRunner> task_runner);
-  virtual ~ScreenCaptureDevice();
-
-  // Helper used in tests to supply a fake capturer.
-  void SetScreenCapturerForTest(
-      scoped_ptr<webrtc::ScreenCapturer> capturer);
-
-  // VideoCaptureDevice interface.
-  virtual void Allocate(const media::VideoCaptureCapability& capture_format,
-                        EventHandler* observer) OVERRIDE;
-  virtual void Start() OVERRIDE;
-  virtual void Stop() OVERRIDE;
-  virtual void DeAllocate() OVERRIDE;
-  virtual const Name& device_name() OVERRIDE;
-
- private:
-  class Core;
-  scoped_refptr<Core> core_;
-  Name name_;
-
-  DISALLOW_COPY_AND_ASSIGN(ScreenCaptureDevice);
-};
-
-}  // namespace content
-
-#endif  // CONTENT_BROWSER_RENDERER_HOST_MEDIA_SCREEN_CAPTURE_DEVICE_H_
diff --git a/content/browser/renderer_host/media/video_capture_buffer_pool.cc b/content/browser/renderer_host/media/video_capture_buffer_pool.cc
index ae29c75..207f86a 100644
--- a/content/browser/renderer_host/media/video_capture_buffer_pool.cc
+++ b/content/browser/renderer_host/media/video_capture_buffer_pool.cc
@@ -144,21 +144,15 @@
 
   Buffer* buffer = buffers_[buffer_id];
   // Wrap the buffer in a VideoFrame container.
-  uint8* base_ptr = static_cast<uint8*>(buffer->shared_memory.memory());
-  size_t u_offset = size.GetArea();
-  size_t v_offset = u_offset + u_offset / 4;
   scoped_refptr<media::VideoFrame> frame =
-      media::VideoFrame::WrapExternalYuvData(
-          media::VideoFrame::YV12,  // Actually it's I420, but equivalent here.
-          size, gfx::Rect(size), size,
-          size.width(),             // y stride
-          size.width() / 2,         // u stride
-          size.width() / 2,         // v stride
-          base_ptr,                 // y address
-          base_ptr + u_offset,      // u address
-          base_ptr + v_offset,      // v address
-          base::TimeDelta(),        // timestamp (unused).
+      media::VideoFrame::WrapExternalSharedMemory(
+          media::VideoFrame::I420,
+          size,
+          gfx::Rect(size),
+          size,
+          static_cast<uint8*>(buffer->shared_memory.memory()),
           buffer->shared_memory.handle(),
+          base::TimeDelta(),
           disposal_handler);
 
   if (buffer->rotation != rotation) {
diff --git a/content/browser/renderer_host/media/video_capture_manager.cc b/content/browser/renderer_host/media/video_capture_manager.cc
index aa27e12..79da412 100644
--- a/content/browser/renderer_host/media/video_capture_manager.cc
+++ b/content/browser/renderer_host/media/video_capture_manager.cc
@@ -16,13 +16,14 @@
 #include "content/browser/renderer_host/media/web_contents_video_capture_device.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/common/content_switches.h"
+#include "content/public/common/desktop_media_id.h"
 #include "content/public/common/media_stream_request.h"
 #include "media/base/scoped_histogram_timer.h"
 #include "media/video/capture/fake_video_capture_device.h"
 #include "media/video/capture/video_capture_device.h"
 
 #if defined(ENABLE_SCREEN_CAPTURE)
-#include "content/browser/renderer_host/media/screen_capture_device.h"
+#include "content/browser/renderer_host/media/desktop_capture_device.h"
 #endif
 
 namespace content {
@@ -157,17 +158,19 @@
 
   // Check if another session has already opened this device. If so, just
   // use that opened device.
-  media::VideoCaptureDevice* video_capture_device = GetOpenedDevice(device);
-  if (video_capture_device) {
+  media::VideoCaptureDevice* opened_video_capture_device =
+      GetOpenedDevice(device);
+  if (opened_video_capture_device) {
     DeviceEntry& new_entry = devices_[capture_session_id];
     new_entry.stream_type = device.device.type;
-    new_entry.capture_device = video_capture_device;
+    new_entry.capture_device = opened_video_capture_device;
     PostOnOpened(device.device.type, capture_session_id);
     return;
   }
 
-  // Open the device.
+  scoped_ptr<media::VideoCaptureDevice> video_capture_device;
 
+  // Open the device.
   switch (device.device.type) {
     case MEDIA_DEVICE_VIDEO_CAPTURE: {
       // We look up the device id from the renderer in our local enumeration
@@ -176,24 +179,23 @@
       media::VideoCaptureDevice::Name* found =
           video_capture_devices_.FindById(device.device.id);
       if (found) {
-        video_capture_device = use_fake_device_ ?
+        video_capture_device.reset(use_fake_device_ ?
             media::FakeVideoCaptureDevice::Create(*found) :
-            media::VideoCaptureDevice::Create(*found);
+            media::VideoCaptureDevice::Create(*found));
       }
       break;
     }
     case MEDIA_TAB_VIDEO_CAPTURE: {
-      video_capture_device = WebContentsVideoCaptureDevice::Create(
-          device.device.id);
+      video_capture_device.reset(
+          WebContentsVideoCaptureDevice::Create(device.device.id));
       break;
     }
-    case MEDIA_SCREEN_VIDEO_CAPTURE: {
+    case MEDIA_DESKTOP_VIDEO_CAPTURE: {
 #if defined(ENABLE_SCREEN_CAPTURE)
-      scoped_refptr<base::SequencedWorkerPool> blocking_pool =
-          BrowserThread::GetBlockingPool();
-      video_capture_device = new ScreenCaptureDevice(
-          blocking_pool->GetSequencedTaskRunner(
-              blocking_pool->GetSequenceToken()));
+      DesktopMediaID id = DesktopMediaID::Parse(device.device.id);
+      if (id.type != DesktopMediaID::TYPE_NONE) {
+        video_capture_device = DesktopCaptureDevice::Create(id);
+      }
 #endif  // defined(ENABLE_SCREEN_CAPTURE)
       break;
     }
@@ -210,7 +212,7 @@
 
   DeviceEntry& new_entry = devices_[capture_session_id];
   new_entry.stream_type = device.device.type;
-  new_entry.capture_device = video_capture_device;
+  new_entry.capture_device = video_capture_device.release();
   PostOnOpened(device.device.type, capture_session_id);
 }
 
@@ -434,7 +436,7 @@
       *device_names = video_capture_devices_;
       break;
 
-    case MEDIA_SCREEN_VIDEO_CAPTURE:
+    case MEDIA_DESKTOP_VIDEO_CAPTURE:
       device_names->clear();
       break;
 
diff --git a/content/browser/renderer_host/media/web_contents_video_capture_device.cc b/content/browser/renderer_host/media/web_contents_video_capture_device.cc
index 2e63e94..e27b703 100644
--- a/content/browser/renderer_host/media/web_contents_video_capture_device.cc
+++ b/content/browser/renderer_host/media/web_contents_video_capture_device.cc
@@ -648,7 +648,7 @@
   }
 
   // Sanity-check the output buffer.
-  if (output->format() != media::VideoFrame::YV12) {
+  if (output->format() != media::VideoFrame::I420) {
     NOTREACHED();
     return;
   }
diff --git a/content/browser/renderer_host/media/web_contents_video_capture_device_unittest.cc b/content/browser/renderer_host/media/web_contents_video_capture_device_unittest.cc
index 7eb28ea..d88d553 100644
--- a/content/browser/renderer_host/media/web_contents_video_capture_device_unittest.cc
+++ b/content/browser/renderer_host/media/web_contents_video_capture_device_unittest.cc
@@ -374,7 +374,7 @@
       const scoped_refptr<media::VideoFrame>& frame,
       base::Time timestamp) OVERRIDE {
     EXPECT_EQ(gfx::Size(kTestWidth, kTestHeight), frame->coded_size());
-    EXPECT_EQ(media::VideoFrame::YV12, frame->format());
+    EXPECT_EQ(media::VideoFrame::I420, frame->format());
     EXPECT_LE(
         0,
         buffer_pool_->RecognizeReservedBuffer(frame->shared_memory_handle()));
diff --git a/content/browser/renderer_host/media/webrtc_identity_service_host.cc b/content/browser/renderer_host/media/webrtc_identity_service_host.cc
index cce3c74..0230b26 100644
--- a/content/browser/renderer_host/media/webrtc_identity_service_host.cc
+++ b/content/browser/renderer_host/media/webrtc_identity_service_host.cc
@@ -6,6 +6,7 @@
 
 #include "base/bind.h"
 #include "base/callback_helpers.h"
+#include "content/browser/child_process_security_policy_impl.h"
 #include "content/browser/media/webrtc_identity_store.h"
 #include "content/common/media/webrtc_identity_messages.h"
 #include "net/base/net_errors.h"
@@ -13,8 +14,10 @@
 namespace content {
 
 WebRTCIdentityServiceHost::WebRTCIdentityServiceHost(
+    int renderer_process_id,
     WebRTCIdentityStore* identity_store)
-    : identity_store_(identity_store) {}
+    : renderer_process_id_(renderer_process_id),
+      identity_store_(identity_store) {}
 
 WebRTCIdentityServiceHost::~WebRTCIdentityServiceHost() {
   if (!cancel_callback_.is_null())
@@ -42,6 +45,15 @@
     SendErrorMessage(net::ERR_INSUFFICIENT_RESOURCES);
     return;
   }
+
+  ChildProcessSecurityPolicyImpl* policy =
+      ChildProcessSecurityPolicyImpl::GetInstance();
+  if (!policy->CanAccessCookiesForOrigin(renderer_process_id_, origin)) {
+    DLOG(WARNING) << "Request rejected because origin access is denied.";
+    SendErrorMessage(net::ERR_ACCESS_DENIED);
+    return;
+  }
+
   cancel_callback_ = identity_store_->RequestIdentity(
       origin,
       identity_name,
diff --git a/content/browser/renderer_host/media/webrtc_identity_service_host.h b/content/browser/renderer_host/media/webrtc_identity_service_host.h
index 4c53056..3676223 100644
--- a/content/browser/renderer_host/media/webrtc_identity_service_host.h
+++ b/content/browser/renderer_host/media/webrtc_identity_service_host.h
@@ -26,7 +26,8 @@
 // ERR_INSUFFICIENT_RESOURCES will be sent back to the renderer.
 class CONTENT_EXPORT WebRTCIdentityServiceHost : public BrowserMessageFilter {
  public:
-  explicit WebRTCIdentityServiceHost(WebRTCIdentityStore* identity_store);
+  explicit WebRTCIdentityServiceHost(int renderer_process_id,
+                                     WebRTCIdentityStore* identity_store);
 
  protected:
   virtual ~WebRTCIdentityServiceHost();
@@ -50,6 +51,7 @@
 
   void SendErrorMessage(int error);
 
+  int renderer_process_id_;
   base::Closure cancel_callback_;
   WebRTCIdentityStore* identity_store_;
 
diff --git a/content/browser/renderer_host/media/webrtc_identity_service_host_unittest.cc b/content/browser/renderer_host/media/webrtc_identity_service_host_unittest.cc
index 058e15b..341378d 100644
--- a/content/browser/renderer_host/media/webrtc_identity_service_host_unittest.cc
+++ b/content/browser/renderer_host/media/webrtc_identity_service_host_unittest.cc
@@ -4,9 +4,11 @@
 
 #include <deque>
 
+#include "content/browser/child_process_security_policy_impl.h"
 #include "content/browser/media/webrtc_identity_store.h"
 #include "content/browser/renderer_host/media/webrtc_identity_service_host.h"
 #include "content/common/media/webrtc_identity_messages.h"
+#include "content/public/test/test_browser_thread_bundle.h"
 #include "ipc/ipc_message.h"
 #include "net/base/net_errors.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -21,9 +23,12 @@
 static const char FAKE_CERTIFICATE[] = "fake cert";
 static const char FAKE_PRIVATE_KEY[] = "fake private key";
 static const int FAKE_ERROR = 100;
+static const int FAKE_RENDERER_ID = 10;
 
 class MockWebRTCIdentityStore : public WebRTCIdentityStore {
  public:
+  MockWebRTCIdentityStore() : WebRTCIdentityStore(base::FilePath(), NULL) {}
+
   virtual base::Closure RequestIdentity(
       const GURL& origin,
       const std::string& identity_name,
@@ -46,6 +51,8 @@
   }
 
  private:
+  virtual ~MockWebRTCIdentityStore() {}
+
   void OnCancel() { callback_.Reset(); }
 
   CompletionCallback callback_;
@@ -54,7 +61,11 @@
 class WebRTCIdentityServiceHostForTest : public WebRTCIdentityServiceHost {
  public:
   explicit WebRTCIdentityServiceHostForTest(WebRTCIdentityStore* identity_store)
-      : WebRTCIdentityServiceHost(identity_store) {}
+      : WebRTCIdentityServiceHost(FAKE_RENDERER_ID, identity_store) {
+    ChildProcessSecurityPolicyImpl* policy =
+        ChildProcessSecurityPolicyImpl::GetInstance();
+    policy->Add(FAKE_RENDERER_ID);
+  }
 
   virtual bool Send(IPC::Message* message) OVERRIDE {
     messages_.push_back(*message);
@@ -75,7 +86,11 @@
   void ClearMessages() { messages_.clear(); }
 
  private:
-  virtual ~WebRTCIdentityServiceHostForTest() {}
+  virtual ~WebRTCIdentityServiceHostForTest() {
+    ChildProcessSecurityPolicyImpl* policy =
+        ChildProcessSecurityPolicyImpl::GetInstance();
+    policy->Remove(FAKE_RENDERER_ID);
+  }
 
   std::deque<IPC::Message> messages_;
 };
@@ -83,7 +98,8 @@
 class WebRTCIdentityServiceHostTest : public ::testing::Test {
  public:
   WebRTCIdentityServiceHostTest()
-      : store_(new MockWebRTCIdentityStore()),
+      : browser_thread_bundle_(TestBrowserThreadBundle::IO_MAINLOOP),
+        store_(new MockWebRTCIdentityStore()),
         host_(new WebRTCIdentityServiceHostForTest(store_.get())) {}
 
   void SendRequestToHost() {
@@ -124,7 +140,8 @@
   }
 
  protected:
-  scoped_ptr<MockWebRTCIdentityStore> store_;
+  TestBrowserThreadBundle browser_thread_bundle_;
+  scoped_refptr<MockWebRTCIdentityStore> store_;
   scoped_refptr<WebRTCIdentityServiceHostForTest> host_;
 };
 
@@ -158,4 +175,13 @@
   VerifyRequestFailedMessage(net::ERR_KEY_GENERATION_FAILED);
 }
 
+TEST_F(WebRTCIdentityServiceHostTest, TestOriginAccessDenied) {
+  ChildProcessSecurityPolicyImpl* policy =
+      ChildProcessSecurityPolicyImpl::GetInstance();
+  policy->Remove(FAKE_RENDERER_ID);
+
+  SendRequestToHost();
+  VerifyRequestFailedMessage(net::ERR_ACCESS_DENIED);
+}
+
 }  // namespace content
diff --git a/content/browser/renderer_host/pepper/pepper_external_file_ref_backend.cc b/content/browser/renderer_host/pepper/pepper_external_file_ref_backend.cc
index 27ba37d..2bd44c1 100644
--- a/content/browser/renderer_host/pepper/pepper_external_file_ref_backend.cc
+++ b/content/browser/renderer_host/pepper/pepper_external_file_ref_backend.cc
@@ -90,7 +90,10 @@
     ppapi::host::ReplyMessageContext reply_context) {
   host_->SendReply(reply_context,
       PpapiPluginMsg_FileRef_GetAbsolutePathReply(path_.AsUTF8Unsafe()));
-  return PP_OK;
+
+  // Use PP_OK_COMPLETIONPENDING instead of PP_OK since we've already sent our
+  // reply above.
+  return PP_OK_COMPLETIONPENDING;
 }
 
 fileapi::FileSystemURL PepperExternalFileRefBackend::GetFileSystemURL() const {
diff --git a/content/browser/renderer_host/pepper/pepper_internal_file_ref_backend.cc b/content/browser/renderer_host/pepper/pepper_internal_file_ref_backend.cc
index 337807d..2d93123 100644
--- a/content/browser/renderer_host/pepper/pepper_internal_file_ref_backend.cc
+++ b/content/browser/renderer_host/pepper/pepper_internal_file_ref_backend.cc
@@ -221,7 +221,7 @@
 
   context.params.set_result(ppapi::PlatformFileErrorToPepperError(error));
 
-  std::vector<ppapi::FileRef_CreateInfo> infos;
+  std::vector<ppapi::FileRefCreateInfo> infos;
   std::vector<PP_FileType> file_types;
   if (error == base::PLATFORM_FILE_OK && fs_host_.get()) {
     std::string dir_path = path_;
@@ -235,7 +235,7 @@
       else
         file_types.push_back(PP_FILETYPE_REGULAR);
 
-      ppapi::FileRef_CreateInfo info;
+      ppapi::FileRefCreateInfo info;
       info.file_system_type = fs_type_;
       info.file_system_plugin_resource = fs_host_->pp_resource();
       std::string path =
diff --git a/content/browser/renderer_host/pepper/pepper_renderer_connection.cc b/content/browser/renderer_host/pepper/pepper_renderer_connection.cc
index a5b95ce..7e3428a 100644
--- a/content/browser/renderer_host/pepper/pepper_renderer_connection.cc
+++ b/content/browser/renderer_host/pepper/pepper_renderer_connection.cc
@@ -16,7 +16,9 @@
 #include "ppapi/host/resource_host.h"
 #include "ppapi/proxy/ppapi_message_utils.h"
 #include "ppapi/proxy/ppapi_messages.h"
+#include "ppapi/proxy/ppapi_message_utils.h"
 #include "ppapi/proxy/resource_message_params.h"
+#include "ppapi/shared_impl/file_ref_detailed_info.h"
 
 namespace content {
 
@@ -76,6 +78,8 @@
                         OnMsgCreateResourceHostFromHost)
     IPC_MESSAGE_HANDLER(PpapiHostMsg_FileRef_GetInfoForRenderer,
                         OnMsgFileRefGetInfoForRenderer)
+    IPC_MESSAGE_HANDLER(PpapiHostMsg_FileRef_SyncGetInfoForRenderer,
+                        OnMsgFileRefSyncGetInfoForRenderer)
     IPC_MESSAGE_HANDLER(ViewHostMsg_DidCreateInProcessInstance,
                         OnMsgDidCreateInProcessInstance)
     IPC_MESSAGE_HANDLER(ViewHostMsg_DidDeleteInProcessInstance,
@@ -132,12 +136,20 @@
     int child_process_id,
     int32_t sequence,
     const std::vector<PP_Resource>& resources) {
-  std::vector<PP_Resource> out_resources;
-  std::vector<PP_FileSystemType> fs_types;
-  std::vector<std::string> file_system_url_specs;
-  std::vector<base::FilePath> external_paths;
+  std::vector<ppapi::FileRefDetailedInfo> infos;
+  OnMsgFileRefSyncGetInfoForRenderer(child_process_id, resources, &infos);
+  Send(new PpapiHostMsg_FileRef_GetInfoForRendererReply(
+       routing_id,
+       sequence,
+       infos));
+}
 
+void PepperRendererConnection::OnMsgFileRefSyncGetInfoForRenderer(
+    int child_process_id,
+    const std::vector<PP_Resource>& resources,
+    std::vector<ppapi::FileRefDetailedInfo>* out_infos) {
   BrowserPpapiHostImpl* host = GetHostForChildProcess(child_process_id);
+
   if (host) {
     for (size_t i = 0; i < resources.size(); ++i) {
       ppapi::host::ResourceHost* resource_host =
@@ -145,20 +157,15 @@
       if (resource_host && resource_host->IsFileRefHost()) {
         PepperFileRefHost* file_ref_host =
             static_cast<PepperFileRefHost*>(resource_host);
-        out_resources.push_back(resources[i]);
-        fs_types.push_back(file_ref_host->GetFileSystemType());
-        file_system_url_specs.push_back(file_ref_host->GetFileSystemURLSpec());
-        external_paths.push_back(file_ref_host->GetExternalPath());
+        ppapi::FileRefDetailedInfo info;
+        info.resource = resources[i];
+        info.file_system_type = file_ref_host->GetFileSystemType();
+        info.file_system_url_spec = file_ref_host->GetFileSystemURLSpec();
+        info.external_path = file_ref_host->GetExternalPath();
+        out_infos->push_back(info);
       }
     }
   }
-  Send(new PpapiHostMsg_FileRef_GetInfoForRendererReply(
-       routing_id,
-       sequence,
-       out_resources,
-       fs_types,
-       file_system_url_specs,
-       external_paths));
 }
 
 void PepperRendererConnection::OnMsgDidCreateInProcessInstance(
diff --git a/content/browser/renderer_host/pepper/pepper_renderer_connection.h b/content/browser/renderer_host/pepper/pepper_renderer_connection.h
index 4392346..074bef6 100644
--- a/content/browser/renderer_host/pepper/pepper_renderer_connection.h
+++ b/content/browser/renderer_host/pepper/pepper_renderer_connection.h
@@ -11,6 +11,7 @@
 #include "content/public/browser/browser_message_filter.h"
 #include "ppapi/c/pp_instance.h"
 #include "ppapi/c/pp_resource.h"
+#include "ppapi/shared_impl/file_ref_detailed_info.h"
 
 class GURL;
 
@@ -58,6 +59,11 @@
       int32_t sequence_num,
       const std::vector<PP_Resource>& resources);
 
+  void OnMsgFileRefSyncGetInfoForRenderer(
+    int child_process_id,
+    const std::vector<PP_Resource>& resources,
+    std::vector<ppapi::FileRefDetailedInfo>* out_infos);
+
   void OnMsgDidCreateInProcessInstance(
       PP_Instance instance,
       const PepperRendererInstanceData& instance_data);
diff --git a/content/browser/renderer_host/render_message_filter.cc b/content/browser/renderer_host/render_message_filter.cc
index e4cb17c..fc84eab 100644
--- a/content/browser/renderer_host/render_message_filter.cc
+++ b/content/browser/renderer_host/render_message_filter.cc
@@ -43,6 +43,7 @@
 #include "content/public/browser/plugin_service_filter.h"
 #include "content/public/browser/resource_context.h"
 #include "content/public/browser/user_metrics.h"
+#include "content/public/common/content_constants.h"
 #include "content/public/common/content_switches.h"
 #include "content/public/common/context_menu_params.h"
 #include "content/public/common/url_constants.h"
@@ -65,7 +66,6 @@
 #include "ppapi/shared_impl/file_type_conversion.h"
 #include "third_party/WebKit/public/web/WebNotificationPresenter.h"
 #include "ui/gfx/color_profile.h"
-#include "webkit/plugins/plugin_constants.h"
 
 #if defined(OS_MACOSX)
 #include "content/common/mac/font_descriptor.h"
diff --git a/content/browser/renderer_host/render_process_host_impl.cc b/content/browser/renderer_host/render_process_host_impl.cc
index d3ba06e..1f6492b 100644
--- a/content/browser/renderer_host/render_process_host_impl.cc
+++ b/content/browser/renderer_host/render_process_host_impl.cc
@@ -132,7 +132,6 @@
 #include "ui/gl/gl_switches.h"
 #include "webkit/browser/fileapi/sandbox_file_system_backend.h"
 #include "webkit/common/resource_type.h"
-#include "webkit/plugins/plugin_switches.h"
 
 #if defined(OS_ANDROID)
 #include "content/browser/android/vibration_message_filter.h"
@@ -652,7 +651,7 @@
   channel_->AddFilter(gpu_message_filter_);
 #if defined(ENABLE_WEBRTC)
   channel_->AddFilter(new WebRTCIdentityServiceHost(
-      storage_partition_impl_->GetWebRTCIdentityStore()));
+      GetID(), storage_partition_impl_->GetWebRTCIdentityStore()));
   peer_connection_tracker_host_ = new PeerConnectionTrackerHost(GetID());
   channel_->AddFilter(peer_connection_tracker_host_.get());
   channel_->AddFilter(new MediaStreamDispatcherHost(
@@ -1028,6 +1027,7 @@
     switches::kVModule,
     switches::kWebCoreLogChannels,
     switches::kEnableWebGLDraftExtensions,
+    switches::kEnableHTMLImports,
     switches::kTraceToConsole,
     switches::kEnableDeviceMotion,
 #if defined(OS_ANDROID)
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 53a05f2..59822b2 100644
--- a/content/browser/renderer_host/render_widget_host_view_android.cc
+++ b/content/browser/renderer_host/render_widget_host_view_android.cc
@@ -403,13 +403,13 @@
 
 void RenderWidgetHostViewAndroid::OnTextInputStateChanged(
     const ViewHostMsg_TextInputState_Params& params) {
-#if defined(OS_ANDROID)
-  if (params.require_ack) {
-    // Regardless of how we exit from this method, we must acknowledge that we
-    // processed the input state change.
-    base::ScopedClosureRunner ack_caller(base::Bind(&SendImeEventAck, host_));
-  }
-#endif
+  // If an acknowledgement is required for this event, regardless of how we exit
+  // from this method, we must acknowledge that we processed the input state
+  // change.
+  base::ScopedClosureRunner ack_caller(base::Bind(&SendImeEventAck, host_));
+  if (!params.require_ack)
+    ack_caller.Release();
+
   if (!IsShowing())
     return;
 
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 10ce7ce..8c52017 100644
--- a/content/browser/renderer_host/render_widget_host_view_aura.cc
+++ b/content/browser/renderer_host/render_widget_host_view_aura.cc
@@ -2165,6 +2165,10 @@
   return text_input_type_;
 }
 
+ui::TextInputMode RenderWidgetHostViewAura::GetTextInputMode() const {
+  return ui::TEXT_INPUT_MODE_DEFAULT;
+}
+
 bool RenderWidgetHostViewAura::CanComposeInline() const {
   return can_compose_inline_;
 }
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 dafe42f..c4a1627 100644
--- a/content/browser/renderer_host/render_widget_host_view_aura.h
+++ b/content/browser/renderer_host/render_widget_host_view_aura.h
@@ -259,6 +259,7 @@
   virtual void InsertChar(char16 ch, int flags) OVERRIDE;
   virtual gfx::NativeWindow GetAttachedWindow() const OVERRIDE;
   virtual ui::TextInputType GetTextInputType() const OVERRIDE;
+  virtual ui::TextInputMode GetTextInputMode() const OVERRIDE;
   virtual bool CanComposeInline() const OVERRIDE;
   virtual gfx::Rect GetCaretBounds() OVERRIDE;
   virtual bool GetCompositionCharacterBounds(uint32 index,
diff --git a/content/browser/renderer_host/render_widget_host_view_base.cc b/content/browser/renderer_host/render_widget_host_view_base.cc
index b35d5b3..d6b1e78 100644
--- a/content/browser/renderer_host/render_widget_host_view_base.cc
+++ b/content/browser/renderer_host/render_widget_host_view_base.cc
@@ -171,8 +171,8 @@
   gfx::Rect* rect = reinterpret_cast<gfx::Rect*>(lparam);
   gfx::Rect rect_in_pixels = ui::win::DIPToScreenRect(*rect);
   static UINT msg = RegisterWindowMessage(kPaintMessageName);
-  WPARAM wparam = rect_in_pixels.x() << 16 | rect_in_pixels.y();
-  lparam = rect_in_pixels.width() << 16 | rect_in_pixels.height();
+  WPARAM wparam = MAKEWPARAM(rect_in_pixels.x(), rect_in_pixels.y());
+  lparam = MAKELPARAM(rect_in_pixels.width(), rect_in_pixels.height());
 
   // SendMessage gets the message across much quicker than PostMessage, since it
   // doesn't get queued.  When the plugin thread calls PeekMessage or other
@@ -218,6 +218,10 @@
     return;
   }
 
+#if defined(USE_AURA)
+  std::vector<RECT> invalidate_rects;
+#endif
+
   for (size_t i = 0; i < moves.size(); ++i) {
     unsigned long flags = 0;
     const WebPluginGeometry& move = moves[i];
@@ -290,6 +294,19 @@
       // Note: System will own the hrgn after we call SetWindowRgn,
       // so we don't need to call DeleteObject(hrgn)
       ::SetWindowRgn(window, hrgn, !move.clip_rect.IsEmpty());
+
+#if defined(USE_AURA)
+      // When using the software compositor, if the clipping rectangle is empty
+      // then DeferWindowPos won't redraw the newly uncovered area under the
+      // plugin.
+      if (clip_rect_in_pixel.IsEmpty() &&
+          !GpuDataManagerImpl::GetInstance()->CanUseGpuBrowserCompositor()) {
+        RECT r;
+        GetClientRect(window, &r);
+        MapWindowPoints(window, parent, reinterpret_cast<POINT*>(&r), 2);
+        invalidate_rects.push_back(r);
+      }
+#endif
     } else {
       flags |= SWP_NOMOVE;
       flags |= SWP_NOSIZE;
@@ -322,6 +339,13 @@
       gfx::Rect gr(r);
       PaintEnumChildProc(move.window, reinterpret_cast<LPARAM>(&gr));
     }
+  } else {
+      for (size_t i = 0; i < invalidate_rects.size(); ++i) {
+      ::RedrawWindow(
+          parent, &invalidate_rects[i], NULL,
+          // These flags are from WebPluginDelegateImpl::NativeWndProc.
+          RDW_INVALIDATE | RDW_ALLCHILDREN | RDW_FRAME | RDW_UPDATENOW);
+    }
   }
 #endif
 }
diff --git a/content/browser/renderer_host/render_widget_host_view_win.cc b/content/browser/renderer_host/render_widget_host_view_win.cc
index 9096e37..dcf3873 100644
--- a/content/browser/renderer_host/render_widget_host_view_win.cc
+++ b/content/browser/renderer_host/render_widget_host_view_win.cc
@@ -404,6 +404,7 @@
       weak_factory_(this),
       is_loading_(false),
       text_input_type_(ui::TEXT_INPUT_TYPE_NONE),
+      text_input_mode_(ui::TEXT_INPUT_MODE_DEFAULT),
       can_compose_inline_(true),
       is_fullscreen_(false),
       ignore_mouse_movement_(true),
@@ -692,9 +693,12 @@
     bool can_compose_inline,
     ui::TextInputMode input_mode) {
   if (text_input_type_ != type ||
+      text_input_mode_ != input_mode ||
       can_compose_inline_ != can_compose_inline) {
-    const bool text_input_type_changed = (text_input_type_ != type);
+    const bool text_input_type_changed = (text_input_type_ != type) ||
+                                         (text_input_mode_ != input_mode);
     text_input_type_ = type;
+    text_input_mode_ = input_mode;
     can_compose_inline_ = can_compose_inline;
     UpdateIMEState();
     if (text_input_type_changed)
@@ -1038,6 +1042,14 @@
   return text_input_type_;
 }
 
+ui::TextInputMode RenderWidgetHostViewWin::GetTextInputMode() const {
+  if (!base::win::IsTSFAwareRequired()) {
+    NOTREACHED();
+    return ui::TEXT_INPUT_MODE_DEFAULT;
+  }
+  return ui::TEXT_INPUT_MODE_DEFAULT;
+}
+
 bool RenderWidgetHostViewWin::CanComposeInline() const {
   if (!base::win::IsTSFAwareRequired()) {
     NOTREACHED();
@@ -3155,6 +3167,8 @@
   } else {
     imm32_manager_->DisableIME(m_hWnd);
   }
+
+  imm32_manager_->SetTextInputMode(m_hWnd, text_input_mode_);
 }
 
 void RenderWidgetHostViewWin::UpdateInputScopeIfNecessary(
diff --git a/content/browser/renderer_host/render_widget_host_view_win.h b/content/browser/renderer_host/render_widget_host_view_win.h
index d613f3a..52030d7 100644
--- a/content/browser/renderer_host/render_widget_host_view_win.h
+++ b/content/browser/renderer_host/render_widget_host_view_win.h
@@ -12,6 +12,7 @@
 #include <vector>
 
 #include "base/compiler_specific.h"
+#include "base/gtest_prod_util.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/memory/scoped_vector.h"
 #include "base/memory/weak_ptr.h"
@@ -270,6 +271,7 @@
   virtual void InsertChar(char16 ch, int flags) OVERRIDE;
   virtual gfx::NativeWindow GetAttachedWindow() const OVERRIDE;
   virtual ui::TextInputType GetTextInputType() const OVERRIDE;
+  virtual ui::TextInputMode GetTextInputMode() const OVERRIDE;
   virtual bool CanComposeInline() const OVERRIDE;
   virtual gfx::Rect GetCaretBounds() OVERRIDE;
   virtual bool GetCompositionCharacterBounds(uint32 index,
@@ -360,6 +362,9 @@
   void OnFinalMessage(HWND window);
 
  private:
+  FRIEND_TEST_ALL_PREFIXES(RenderWidgetHostViewWinBrowserTest,
+                           TextInputTypeChanged);
+
   // Updates the display cursor to the current cursor if the cursor is over this
   // render view.
   void UpdateCursorIfOverSelf();
@@ -533,6 +538,7 @@
   // Stores the current text input type received by TextInputStateChanged()
   // method.
   ui::TextInputType text_input_type_;
+  ui::TextInputMode text_input_mode_;
   bool can_compose_inline_;
 
   ScopedVector<ui::ViewProp> props_;
diff --git a/content/browser/renderer_host/render_widget_host_view_win_browsertest.cc b/content/browser/renderer_host/render_widget_host_view_win_browsertest.cc
index 77763ab..76070bc 100644
--- a/content/browser/renderer_host/render_widget_host_view_win_browsertest.cc
+++ b/content/browser/renderer_host/render_widget_host_view_win_browsertest.cc
@@ -2,8 +2,12 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include <vector>
+
 #include "base/command_line.h"
 #include "base/win/metro.h"
+#include "content/browser/renderer_host/render_widget_host_view_win.h"
+#include "content/public/browser/render_view_host.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/common/content_switches.h"
 #include "content/public/test/test_utils.h"
@@ -11,14 +15,94 @@
 #include "content/shell/shell.h"
 #include "content/test/content_browser_test_utils.h"
 #include "content/test/content_browser_test.h"
+#include "ui/base/ime/composition_text.h"
 #include "ui/base/ime/text_input_type.h"
+#include "ui/base/ime/win/imm32_manager.h"
 #include "ui/base/ime/win/mock_tsf_bridge.h"
 #include "ui/base/ime/win/tsf_bridge.h"
 
 namespace content {
-class RenderWidgetHostViewWinTest : public ContentBrowserTest {
+namespace {
+
+class MockIMM32Manager : public ui::IMM32Manager {
  public:
-  RenderWidgetHostViewWinTest() {}
+   MockIMM32Manager()
+       : window_handle_(NULL),
+         input_mode_(ui::TEXT_INPUT_MODE_DEFAULT),
+         call_count_(0) {
+   }
+  virtual ~MockIMM32Manager() {}
+
+  virtual void SetTextInputMode(HWND window_handle,
+                                ui::TextInputMode input_mode) OVERRIDE {
+    ++call_count_;
+    window_handle_ = window_handle;
+    input_mode_ = input_mode;
+  }
+
+  void Reset() {
+    window_handle_ = NULL;
+    input_mode_ = ui::TEXT_INPUT_MODE_DEFAULT;
+    call_count_ = 0;
+  }
+
+  HWND window_handle() const { return window_handle_; }
+  ui::TextInputMode input_mode() const { return input_mode_; }
+  size_t call_count() const { return call_count_; }
+
+ private:
+  HWND window_handle_;
+  ui::TextInputMode input_mode_;
+  size_t call_count_;
+
+  DISALLOW_COPY_AND_ASSIGN(MockIMM32Manager);
+};
+
+// Testing class serving initialized RenderWidgetHostViewWin instance;
+class RenderWidgetHostViewWinBrowserTest : public ContentBrowserTest {
+ public:
+  RenderWidgetHostViewWinBrowserTest() {}
+
+  virtual void SetUpOnMainThread() OVERRIDE {
+    ContentBrowserTest::SetUpOnMainThread();
+
+    NavigateToURL(shell(), GURL("about:blank"));
+
+    view_ = static_cast<RenderWidgetHostViewWin*>(
+        RenderWidgetHostViewPort::FromRWHV(
+            shell()->web_contents()->GetRenderViewHost()->GetView()));
+    CHECK(view_);
+  }
+
+ protected:
+  RenderWidgetHostViewWin* view_;
+};
+
+}  // namespace
+
+IN_PROC_BROWSER_TEST_F(RenderWidgetHostViewWinBrowserTest,
+                       TextInputTypeChanged) {
+  ASSERT_TRUE(view_->m_hWnd);
+
+  MockIMM32Manager* mock = new MockIMM32Manager();
+  mock->Reset();
+  view_->imm32_manager_.reset(mock);
+  view_->TextInputTypeChanged(ui::TEXT_INPUT_TYPE_NONE, false,
+                              ui::TEXT_INPUT_MODE_EMAIL);
+
+  EXPECT_EQ(1, mock->call_count());
+  EXPECT_EQ(view_->m_hWnd, mock->window_handle());
+  EXPECT_EQ(ui::TEXT_INPUT_MODE_EMAIL, mock->input_mode());
+
+  mock->Reset();
+  view_->TextInputTypeChanged(ui::TEXT_INPUT_TYPE_NONE, false,
+                              ui::TEXT_INPUT_MODE_EMAIL);
+  EXPECT_EQ(0, mock->call_count());
+}
+
+class RenderWidgetHostViewWinTSFTest : public ContentBrowserTest {
+ public:
+  RenderWidgetHostViewWinTSFTest() {}
 
   virtual void SetUpCommandLine(CommandLine* command_line) {
     command_line->AppendSwitch(switches::kEnableTextServicesFramework);
@@ -26,7 +110,7 @@
 };
 
 // crbug.com/151798
-IN_PROC_BROWSER_TEST_F(RenderWidgetHostViewWinTest,
+IN_PROC_BROWSER_TEST_F(RenderWidgetHostViewWinTSFTest,
                        DISABLED_SwichToPasswordField) {
   ui::MockTSFBridge mock_bridge;
   ui::TSFBridge* old_bridge = ui::TSFBridge::ReplaceForTesting(&mock_bridge);
@@ -64,7 +148,7 @@
 }
 
 // crbug.com/151798
-IN_PROC_BROWSER_TEST_F(RenderWidgetHostViewWinTest,
+IN_PROC_BROWSER_TEST_F(RenderWidgetHostViewWinTSFTest,
                        DISABLED_SwitchToSameField) {
   ui::MockTSFBridge mock_bridge;
   ui::TSFBridge* old_bridge = ui::TSFBridge::ReplaceForTesting(&mock_bridge);
@@ -102,7 +186,7 @@
 }
 
 // crbug.com/151798
-IN_PROC_BROWSER_TEST_F(RenderWidgetHostViewWinTest,
+IN_PROC_BROWSER_TEST_F(RenderWidgetHostViewWinTSFTest,
                        DISABLED_SwitchToSamePasswordField) {
   ui::MockTSFBridge mock_bridge;
   ui::TSFBridge* old_bridge = ui::TSFBridge::ReplaceForTesting(&mock_bridge);
diff --git a/content/browser/renderer_host/test_render_view_host.cc b/content/browser/renderer_host/test_render_view_host.cc
index 56be05c..129591c 100644
--- a/content/browser/renderer_host/test_render_view_host.cc
+++ b/content/browser/renderer_host/test_render_view_host.cc
@@ -311,8 +311,12 @@
 void TestRenderViewHost::SendNavigateWithTransitionAndResponseCode(
     int page_id, const GURL& url, PageTransition transition,
     int response_code) {
-  OnDidStartProvisionalLoadForFrame(kFrameId, -1, true, url);
-  SendNavigateWithParameters(page_id, url, transition, url, response_code, 0);
+  // 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(kFrameId, -1, true, url_copy);
+  SendNavigateWithParameters(page_id, url_copy, transition, url_copy,
+                             response_code, 0);
 }
 
 void TestRenderViewHost::SendNavigateWithParameters(
diff --git a/content/browser/safe_util_win.cc b/content/browser/safe_util_win.cc
index 2dce2ca..ac077f1 100644
--- a/content/browser/safe_util_win.cc
+++ b/content/browser/safe_util_win.cc
@@ -19,12 +19,6 @@
 namespace content {
 namespace {
 
-// This GUID is associated with any 'don't ask me again' settings that the
-// user can select for different file types.
-// {2676A9A2-D919-4fee-9187-152100393AB2}
-static const GUID kClientID = { 0x2676a9a2, 0xd919, 0x4fee,
-  { 0x91, 0x87, 0x15, 0x21, 0x0, 0x39, 0x3a, 0xb2 } };
-
 // Sets the Zone Identifier on the file to "Internet" (3). Returns true if the
 // function succeeds, false otherwise. A failure is expected on system where
 // the Zone Identifier is not supported, like a machine with a FAT32 filesystem.
@@ -55,72 +49,11 @@
   return true;
 }
 
-}
+}  // namespace
 
-// This function implementation is based on the attachment execution
-// services functionally deployed with IE6 or Service pack 2. This
-// functionality is exposed in the IAttachmentExecute COM interface.
-// more information at:
-// http://msdn2.microsoft.com/en-us/library/ms647048.aspx
-bool SaferOpenItemViaShell(HWND hwnd, const std::wstring& window_title,
-                           const base::FilePath& full_path,
-                           const std::wstring& source_url) {
-  base::win::ScopedComPtr<IAttachmentExecute> attachment_services;
-  HRESULT hr = attachment_services.CreateInstance(CLSID_AttachmentServices);
-  if (FAILED(hr)) {
-    // We don't have Attachment Execution Services, it must be a pre-XP.SP2
-    // Windows installation, or the thread does not have COM initialized.
-    if (hr == CO_E_NOTINITIALIZED) {
-      NOTREACHED();
-      return false;
-    }
-    return ui::win::OpenItemViaShell(full_path);
-  }
-
-  attachment_services->SetClientGuid(kClientID);
-
-  if (!window_title.empty())
-    attachment_services->SetClientTitle(window_title.c_str());
-
-  // To help windows decide if the downloaded file is dangerous we can provide
-  // what the documentation calls evidence. Which we provide now:
-  //
-  // Set the file itself as evidence.
-  hr = attachment_services->SetLocalPath(full_path.value().c_str());
-  if (FAILED(hr))
-    return false;
-  // Set the origin URL as evidence.
-  hr = attachment_services->SetSource(source_url.c_str());
-  if (FAILED(hr))
-    return false;
-
-  // Now check the windows policy.
-  if (attachment_services->CheckPolicy() != S_OK) {
-    // It is possible that the above call returns an undocumented result
-    // equal to 0x800c000e which seems to indicate that the URL failed the
-    // the security check. If you proceed with the Prompt() call the
-    // Shell might show a dialog that says:
-    // "windows found that this file is potentially harmful. To help protect
-    // your computer, Windows has blocked access to this file."
-    // Upon dismissal of the dialog windows will delete the file (!!).
-    // So, we can 'return' in that case but maybe is best to let it happen to
-    // fail on the safe side.
-
-    ATTACHMENT_ACTION action;
-    // We cannot control what the prompt says or does directly but it
-    // is a pretty decent dialog; for example, if an executable is signed it can
-    // decode and show the publisher and the certificate.
-    hr = attachment_services->Prompt(hwnd, ATTACHMENT_PROMPT_EXEC, &action);
-    if (FAILED(hr) || (ATTACHMENT_ACTION_CANCEL == action)) {
-      // The user has declined opening the item.
-      return false;
-    }
-  }
-  return ui::win::OpenItemViaShellNoZoneCheck(full_path);
-}
-
-HRESULT ScanAndSaveDownloadedFile(const base::FilePath& full_path,
-                                  const GURL& source_url) {
+HRESULT AVScanFile(const base::FilePath& full_path,
+                   const std::string& source_url,
+                   const GUID& client_guid) {
   base::win::ScopedComPtr<IAttachmentExecute> attachment_services;
   HRESULT hr = attachment_services.CreateInstance(CLSID_AttachmentServices);
 
@@ -135,15 +68,20 @@
     return hr;
   }
 
-  hr = attachment_services->SetClientGuid(kClientID);
-  if (FAILED(hr))
-    return hr;
+  if (!IsEqualGUID(client_guid, GUID_NULL)) {
+    hr = attachment_services->SetClientGuid(client_guid);
+    if (FAILED(hr))
+      return hr;
+  }
 
   hr = attachment_services->SetLocalPath(full_path.value().c_str());
   if (FAILED(hr))
     return hr;
 
-  hr = attachment_services->SetSource(UTF8ToWide(source_url.spec()).c_str());
+  // Note: SetSource looks like it needs to be called, even if empty.
+  // Docs say it is optional, but it appears not calling it at all sets
+  // a zone that is too restrictive.
+  hr = attachment_services->SetSource(UTF8ToWide(source_url).c_str());
   if (FAILED(hr))
     return hr;
 
diff --git a/content/browser/safe_util_win.h b/content/browser/safe_util_win.h
index 1636748..3860429 100644
--- a/content/browser/safe_util_win.h
+++ b/content/browser/safe_util_win.h
@@ -16,34 +16,6 @@
 
 namespace content {
 
-// Open or run a downloaded file via the Windows shell, possibly showing first
-// a consent dialog if the the file is deemed dangerous. This function is an
-// enhancement over the OpenItemViaShell() function of win_util.h.
-//
-// The user consent dialog will be shown or not according to the windows
-// execution policy defined in the registry which can be overridden per user.
-// The mechanics of the policy are explained in the Microsoft Knowledge base
-// number 883260: http://support.microsoft.com/kb/883260
-//
-// The 'hwnd' is the handle to the parent window. In case a dialog is displayed
-// the parent window will be disabled since the dialog is meant to be modal.
-// The 'window_title' is the text displayed on the title bar of the dialog. If
-// you pass an empty string the dialog will have a generic 'windows security'
-// name on the title bar.
-//
-// You must provide a valid 'full_path' to the file to be opened and a well
-// formed url in 'source_url'. The url should identify the source of the file
-// but does not have to be network-reachable. If the url is malformed a
-// dialog will be shown telling the user that the file will be blocked.
-//
-// In the event that there is no default application registered for the file
-// specified by 'full_path' it ask the user, via the Windows "Open With"
-// dialog.
-// Returns 'true' on successful open, 'false' otherwise.
-bool SaferOpenItemViaShell(HWND hwnd, const std::wstring& window_title,
-                           const base::FilePath& full_path,
-                           const std::wstring& source_url);
-
 // Invokes IAttachmentExecute::Save to validate the downloaded file. The call
 // may scan the file for viruses and if necessary, annotate it with evidence. As
 // a result of the validation, the file may be deleted.  See:
@@ -67,10 +39,15 @@
 // Any other return value indicates an unexpected error during the scan.
 //
 // |full_path| : is the path to the downloaded file. This should be the final
-//               path of the download.
-// |source_url|: the source URL for the download.
-HRESULT ScanAndSaveDownloadedFile(const base::FilePath& full_path,
-                                  const GURL& source_url);
+//               path of the download. Must be present.
+// |source_url|: the source URL for the download. If empty, the source will
+//               not be set.
+// |client_guid|: the GUID to be set in the IAttachmentExecute client slot.
+//                Used to identify the app to the system AV function.
+//                If GUID_NULL is passed, no client GUID is set.
+HRESULT AVScanFile(const base::FilePath& full_path,
+                   const std::string& source_url,
+                   const GUID& client_guid);
 }  // namespace content
 
 #endif  // CONTENT_COMMON_SAFE_UTIL_WIN_H_
diff --git a/content/browser/storage_partition_impl.cc b/content/browser/storage_partition_impl.cc
index 1775b5f..361b4d1 100644
--- a/content/browser/storage_partition_impl.cc
+++ b/content/browser/storage_partition_impl.cc
@@ -252,6 +252,7 @@
                            net::URLRequestContextGetter* rq_context,
                            DOMStorageContextWrapper* dom_storage_context,
                            quota::QuotaManager* quota_manager,
+                           WebRTCIdentityStore* webrtc_identity_store,
                            const base::Time begin,
                            const base::Time end);
 
@@ -284,7 +285,7 @@
     webkit_database::DatabaseTracker* database_tracker,
     DOMStorageContextWrapper* dom_storage_context,
     IndexedDBContextImpl* indexed_db_context,
-    scoped_ptr<WebRTCIdentityStore> webrtc_identity_store)
+    WebRTCIdentityStore* webrtc_identity_store)
     : partition_path_(partition_path),
       quota_manager_(quota_manager),
       appcache_service_(appcache_service),
@@ -292,7 +293,7 @@
       database_tracker_(database_tracker),
       dom_storage_context_(dom_storage_context),
       indexed_db_context_(indexed_db_context),
-      webrtc_identity_store_(webrtc_identity_store.Pass()) {}
+      webrtc_identity_store_(webrtc_identity_store) {}
 
 StoragePartitionImpl::~StoragePartitionImpl() {
   // These message loop checks are just to avoid leaks in unittests.
@@ -367,8 +368,8 @@
   scoped_refptr<ChromeAppCacheService> appcache_service =
       new ChromeAppCacheService(quota_manager->proxy());
 
-  scoped_ptr<WebRTCIdentityStore> webrtc_identity_store(
-      new WebRTCIdentityStore());
+  scoped_refptr<WebRTCIdentityStore> webrtc_identity_store(
+      new WebRTCIdentityStore(path, context->GetSpecialStoragePolicy()));
 
   return new StoragePartitionImpl(partition_path,
                                   quota_manager.get(),
@@ -377,7 +378,7 @@
                                   database_tracker.get(),
                                   dom_storage_context.get(),
                                   indexed_db_context.get(),
-                                  webrtc_identity_store.Pass());
+                                  webrtc_identity_store.get());
 }
 
 base::FilePath StoragePartitionImpl::GetPath() {
@@ -431,7 +432,8 @@
   // DataDeletionHelper::DecrementTaskCountOnUI().
   helper->ClearDataOnUIThread(
       remove_mask, quota_storage_remove_mask, remove_origin,
-      GetPath(), rq_context, dom_storage_context_, quota_manager_, begin, end);
+      GetPath(), rq_context, dom_storage_context_, quota_manager_,
+      webrtc_identity_store_, begin, end);
 }
 
 void StoragePartitionImpl::
@@ -546,6 +548,7 @@
     net::URLRequestContextGetter* rq_context,
     DOMStorageContextWrapper* dom_storage_context,
     quota::QuotaManager* quota_manager,
+    WebRTCIdentityStore* webrtc_identity_store,
     const base::Time begin,
     const base::Time end) {
   DCHECK_NE(remove_mask, 0u);
@@ -602,6 +605,18 @@
                    path, begin, end, decrement_callback));
   }
 
+  if (remove_mask & REMOVE_DATA_MASK_WEBRTC_IDENTITY) {
+    IncrementTaskCountOnUI();
+    BrowserThread::PostTask(
+        BrowserThread::IO,
+        FROM_HERE,
+        base::Bind(&WebRTCIdentityStore::DeleteBetween,
+                   webrtc_identity_store,
+                   begin,
+                   end,
+                   decrement_callback));
+  }
+
   DecrementTaskCountOnUI();
 }
 
diff --git a/content/browser/storage_partition_impl.h b/content/browser/storage_partition_impl.h
index 8665a74..e59347c 100644
--- a/content/browser/storage_partition_impl.h
+++ b/content/browser/storage_partition_impl.h
@@ -77,7 +77,7 @@
       webkit_database::DatabaseTracker* database_tracker,
       DOMStorageContextWrapper* dom_storage_context,
       IndexedDBContextImpl* indexed_db_context,
-      scoped_ptr<WebRTCIdentityStore> webrtc_identity_store);
+      WebRTCIdentityStore* webrtc_identity_store);
 
   void ClearDataImpl(uint32 remove_mask,
                      uint32 quota_storage_remove_mask,
@@ -112,7 +112,7 @@
   scoped_refptr<webkit_database::DatabaseTracker> database_tracker_;
   scoped_refptr<DOMStorageContextWrapper> dom_storage_context_;
   scoped_refptr<IndexedDBContextImpl> indexed_db_context_;
-  scoped_ptr<WebRTCIdentityStore> webrtc_identity_store_;
+  scoped_refptr<WebRTCIdentityStore> webrtc_identity_store_;
 
   DISALLOW_COPY_AND_ASSIGN(StoragePartitionImpl);
 };
diff --git a/content/browser/storage_partition_impl_unittest.cc b/content/browser/storage_partition_impl_unittest.cc
index 2207837..a8b47bc 100644
--- a/content/browser/storage_partition_impl_unittest.cc
+++ b/content/browser/storage_partition_impl_unittest.cc
@@ -109,14 +109,8 @@
   EXPECT_EQ(1u, Size());
 
   TestClosureCallback clear_cb;
-  StoragePartitionImpl sp(cache_path(),
-                          NULL,
-                          NULL,
-                          NULL,
-                          NULL,
-                          NULL,
-                          NULL,
-                          scoped_ptr<WebRTCIdentityStore>());
+  StoragePartitionImpl sp(
+      cache_path(), NULL, NULL, NULL, NULL, NULL, NULL, NULL);
   base::MessageLoop::current()->PostTask(
       FROM_HERE, base::Bind(&ClearData, &sp, clear_cb.callback()));
   clear_cb.WaitForResult();
diff --git a/content/browser/utility_process_host_impl.cc b/content/browser/utility_process_host_impl.cc
index db062c5..2e56218 100644
--- a/content/browser/utility_process_host_impl.cc
+++ b/content/browser/utility_process_host_impl.cc
@@ -27,7 +27,6 @@
 #include "content/utility/utility_thread_impl.h"
 #include "ipc/ipc_switches.h"
 #include "ui/base/ui_base_switches.h"
-#include "webkit/plugins/plugin_switches.h"
 
 #if defined(OS_WIN)
 #include "content/public/common/sandboxed_process_launcher_delegate.h"
diff --git a/content/browser/web_contents/debug_urls.cc b/content/browser/web_contents/debug_urls.cc
index b554eca..1f1222c 100644
--- a/content/browser/web_contents/debug_urls.cc
+++ b/content/browser/web_contents/debug_urls.cc
@@ -10,10 +10,10 @@
 #include "content/browser/gpu/gpu_process_host_ui_shim.h"
 #include "content/browser/ppapi_plugin_process_host.h"
 #include "content/public/browser/browser_thread.h"
+#include "content/public/common/content_constants.h"
 #include "content/public/common/url_constants.h"
 #include "ppapi/proxy/ppapi_messages.h"
 #include "url/gurl.h"
-#include "webkit/plugins/plugin_constants.h"
 
 namespace content {
 
diff --git a/content/browser/web_contents/navigation_controller_impl_unittest.cc b/content/browser/web_contents/navigation_controller_impl_unittest.cc
index c86e3a5..c3e9b19 100644
--- a/content/browser/web_contents/navigation_controller_impl_unittest.cc
+++ b/content/browser/web_contents/navigation_controller_impl_unittest.cc
@@ -2611,6 +2611,52 @@
   EXPECT_EQ(controller.GetEntryAtIndex(1)->GetURL(), transient_url);
 }
 
+// Ensure that renderer initiated pending entries get replaced, so that we
+// don't show a stale virtual URL when a navigation commits.
+// See http://crbug.com/266922.
+TEST_F(NavigationControllerTest, RendererInitiatedPendingEntries) {
+  NavigationControllerImpl& controller = controller_impl();
+
+  const GURL url1("nonexistent:12121");
+  const GURL url1_fixed("http://nonexistent:12121/");
+  const GURL url2("http://foo");
+
+  // We create pending entries for renderer-initiated navigations so that we
+  // can show them in new tabs when it is safe.
+  contents()->DidStartProvisionalLoadForFrame(
+      test_rvh(), 1, -1, true, url1);
+
+  // Simulate what happens if a BrowserURLHandler rewrites the URL, causing
+  // the virtual URL to differ from the URL.
+  controller.GetPendingEntry()->SetURL(url1_fixed);
+  controller.GetPendingEntry()->SetVirtualURL(url1);
+
+  EXPECT_EQ(url1_fixed, controller.GetPendingEntry()->GetURL());
+  EXPECT_EQ(url1, controller.GetPendingEntry()->GetVirtualURL());
+  EXPECT_TRUE(
+      NavigationEntryImpl::FromNavigationEntry(controller.GetPendingEntry())->
+          is_renderer_initiated());
+
+  // If the user clicks another link, we should replace the pending entry.
+  contents()->DidStartProvisionalLoadForFrame(
+      test_rvh(), 1, -1, true, url2);
+  EXPECT_EQ(url2, controller.GetPendingEntry()->GetURL());
+  EXPECT_EQ(url2, controller.GetPendingEntry()->GetVirtualURL());
+
+  // Once it commits, the URL and virtual URL should reflect the actual page.
+  test_rvh()->SendNavigate(0, url2);
+  EXPECT_EQ(url2, controller.GetLastCommittedEntry()->GetURL());
+  EXPECT_EQ(url2, controller.GetLastCommittedEntry()->GetVirtualURL());
+
+  // We should not replace the pending entry for an error URL.
+  contents()->DidStartProvisionalLoadForFrame(
+      test_rvh(), 1, -1, true, url1);
+  EXPECT_EQ(url1, controller.GetPendingEntry()->GetURL());
+  contents()->DidStartProvisionalLoadForFrame(
+      test_rvh(), 1, -1, true, GURL(kUnreachableWebDataURL));
+  EXPECT_EQ(url1, controller.GetPendingEntry()->GetURL());
+}
+
 // Tests that the URLs for renderer-initiated navigations are not displayed to
 // the user until the navigation commits, to prevent URL spoof attacks.
 // See http://crbug.com/99016.
diff --git a/content/browser/web_contents/web_contents_impl.cc b/content/browser/web_contents/web_contents_impl.cc
index 66e110e..551be51 100644
--- a/content/browser/web_contents/web_contents_impl.cc
+++ b/content/browser/web_contents/web_contents_impl.cc
@@ -2133,24 +2133,31 @@
       render_view_host->GetProcess();
   RenderViewHost::FilterURL(render_process_host, false, &validated_url);
 
-  if (is_main_frame)
+  if (is_main_frame) {
     DidChangeLoadProgress(0);
 
-  // Create a pending entry for this provisional load (if none exists) using the
-  // current SiteInstance, and ensure the address bar updates accordingly.
-  // We don't know the referrer or extra headers at this point, but the referrer
-  // will be set properly upon commit.
-  if (is_main_frame && !controller_.GetPendingEntry()) {
-    NavigationEntryImpl* entry = NavigationEntryImpl::FromNavigationEntry(
-        controller_.CreateNavigationEntry(validated_url,
-                                          content::Referrer(),
-                                          content::PAGE_TRANSITION_LINK,
-                                          true /* is_renderer_initiated */,
-                                          std::string(), GetBrowserContext()));
-    entry->set_site_instance(
-        static_cast<SiteInstanceImpl*>(GetSiteInstance()));
-    controller_.SetPendingEntry(entry);
-    NotifyNavigationStateChanged(content::INVALIDATE_TYPE_URL);
+    // 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
+    // SiteInstance, and ensure the address bar updates accordingly.  We don't
+    // know the referrer or extra headers at this point, but the referrer will
+    // be set properly upon commit.
+    NavigationEntry* pending_entry = controller_.GetPendingEntry();
+    bool has_browser_initiated_pending_entry = pending_entry &&
+        !NavigationEntryImpl::FromNavigationEntry(pending_entry)->
+            is_renderer_initiated();
+    if (!has_browser_initiated_pending_entry && !is_error_page) {
+      NavigationEntryImpl* entry = NavigationEntryImpl::FromNavigationEntry(
+          controller_.CreateNavigationEntry(validated_url,
+                                            content::Referrer(),
+                                            content::PAGE_TRANSITION_LINK,
+                                            true /* is_renderer_initiated */,
+                                            std::string(),
+                                            GetBrowserContext()));
+      entry->set_site_instance(
+          static_cast<SiteInstanceImpl*>(GetSiteInstance()));
+      controller_.SetPendingEntry(entry);
+      NotifyNavigationStateChanged(content::INVALIDATE_TYPE_URL);
+    }
   }
 
   // Notify observers about the start of the provisional load.
@@ -2603,7 +2610,7 @@
           "Playing video");
 #if defined(OS_ANDROID)
       static_cast<PowerSaveBlockerImpl*>(blocker.get())->
-          InitDisplaySleepBlocker(GetView()->GetTopLevelNativeWindow());
+          InitDisplaySleepBlocker(GetView()->GetNativeView());
 #endif
     } else if (has_audio) {
       blocker = PowerSaveBlocker::Create(
diff --git a/content/child/appcache/OWNERS b/content/child/appcache/OWNERS
new file mode 100644
index 0000000..3723f40
--- /dev/null
+++ b/content/child/appcache/OWNERS
@@ -0,0 +1 @@
+michaeln@chromium.org
diff --git a/content/child/appcache_backend_proxy.cc b/content/child/appcache/appcache_backend_proxy.cc
similarity index 95%
rename from content/child/appcache_backend_proxy.cc
rename to content/child/appcache/appcache_backend_proxy.cc
index 8323751..8f9d06a 100644
--- a/content/child/appcache_backend_proxy.cc
+++ b/content/child/appcache/appcache_backend_proxy.cc
@@ -1,8 +1,8 @@
-// Copyright (c) 2011 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.
 
-#include "content/child/appcache_backend_proxy.h"
+#include "content/child/appcache/appcache_backend_proxy.h"
 
 #include "content/common/appcache_messages.h"
 
diff --git a/content/child/appcache_backend_proxy.h b/content/child/appcache/appcache_backend_proxy.h
similarity index 87%
rename from content/child/appcache_backend_proxy.h
rename to content/child/appcache/appcache_backend_proxy.h
index 943990a..467d385 100644
--- a/content/child/appcache_backend_proxy.h
+++ b/content/child/appcache/appcache_backend_proxy.h
@@ -1,9 +1,9 @@
-// Copyright (c) 2012 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.
 
-#ifndef CONTENT_CHILD_APPCACHE_BACKEND_PROXY_H_
-#define CONTENT_CHILD_APPCACHE_BACKEND_PROXY_H_
+#ifndef CONTENT_CHILD_APPCACHE_APPCACHE_BACKEND_PROXY_H_
+#define CONTENT_CHILD_APPCACHE_APPCACHE_BACKEND_PROXY_H_
 
 #include <vector>
 
@@ -51,4 +51,4 @@
 
 }  // namespace content
 
-#endif  // CONTENT_CHILD_APPCACHE_BACKEND_PROXY_H_
\ No newline at end of file
+#endif  // CONTENT_CHILD_APPCACHE_APPCACHE_BACKEND_PROXY_H_
\ No newline at end of file
diff --git a/content/child/appcache_dispatcher.cc b/content/child/appcache/appcache_dispatcher.cc
similarity index 95%
rename from content/child/appcache_dispatcher.cc
rename to content/child/appcache/appcache_dispatcher.cc
index 96adc89..c3b4ec6 100644
--- a/content/child/appcache_dispatcher.cc
+++ b/content/child/appcache/appcache_dispatcher.cc
@@ -1,8 +1,8 @@
-// Copyright (c) 2011 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.
 
-#include "content/child/appcache_dispatcher.h"
+#include "content/child/appcache/appcache_dispatcher.h"
 
 #include "content/common/appcache_messages.h"
 
diff --git a/content/child/appcache_dispatcher.h b/content/child/appcache/appcache_dispatcher.h
similarity index 85%
rename from content/child/appcache_dispatcher.h
rename to content/child/appcache/appcache_dispatcher.h
index 0ce2acb..0b62563 100644
--- a/content/child/appcache_dispatcher.h
+++ b/content/child/appcache/appcache_dispatcher.h
@@ -1,15 +1,15 @@
-// Copyright (c) 2012 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.
 
-#ifndef CONTENT_CHILD_APPCACHE_DISPATCHER_H_
-#define CONTENT_CHILD_APPCACHE_DISPATCHER_H_
+#ifndef CONTENT_CHILD_APPCACHE_APPCACHE_DISPATCHER_H_
+#define CONTENT_CHILD_APPCACHE_APPCACHE_DISPATCHER_H_
 
 #include <string>
 #include <vector>
 
 #include "base/memory/scoped_ptr.h"
-#include "content/child/appcache_backend_proxy.h"
+#include "content/child/appcache/appcache_backend_proxy.h"
 #include "ipc/ipc_listener.h"
 #include "webkit/common/appcache/appcache_interfaces.h"
 
@@ -50,4 +50,4 @@
 
 }  // namespace content
 
-#endif  // CONTENT_CHILD_APPCACHE_DISPATCHER_H_
+#endif  // CONTENT_CHILD_APPCACHE_APPCACHE_DISPATCHER_H_
diff --git a/webkit/renderer/appcache/appcache_frontend_impl.cc b/content/child/appcache/appcache_frontend_impl.cc
similarity index 61%
rename from webkit/renderer/appcache/appcache_frontend_impl.cc
rename to content/child/appcache/appcache_frontend_impl.cc
index 519bcd5..0163df2 100644
--- a/webkit/renderer/appcache/appcache_frontend_impl.cc
+++ b/content/child/appcache/appcache_frontend_impl.cc
@@ -1,33 +1,33 @@
-// Copyright (c) 2010 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.
 
-#include "webkit/renderer/appcache/appcache_frontend_impl.h"
+#include "content/child/appcache/appcache_frontend_impl.h"
 
 #include "base/logging.h"
+#include "content/child/appcache/web_application_cache_host_impl.h"
 #include "third_party/WebKit/public/web/WebApplicationCacheHost.h"
 #include "third_party/WebKit/public/web/WebConsoleMessage.h"
-#include "webkit/renderer/appcache/web_application_cache_host_impl.h"
 
 using WebKit::WebApplicationCacheHost;
 using WebKit::WebConsoleMessage;
 
-namespace appcache {
+namespace content {
 
 // Inline helper to keep the lines shorter and unwrapped.
 inline WebApplicationCacheHostImpl* GetHost(int id) {
   return WebApplicationCacheHostImpl::FromId(id);
 }
 
-void AppCacheFrontendImpl::OnCacheSelected(
-    int host_id, const AppCacheInfo& info) {
+void AppCacheFrontendImpl::OnCacheSelected(int host_id,
+                                           const appcache::AppCacheInfo& info) {
   WebApplicationCacheHostImpl* host = GetHost(host_id);
   if (host)
     host->OnCacheSelected(info);
 }
 
 void AppCacheFrontendImpl::OnStatusChanged(const std::vector<int>& host_ids,
-                                           Status status) {
+                                           appcache::Status status) {
   for (std::vector<int>::const_iterator i = host_ids.begin();
        i != host_ids.end(); ++i) {
     WebApplicationCacheHostImpl* host = GetHost(*i);
@@ -37,9 +37,9 @@
 }
 
 void AppCacheFrontendImpl::OnEventRaised(const std::vector<int>& host_ids,
-                                         EventID event_id) {
-  DCHECK(event_id != PROGRESS_EVENT);  // See OnProgressEventRaised.
-  DCHECK(event_id != ERROR_EVENT);  // See OnErrorEventRaised.
+                                         appcache::EventID event_id) {
+  DCHECK(event_id != appcache::PROGRESS_EVENT);  // See OnProgressEventRaised.
+  DCHECK(event_id != appcache::ERROR_EVENT);  // See OnErrorEventRaised.
   for (std::vector<int>::const_iterator i = host_ids.begin();
        i != host_ids.end(); ++i) {
     WebApplicationCacheHostImpl* host = GetHost(*i);
@@ -50,7 +50,9 @@
 
 void AppCacheFrontendImpl::OnProgressEventRaised(
     const std::vector<int>& host_ids,
-    const GURL& url, int num_total, int num_complete) {
+    const GURL& url,
+    int num_total,
+    int num_complete) {
   for (std::vector<int>::const_iterator i = host_ids.begin();
        i != host_ids.end(); ++i) {
     WebApplicationCacheHostImpl* host = GetHost(*i);
@@ -59,9 +61,8 @@
   }
 }
 
-void AppCacheFrontendImpl::OnErrorEventRaised(
-    const std::vector<int>& host_ids,
-    const std::string& message) {
+void AppCacheFrontendImpl::OnErrorEventRaised(const std::vector<int>& host_ids,
+                                              const std::string& message) {
   for (std::vector<int>::const_iterator i = host_ids.begin();
        i != host_ids.end(); ++i) {
     WebApplicationCacheHostImpl* host = GetHost(*i);
@@ -70,7 +71,8 @@
   }
 }
 
-void AppCacheFrontendImpl::OnLogMessage(int host_id, LogLevel log_level,
+void AppCacheFrontendImpl::OnLogMessage(int host_id,
+                                        appcache::LogLevel log_level,
                                         const std::string& message) {
   WebApplicationCacheHostImpl* host = GetHost(host_id);
   if (host)
@@ -87,40 +89,40 @@
 // Ensure that enum values never get out of sync with the
 // ones declared for use within the WebKit api
 COMPILE_ASSERT((int)WebApplicationCacheHost::Uncached ==
-               (int)UNCACHED, Uncached);
+               (int)appcache::UNCACHED, Uncached);
 COMPILE_ASSERT((int)WebApplicationCacheHost::Idle ==
-               (int)IDLE, Idle);
+               (int)appcache::IDLE, Idle);
 COMPILE_ASSERT((int)WebApplicationCacheHost::Checking ==
-               (int)CHECKING, Checking);
+               (int)appcache::CHECKING, Checking);
 COMPILE_ASSERT((int)WebApplicationCacheHost::Downloading ==
-               (int)DOWNLOADING, Downloading);
+               (int)appcache::DOWNLOADING, Downloading);
 COMPILE_ASSERT((int)WebApplicationCacheHost::UpdateReady ==
-               (int)UPDATE_READY, UpdateReady);
+               (int)appcache::UPDATE_READY, UpdateReady);
 COMPILE_ASSERT((int)WebApplicationCacheHost::Obsolete ==
-               (int)OBSOLETE, Obsolete);
+               (int)appcache::OBSOLETE, Obsolete);
 COMPILE_ASSERT((int)WebApplicationCacheHost::CheckingEvent ==
-               (int)CHECKING_EVENT, CheckingEvent);
+               (int)appcache::CHECKING_EVENT, CheckingEvent);
 COMPILE_ASSERT((int)WebApplicationCacheHost::ErrorEvent ==
-               (int)ERROR_EVENT, ErrorEvent);
+               (int)appcache::ERROR_EVENT, ErrorEvent);
 COMPILE_ASSERT((int)WebApplicationCacheHost::NoUpdateEvent ==
-               (int)NO_UPDATE_EVENT, NoUpdateEvent);
+               (int)appcache::NO_UPDATE_EVENT, NoUpdateEvent);
 COMPILE_ASSERT((int)WebApplicationCacheHost::DownloadingEvent ==
-               (int)DOWNLOADING_EVENT, DownloadingEvent);
+               (int)appcache::DOWNLOADING_EVENT, DownloadingEvent);
 COMPILE_ASSERT((int)WebApplicationCacheHost::ProgressEvent ==
-               (int)PROGRESS_EVENT, ProgressEvent);
+               (int)appcache::PROGRESS_EVENT, ProgressEvent);
 COMPILE_ASSERT((int)WebApplicationCacheHost::UpdateReadyEvent ==
-               (int)UPDATE_READY_EVENT, UpdateReadyEvent);
+               (int)appcache::UPDATE_READY_EVENT, UpdateReadyEvent);
 COMPILE_ASSERT((int)WebApplicationCacheHost::CachedEvent ==
-               (int)CACHED_EVENT, CachedEvent);
+               (int)appcache::CACHED_EVENT, CachedEvent);
 COMPILE_ASSERT((int)WebApplicationCacheHost::ObsoleteEvent ==
-               (int)OBSOLETE_EVENT, ObsoleteEvent);
+               (int)appcache::OBSOLETE_EVENT, ObsoleteEvent);
 COMPILE_ASSERT((int)WebConsoleMessage::LevelDebug ==
-               (int)LOG_DEBUG, LevelDebug);
+               (int)appcache::LOG_DEBUG, LevelDebug);
 COMPILE_ASSERT((int)WebConsoleMessage::LevelLog ==
-               (int)LOG_INFO, LevelLog);
+               (int)appcache::LOG_INFO, LevelLog);
 COMPILE_ASSERT((int)WebConsoleMessage::LevelWarning ==
-               (int)LOG_WARNING, LevelWarning);
+               (int)appcache::LOG_WARNING, LevelWarning);
 COMPILE_ASSERT((int)WebConsoleMessage::LevelError ==
-               (int)LOG_ERROR, LevelError);
+               (int)appcache::LOG_ERROR, LevelError);
 
-}  // namespace appcache
+}  // namespace content
diff --git a/content/child/appcache/appcache_frontend_impl.h b/content/child/appcache/appcache_frontend_impl.h
new file mode 100644
index 0000000..90774fa
--- /dev/null
+++ b/content/child/appcache/appcache_frontend_impl.h
@@ -0,0 +1,34 @@
+// 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_CHILD_APPCACHE_APPCACHE_FRONTEND_IMPL_H_
+#define CONTENT_CHILD_APPCACHE_APPCACHE_FRONTEND_IMPL_H_
+
+#include "webkit/common/appcache/appcache_interfaces.h"
+
+namespace content {
+
+class AppCacheFrontendImpl : public appcache::AppCacheFrontend {
+ public:
+  virtual void OnCacheSelected(int host_id,
+                               const appcache::AppCacheInfo& info) OVERRIDE;
+  virtual void OnStatusChanged(const std::vector<int>& host_ids,
+                               appcache::Status status) OVERRIDE;
+  virtual void OnEventRaised(const std::vector<int>& host_ids,
+                             appcache::EventID event_id) OVERRIDE;
+  virtual void OnProgressEventRaised(const std::vector<int>& host_ids,
+                                     const GURL& url,
+                                     int num_total,
+                                     int num_complete) OVERRIDE;
+  virtual void OnErrorEventRaised(const std::vector<int>& host_ids,
+                                  const std::string& message) OVERRIDE;
+  virtual void OnLogMessage(int host_id,
+                            appcache::LogLevel log_level,
+                            const std::string& message) OVERRIDE;
+  virtual void OnContentBlocked(int host_id, const GURL& manifest_url) OVERRIDE;
+};
+
+}  // namespace content
+
+#endif  // CONTENT_CHILD_APPCACHE_APPCACHE_FRONTEND_IMPL_H_
diff --git a/webkit/renderer/appcache/web_application_cache_host_impl.cc b/content/child/appcache/web_application_cache_host_impl.cc
similarity index 81%
rename from webkit/renderer/appcache/web_application_cache_host_impl.cc
rename to content/child/appcache/web_application_cache_host_impl.cc
index db67df5..b4a15f3 100644
--- a/webkit/renderer/appcache/web_application_cache_host_impl.cc
+++ b/content/child/appcache/web_application_cache_host_impl.cc
@@ -1,18 +1,18 @@
-// Copyright (c) 2012 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.
 
-#include "webkit/renderer/appcache/web_application_cache_host_impl.h"
+#include "content/child/appcache/web_application_cache_host_impl.h"
 
 #include "base/compiler_specific.h"
 #include "base/id_map.h"
 #include "base/strings/string_util.h"
 #include "base/strings/stringprintf.h"
-#include "third_party/WebKit/public/web/WebDataSource.h"
-#include "third_party/WebKit/public/web/WebFrame.h"
 #include "third_party/WebKit/public/platform/WebURL.h"
 #include "third_party/WebKit/public/platform/WebURLRequest.h"
 #include "third_party/WebKit/public/platform/WebURLResponse.h"
+#include "third_party/WebKit/public/web/WebDataSource.h"
+#include "third_party/WebKit/public/web/WebFrame.h"
 
 using WebKit::WebApplicationCacheHost;
 using WebKit::WebApplicationCacheHostClient;
@@ -22,8 +22,10 @@
 using WebKit::WebURL;
 using WebKit::WebURLResponse;
 using WebKit::WebVector;
+using appcache::AppCacheBackend;
+using appcache::AppCacheResourceInfo;
 
-namespace appcache {
+namespace content {
 
 namespace {
 
@@ -72,12 +74,12 @@
     : client_(client),
       backend_(backend),
       host_id_(all_hosts()->Add(this)),
-      status_(UNCACHED),
+      status_(appcache::UNCACHED),
       is_scheme_supported_(false),
       is_get_method_(false),
       is_new_master_entry_(MAYBE),
       was_select_cache_called_(false) {
-  DCHECK(client && backend && (host_id_ != kNoHostId));
+  DCHECK(client && backend && (host_id_ != appcache::kNoHostId));
 
   backend_->RegisterHost(host_id_);
 }
@@ -98,32 +100,32 @@
 }
 
 void WebApplicationCacheHostImpl::OnEventRaised(appcache::EventID event_id) {
-  DCHECK(event_id != PROGRESS_EVENT);  // See OnProgressEventRaised.
-  DCHECK(event_id != ERROR_EVENT);  // See OnErrorEventRaised.
+  DCHECK(event_id != appcache::PROGRESS_EVENT);  // See OnProgressEventRaised.
+  DCHECK(event_id != appcache::ERROR_EVENT);  // See OnErrorEventRaised.
 
   // Emit logging output prior to calling out to script as we can get
   // deleted within the script event handler.
   const char* kFormatString = "Application Cache %s event";
   std::string message = base::StringPrintf(kFormatString,
                                            kEventNames[event_id]);
-  OnLogMessage(LOG_INFO, message);
+  OnLogMessage(appcache::LOG_INFO, message);
 
   switch (event_id) {
-    case CHECKING_EVENT:
-      status_ = CHECKING;
+    case appcache::CHECKING_EVENT:
+      status_ = appcache::CHECKING;
       break;
-    case DOWNLOADING_EVENT:
-      status_ = DOWNLOADING;
+    case appcache::DOWNLOADING_EVENT:
+      status_ = appcache::DOWNLOADING;
       break;
-    case UPDATE_READY_EVENT:
-      status_ = UPDATE_READY;
+    case appcache::UPDATE_READY_EVENT:
+      status_ = appcache::UPDATE_READY;
       break;
-    case CACHED_EVENT:
-    case NO_UPDATE_EVENT:
-      status_ = IDLE;
+    case appcache::CACHED_EVENT:
+    case appcache::NO_UPDATE_EVENT:
+      status_ = appcache::IDLE;
       break;
-    case OBSOLETE_EVENT:
-      status_ = OBSOLETE;
+    case appcache::OBSOLETE_EVENT:
+      status_ = appcache::OBSOLETE;
       break;
     default:
       NOTREACHED();
@@ -140,8 +142,8 @@
   const char* kFormatString = "Application Cache Progress event (%d of %d) %s";
   std::string message = base::StringPrintf(kFormatString, num_complete,
                                            num_total, url.spec().c_str());
-  OnLogMessage(LOG_INFO, message);
-  status_ = DOWNLOADING;
+  OnLogMessage(appcache::LOG_INFO, message);
+  status_ = appcache::DOWNLOADING;
   client_->notifyProgressEventListener(url, num_total, num_complete);
 }
 
@@ -152,10 +154,10 @@
   const char* kFormatString = "Application Cache Error event: %s";
   std::string full_message = base::StringPrintf(kFormatString,
                                                 message.c_str());
-  OnLogMessage(LOG_ERROR, full_message);
+  OnLogMessage(appcache::LOG_ERROR, full_message);
 
-  status_ = cache_info_.is_complete ? IDLE : UNCACHED;
-  client_->notifyEventListener(static_cast<EventID>(ERROR_EVENT));
+  status_ = cache_info_.is_complete ? appcache::IDLE : appcache::UNCACHED;
+  client_->notifyEventListener(static_cast<EventID>(appcache::ERROR_EVENT));
 }
 
 void WebApplicationCacheHostImpl::willStartMainResourceRequest(
@@ -165,7 +167,7 @@
   original_main_resource_url_ = ClearUrlRef(request.url());
 
   std::string method = request.httpMethod().utf8();
-  is_get_method_ = (method == kHttpGETMethod);
+  is_get_method_ = (method == appcache::kHttpGETMethod);
   DCHECK(method == StringToUpperASCII(method));
 
   if (frame) {
@@ -177,7 +179,7 @@
 
     WebApplicationCacheHostImpl* spawning_host = FromFrame(spawning_frame);
     if (spawning_host && (spawning_host != this) &&
-        (spawning_host->status_ != UNCACHED)) {
+        (spawning_host->status_ != appcache::UNCACHED)) {
       backend_->SetSpawningHostId(host_id_, spawning_host->host_id());
     }
   }
@@ -193,8 +195,8 @@
     return;
   was_select_cache_called_ = true;
 
-  status_ = (document_response_.appCacheID() == kNoCacheId) ?
-      UNCACHED : CHECKING;
+  status_ = (document_response_.appCacheID() == appcache::kNoCacheId) ?
+      appcache::UNCACHED : appcache::CHECKING;
   is_new_master_entry_ = NO;
   backend_->SelectCache(host_id_, document_url_,
                         document_response_.appCacheID(),
@@ -211,18 +213,18 @@
 
   // 6.9.6 The application cache selection algorithm
   // Check for new 'master' entries.
-  if (document_response_.appCacheID() == kNoCacheId) {
+  if (document_response_.appCacheID() == appcache::kNoCacheId) {
     if (is_scheme_supported_ && is_get_method_ &&
         (manifest_gurl.GetOrigin() == document_url_.GetOrigin())) {
-      status_ = CHECKING;
+      status_ = appcache::CHECKING;
       is_new_master_entry_ = YES;
     } else {
-      status_ = UNCACHED;
+      status_ = appcache::UNCACHED;
       is_new_master_entry_ = NO;
       manifest_gurl = GURL();
     }
-    backend_->SelectCache(host_id_, document_url_,
-                          kNoCacheId, manifest_gurl);
+    backend_->SelectCache(
+        host_id_, document_url_, appcache::kNoCacheId, manifest_gurl);
     return true;
   }
 
@@ -234,11 +236,11 @@
   if (document_manifest_gurl != manifest_gurl) {
     backend_->MarkAsForeignEntry(host_id_, document_url_,
                                  document_response_.appCacheID());
-    status_ = UNCACHED;
+    status_ = appcache::UNCACHED;
     return false;  // the navigation will be restarted
   }
 
-  status_ = CHECKING;
+  status_ = appcache::CHECKING;
 
   // Its a 'master' entry thats already in the cache.
   backend_->SelectCache(host_id_, document_url_,
@@ -255,8 +257,8 @@
     is_get_method_ = true;  // A redirect was involved.
   original_main_resource_url_ = GURL();
 
-  is_scheme_supported_ =  IsSchemeSupported(document_url_);
-  if ((document_response_.appCacheID() != kNoCacheId) ||
+  is_scheme_supported_ =  appcache::IsSchemeSupported(document_url_);
+  if ((document_response_.appCacheID() != appcache::kNoCacheId) ||
       !is_scheme_supported_ || !is_get_method_)
     is_new_master_entry_ = NO;
 }
@@ -281,8 +283,8 @@
 bool WebApplicationCacheHostImpl::startUpdate() {
   if (!backend_->StartUpdate(host_id_))
     return false;
-  if (status_ == IDLE || status_ == UPDATE_READY)
-    status_ = CHECKING;
+  if (status_ == appcache::IDLE || status_ == appcache::UPDATE_READY)
+    status_ = appcache::CHECKING;
   else
     status_ = backend_->GetStatus(host_id_);
   return true;
@@ -325,4 +327,4 @@
   resources->swap(web_resources);
 }
 
-}  // appcache namespace
+}  // namespace content
diff --git a/webkit/renderer/appcache/web_application_cache_host_impl.h b/content/child/appcache/web_application_cache_host_impl.h
similarity index 78%
rename from webkit/renderer/appcache/web_application_cache_host_impl.h
rename to content/child/appcache/web_application_cache_host_impl.h
index 752ad83..c0cdea9 100644
--- a/webkit/renderer/appcache/web_application_cache_host_impl.h
+++ b/content/child/appcache/web_application_cache_host_impl.h
@@ -1,9 +1,9 @@
-// Copyright (c) 2011 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.
 
-#ifndef WEBKIT_RENDERER_APPCACHE_WEB_APPLICATION_CACHE_HOST_IMPL_H_
-#define WEBKIT_RENDERER_APPCACHE_WEB_APPLICATION_CACHE_HOST_IMPL_H_
+#ifndef CONTENT_CHILD_APPCACHE_WEB_APPLICATION_CACHE_HOST_IMPL_H_
+#define CONTENT_CHILD_APPCACHE_WEB_APPLICATION_CACHE_HOST_IMPL_H_
 
 #include <string>
 
@@ -12,15 +12,14 @@
 #include "third_party/WebKit/public/web/WebApplicationCacheHostClient.h"
 #include "url/gurl.h"
 #include "webkit/common/appcache/appcache_interfaces.h"
-#include "webkit/renderer/webkit_storage_renderer_export.h"
 
 namespace WebKit {
 class WebFrame;
 }
 
-namespace appcache {
+namespace content {
 
-class WEBKIT_STORAGE_RENDERER_EXPORT WebApplicationCacheHostImpl
+class WebApplicationCacheHostImpl
     : NON_EXPORTED_BASE(public WebKit::WebApplicationCacheHost) {
  public:
   // Returns the host having given id or NULL if there is no such host.
@@ -30,11 +29,11 @@
   static WebApplicationCacheHostImpl* FromFrame(const WebKit::WebFrame* frame);
 
   WebApplicationCacheHostImpl(WebKit::WebApplicationCacheHostClient* client,
-                              AppCacheBackend* backend);
+                              appcache::AppCacheBackend* backend);
   virtual ~WebApplicationCacheHostImpl();
 
   int host_id() const { return host_id_; }
-  AppCacheBackend* backend() const { return backend_; }
+  appcache::AppCacheBackend* backend() const { return backend_; }
   WebKit::WebApplicationCacheHostClient* client() const { return client_; }
 
   virtual void OnCacheSelected(const appcache::AppCacheInfo& info);
@@ -42,10 +41,11 @@
   void OnEventRaised(appcache::EventID);
   void OnProgressEventRaised(const GURL& url, int num_total, int num_complete);
   void OnErrorEventRaised(const std::string& message);
-  virtual void OnLogMessage(LogLevel log_level, const std::string& message) {}
+  virtual void OnLogMessage(appcache::LogLevel log_level,
+                            const std::string& message) {}
   virtual void OnContentBlocked(const GURL& manifest_url) {}
 
-  // WebApplicationCacheHost methods
+  // WebKit::WebApplicationCacheHost:
   virtual void willStartMainResourceRequest(WebKit::WebURLRequest&,
                                             const WebKit::WebFrame*);
   virtual void willStartSubResourceRequest(WebKit::WebURLRequest&);
@@ -68,7 +68,7 @@
   };
 
   WebKit::WebApplicationCacheHostClient* client_;
-  AppCacheBackend* backend_;
+  appcache::AppCacheBackend* backend_;
   int host_id_;
   appcache::Status status_;
   WebKit::WebURLResponse document_response_;
@@ -81,6 +81,6 @@
   bool was_select_cache_called_;
 };
 
-}  // namespace
+}  // namespace content
 
-#endif  // WEBKIT_RENDERER_APPCACHE_WEB_APPLICATION_CACHE_HOST_IMPL_H_
+#endif  // CONTENT_CHILD_APPCACHE_WEB_APPLICATION_CACHE_HOST_IMPL_H_
diff --git a/content/child/npapi/plugin_instance.cc b/content/child/npapi/plugin_instance.cc
index ac4c8b4..c279b9b 100644
--- a/content/child/npapi/plugin_instance.cc
+++ b/content/child/npapi/plugin_instance.cc
@@ -16,8 +16,8 @@
 #include "content/child/npapi/plugin_string_stream.h"
 #include "content/child/npapi/webplugin.h"
 #include "content/child/npapi/webplugin_delegate.h"
+#include "content/public/common/content_constants.h"
 #include "net/base/escape.h"
-#include "webkit/plugins/plugin_constants.h"
 
 #if defined(OS_MACOSX)
 #include <ApplicationServices/ApplicationServices.h>
diff --git a/content/child/npapi/webplugin_delegate_impl_gtk.cc b/content/child/npapi/webplugin_delegate_impl_gtk.cc
index 9b608b9..36906c5 100644
--- a/content/child/npapi/webplugin_delegate_impl_gtk.cc
+++ b/content/child/npapi/webplugin_delegate_impl_gtk.cc
@@ -13,12 +13,12 @@
 #include "base/metrics/stats_counters.h"
 #include "content/child/npapi/plugin_instance.h"
 #include "content/child/npapi/webplugin.h"
+#include "content/public/common/content_constants.h"
 #include "skia/ext/platform_canvas.h"
 #include "third_party/WebKit/public/web/WebInputEvent.h"
 #include "ui/base/gtk/gtk_compat.h"
 #include "ui/gfx/blit.h"
 #include "webkit/common/cursors/webcursor.h"
-#include "webkit/plugins/plugin_constants.h"
 
 #include "third_party/npapi/bindings/npapi_x11.h"
 
diff --git a/content/child/npapi/webplugin_delegate_impl_win.cc b/content/child/npapi/webplugin_delegate_impl_win.cc
index 1ac124f..01f2100 100644
--- a/content/child/npapi/webplugin_delegate_impl_win.cc
+++ b/content/child/npapi/webplugin_delegate_impl_win.cc
@@ -28,12 +28,12 @@
 #include "content/child/npapi/webplugin.h"
 #include "content/child/npapi/webplugin_ime_win.h"
 #include "content/common/plugin_constants_win.h"
+#include "content/public/common/content_constants.h"
 #include "skia/ext/platform_canvas.h"
 #include "third_party/WebKit/public/web/WebInputEvent.h"
 #include "ui/base/win/dpi.h"
 #include "ui/base/win/hwnd_util.h"
 #include "webkit/common/cursors/webcursor.h"
-#include "webkit/plugins/plugin_constants.h"
 
 using WebKit::WebKeyboardEvent;
 using WebKit::WebInputEvent;
@@ -947,10 +947,10 @@
     // Get the invalid rect which is in screen coordinates and convert to
     // window coordinates.
     gfx::Rect invalid_rect;
-    invalid_rect.set_x(wparam >> 16);
-    invalid_rect.set_y(wparam & 0xFFFF);
-    invalid_rect.set_width(lparam >> 16);
-    invalid_rect.set_height(lparam & 0xFFFF);
+    invalid_rect.set_x(static_cast<short>(LOWORD(wparam)));
+    invalid_rect.set_y(static_cast<short>(HIWORD(wparam)));
+    invalid_rect.set_width(static_cast<short>(LOWORD(lparam)));
+    invalid_rect.set_height(static_cast<short>(HIWORD(lparam)));
 
     RECT window_rect;
     GetWindowRect(hwnd, &window_rect);
diff --git a/content/child/power_monitor_broadcast_source_unittest.cc b/content/child/power_monitor_broadcast_source_unittest.cc
index 0d09f60..b665e90 100644
--- a/content/child/power_monitor_broadcast_source_unittest.cc
+++ b/content/child/power_monitor_broadcast_source_unittest.cc
@@ -3,7 +3,7 @@
 // found in the LICENSE file.
 
 #include "base/message_loop/message_loop.h"
-#include "base/power_monitor/power_monitor_test_base.h"
+#include "base/test/power_monitor_test_base.h"
 #include "content/child/power_monitor_broadcast_source.h"
 #include "content/common/power_monitor_messages.h"
 #include "testing/gtest/include/gtest/gtest.h"
diff --git a/content/child/runtime_features.cc b/content/child/runtime_features.cc
index ec8f617..5c74ca6 100644
--- a/content/child/runtime_features.cc
+++ b/content/child/runtime_features.cc
@@ -132,6 +132,9 @@
 
   if (command_line.HasSwitch(switches::kEnableWebGLDraftExtensions))
     WebRuntimeFeatures::enableWebGLDraftExtensions(true);
+
+  if (command_line.HasSwitch(switches::kEnableHTMLImports))
+    WebRuntimeFeatures::enableHTMLImports(true);
 }
 
 }  // namespace content
diff --git a/content/common/browser_plugin/browser_plugin_constants.cc b/content/common/browser_plugin/browser_plugin_constants.cc
index bd20b85..691366b 100644
--- a/content/common/browser_plugin/browser_plugin_constants.cc
+++ b/content/common/browser_plugin/browser_plugin_constants.cc
@@ -47,16 +47,13 @@
 const char kEventDialog[] = "dialog";
 const char kEventNewWindow[] = "newwindow";
 const char kEventRequestPermission[] = "permissionrequest";
-const char kEventResponsive[] = "responsive";
 const char kEventSizeChanged[] = "sizechanged";
-const char kEventUnresponsive[] = "unresponsive";
 
 // Parameters/properties on events.
 const char kDefaultPromptText[] = "defaultPromptText";
 const char kId[] = "id";
 const char kInitialHeight[] = "initialHeight";
 const char kInitialWidth[] = "initialWidth";
-const char kIsTopLevel[] = "isTopLevel";
 const char kLastUnlockedBySelf[] = "lastUnlockedBySelf";
 const char kMessageText[] = "messageText";
 const char kMessageType[] = "messageType";
diff --git a/content/common/browser_plugin/browser_plugin_constants.h b/content/common/browser_plugin/browser_plugin_constants.h
index ba8dd06..a411741 100644
--- a/content/common/browser_plugin/browser_plugin_constants.h
+++ b/content/common/browser_plugin/browser_plugin_constants.h
@@ -56,7 +56,6 @@
 extern const char kId[];
 extern const char kInitialHeight[];
 extern const char kInitialWidth[];
-extern const char kIsTopLevel[];
 extern const char kLastUnlockedBySelf[];
 extern const char kMessageText[];
 extern const char kMessageType[];
diff --git a/content/common/content_constants_internal.cc b/content/common/content_constants_internal.cc
index c2bcaff..f5da70e 100644
--- a/content/common/content_constants_internal.cc
+++ b/content/common/content_constants_internal.cc
@@ -8,6 +8,10 @@
 
 const int kHungRendererDelayMs = 30000;
 
+const uint16 kMaxPluginSideLength = 1 << 15;
+// 8m pixels.
+const uint32 kMaxPluginSize = 8 << 20;
+
 const int kTraceEventBrowserProcessSortIndex = -6;
 const int kTraceEventRendererProcessSortIndex = -5;
 const int kTraceEventPluginProcessSortIndex = -4;
diff --git a/content/common/content_constants_internal.h b/content/common/content_constants_internal.h
index ddb082f..55a2ade 100644
--- a/content/common/content_constants_internal.h
+++ b/content/common/content_constants_internal.h
@@ -5,6 +5,7 @@
 #ifndef CONTENT_COMMON_CONTENT_CONSTANTS_INTERNAL_H_
 #define CONTENT_COMMON_CONTENT_CONSTANTS_INTERNAL_H_
 
+#include "base/basictypes.h"
 #include "content/common/content_export.h"
 
 namespace content {
@@ -12,6 +13,12 @@
 // How long to wait before we consider a renderer hung.
 CONTENT_EXPORT extern const int kHungRendererDelayMs;
 
+// The maximum plugin width and height.
+extern const uint16 kMaxPluginSideLength;
+// The maximum plugin size, defined as the number of pixels occupied by the
+// plugin.
+extern const uint32 kMaxPluginSize;
+
 // Constants used to organize content processes in about:tracing.
 CONTENT_EXPORT extern const int kTraceEventBrowserProcessSortIndex;
 CONTENT_EXPORT extern const int kTraceEventRendererProcessSortIndex;
diff --git a/content/common/gpu/media/exynos_video_decode_accelerator.cc b/content/common/gpu/media/exynos_video_decode_accelerator.cc
index 6817ca9..677df9c 100644
--- a/content/common/gpu/media/exynos_video_decode_accelerator.cc
+++ b/content/common/gpu/media/exynos_video_decode_accelerator.cc
@@ -50,6 +50,11 @@
 
 namespace {
 
+// TODO(posciak): remove once we update linux-headers.
+#ifndef V4L2_EVENT_RESOLUTION_CHANGE
+#define V4L2_EVENT_RESOLUTION_CHANGE 5
+#endif
+
 const char kExynosMfcDevice[] = "/dev/mfc-dec";
 const char kExynosGscDevice[] = "/dev/gsc1";
 const char kMaliDriver[] = "libmali.so";
@@ -212,6 +217,8 @@
       decoder_decode_buffer_tasks_scheduled_(0),
       decoder_frames_at_client_(0),
       decoder_flushing_(false),
+      resolution_change_pending_(false),
+      resolution_change_reset_pending_(false),
       decoder_partial_frame_pending_(false),
       mfc_fd_(-1),
       mfc_input_streamon_(false),
@@ -379,6 +386,12 @@
   format.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_NV12MT_16X16;
   IOCTL_OR_ERROR_RETURN_FALSE(mfc_fd_, VIDIOC_S_FMT, &format);
 
+  // Subscribe to the resolution change event.
+  struct v4l2_event_subscription sub;
+  memset(&sub, 0, sizeof(sub));
+  sub.type = V4L2_EVENT_RESOLUTION_CHANGE;
+  IOCTL_OR_ERROR_RETURN_FALSE(mfc_fd_, VIDIOC_SUBSCRIBE_EVENT, &sub);
+
   // Initialize format-specific bits.
   if (video_profile_ >= media::H264PROFILE_MIN &&
       video_profile_ <= media::H264PROFILE_MAX) {
@@ -637,6 +650,9 @@
   } else if (decoder_state_ == kError) {
     DVLOG(2) << "DecodeBufferTask(): early out: kError state";
     return;
+  } else if (decoder_state_ == kChangingResolution) {
+    DVLOG(2) << "DecodeBufferTask(): early out: resolution change pending";
+    return;
   }
 
   if (decoder_current_bitstream_buffer_ == NULL) {
@@ -862,35 +878,21 @@
 
   // Check and see if we have format info yet.
   struct v4l2_format format;
-  format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
-  if (ioctl(mfc_fd_, VIDIOC_G_FMT, &format) != 0) {
-    if (errno == EINVAL) {
-      // We will get EINVAL if we haven't seen sufficient stream to decode the
-      // format.  Return true and schedule the next buffer.
-      *endpos = size;
-      return true;
-    } else {
-      DPLOG(ERROR) << "DecodeBufferInitial(): ioctl() failed: VIDIOC_G_FMT";
-      NOTIFY_ERROR(PLATFORM_FAILURE);
-      return false;
-    }
+  bool again = false;
+  if (!GetFormatInfo(&format, &again))
+    return false;
+
+  if (again) {
+    // Need more stream to decode format, return true and schedule next buffer.
+    *endpos = size;
+    return true;
   }
 
   // Run this initialization only on first startup.
   if (decoder_state_ == kInitialized) {
-    DVLOG(3) << "DecodeBufferInitial(): running one-time initialization";
+    DVLOG(3) << "DecodeBufferInitial(): running initialization";
     // Success! Setup our parameters.
-    CHECK_EQ(format.fmt.pix_mp.num_planes, 2);
-    frame_buffer_size_.SetSize(
-        format.fmt.pix_mp.width, format.fmt.pix_mp.height);
-    mfc_output_buffer_size_[0] = format.fmt.pix_mp.plane_fmt[0].sizeimage;
-    mfc_output_buffer_size_[1] = format.fmt.pix_mp.plane_fmt[1].sizeimage;
-    mfc_output_buffer_pixelformat_ = format.fmt.pix_mp.pixelformat;
-    DCHECK_EQ(mfc_output_buffer_pixelformat_, V4L2_PIX_FMT_NV12MT_16X16);
-
-    // Create our other buffers.
-    if (!CreateMfcOutputBuffers() || !CreateGscInputBuffers() ||
-        !CreateGscOutputBuffers())
+    if (!CreateBuffersForFormat(format))
       return false;
 
     // MFC expects to process the initial buffer once during stream init to
@@ -1064,9 +1066,12 @@
 
   // We got buffers!  Kick the GSC.
   EnqueueGsc();
+
+  if (decoder_state_ == kChangingResolution)
+    ResumeAfterResolutionChange();
 }
 
-void ExynosVideoDecodeAccelerator::ServiceDeviceTask() {
+void ExynosVideoDecodeAccelerator::ServiceDeviceTask(bool mfc_event_pending) {
   DVLOG(3) << "ServiceDeviceTask()";
   DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current());
   DCHECK_NE(decoder_state_, kUninitialized);
@@ -1080,8 +1085,13 @@
   } else if (decoder_state_ == kError) {
     DVLOG(2) << "ServiceDeviceTask(): early out: kError state";
     return;
+  } else if (decoder_state_ == kChangingResolution) {
+    DVLOG(2) << "ServiceDeviceTask(): early out: kChangingResolution state";
+    return;
   }
 
+  if (mfc_event_pending)
+    DequeueMfcEvents();
   DequeueMfc();
   DequeueGsc();
   EnqueueMfc();
@@ -1133,6 +1143,7 @@
            << decoder_frames_at_client_ << "]";
 
   ScheduleDecodeBufferTaskIfNeeded();
+  StartResolutionChangeIfNeeded();
 }
 
 void ExynosVideoDecodeAccelerator::EnqueueMfc() {
@@ -1180,6 +1191,26 @@
   }
 }
 
+void ExynosVideoDecodeAccelerator::DequeueMfcEvents() {
+  DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current());
+  DCHECK_EQ(decoder_state_, kDecoding);
+  DVLOG(3) << "DequeueMfcEvents()";
+
+  struct v4l2_event ev;
+  memset(&ev, 0, sizeof(ev));
+
+  while (ioctl(mfc_fd_, VIDIOC_DQEVENT, &ev) == 0) {
+    if (ev.type == V4L2_EVENT_RESOLUTION_CHANGE) {
+      DVLOG(3) << "DequeueMfcEvents(): got resolution change event.";
+      DCHECK(!resolution_change_pending_);
+      resolution_change_pending_ = true;
+    } else {
+      DLOG(FATAL) << "DequeueMfcEvents(): got an event (" << ev.type
+                  << ") we haven't subscribed to.";
+    }
+  }
+}
+
 void ExynosVideoDecodeAccelerator::DequeueMfc() {
   DVLOG(3) << "DequeueMfc()";
   DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current());
@@ -1538,6 +1569,11 @@
     return;
   }
 
+  if (decoder_state_ == kChangingResolution) {
+    DVLOG(2) << "ReusePictureBufferTask(): early out: kChangingResolution";
+    return;
+  }
+
   size_t index;
   for (index = 0; index < gsc_output_buffer_map_.size(); ++index)
     if (gsc_output_buffer_map_[index].picture_id == picture_buffer_id)
@@ -1619,6 +1655,21 @@
        gsc_input_buffer_queued_count_ + gsc_output_buffer_queued_count_ ) != 0)
     return;
 
+  // TODO(posciak): crbug.com/270039. MFC requires a streamoff-streamon
+  // sequence after flush to continue, even if we are not resetting. This would
+  // make sense, because we don't really want to resume from a non-resume point
+  // (e.g. not from an IDR) if we are flushed.
+  // MSE player however triggers a Flush() on chunk end, but never Reset(). One
+  // could argue either way, or even say that Flush() is not needed/harmful when
+  // transitioning to next chunk.
+  // For now, do the streamoff-streamon cycle to satisfy MFC and not freeze when
+  // doing MSE. This should be harmless otherwise.
+  if (!StopDevicePoll(false))
+    return;
+
+  if (!StartDevicePoll())
+    return;
+
   decoder_delay_bitstream_buffer_id_ = -1;
   decoder_flushing_ = false;
   DVLOG(3) << "NotifyFlushDoneIfNeeded(): returning flush";
@@ -1639,10 +1690,25 @@
     return;
   }
 
-  // We stop streaming, but we _don't_ destroy our buffers.
-  if (!StopDevicePoll())
+  // If we are in the middle of switching resolutions, postpone reset until
+  // it's done. We don't have to worry about timing of this wrt to decoding,
+  // because MFC input pipe is already stopped if we are changing resolution.
+  // We will come back here after we are done with the resolution change.
+  DCHECK(!resolution_change_reset_pending_);
+  if (resolution_change_pending_ || decoder_state_ == kChangingResolution) {
+    resolution_change_reset_pending_ = true;
+    return;
+  }
+
+  // We stop streaming and clear buffer tracking info (not preserving
+  // MFC inputs).
+  // StopDevicePoll() unconditionally does _not_ destroy buffers, however.
+  if (!StopDevicePoll(false))
     return;
 
+  DequeueMfcEvents();
+
+  resolution_change_pending_ = false;
   decoder_current_bitstream_buffer_.reset();
   decoder_input_queue_.clear();
 
@@ -1694,7 +1760,7 @@
   // DestroyTask() should run regardless of decoder_state_.
 
   // Stop streaming and the device_poll_thread_.
-  StopDevicePoll();
+  StopDevicePoll(false);
 
   decoder_current_bitstream_buffer_.reset();
   decoder_current_input_buffer_ = -1;
@@ -1726,7 +1792,7 @@
   return true;
 }
 
-bool ExynosVideoDecodeAccelerator::StopDevicePoll() {
+bool ExynosVideoDecodeAccelerator::StopDevicePoll(bool keep_mfc_input_state) {
   DVLOG(3) << "StopDevicePoll()";
   DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current());
 
@@ -1739,11 +1805,13 @@
     return false;
 
   // Stop streaming.
-  if (mfc_input_streamon_) {
-    __u32 type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
-    IOCTL_OR_ERROR_RETURN_FALSE(mfc_fd_, VIDIOC_STREAMOFF, &type);
+  if (!keep_mfc_input_state) {
+    if (mfc_input_streamon_) {
+      __u32 type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
+      IOCTL_OR_ERROR_RETURN_FALSE(mfc_fd_, VIDIOC_STREAMOFF, &type);
+    }
+    mfc_input_streamon_ = false;
   }
-  mfc_input_streamon_ = false;
   if (mfc_output_streamon_) {
     __u32 type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
     IOCTL_OR_ERROR_RETURN_FALSE(mfc_fd_, VIDIOC_STREAMOFF, &type);
@@ -1761,15 +1829,17 @@
   gsc_output_streamon_ = false;
 
   // Reset all our accounting info.
-  mfc_input_ready_queue_.clear();
-  mfc_free_input_buffers_.clear();
-  for (size_t i = 0; i < mfc_input_buffer_map_.size(); ++i) {
-    mfc_free_input_buffers_.push_back(i);
-    mfc_input_buffer_map_[i].at_device = false;
-    mfc_input_buffer_map_[i].bytes_used = 0;
-    mfc_input_buffer_map_[i].input_id = -1;
+  if (!keep_mfc_input_state) {
+    mfc_input_ready_queue_.clear();
+    mfc_free_input_buffers_.clear();
+    for (size_t i = 0; i < mfc_input_buffer_map_.size(); ++i) {
+      mfc_free_input_buffers_.push_back(i);
+      mfc_input_buffer_map_[i].at_device = false;
+      mfc_input_buffer_map_[i].bytes_used = 0;
+      mfc_input_buffer_map_[i].input_id = -1;
+    }
+    mfc_input_buffer_queued_count_ = 0;
   }
-  mfc_input_buffer_queued_count_ = 0;
   mfc_free_output_buffers_.clear();
   for (size_t i = 0; i < mfc_output_buffer_map_.size(); ++i) {
     mfc_free_output_buffers_.push_back(i);
@@ -1830,6 +1900,84 @@
   return true;
 }
 
+void ExynosVideoDecodeAccelerator::StartResolutionChangeIfNeeded() {
+  DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current());
+  DCHECK_EQ(decoder_state_, kDecoding);
+
+  if (!resolution_change_pending_)
+    return;
+
+  if (!mfc_output_gsc_input_queue_.empty() ||
+      gsc_input_buffer_queued_count_ + gsc_output_buffer_queued_count_ > 0) {
+    DVLOG(3) << "StartResolutionChangeIfNeeded(): waiting for GSC to finish.";
+    return;
+  }
+
+  DVLOG(3) << "No more work for GSC, initiate resolution change";
+
+  // Keep MFC input queue.
+  if (!StopDevicePoll(true))
+    return;
+
+  decoder_state_ = kChangingResolution;
+  DCHECK(resolution_change_pending_);
+  resolution_change_pending_ = false;
+
+  // Post a task to clean up buffers on child thread. This will also ensure
+  // that we won't accept ReusePictureBuffer() anymore after that.
+  child_message_loop_proxy_->PostTask(FROM_HERE, base::Bind(
+      &ExynosVideoDecodeAccelerator::ResolutionChangeDestroyBuffers,
+      weak_this_));
+}
+
+void ExynosVideoDecodeAccelerator::FinishResolutionChange() {
+  DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current());
+  DVLOG(3) << "FinishResolutionChange()";
+
+  if (decoder_state_ == kError) {
+    DVLOG(2) << "FinishResolutionChange(): early out: kError state";
+    return;
+  }
+
+  struct v4l2_format format;
+  bool again;
+  bool ret = GetFormatInfo(&format, &again);
+  if (!ret || again) {
+    DVLOG(3) << "Couldn't get format information after resolution change";
+    NOTIFY_ERROR(PLATFORM_FAILURE);
+    return;
+  }
+
+  if (!CreateBuffersForFormat(format)) {
+    DVLOG(3) << "Couldn't reallocate buffers after resolution change";
+    NOTIFY_ERROR(PLATFORM_FAILURE);
+    return;
+  }
+
+  // From here we stay in kChangingResolution and wait for
+  // AssignPictureBuffers() before we can resume.
+}
+
+void ExynosVideoDecodeAccelerator::ResumeAfterResolutionChange() {
+  DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current());
+  DVLOG(3) << "ResumeAfterResolutionChange()";
+
+  decoder_state_ = kDecoding;
+
+  if (resolution_change_reset_pending_) {
+    resolution_change_reset_pending_ = false;
+    ResetTask();
+    return;
+  }
+
+  if (!StartDevicePoll())
+    return;
+
+  EnqueueMfc();
+  // Gsc will get enqueued in AssignPictureBuffersTask().
+  ScheduleDecodeBufferTaskIfNeeded();
+}
+
 void ExynosVideoDecodeAccelerator::DevicePollTask(unsigned int poll_fds) {
   DVLOG(3) << "DevicePollTask()";
   DCHECK_EQ(device_poll_thread_.message_loop(), base::MessageLoop::current());
@@ -1841,6 +1989,7 @@
   // device_poll_interrupt_fd_.
   struct pollfd pollfds[3];
   nfds_t nfds;
+  int mfc_pollfd = -1;
 
   // Add device_poll_interrupt_fd_;
   pollfds[0].fd = device_poll_interrupt_fd_;
@@ -1850,7 +1999,8 @@
   if (poll_fds & kPollMfc) {
     DVLOG(3) << "DevicePollTask(): adding MFC to poll() set";
     pollfds[nfds].fd = mfc_fd_;
-    pollfds[nfds].events = POLLIN | POLLOUT | POLLERR;
+    pollfds[nfds].events = POLLIN | POLLOUT | POLLERR | POLLPRI;
+    mfc_pollfd = nfds;
     nfds++;
   }
   // Add GSC fd, if we should poll on it.
@@ -1869,11 +2019,14 @@
     return;
   }
 
+  bool mfc_event_pending = (mfc_pollfd != -1 &&
+                            pollfds[mfc_pollfd].revents & POLLPRI);
+
   // All processing should happen on ServiceDeviceTask(), since we shouldn't
   // touch decoder state from this thread.
   decoder_thread_.message_loop()->PostTask(FROM_HERE, base::Bind(
       &ExynosVideoDecodeAccelerator::ServiceDeviceTask,
-      base::Unretained(this)));
+      base::Unretained(this), mfc_event_pending));
 }
 
 void ExynosVideoDecodeAccelerator::NotifyError(Error error) {
@@ -1906,6 +2059,48 @@
   }
 }
 
+bool ExynosVideoDecodeAccelerator::GetFormatInfo(struct v4l2_format* format,
+                                                 bool* again) {
+  DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current());
+
+  *again = false;
+  memset(format, 0, sizeof(*format));
+  format->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
+  if (HANDLE_EINTR(ioctl(mfc_fd_, VIDIOC_G_FMT, format)) != 0) {
+    if (errno == EINVAL) {
+      // EINVAL means we haven't seen sufficient stream to decode the format.
+      *again = true;
+      return true;
+    } else {
+      DPLOG(ERROR) << "DecodeBufferInitial(): ioctl() failed: VIDIOC_G_FMT";
+      NOTIFY_ERROR(PLATFORM_FAILURE);
+      return false;
+    }
+  }
+
+  return true;
+}
+
+bool ExynosVideoDecodeAccelerator::CreateBuffersForFormat(
+    const struct v4l2_format& format) {
+  DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current());
+  CHECK_EQ(format.fmt.pix_mp.num_planes, 2);
+  frame_buffer_size_.SetSize(
+      format.fmt.pix_mp.width, format.fmt.pix_mp.height);
+  mfc_output_buffer_size_[0] = format.fmt.pix_mp.plane_fmt[0].sizeimage;
+  mfc_output_buffer_size_[1] = format.fmt.pix_mp.plane_fmt[1].sizeimage;
+  mfc_output_buffer_pixelformat_ = format.fmt.pix_mp.pixelformat;
+  DCHECK_EQ(mfc_output_buffer_pixelformat_, V4L2_PIX_FMT_NV12MT_16X16);
+  DVLOG(3) << "CreateBuffersForFormat(): new resolution: "
+           << frame_buffer_size_.ToString();
+
+  if (!CreateMfcOutputBuffers() || !CreateGscInputBuffers() ||
+      !CreateGscOutputBuffers())
+    return false;
+
+  return true;
+}
+
 bool ExynosVideoDecodeAccelerator::CreateMfcInputBuffers() {
   DVLOG(3) << "CreateMfcInputBuffers()";
   // We always run this as we prepare to initialize.
@@ -1969,7 +2164,8 @@
 
 bool ExynosVideoDecodeAccelerator::CreateMfcOutputBuffers() {
   DVLOG(3) << "CreateMfcOutputBuffers()";
-  DCHECK_EQ(decoder_state_, kInitialized);
+  DCHECK(decoder_state_ == kInitialized ||
+         decoder_state_ == kChangingResolution);
   DCHECK(!mfc_output_streamon_);
   DCHECK(mfc_output_buffer_map_.empty());
 
@@ -2026,7 +2222,8 @@
 
 bool ExynosVideoDecodeAccelerator::CreateGscInputBuffers() {
   DVLOG(3) << "CreateGscInputBuffers()";
-  DCHECK_EQ(decoder_state_, kInitialized);
+  DCHECK(decoder_state_ == kInitialized ||
+         decoder_state_ == kChangingResolution);
   DCHECK(!gsc_input_streamon_);
   DCHECK(gsc_input_buffer_map_.empty());
 
@@ -2089,7 +2286,8 @@
 
 bool ExynosVideoDecodeAccelerator::CreateGscOutputBuffers() {
   DVLOG(3) << "CreateGscOutputBuffers()";
-  DCHECK_EQ(decoder_state_, kInitialized);
+  DCHECK(decoder_state_ == kInitialized ||
+         decoder_state_ == kChangingResolution);
   DCHECK(!gsc_output_streamon_);
   DCHECK(gsc_output_buffer_map_.empty());
 
@@ -2216,8 +2414,11 @@
         eglDestroyImageKHR(egl_display_, output_record.egl_image);
       if (output_record.egl_sync != EGL_NO_SYNC_KHR)
         eglDestroySyncKHR(egl_display_, output_record.egl_sync);
-      if (client_)
+      if (client_) {
+        DVLOG(1) << "DestroyGscOutputBuffers(): "
+                 << "dismissing PictureBuffer id=" << output_record.picture_id;
         client_->DismissPictureBuffer(output_record.picture_id);
+      }
       ++i;
     } while (i < gsc_output_buffer_map_.size());
   }
@@ -2234,4 +2435,18 @@
   gsc_free_output_buffers_.clear();
 }
 
+void ExynosVideoDecodeAccelerator::ResolutionChangeDestroyBuffers() {
+  DCHECK(child_message_loop_proxy_->BelongsToCurrentThread());
+  DVLOG(3) << "ResolutionChangeDestroyBuffers()";
+
+  DestroyGscInputBuffers();
+  DestroyGscOutputBuffers();
+  DestroyMfcOutputBuffers();
+
+  // Finish resolution change on decoder thread.
+  decoder_thread_.message_loop()->PostTask(FROM_HERE, base::Bind(
+      &ExynosVideoDecodeAccelerator::FinishResolutionChange,
+      base::Unretained(this)));
+}
+
 }  // namespace content
diff --git a/content/common/gpu/media/exynos_video_decode_accelerator.h b/content/common/gpu/media/exynos_video_decode_accelerator.h
index b1b9375..77471402 100644
--- a/content/common/gpu/media/exynos_video_decode_accelerator.h
+++ b/content/common/gpu/media/exynos_video_decode_accelerator.h
@@ -102,6 +102,8 @@
     kDecoding,           // DecodeBufferInitial() successful; decoding frames.
     kResetting,          // Presently resetting.
     kAfterReset,         // After Reset(), ready to start decoding again.
+    kChangingResolution, // Performing resolution change, all remaining
+                         // pre-change frames decoded and processed.
     kError,              // Error in kDecoding state.
   };
 
@@ -204,13 +206,16 @@
   void AssignPictureBuffersTask(scoped_ptr<PictureBufferArrayRef> pic_buffers);
 
   // Service I/O on the V4L2 devices.  This task should only be scheduled from
-  // DevicePollTask().
-  void ServiceDeviceTask();
+  // DevicePollTask().  If |mfc_event_pending| is true, one or more events
+  // on MFC file descriptor are pending.
+  void ServiceDeviceTask(bool mfc_event_pending);
   // Handle the various device queues.
   void EnqueueMfc();
   void DequeueMfc();
   void EnqueueGsc();
   void DequeueGsc();
+  // Handle incoming MFC events.
+  void DequeueMfcEvents();
   // Enqueue a buffer on the corresponding queue.
   bool EnqueueMfcInputRecord();
   bool EnqueueMfcOutputRecord();
@@ -245,11 +250,23 @@
 
   // Attempt to start/stop device_poll_thread_.
   bool StartDevicePoll();
-  bool StopDevicePoll();
+  // If |keep_mfc_input_state| is true, don't reset MFC input state; used during
+  // resolution change.
+  bool StopDevicePoll(bool keep_mfc_input_state);
   // Set/clear the device poll interrupt (using device_poll_interrupt_fd_).
   bool SetDevicePollInterrupt();
   bool ClearDevicePollInterrupt();
 
+  void StartResolutionChangeIfNeeded();
+  void FinishResolutionChange();
+  void ResumeAfterResolutionChange();
+
+  // Try to get output format from MFC, detected after parsing the beginning
+  // of the stream. Sets |again| to true if more parsing is needed.
+  bool GetFormatInfo(struct v4l2_format* format, bool* again);
+  // Create MFC output and GSC input and output buffers for the given |format|.
+  bool CreateBuffersForFormat(const struct v4l2_format& format);
+
   //
   // Device tasks, to be run on device_poll_thread_.
   //
@@ -280,11 +297,16 @@
   bool CreateGscInputBuffers();
   bool CreateGscOutputBuffers();
 
-  // Destroy these buffers.
+  //
+  // Methods run on child thread.
+  //
+
+  // Destroy buffers.
   void DestroyMfcInputBuffers();
   void DestroyMfcOutputBuffers();
   void DestroyGscInputBuffers();
   void DestroyGscOutputBuffers();
+  void ResolutionChangeDestroyBuffers();
 
   // Our original calling message loop for the child thread.
   scoped_refptr<base::MessageLoopProxy> child_message_loop_proxy_;
@@ -331,6 +353,11 @@
   int decoder_frames_at_client_;
   // Are we flushing?
   bool decoder_flushing_;
+  // Got a notification from driver that it reached resolution change point
+  // in the stream.
+  bool resolution_change_pending_;
+  // Got a reset request while we were performing resolution change.
+  bool resolution_change_reset_pending_;
   // Input queue for decoder_thread_: BitstreamBuffers in.
   std::list<linked_ptr<BitstreamBufferRef> > decoder_input_queue_;
   // For H264 decode, hardware requires that we send it frame-sized chunks.
diff --git a/content/common/media/media_stream_messages.h b/content/common/media/media_stream_messages.h
index a388f85..8edd0e0 100644
--- a/content/common/media/media_stream_messages.h
+++ b/content/common/media/media_stream_messages.h
@@ -49,6 +49,12 @@
 IPC_MESSAGE_ROUTED1(MediaStreamMsg_StreamGenerationFailed,
                     int /* request id */)
 
+// The browser requests to stop streaming.
+// Note that this differs from MediaStreamHostMsg_StopGeneratedStream below
+// which is a request from the renderer.
+IPC_MESSAGE_ROUTED1(MediaStreamMsg_StopGeneratedStream,
+                    std::string /* label */)
+
 // The browser has enumerated devices successfully.
 // Used by Pepper.
 // TODO(vrk,wjia): Move this to pepper code.
diff --git a/content/common/plugin_list.cc b/content/common/plugin_list.cc
index 79f8cc5..69102c5 100644
--- a/content/common/plugin_list.cc
+++ b/content/common/plugin_list.cc
@@ -13,9 +13,9 @@
 #include "base/strings/string_util.h"
 #include "base/strings/sys_string_conversions.h"
 #include "base/strings/utf_string_conversions.h"
+#include "content/public/common/content_switches.h"
 #include "net/base/mime_util.h"
 #include "url/gurl.h"
-#include "webkit/plugins/plugin_switches.h"
 
 #if defined(OS_WIN)
 #include "content/common/plugin_constants_win.h"
diff --git a/content/common/sandbox_seccomp_bpf_linux.cc b/content/common/sandbox_seccomp_bpf_linux.cc
index 8216549..5d8c42a 100644
--- a/content/common/sandbox_seccomp_bpf_linux.cc
+++ b/content/common/sandbox_seccomp_bpf_linux.cc
@@ -1781,6 +1781,10 @@
   return true;
 }
 
+// Files needed by the ARM GPU userspace.
+static const char kLibGlesPath[] = "/usr/lib/libGLESv2.so.2";
+static const char kLibEglPath[] = "/usr/lib/libEGL.so.1";
+
 void AddArmMaliGpuWhitelist(std::vector<std::string>* read_whitelist,
                             std::vector<std::string>* write_whitelist) {
   // Device file needed by the ARM GPU userspace.
@@ -1831,13 +1835,11 @@
                         std::vector<std::string>* write_whitelist) {
   // On ARM we're enabling the sandbox before the X connection is made,
   // so we need to allow access to |.Xauthority|.
-  static const char kXAutorityPath[] = "/home/chronos/.Xauthority";
+  static const char kXAuthorityPath[] = "/home/chronos/.Xauthority";
+  static const char kLdSoCache[] = "/etc/ld.so.cache";
 
-  // Files needed by the ARM GPU userspace.
-  static const char kLibGlesPath[] = "/usr/lib/libGLESv2.so.2";
-  static const char kLibEglPath[] = "/usr/lib/libEGL.so.1";
-
-  read_whitelist->push_back(kXAutorityPath);
+  read_whitelist->push_back(kXAuthorityPath);
+  read_whitelist->push_back(kLdSoCache);
   read_whitelist->push_back(kLibGlesPath);
   read_whitelist->push_back(kLibEglPath);
 
@@ -1911,6 +1913,11 @@
     // Create a new broker process.
     InitGpuBrokerProcess(policy, broker_process);
 
+    // Preload the GL libraries. These are in the read whitelist but we have to
+    // preload them anyways to work around ld.so bugs. See crbug.com/268439.
+    dlopen(kLibGlesPath, RTLD_NOW|RTLD_GLOBAL|RTLD_NODELETE);
+    dlopen(kLibEglPath, RTLD_NOW|RTLD_GLOBAL|RTLD_NODELETE);
+
     // Preload the Tegra libraries.
     dlopen("/usr/lib/libnvrm.so", RTLD_NOW|RTLD_GLOBAL|RTLD_NODELETE);
     dlopen("/usr/lib/libnvrm_graphics.so", RTLD_NOW|RTLD_GLOBAL|RTLD_NODELETE);
diff --git a/content/common/url_schemes.cc b/content/common/url_schemes.cc
index c7446a3..ac8dbf4 100644
--- a/content/common/url_schemes.cc
+++ b/content/common/url_schemes.cc
@@ -38,8 +38,8 @@
   // the new tab page.
   url_util::AddStandardScheme(chrome::kChromeDevToolsScheme);
   url_util::AddStandardScheme(chrome::kChromeUIScheme);
-  url_util::AddStandardScheme(chrome::kMetadataScheme);
   url_util::AddStandardScheme(chrome::kGuestScheme);
+  url_util::AddStandardScheme(kMetadataScheme);
   std::for_each(additional_standard_schemes.begin(),
                 additional_standard_schemes.end(),
                 AddStandardSchemeHelper);
diff --git a/content/content_app_both.target.darwin-arm.mk b/content/content_app_both.target.darwin-arm.mk
index e90575c..21c2dca 100644
--- a/content/content_app_both.target.darwin-arm.mk
+++ b/content/content_app_both.target.darwin-arm.mk
@@ -91,6 +91,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -201,6 +202,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=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 292cfa3..d3ccd15 100644
--- a/content/content_app_both.target.darwin-mips.mk
+++ b/content/content_app_both.target.darwin-mips.mk
@@ -90,6 +90,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -199,6 +200,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=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 5be1f6c..1272873 100644
--- a/content/content_app_both.target.darwin-x86.mk
+++ b/content/content_app_both.target.darwin-x86.mk
@@ -92,6 +92,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -204,6 +205,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/content/content_app_both.target.linux-arm.mk b/content/content_app_both.target.linux-arm.mk
index e90575c..21c2dca 100644
--- a/content/content_app_both.target.linux-arm.mk
+++ b/content/content_app_both.target.linux-arm.mk
@@ -91,6 +91,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -201,6 +202,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=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 292cfa3..d3ccd15 100644
--- a/content/content_app_both.target.linux-mips.mk
+++ b/content/content_app_both.target.linux-mips.mk
@@ -90,6 +90,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -199,6 +200,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=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 5be1f6c..1272873 100644
--- a/content/content_app_both.target.linux-x86.mk
+++ b/content/content_app_both.target.linux-x86.mk
@@ -92,6 +92,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -204,6 +205,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/content/content_browser.gypi b/content/content_browser.gypi
index b3751ac..3396cf9 100644
--- a/content/content_browser.gypi
+++ b/content/content_browser.gypi
@@ -707,6 +707,8 @@
     'browser/media/media_internals_ui.h',
     'browser/media/webrtc_identity_store.cc',
     'browser/media/webrtc_identity_store.h',
+    'browser/media/webrtc_identity_store_backend.cc',
+    'browser/media/webrtc_identity_store_backend.h',
     'browser/media/webrtc_internals.cc',
     'browser/media/webrtc_internals.h',
     'browser/media/webrtc_internals_message_handler.cc',
@@ -1290,8 +1292,8 @@
     }],
     ['enable_webrtc==1 and (OS=="linux" or OS=="mac" or OS=="win")', {
       'sources': [
-        'browser/renderer_host/media/screen_capture_device.cc',
-        'browser/renderer_host/media/screen_capture_device.h',
+        'browser/renderer_host/media/desktop_capture_device.cc',
+        'browser/renderer_host/media/desktop_capture_device.h',
       ],
       'dependencies': [
         '../third_party/webrtc/modules/modules.gyp:desktop_capture',
@@ -1349,14 +1351,6 @@
         '../build/linux/system.gyp:udev',
         '../sandbox/sandbox.gyp:libc_urandom_override',
       ],
-      # Set LINUX_SANDBOX_PATH for Linux, including Chrome OS
-      'conditions': [
-        ['linux_sandbox_path != ""', {
-          'defines': [
-            'LINUX_SANDBOX_PATH="<(linux_sandbox_path)"',
-          ],
-        }],
-      ],
     }],
     ['OS=="linux" and use_aura==1', {
       'dependencies': [
diff --git a/content/content_browser.target.darwin-arm.mk b/content/content_browser.target.darwin-arm.mk
index 1b6db5c..6a78080 100644
--- a/content/content_browser.target.darwin-arm.mk
+++ b/content/content_browser.target.darwin-arm.mk
@@ -273,6 +273,7 @@
 	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 \
@@ -476,6 +477,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DMEDIA_DISABLE_LIBVPX' \
 	'-D__STDC_CONSTANT_MACROS' \
@@ -605,6 +607,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DMEDIA_DISABLE_LIBVPX' \
 	'-D__STDC_CONSTANT_MACROS' \
diff --git a/content/content_browser.target.darwin-mips.mk b/content/content_browser.target.darwin-mips.mk
index ee0dac8..44495ca 100644
--- a/content/content_browser.target.darwin-mips.mk
+++ b/content/content_browser.target.darwin-mips.mk
@@ -273,6 +273,7 @@
 	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 \
@@ -475,6 +476,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DMEDIA_DISABLE_LIBVPX' \
 	'-D__STDC_CONSTANT_MACROS' \
@@ -603,6 +605,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DMEDIA_DISABLE_LIBVPX' \
 	'-D__STDC_CONSTANT_MACROS' \
diff --git a/content/content_browser.target.darwin-x86.mk b/content/content_browser.target.darwin-x86.mk
index bac157c..cf3658e 100644
--- a/content/content_browser.target.darwin-x86.mk
+++ b/content/content_browser.target.darwin-x86.mk
@@ -273,6 +273,7 @@
 	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 \
@@ -477,6 +478,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DMEDIA_DISABLE_LIBVPX' \
 	'-D__STDC_CONSTANT_MACROS' \
@@ -608,6 +610,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DMEDIA_DISABLE_LIBVPX' \
 	'-D__STDC_CONSTANT_MACROS' \
diff --git a/content/content_browser.target.linux-arm.mk b/content/content_browser.target.linux-arm.mk
index 1b6db5c..6a78080 100644
--- a/content/content_browser.target.linux-arm.mk
+++ b/content/content_browser.target.linux-arm.mk
@@ -273,6 +273,7 @@
 	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 \
@@ -476,6 +477,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DMEDIA_DISABLE_LIBVPX' \
 	'-D__STDC_CONSTANT_MACROS' \
@@ -605,6 +607,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DMEDIA_DISABLE_LIBVPX' \
 	'-D__STDC_CONSTANT_MACROS' \
diff --git a/content/content_browser.target.linux-mips.mk b/content/content_browser.target.linux-mips.mk
index ee0dac8..44495ca 100644
--- a/content/content_browser.target.linux-mips.mk
+++ b/content/content_browser.target.linux-mips.mk
@@ -273,6 +273,7 @@
 	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 \
@@ -475,6 +476,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DMEDIA_DISABLE_LIBVPX' \
 	'-D__STDC_CONSTANT_MACROS' \
@@ -603,6 +605,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DMEDIA_DISABLE_LIBVPX' \
 	'-D__STDC_CONSTANT_MACROS' \
diff --git a/content/content_browser.target.linux-x86.mk b/content/content_browser.target.linux-x86.mk
index bac157c..cf3658e 100644
--- a/content/content_browser.target.linux-x86.mk
+++ b/content/content_browser.target.linux-x86.mk
@@ -273,6 +273,7 @@
 	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 \
@@ -477,6 +478,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DMEDIA_DISABLE_LIBVPX' \
 	'-D__STDC_CONSTANT_MACROS' \
@@ -608,6 +610,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DMEDIA_DISABLE_LIBVPX' \
 	'-D__STDC_CONSTANT_MACROS' \
diff --git a/content/content_child.gypi b/content/content_child.gypi
index b0c18ed..dd980e3 100644
--- a/content/content_child.gypi
+++ b/content/content_child.gypi
@@ -19,10 +19,14 @@
   'sources': [
     'child/android/child_jni_registrar.cc',
     'child/android/child_jni_registrar.h',
-    'child/appcache_backend_proxy.cc',
-    'child/appcache_backend_proxy.h',
-    'child/appcache_dispatcher.cc',
-    'child/appcache_dispatcher.h',
+    'child/appcache/appcache_backend_proxy.cc',
+    'child/appcache/appcache_backend_proxy.h',
+    'child/appcache/appcache_dispatcher.cc',
+    'child/appcache/appcache_dispatcher.h',
+    'child/appcache/appcache_frontend_impl.cc',
+    'child/appcache/appcache_frontend_impl.h',
+    'child/appcache/web_application_cache_host_impl.cc',
+    'child/appcache/web_application_cache_host_impl.h',
     'child/browser_font_resource_trusted.cc',
     'child/browser_font_resource_trusted.h',
     'child/child_histogram_message_filter.cc',
diff --git a/content/content_child.target.darwin-arm.mk b/content/content_child.target.darwin-arm.mk
index 264be10..abeb044 100644
--- a/content/content_child.target.darwin-arm.mk
+++ b/content/content_child.target.darwin-arm.mk
@@ -31,8 +31,10 @@
 
 LOCAL_SRC_FILES := \
 	content/child/android/child_jni_registrar.cc \
-	content/child/appcache_backend_proxy.cc \
-	content/child/appcache_dispatcher.cc \
+	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/child_histogram_message_filter.cc \
 	content/child/child_process.cc \
 	content/child/child_resource_message_filter.cc \
@@ -125,6 +127,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DPOSIX_AVOID_MMAP' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-D__STDC_CONSTANT_MACROS' \
@@ -239,6 +242,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DPOSIX_AVOID_MMAP' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-D__STDC_CONSTANT_MACROS' \
diff --git a/content/content_child.target.darwin-mips.mk b/content/content_child.target.darwin-mips.mk
index aea02dd..ef40461 100644
--- a/content/content_child.target.darwin-mips.mk
+++ b/content/content_child.target.darwin-mips.mk
@@ -31,8 +31,10 @@
 
 LOCAL_SRC_FILES := \
 	content/child/android/child_jni_registrar.cc \
-	content/child/appcache_backend_proxy.cc \
-	content/child/appcache_dispatcher.cc \
+	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/child_histogram_message_filter.cc \
 	content/child/child_process.cc \
 	content/child/child_resource_message_filter.cc \
@@ -124,6 +126,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DPOSIX_AVOID_MMAP' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-D__STDC_CONSTANT_MACROS' \
@@ -237,6 +240,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DPOSIX_AVOID_MMAP' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-D__STDC_CONSTANT_MACROS' \
diff --git a/content/content_child.target.darwin-x86.mk b/content/content_child.target.darwin-x86.mk
index affffa7..8eb7fa0 100644
--- a/content/content_child.target.darwin-x86.mk
+++ b/content/content_child.target.darwin-x86.mk
@@ -31,8 +31,10 @@
 
 LOCAL_SRC_FILES := \
 	content/child/android/child_jni_registrar.cc \
-	content/child/appcache_backend_proxy.cc \
-	content/child/appcache_dispatcher.cc \
+	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/child_histogram_message_filter.cc \
 	content/child/child_process.cc \
 	content/child/child_resource_message_filter.cc \
@@ -127,6 +129,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
@@ -243,6 +246,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
diff --git a/content/content_child.target.linux-arm.mk b/content/content_child.target.linux-arm.mk
index 264be10..abeb044 100644
--- a/content/content_child.target.linux-arm.mk
+++ b/content/content_child.target.linux-arm.mk
@@ -31,8 +31,10 @@
 
 LOCAL_SRC_FILES := \
 	content/child/android/child_jni_registrar.cc \
-	content/child/appcache_backend_proxy.cc \
-	content/child/appcache_dispatcher.cc \
+	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/child_histogram_message_filter.cc \
 	content/child/child_process.cc \
 	content/child/child_resource_message_filter.cc \
@@ -125,6 +127,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DPOSIX_AVOID_MMAP' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-D__STDC_CONSTANT_MACROS' \
@@ -239,6 +242,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DPOSIX_AVOID_MMAP' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-D__STDC_CONSTANT_MACROS' \
diff --git a/content/content_child.target.linux-mips.mk b/content/content_child.target.linux-mips.mk
index aea02dd..ef40461 100644
--- a/content/content_child.target.linux-mips.mk
+++ b/content/content_child.target.linux-mips.mk
@@ -31,8 +31,10 @@
 
 LOCAL_SRC_FILES := \
 	content/child/android/child_jni_registrar.cc \
-	content/child/appcache_backend_proxy.cc \
-	content/child/appcache_dispatcher.cc \
+	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/child_histogram_message_filter.cc \
 	content/child/child_process.cc \
 	content/child/child_resource_message_filter.cc \
@@ -124,6 +126,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DPOSIX_AVOID_MMAP' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-D__STDC_CONSTANT_MACROS' \
@@ -237,6 +240,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DPOSIX_AVOID_MMAP' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-D__STDC_CONSTANT_MACROS' \
diff --git a/content/content_child.target.linux-x86.mk b/content/content_child.target.linux-x86.mk
index affffa7..8eb7fa0 100644
--- a/content/content_child.target.linux-x86.mk
+++ b/content/content_child.target.linux-x86.mk
@@ -31,8 +31,10 @@
 
 LOCAL_SRC_FILES := \
 	content/child/android/child_jni_registrar.cc \
-	content/child/appcache_backend_proxy.cc \
-	content/child/appcache_dispatcher.cc \
+	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/child_histogram_message_filter.cc \
 	content/child/child_process.cc \
 	content/child/child_resource_message_filter.cc \
@@ -127,6 +129,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
@@ -243,6 +246,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
diff --git a/content/content_common.gypi b/content/content_common.gypi
index 42a345b..f7413b5 100644
--- a/content/content_common.gypi
+++ b/content/content_common.gypi
@@ -37,6 +37,8 @@
     'public/common/context_menu_params.cc',
     'public/common/context_menu_params.h',
     'public/common/console_message_level.h',
+    'public/common/desktop_media_id.cc',
+    'public/common/desktop_media_id.h',
     'public/common/drop_data.cc',
     'public/common/drop_data.h',
     'public/common/favicon_url.cc',
diff --git a/content/content_common.target.darwin-arm.mk b/content/content_common.target.darwin-arm.mk
index d1a213b..9738bb5 100644
--- a/content/content_common.target.darwin-arm.mk
+++ b/content/content_common.target.darwin-arm.mk
@@ -37,6 +37,7 @@
 	content/public/common/content_constants.cc \
 	content/public/common/content_switches.cc \
 	content/public/common/context_menu_params.cc \
+	content/public/common/desktop_media_id.cc \
 	content/public/common/drop_data.cc \
 	content/public/common/favicon_url.cc \
 	content/public/common/file_chooser_params.cc \
@@ -193,6 +194,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-D__STDC_CONSTANT_MACROS' \
@@ -309,6 +311,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-D__STDC_CONSTANT_MACROS' \
diff --git a/content/content_common.target.darwin-mips.mk b/content/content_common.target.darwin-mips.mk
index ba84ef0..d2200cc 100644
--- a/content/content_common.target.darwin-mips.mk
+++ b/content/content_common.target.darwin-mips.mk
@@ -37,6 +37,7 @@
 	content/public/common/content_constants.cc \
 	content/public/common/content_switches.cc \
 	content/public/common/context_menu_params.cc \
+	content/public/common/desktop_media_id.cc \
 	content/public/common/drop_data.cc \
 	content/public/common/favicon_url.cc \
 	content/public/common/file_chooser_params.cc \
@@ -192,6 +193,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-D__STDC_CONSTANT_MACROS' \
@@ -307,6 +309,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-D__STDC_CONSTANT_MACROS' \
diff --git a/content/content_common.target.darwin-x86.mk b/content/content_common.target.darwin-x86.mk
index 9d0a842..c4449d0 100644
--- a/content/content_common.target.darwin-x86.mk
+++ b/content/content_common.target.darwin-x86.mk
@@ -37,6 +37,7 @@
 	content/public/common/content_constants.cc \
 	content/public/common/content_switches.cc \
 	content/public/common/context_menu_params.cc \
+	content/public/common/desktop_media_id.cc \
 	content/public/common/drop_data.cc \
 	content/public/common/favicon_url.cc \
 	content/public/common/file_chooser_params.cc \
@@ -194,6 +195,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-D__STDC_CONSTANT_MACROS' \
@@ -312,6 +314,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-D__STDC_CONSTANT_MACROS' \
diff --git a/content/content_common.target.linux-arm.mk b/content/content_common.target.linux-arm.mk
index d1a213b..9738bb5 100644
--- a/content/content_common.target.linux-arm.mk
+++ b/content/content_common.target.linux-arm.mk
@@ -37,6 +37,7 @@
 	content/public/common/content_constants.cc \
 	content/public/common/content_switches.cc \
 	content/public/common/context_menu_params.cc \
+	content/public/common/desktop_media_id.cc \
 	content/public/common/drop_data.cc \
 	content/public/common/favicon_url.cc \
 	content/public/common/file_chooser_params.cc \
@@ -193,6 +194,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-D__STDC_CONSTANT_MACROS' \
@@ -309,6 +311,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-D__STDC_CONSTANT_MACROS' \
diff --git a/content/content_common.target.linux-mips.mk b/content/content_common.target.linux-mips.mk
index ba84ef0..d2200cc 100644
--- a/content/content_common.target.linux-mips.mk
+++ b/content/content_common.target.linux-mips.mk
@@ -37,6 +37,7 @@
 	content/public/common/content_constants.cc \
 	content/public/common/content_switches.cc \
 	content/public/common/context_menu_params.cc \
+	content/public/common/desktop_media_id.cc \
 	content/public/common/drop_data.cc \
 	content/public/common/favicon_url.cc \
 	content/public/common/file_chooser_params.cc \
@@ -192,6 +193,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-D__STDC_CONSTANT_MACROS' \
@@ -307,6 +309,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-D__STDC_CONSTANT_MACROS' \
diff --git a/content/content_common.target.linux-x86.mk b/content/content_common.target.linux-x86.mk
index 9d0a842..c4449d0 100644
--- a/content/content_common.target.linux-x86.mk
+++ b/content/content_common.target.linux-x86.mk
@@ -37,6 +37,7 @@
 	content/public/common/content_constants.cc \
 	content/public/common/content_switches.cc \
 	content/public/common/context_menu_params.cc \
+	content/public/common/desktop_media_id.cc \
 	content/public/common/drop_data.cc \
 	content/public/common/favicon_url.cc \
 	content/public/common/file_chooser_params.cc \
@@ -194,6 +195,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-D__STDC_CONSTANT_MACROS' \
@@ -312,6 +314,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-D__STDC_CONSTANT_MACROS' \
diff --git a/content/content_gpu.target.darwin-arm.mk b/content/content_gpu.target.darwin-arm.mk
index b6b56ad..46eec2f 100644
--- a/content/content_gpu.target.darwin-arm.mk
+++ b/content/content_gpu.target.darwin-arm.mk
@@ -87,6 +87,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
@@ -196,6 +197,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
diff --git a/content/content_gpu.target.darwin-mips.mk b/content/content_gpu.target.darwin-mips.mk
index 2f69c62..248aea2 100644
--- a/content/content_gpu.target.darwin-mips.mk
+++ b/content/content_gpu.target.darwin-mips.mk
@@ -86,6 +86,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
@@ -194,6 +195,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
diff --git a/content/content_gpu.target.darwin-x86.mk b/content/content_gpu.target.darwin-x86.mk
index 868fb4e..b2e3430 100644
--- a/content/content_gpu.target.darwin-x86.mk
+++ b/content/content_gpu.target.darwin-x86.mk
@@ -89,6 +89,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
@@ -201,6 +202,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
diff --git a/content/content_gpu.target.linux-arm.mk b/content/content_gpu.target.linux-arm.mk
index b6b56ad..46eec2f 100644
--- a/content/content_gpu.target.linux-arm.mk
+++ b/content/content_gpu.target.linux-arm.mk
@@ -87,6 +87,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
@@ -196,6 +197,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
diff --git a/content/content_gpu.target.linux-mips.mk b/content/content_gpu.target.linux-mips.mk
index 2f69c62..248aea2 100644
--- a/content/content_gpu.target.linux-mips.mk
+++ b/content/content_gpu.target.linux-mips.mk
@@ -86,6 +86,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
@@ -194,6 +195,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
diff --git a/content/content_gpu.target.linux-x86.mk b/content/content_gpu.target.linux-x86.mk
index 868fb4e..b2e3430 100644
--- a/content/content_gpu.target.linux-x86.mk
+++ b/content/content_gpu.target.linux-x86.mk
@@ -89,6 +89,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
@@ -201,6 +202,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
diff --git a/content/content_plugin.gypi b/content/content_plugin.gypi
index e00e563..7ff4221 100644
--- a/content/content_plugin.gypi
+++ b/content/content_plugin.gypi
@@ -9,9 +9,7 @@
         '../skia/skia.gyp:skia',
         '../third_party/npapi/npapi.gyp:npapi',
         '../third_party/WebKit/public/blink.gyp:blink',
-        '../webkit/plugins/webkit_plugins.gyp:plugins_common',
         '../webkit/support/webkit_support.gyp:glue',
-        '../webkit/support/webkit_support.gyp:plugins',
       ],
       'include_dirs': [
         '<(INTERMEDIATE_DIR)',
diff --git a/content/content_renderer.gypi b/content/content_renderer.gypi
index 25ad0ea..4b011ab 100644
--- a/content/content_renderer.gypi
+++ b/content/content_renderer.gypi
@@ -19,7 +19,6 @@
     '../v8/tools/gyp/v8.gyp:v8',
     '../webkit/common/gpu/webkit_gpu.gyp:webkit_gpu',
     '../webkit/common/webkit_common.gyp:webkit_common',
-    '../webkit/plugins/webkit_plugins.gyp:plugins_common',
     '../webkit/renderer/compositor_bindings/compositor_bindings.gyp:webkit_compositor_bindings',
     '../webkit/renderer/compositor_bindings/compositor_bindings.gyp:webkit_compositor_support',
     '../webkit/renderer/webkit_renderer.gyp:webkit_renderer',
@@ -27,7 +26,6 @@
     '../webkit/storage_renderer.gyp:webkit_storage_renderer',
     '../webkit/support/webkit_support.gyp:glue',
     '../webkit/support/webkit_support.gyp:glue_child',
-    '../webkit/support/webkit_support.gyp:plugins',
   ],
   'include_dirs': [
     '..',
@@ -69,8 +67,6 @@
     'renderer/accessibility/renderer_accessibility_focus_only.h',
     'renderer/active_notification_tracker.cc',
     'renderer/active_notification_tracker.h',
-    'renderer/all_rendering_benchmarks.cc',
-    'renderer/all_rendering_benchmarks.h',
     'renderer/android/address_detector.cc',
     'renderer/android/address_detector.h',
     'renderer/android/content_detector.cc',
@@ -167,8 +163,11 @@
     'renderer/media/android/proxy_media_keys.h',
     'renderer/media/android/renderer_media_player_manager.cc',
     'renderer/media/android/renderer_media_player_manager.h',
-    'renderer/media/android/stream_texture_factory_android.cc',
     'renderer/media/android/stream_texture_factory_android.h',
+    'renderer/media/android/stream_texture_factory_android_impl.cc',
+    'renderer/media/android/stream_texture_factory_android_impl.h',
+    'renderer/media/android/stream_texture_factory_android_synchronous_impl.cc',
+    'renderer/media/android/stream_texture_factory_android_synchronous_impl.h',
     'renderer/media/android/webmediaplayer_android.cc',
     'renderer/media/android/webmediaplayer_android.h',
     'renderer/media/android/webmediaplayer_proxy_android.cc',
@@ -356,8 +355,6 @@
     'renderer/pepper/ppb_broker_impl.h',
     'renderer/pepper/ppb_buffer_impl.cc',
     'renderer/pepper/ppb_buffer_impl.h',
-    'renderer/pepper/ppb_file_ref_impl.cc',
-    'renderer/pepper/ppb_file_ref_impl.h',
     'renderer/pepper/ppb_flash_message_loop_impl.cc',
     'renderer/pepper/ppb_flash_message_loop_impl.h',
     'renderer/pepper/ppb_gpu_blacklist_private_impl.cc',
@@ -478,6 +475,8 @@
     'renderer/renderer_webkitplatformsupport_impl.h',
     'renderer/rendering_benchmark.cc',
     'renderer/rendering_benchmark.h',
+    'renderer/sad_plugin.cc',
+    'renderer/sad_plugin.h',
     'renderer/savable_resources.cc',
     'renderer/savable_resources.h',
     'renderer/scoped_clipboard_writer_glue.cc',
diff --git a/content/content_renderer.target.darwin-arm.mk b/content/content_renderer.target.darwin-arm.mk
index 4fb613c..8679aad 100644
--- a/content/content_renderer.target.darwin-arm.mk
+++ b/content/content_renderer.target.darwin-arm.mk
@@ -48,7 +48,6 @@
 	content/renderer/accessibility/renderer_accessibility.cc \
 	content/renderer/accessibility/renderer_accessibility_complete.cc \
 	content/renderer/accessibility/renderer_accessibility_focus_only.cc \
-	content/renderer/all_rendering_benchmarks.cc \
 	content/renderer/android/address_detector.cc \
 	content/renderer/android/content_detector.cc \
 	content/renderer/android/email_detector.cc \
@@ -95,7 +94,8 @@
 	content/renderer/media/android/media_source_delegate.cc \
 	content/renderer/media/android/proxy_media_keys.cc \
 	content/renderer/media/android/renderer_media_player_manager.cc \
-	content/renderer/media/android/stream_texture_factory_android.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/android/webmediaplayer_proxy_android.cc \
 	content/renderer/media/audio_decoder.cc \
@@ -171,6 +171,7 @@
 	content/renderer/renderer_webcolorchooser_impl.cc \
 	content/renderer/renderer_webkitplatformsupport_impl.cc \
 	content/renderer/rendering_benchmark.cc \
+	content/renderer/sad_plugin.cc \
 	content/renderer/savable_resources.cc \
 	content/renderer/scoped_clipboard_writer_glue.cc \
 	content/renderer/shared_memory_seqlock_reader.cc \
@@ -244,6 +245,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DFEATURE_ENABLE_SSL' \
 	'-DFEATURE_ENABLE_VOICEMAIL' \
@@ -385,6 +387,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DFEATURE_ENABLE_SSL' \
 	'-DFEATURE_ENABLE_VOICEMAIL' \
diff --git a/content/content_renderer.target.darwin-mips.mk b/content/content_renderer.target.darwin-mips.mk
index 5ccec42..09fe76f 100644
--- a/content/content_renderer.target.darwin-mips.mk
+++ b/content/content_renderer.target.darwin-mips.mk
@@ -48,7 +48,6 @@
 	content/renderer/accessibility/renderer_accessibility.cc \
 	content/renderer/accessibility/renderer_accessibility_complete.cc \
 	content/renderer/accessibility/renderer_accessibility_focus_only.cc \
-	content/renderer/all_rendering_benchmarks.cc \
 	content/renderer/android/address_detector.cc \
 	content/renderer/android/content_detector.cc \
 	content/renderer/android/email_detector.cc \
@@ -95,7 +94,8 @@
 	content/renderer/media/android/media_source_delegate.cc \
 	content/renderer/media/android/proxy_media_keys.cc \
 	content/renderer/media/android/renderer_media_player_manager.cc \
-	content/renderer/media/android/stream_texture_factory_android.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/android/webmediaplayer_proxy_android.cc \
 	content/renderer/media/audio_decoder.cc \
@@ -171,6 +171,7 @@
 	content/renderer/renderer_webcolorchooser_impl.cc \
 	content/renderer/renderer_webkitplatformsupport_impl.cc \
 	content/renderer/rendering_benchmark.cc \
+	content/renderer/sad_plugin.cc \
 	content/renderer/savable_resources.cc \
 	content/renderer/scoped_clipboard_writer_glue.cc \
 	content/renderer/shared_memory_seqlock_reader.cc \
@@ -243,6 +244,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DFEATURE_ENABLE_SSL' \
 	'-DFEATURE_ENABLE_VOICEMAIL' \
@@ -383,6 +385,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DFEATURE_ENABLE_SSL' \
 	'-DFEATURE_ENABLE_VOICEMAIL' \
diff --git a/content/content_renderer.target.darwin-x86.mk b/content/content_renderer.target.darwin-x86.mk
index 1db78f3..ad20f15 100644
--- a/content/content_renderer.target.darwin-x86.mk
+++ b/content/content_renderer.target.darwin-x86.mk
@@ -48,7 +48,6 @@
 	content/renderer/accessibility/renderer_accessibility.cc \
 	content/renderer/accessibility/renderer_accessibility_complete.cc \
 	content/renderer/accessibility/renderer_accessibility_focus_only.cc \
-	content/renderer/all_rendering_benchmarks.cc \
 	content/renderer/android/address_detector.cc \
 	content/renderer/android/content_detector.cc \
 	content/renderer/android/email_detector.cc \
@@ -95,7 +94,8 @@
 	content/renderer/media/android/media_source_delegate.cc \
 	content/renderer/media/android/proxy_media_keys.cc \
 	content/renderer/media/android/renderer_media_player_manager.cc \
-	content/renderer/media/android/stream_texture_factory_android.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/android/webmediaplayer_proxy_android.cc \
 	content/renderer/media/audio_decoder.cc \
@@ -171,6 +171,7 @@
 	content/renderer/renderer_webcolorchooser_impl.cc \
 	content/renderer/renderer_webkitplatformsupport_impl.cc \
 	content/renderer/rendering_benchmark.cc \
+	content/renderer/sad_plugin.cc \
 	content/renderer/savable_resources.cc \
 	content/renderer/scoped_clipboard_writer_glue.cc \
 	content/renderer/shared_memory_seqlock_reader.cc \
@@ -245,6 +246,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DFEATURE_ENABLE_SSL' \
 	'-DFEATURE_ENABLE_VOICEMAIL' \
@@ -388,6 +390,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DFEATURE_ENABLE_SSL' \
 	'-DFEATURE_ENABLE_VOICEMAIL' \
diff --git a/content/content_renderer.target.linux-arm.mk b/content/content_renderer.target.linux-arm.mk
index 4fb613c..8679aad 100644
--- a/content/content_renderer.target.linux-arm.mk
+++ b/content/content_renderer.target.linux-arm.mk
@@ -48,7 +48,6 @@
 	content/renderer/accessibility/renderer_accessibility.cc \
 	content/renderer/accessibility/renderer_accessibility_complete.cc \
 	content/renderer/accessibility/renderer_accessibility_focus_only.cc \
-	content/renderer/all_rendering_benchmarks.cc \
 	content/renderer/android/address_detector.cc \
 	content/renderer/android/content_detector.cc \
 	content/renderer/android/email_detector.cc \
@@ -95,7 +94,8 @@
 	content/renderer/media/android/media_source_delegate.cc \
 	content/renderer/media/android/proxy_media_keys.cc \
 	content/renderer/media/android/renderer_media_player_manager.cc \
-	content/renderer/media/android/stream_texture_factory_android.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/android/webmediaplayer_proxy_android.cc \
 	content/renderer/media/audio_decoder.cc \
@@ -171,6 +171,7 @@
 	content/renderer/renderer_webcolorchooser_impl.cc \
 	content/renderer/renderer_webkitplatformsupport_impl.cc \
 	content/renderer/rendering_benchmark.cc \
+	content/renderer/sad_plugin.cc \
 	content/renderer/savable_resources.cc \
 	content/renderer/scoped_clipboard_writer_glue.cc \
 	content/renderer/shared_memory_seqlock_reader.cc \
@@ -244,6 +245,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DFEATURE_ENABLE_SSL' \
 	'-DFEATURE_ENABLE_VOICEMAIL' \
@@ -385,6 +387,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DFEATURE_ENABLE_SSL' \
 	'-DFEATURE_ENABLE_VOICEMAIL' \
diff --git a/content/content_renderer.target.linux-mips.mk b/content/content_renderer.target.linux-mips.mk
index 5ccec42..09fe76f 100644
--- a/content/content_renderer.target.linux-mips.mk
+++ b/content/content_renderer.target.linux-mips.mk
@@ -48,7 +48,6 @@
 	content/renderer/accessibility/renderer_accessibility.cc \
 	content/renderer/accessibility/renderer_accessibility_complete.cc \
 	content/renderer/accessibility/renderer_accessibility_focus_only.cc \
-	content/renderer/all_rendering_benchmarks.cc \
 	content/renderer/android/address_detector.cc \
 	content/renderer/android/content_detector.cc \
 	content/renderer/android/email_detector.cc \
@@ -95,7 +94,8 @@
 	content/renderer/media/android/media_source_delegate.cc \
 	content/renderer/media/android/proxy_media_keys.cc \
 	content/renderer/media/android/renderer_media_player_manager.cc \
-	content/renderer/media/android/stream_texture_factory_android.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/android/webmediaplayer_proxy_android.cc \
 	content/renderer/media/audio_decoder.cc \
@@ -171,6 +171,7 @@
 	content/renderer/renderer_webcolorchooser_impl.cc \
 	content/renderer/renderer_webkitplatformsupport_impl.cc \
 	content/renderer/rendering_benchmark.cc \
+	content/renderer/sad_plugin.cc \
 	content/renderer/savable_resources.cc \
 	content/renderer/scoped_clipboard_writer_glue.cc \
 	content/renderer/shared_memory_seqlock_reader.cc \
@@ -243,6 +244,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DFEATURE_ENABLE_SSL' \
 	'-DFEATURE_ENABLE_VOICEMAIL' \
@@ -383,6 +385,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DFEATURE_ENABLE_SSL' \
 	'-DFEATURE_ENABLE_VOICEMAIL' \
diff --git a/content/content_renderer.target.linux-x86.mk b/content/content_renderer.target.linux-x86.mk
index 1db78f3..ad20f15 100644
--- a/content/content_renderer.target.linux-x86.mk
+++ b/content/content_renderer.target.linux-x86.mk
@@ -48,7 +48,6 @@
 	content/renderer/accessibility/renderer_accessibility.cc \
 	content/renderer/accessibility/renderer_accessibility_complete.cc \
 	content/renderer/accessibility/renderer_accessibility_focus_only.cc \
-	content/renderer/all_rendering_benchmarks.cc \
 	content/renderer/android/address_detector.cc \
 	content/renderer/android/content_detector.cc \
 	content/renderer/android/email_detector.cc \
@@ -95,7 +94,8 @@
 	content/renderer/media/android/media_source_delegate.cc \
 	content/renderer/media/android/proxy_media_keys.cc \
 	content/renderer/media/android/renderer_media_player_manager.cc \
-	content/renderer/media/android/stream_texture_factory_android.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/android/webmediaplayer_proxy_android.cc \
 	content/renderer/media/audio_decoder.cc \
@@ -171,6 +171,7 @@
 	content/renderer/renderer_webcolorchooser_impl.cc \
 	content/renderer/renderer_webkitplatformsupport_impl.cc \
 	content/renderer/rendering_benchmark.cc \
+	content/renderer/sad_plugin.cc \
 	content/renderer/savable_resources.cc \
 	content/renderer/scoped_clipboard_writer_glue.cc \
 	content/renderer/shared_memory_seqlock_reader.cc \
@@ -245,6 +246,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DFEATURE_ENABLE_SSL' \
 	'-DFEATURE_ENABLE_VOICEMAIL' \
@@ -388,6 +390,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DFEATURE_ENABLE_SSL' \
 	'-DFEATURE_ENABLE_VOICEMAIL' \
diff --git a/content/content_tests.gypi b/content/content_tests.gypi
index bbd785c..115ba8a 100644
--- a/content/content_tests.gypi
+++ b/content/content_tests.gypi
@@ -175,7 +175,7 @@
             '../ppapi/ppapi_internal.gyp:ppapi_shared',
             '../ppapi/ppapi_internal.gyp:ppapi_unittest_shared',
             '../third_party/WebKit/public/blink.gyp:blink',
-            '../third_party/WebKit/Tools/DumpRenderTree/DumpRenderTree.gyp/DumpRenderTree.gyp:TestRunner',
+            '../third_party/WebKit/public/blink_test_runner.gyp:blink_test_runner',
             '../ui/surface/surface.gyp:surface',
             '../webkit/common/gpu/webkit_gpu.gyp:webkit_gpu',
             '../webkit/renderer/compositor_bindings/compositor_bindings.gyp:webkit_compositor_support',
@@ -586,15 +586,12 @@
             '../ui/gl/gl.gyp:gl',
             '../v8/tools/gyp/v8.gyp:v8',
             '../webkit/common/webkit_common.gyp:webkit_common',
-            '../webkit/plugins/webkit_plugins.gyp:plugins_common',
             '../webkit/renderer/webkit_renderer.gyp:webkit_renderer',
             '../webkit/storage_browser.gyp:webkit_storage_browser',
             '../webkit/storage_common.gyp:webkit_storage_common',
             '../webkit/storage_renderer.gyp:webkit_storage_renderer',
             '../webkit/support/webkit_support.gyp:glue',
             '../webkit/support/webkit_support.gyp:glue_child',
-            '../webkit/support/webkit_support.gyp:plugins',
-            '../webkit/plugins/webkit_plugins.gyp:plugins_common',
           ],
         }],
         ['enable_plugins==0', {
@@ -640,7 +637,7 @@
         }],
         ['enable_webrtc==1 and (OS=="linux" or OS=="mac" or OS=="win")', {
           'sources': [
-            'browser/renderer_host/media/screen_capture_device_unittest.cc',
+            'browser/renderer_host/media/desktop_capture_device_unittest.cc',
           ],
           'dependencies': [
             '../third_party/webrtc/modules/modules.gyp:desktop_capture',
@@ -776,7 +773,6 @@
             '../webkit/renderer/webkit_renderer.gyp:webkit_renderer',
             '../webkit/support/webkit_support.gyp:glue',
             '../webkit/support/webkit_support.gyp:glue_child',
-            '../webkit/plugins/webkit_plugins.gyp:plugins_common',
           ],
           'include_dirs': [
             '..',
@@ -955,6 +951,7 @@
                 'browser/accessibility/accessibility_win_browsertest.cc',
                 'browser/accessibility/dump_accessibility_tree_browsertest.cc',
                 'browser/plugin_browsertest.cc',
+                'browser/renderer_host/render_widget_host_view_win_browsertest.cc',
               ],
             }],
             ['OS!="android" and OS!="ios"', {
@@ -982,7 +979,7 @@
               'dependencies': [
                 # Runtime dependencies.
                 '../third_party/widevine/cdm/widevine_cdm.gyp:widevinecdmadapter',
-                '../webkit/support/webkit_support.gyp:clearkeycdmadapter',
+                '../media/media.gyp:clearkeycdmadapter',
               ],
             }],
             ['input_speech==0', {
diff --git a/content/plugin/DEPS b/content/plugin/DEPS
index 71cb2f3..a87bacc 100644
--- a/content/plugin/DEPS
+++ b/content/plugin/DEPS
@@ -6,6 +6,5 @@
   "+skia/ext",
   "+third_party/npapi",
   "+webkit/glue",
-  "+webkit/plugins",
 ]
 
diff --git a/content/ppapi_plugin/ppapi_thread.cc b/content/ppapi_plugin/ppapi_thread.cc
index 2315729..73d51ad 100644
--- a/content/ppapi_plugin/ppapi_thread.cc
+++ b/content/ppapi_plugin/ppapi_thread.cc
@@ -23,6 +23,7 @@
 #include "content/ppapi_plugin/plugin_process_dispatcher.h"
 #include "content/ppapi_plugin/ppapi_webkitplatformsupport_impl.h"
 #include "content/public/common/content_client.h"
+#include "content/public/common/content_switches.h"
 #include "content/public/common/pepper_plugin_info.h"
 #include "content/public/common/sandbox_init.h"
 #include "content/public/plugin/content_plugin_client.h"
@@ -39,7 +40,6 @@
 #include "ppapi/shared_impl/api_id.h"
 #include "third_party/WebKit/public/web/WebKit.h"
 #include "ui/base/ui_base_switches.h"
-#include "webkit/plugins/plugin_switches.h"
 
 #if defined(OS_WIN)
 #include "base/win/win_util.h"
diff --git a/content/public/android/java/src/org/chromium/content/browser/ChildProcessLauncher.java b/content/public/android/java/src/org/chromium/content/browser/ChildProcessLauncher.java
index de71a63..db41c53 100644
--- a/content/public/android/java/src/org/chromium/content/browser/ChildProcessLauncher.java
+++ b/content/public/android/java/src/org/chromium/content/browser/ChildProcessLauncher.java
@@ -116,26 +116,26 @@
 
     // Service class for child process. As the default value it uses SandboxedProcessService0 and
     // PrivilegedProcessService0.
-    private static final ChildConnectionAllocator mSandboxedChildConnectionAllocator =
+    private static final ChildConnectionAllocator sSandboxedChildConnectionAllocator =
             new ChildConnectionAllocator(true);
-    private static final ChildConnectionAllocator mPrivilegedChildConnectionAllocator =
+    private static final ChildConnectionAllocator sPrivilegedChildConnectionAllocator =
             new ChildConnectionAllocator(false);
 
-    private static boolean mConnectionAllocated = false;
+    private static boolean sConnectionAllocated = false;
 
     // Sets service class for sandboxed service and privileged service.
     public static void setChildProcessClass(
             Class<? extends SandboxedProcessService> sandboxedServiceClass,
             Class<? extends PrivilegedProcessService> privilegedServiceClass) {
         // We should guarantee this is called before allocating connection.
-        assert !mConnectionAllocated;
-        mSandboxedChildConnectionAllocator.setServiceClass(sandboxedServiceClass);
-        mPrivilegedChildConnectionAllocator.setServiceClass(privilegedServiceClass);
+        assert !sConnectionAllocated;
+        sSandboxedChildConnectionAllocator.setServiceClass(sandboxedServiceClass);
+        sPrivilegedChildConnectionAllocator.setServiceClass(privilegedServiceClass);
     }
 
     private static ChildConnectionAllocator getConnectionAllocator(boolean inSandbox) {
         return inSandbox ?
-                mSandboxedChildConnectionAllocator : mPrivilegedChildConnectionAllocator;
+                sSandboxedChildConnectionAllocator : sPrivilegedChildConnectionAllocator;
     }
 
     private static ChildProcessConnection allocateConnection(Context context,
@@ -147,7 +147,7 @@
                     stop(pid);
                 }
             };
-        mConnectionAllocated = true;
+        sConnectionAllocated = true;
         return getConnectionAllocator(inSandbox).allocate(context, deathCallback);
     }
 
@@ -172,7 +172,7 @@
     private static final int NULL_PROCESS_HANDLE = 0;
 
     // Map from pid to ChildService connection.
-    private static Map<Integer, ChildProcessConnection> mServiceMap =
+    private static Map<Integer, ChildProcessConnection> sServiceMap =
             new ConcurrentHashMap<Integer, ChildProcessConnection>();
 
     // Map from pid to the count of oom bindings. "Oom binding" is a binding that raises the process
@@ -181,7 +181,7 @@
     private static SparseIntArray sOomBindingCount = new SparseIntArray();
 
     // A pre-allocated and pre-bound connection ready for connection setup, or null.
-    static ChildProcessConnection mSpareSandboxedConnection = null;
+    private static ChildProcessConnection sSpareSandboxedConnection = null;
 
     /**
      * Returns the child process service interface for the given pid. This may be called on
@@ -192,7 +192,7 @@
      * @return The IChildProcessService or null if the service no longer exists.
      */
     public static IChildProcessService getChildService(int pid) {
-        ChildProcessConnection connection = mServiceMap.get(pid);
+        ChildProcessConnection connection = sServiceMap.get(pid);
         if (connection != null) {
             return connection.getService();
         }
@@ -208,8 +208,8 @@
     public static void warmUp(Context context) {
         synchronized (ChildProcessLauncher.class) {
             assert !ThreadUtils.runningOnUiThread();
-            if (mSpareSandboxedConnection == null) {
-                mSpareSandboxedConnection = allocateBoundConnection(context, null, true);
+            if (sSpareSandboxedConnection == null) {
+                sSpareSandboxedConnection = allocateBoundConnection(context, null, true);
             }
         }
     }
@@ -272,8 +272,8 @@
         ChildProcessConnection allocatedConnection = null;
         synchronized (ChildProcessLauncher.class) {
             if (inSandbox) {
-                allocatedConnection = mSpareSandboxedConnection;
-                mSpareSandboxedConnection = null;
+                allocatedConnection = sSpareSandboxedConnection;
+                sSpareSandboxedConnection = null;
             }
         }
         if (allocatedConnection == null) {
@@ -293,7 +293,7 @@
                 Log.d(TAG, "on connect callback, pid=" + pid + " context=" + clientContext);
                 if (pid != NULL_PROCESS_HANDLE) {
                     sOomBindingCount.put(pid, oomBindingCount);
-                    mServiceMap.put(pid, connection);
+                    sServiceMap.put(pid, connection);
                 } else {
                     freeConnection(connection);
                 }
@@ -335,7 +335,7 @@
     @CalledByNative
     static void stop(int pid) {
         Log.d(TAG, "stopping child connection: pid=" + pid);
-        ChildProcessConnection connection = mServiceMap.remove(pid);
+        ChildProcessConnection connection = sServiceMap.remove(pid);
         if (connection == null) {
             LogPidWarning(pid, "Tried to stop non-existent connection");
             return;
@@ -350,7 +350,7 @@
      * binding once it is no longer needed.
      */
     static void removeInitialBinding(int pid) {
-        ChildProcessConnection connection = mServiceMap.get(pid);
+        ChildProcessConnection connection = sServiceMap.get(pid);
         if (connection == null) {
             LogPidWarning(pid, "Tried to remove a binding for a non-existent connection");
             return;
@@ -366,7 +366,7 @@
      * @param pid The process handle of the service connection obtained from {@link #start}.
      */
     static void bindAsHighPriority(int pid) {
-        ChildProcessConnection connection = mServiceMap.get(pid);
+        ChildProcessConnection connection = sServiceMap.get(pid);
         if (connection == null) {
             LogPidWarning(pid, "Tried to bind a non-existent connection");
             return;
@@ -380,7 +380,7 @@
      * @param pid The process handle of the service obtained from {@link #start}.
      */
     static void unbindAsHighPriority(int pid) {
-        ChildProcessConnection connection = mServiceMap.get(pid);
+        ChildProcessConnection connection = sServiceMap.get(pid);
         if (connection == null) {
             LogPidWarning(pid, "Tried to unbind non-existent connection");
             return;
@@ -392,7 +392,7 @@
      * @return True iff the given service process is protected from the out-of-memory killing, or it
      * was protected from it when it died.
      */
-    public static boolean isOomProtected(int pid) {
+    static boolean isOomProtected(int pid) {
         return sOomBindingCount.get(pid) > 0;
     }
 
diff --git a/content/public/android/java/src/org/chromium/content/browser/ContentView.java b/content/public/android/java/src/org/chromium/content/browser/ContentView.java
index 135cb26..9a19f97 100644
--- a/content/public/android/java/src/org/chromium/content/browser/ContentView.java
+++ b/content/public/android/java/src/org/chromium/content/browser/ContentView.java
@@ -96,6 +96,11 @@
             AttributeSet attrs, int defStyle) {
         super(context, attrs, defStyle);
 
+        if (getScrollBarStyle() == View.SCROLLBARS_INSIDE_OVERLAY) {
+            setHorizontalScrollBarEnabled(false);
+            setVerticalScrollBarEnabled(false);
+        }
+
         mContentViewCore = new ContentViewCore(context);
         mContentViewCore.initialize(this, this, nativeWebContents, windowAndroid,
                 Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN ?
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 95ed270..b6e5580 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
@@ -531,9 +531,16 @@
                     lp.topMargin = topMargin;
                     view.setLayoutParams(lp);
                 } else if (mContainerView instanceof AbsoluteLayout) {
+                    // This fixes the offset due to a difference in
+                    // scrolling model of WebView vs. Chrome.
+                    // TODO(sgurun) fix this to use mContainerView.getScroll[X/Y]()
+                    // as it naturally accounts for scroll differences between
+                    // these models.
+                    leftMargin += mRenderCoordinates.getScrollXPixInt();
+                    topMargin += mRenderCoordinates.getScrollYPixInt();
                     android.widget.AbsoluteLayout.LayoutParams lp =
                             new android.widget.AbsoluteLayout.LayoutParams((int)width,
-                                    (int)height, leftMargin, topMargin);
+                                    (int)(height * scale), leftMargin, topMargin);
                     view.setLayoutParams(lp);
                 } else {
                     Log.e(TAG, "Unknown layout " + mContainerView.getClass().getName());
@@ -754,11 +761,6 @@
         mContainerView.setFocusableInTouchMode(true);
         mContainerView.setClickable(true);
 
-        if (mContainerView.getScrollBarStyle() == View.SCROLLBARS_INSIDE_OVERLAY) {
-            mContainerView.setHorizontalScrollBarEnabled(false);
-            mContainerView.setVerticalScrollBarEnabled(false);
-        }
-
         mZoomManager = new ZoomManager(mContext, this);
         mContentViewGestureHandler = new ContentViewGestureHandler(mContext, this, mZoomManager,
                 inputEventDeliveryMode);
diff --git a/content/public/android/java/src/org/chromium/content/browser/PowerSaveBlocker.java b/content/public/android/java/src/org/chromium/content/browser/PowerSaveBlocker.java
index 26a9d62..548c66d 100644
--- a/content/public/android/java/src/org/chromium/content/browser/PowerSaveBlocker.java
+++ b/content/public/android/java/src/org/chromium/content/browser/PowerSaveBlocker.java
@@ -5,16 +5,16 @@
 package org.chromium.content.browser;
 
 import org.chromium.base.CalledByNative;
-import org.chromium.ui.WindowAndroid;
+import org.chromium.ui.ViewAndroid;
 
 class PowerSaveBlocker {
     @CalledByNative
-    private static void applyBlock(WindowAndroid windowAndroid) {
-        windowAndroid.keepScreenOn(true);
+    private static void applyBlock(ViewAndroid view) {
+        view.incrementKeepScreenOnCount();
     }
 
     @CalledByNative
-    private static void removeBlock(WindowAndroid windowAndroid) {
-        windowAndroid.keepScreenOn(false);
+    private static void removeBlock(ViewAndroid view) {
+        view.decrementKeepScreenOnCount();
     }
 }
\ No newline at end of file
diff --git a/content/public/android/java/src/org/chromium/content/browser/ResourceExtractor.java b/content/public/android/java/src/org/chromium/content/browser/ResourceExtractor.java
index 2b650ce..8a943f7 100644
--- a/content/public/android/java/src/org/chromium/content/browser/ResourceExtractor.java
+++ b/content/public/android/java/src/org/chromium/content/browser/ResourceExtractor.java
@@ -52,11 +52,6 @@
 
         @Override
         protected Void doInBackground(Void... unused) {
-            if (sMandatoryPaks == null) {
-                assert false : "No pak files specified.  Call setMandatoryPaksToExtract before "
-                        + "beginning the resource extractions";
-                return null;
-            }
             if (!mOutputDir.exists() && !mOutputDir.mkdirs()) {
                 Log.e(LOGTAG, "Unable to create pak resources directory!");
                 return null;
@@ -242,7 +237,8 @@
     /**
      * Specifies the .pak files that should be extracted from the APK's asset resources directory
      * and moved to {@link #getOutputDirFromContext(Context)}.
-     * @param mandatoryPaks The list of pak files to be loaded.
+     * @param mandatoryPaks The list of pak files to be loaded. If no pak files are
+     *     required, pass a single empty string.
      */
     public static void setMandatoryPaksToExtract(String... mandatoryPaks) {
         assert (sInstance == null || sInstance.mExtractTask == null)
@@ -271,6 +267,10 @@
     }
 
     public void waitForCompletion() {
+        if (shouldSkipPakExtraction()) {
+            return;
+        }
+
         assert mExtractTask != null;
 
         try {
@@ -296,6 +296,10 @@
             return;
         }
 
+        if (shouldSkipPakExtraction()) {
+            return;
+        }
+
         mExtractTask = new ExtractTask();
         mExtractTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
     }
@@ -315,4 +319,14 @@
             }
         }
     }
+
+    /**
+     * Pak extraction not necessarily required by the embedder; we allow them to skip
+     * this process if they call setMandatoryPaksToExtract with a single empty String.
+     */
+    private static boolean shouldSkipPakExtraction() {
+        // Must call setMandatoryPaksToExtract before beginning resource extraction.
+        assert sMandatoryPaks != null;
+        return sMandatoryPaks.length == 1 && "".equals(sMandatoryPaks[0]);
+    }
 }
diff --git a/content/public/browser/browser_thread.h b/content/public/browser/browser_thread.h
index 5f9fc22..ab44eda 100644
--- a/content/public/browser/browser_thread.h
+++ b/content/public/browser/browser_thread.h
@@ -179,9 +179,9 @@
   // Windows registry.
   static base::SequencedWorkerPool* GetBlockingPool();
 
-  // Callable on any thread.  Returns whether the given ID corresponds to a well
-  // known thread.
-  static bool IsWellKnownThread(ID identifier);
+  // Callable on any thread.  Returns whether the given well-known thread is
+  // initialized.
+  static bool IsThreadInitialized(ID identifier);
 
   // Callable on any thread.  Returns whether you're currently on a particular
   // thread.
diff --git a/content/public/browser/download_manager.h b/content/public/browser/download_manager.h
index 35f191b..37c6d09 100644
--- a/content/public/browser/download_manager.h
+++ b/content/public/browser/download_manager.h
@@ -52,7 +52,6 @@
 class DownloadQuery;
 class DownloadRequestHandle;
 struct DownloadCreateInfo;
-struct DownloadRetrieveInfo;
 
 // Browser's download manager: manages all downloads and destination view.
 class CONTENT_EXPORT DownloadManager : public base::SupportsUserData::Data {
@@ -145,6 +144,8 @@
       const GURL& referrer_url,
       const base::Time& start_time,
       const base::Time& end_time,
+      const std::string& etag,
+      const std::string& last_modified,
       int64 received_bytes,
       int64 total_bytes,
       DownloadItem::DownloadState state,
diff --git a/content/public/browser/download_manager_delegate.cc b/content/public/browser/download_manager_delegate.cc
index c33fcd4..9351ce2 100644
--- a/content/public/browser/download_manager_delegate.cc
+++ b/content/public/browser/download_manager_delegate.cc
@@ -38,6 +38,11 @@
   return false;
 }
 
+std::string
+DownloadManagerDelegate::ApplicationClientIdForFileScanning() const {
+  return std::string();
+}
+
 DownloadManagerDelegate::~DownloadManagerDelegate() {}
 
 }  // namespace content
diff --git a/content/public/browser/download_manager_delegate.h b/content/public/browser/download_manager_delegate.h
index 98bad43..89be2df 100644
--- a/content/public/browser/download_manager_delegate.h
+++ b/content/public/browser/download_manager_delegate.h
@@ -129,6 +129,12 @@
       DownloadItem* download,
       const CheckForFileExistenceCallback& callback) {}
 
+  // Return a GUID string used for identifying the application to the
+  // system AV function for scanning downloaded files. If an empty
+  // or invalid GUID string is returned, no client identification
+  // will be given to the AV function.
+  virtual std::string ApplicationClientIdForFileScanning() const;
+
  protected:
   virtual ~DownloadManagerDelegate();
 };
diff --git a/content/public/browser/storage_partition.h b/content/public/browser/storage_partition.h
index f69feaa..b30ca42 100644
--- a/content/public/browser/storage_partition.h
+++ b/content/public/browser/storage_partition.h
@@ -64,7 +64,7 @@
     REMOVE_DATA_MASK_LOCAL_STORAGE = 1 << 4,
     REMOVE_DATA_MASK_SHADER_CACHE = 1 << 5,
     REMOVE_DATA_MASK_WEBSQL = 1 << 6,
-
+    REMOVE_DATA_MASK_WEBRTC_IDENTITY = 1 << 7,
     REMOVE_DATA_MASK_ALL = -1
   };
 
diff --git a/content/public/browser/web_contents.h b/content/public/browser/web_contents.h
index 35a6eac..86b51a2 100644
--- a/content/public/browser/web_contents.h
+++ b/content/public/browser/web_contents.h
@@ -79,7 +79,12 @@
     CreateParams(BrowserContext* context, SiteInstance* site);
 
     BrowserContext* browser_context;
+
+    // Specifying a SiteInstance here is optional.  It can be set to avoid an
+    // extra process swap if the first navigation is expected to require a
+    // privileged process.
     SiteInstance* site_instance;
+
     WebContents* opener;
     int routing_id;
     int main_frame_routing_id;
diff --git a/content/public/common/content_constants.cc b/content/public/common/content_constants.cc
index 5c73ecd..75e9273 100644
--- a/content/public/common/content_constants.cc
+++ b/content/public/common/content_constants.cc
@@ -3,6 +3,7 @@
 // found in the LICENSE file.
 
 #include "content/public/common/content_constants.h"
+
 namespace content {
 
 const base::FilePath::CharType kAppCacheDirname[] =
@@ -12,6 +13,14 @@
 
 const char kBrowserPluginMimeType[] = "application/browser-plugin";
 
+const char kFlashPluginName[] = "Shockwave Flash";
+const char kFlashPluginSwfMimeType[] = "application/x-shockwave-flash";
+const char kFlashPluginSwfExtension[] = "swf";
+const char kFlashPluginSwfDescription[] = "Shockwave Flash";
+const char kFlashPluginSplMimeType[] = "application/futuresplash";
+const char kFlashPluginSplExtension[] = "spl";
+const char kFlashPluginSplDescription[] = "FutureSplash Player";
+
 // This number used to be limited to 32 in the past (see b/535234).
 const size_t kMaxRendererProcessCount = 82;
 const int kMaxSessionHistoryEntries = 50;
diff --git a/content/public/common/content_constants.h b/content/public/common/content_constants.h
index c6d3dd5..012b00f 100644
--- a/content/public/common/content_constants.h
+++ b/content/public/common/content_constants.h
@@ -24,6 +24,14 @@
 // The MIME type used for the browser plugin.
 CONTENT_EXPORT extern const char kBrowserPluginMimeType[];
 
+CONTENT_EXPORT extern const char kFlashPluginName[];
+CONTENT_EXPORT extern const char kFlashPluginSwfMimeType[];
+CONTENT_EXPORT extern const char kFlashPluginSwfExtension[];
+CONTENT_EXPORT extern const char kFlashPluginSwfDescription[];
+CONTENT_EXPORT extern const char kFlashPluginSplMimeType[];
+CONTENT_EXPORT extern const char kFlashPluginSplExtension[];
+CONTENT_EXPORT extern const char kFlashPluginSplDescription[];
+
 CONTENT_EXPORT extern const size_t kMaxRendererProcessCount;
 
 // The maximum number of session history entries per tab.
diff --git a/content/public/common/content_switches.cc b/content/public/common/content_switches.cc
index 40e932b..07c6ff3f 100644
--- a/content/public/common/content_switches.cc
+++ b/content/public/common/content_switches.cc
@@ -10,18 +10,33 @@
 // override for developers who need the old behavior for testing.
 const char kAllowFileAccessFromFiles[]      = "allow-file-access-from-files";
 
+// Enables the sandboxed processes to run without a job object assigned to them.
+// This flag is required to allow Chrome to run in RemoteApps or Citrix. This
+// flag can reduce the security of the sandboxed processes and allow them to do
+// certain API calls like shut down Windows or access the clipboard. Also we
+// lose the chance to kill some processes until the outer job that owns them
+// finishes.
+const char kAllowNoSandboxJob[]             = "allow-no-sandbox-job";
+
 // Allows debugging of sandboxed processes (see zygote_main_linux.cc).
 const char kAllowSandboxDebugging[]         = "allow-sandbox-debugging";
 
 // Allow compositing on chrome:// pages.
 const char kAllowWebUICompositing[]         = "allow-webui-compositing";
 
+// The same as kAuditHandles except all handles are enumerated.
+const char kAuditAllHandles[]               = "enable-handle-auditing-all";
+
 // Enumerates and prints a child process' most dangerous handles when it
 // is terminated.
 const char kAuditHandles[]                  = "enable-handle-auditing";
 
-// The same as kAuditHandles except all handles are enumerated.
-const char kAuditAllHandles[]               = "enable-handle-auditing-all";
+// Blacklist the GPU for accelerated compositing.
+const char kBlacklistAcceleratedCompositing[] =
+    "blacklist-accelerated-compositing";
+
+// Blacklist the GPU for WebGL.
+const char kBlacklistWebGL[]                = "blacklist-webgl";
 
 // Causes the browser process to throw an assertion on startup.
 const char kBrowserAssertTest[]             = "assert-test";
@@ -32,6 +47,16 @@
 // Path to the exe to run for the renderer and plugin subprocesses.
 const char kBrowserSubprocessPath[]         = "browser-subprocess-path";
 
+// Dumps extra logging about plugin loading to the log file.
+const char kDebugPluginLoading[] = "debug-plugin-loading";
+
+// Sets the tile size used by composited layers.
+const char kDefaultTileWidth[]              = "default-tile-width";
+const char kDefaultTileHeight[]             = "default-tile-height";
+
+// Disable antialiasing on 2d canvas.
+const char kDisable2dCanvasAntialiasing[]   = "disable-canvas-aa";
+
 // Disables client-visible 3D APIs, in particular WebGL and Pepper 3D.
 // This is controlled by policy and is kept separate from the other
 // enable/disable switches to avoid accidentally regressing the policy
@@ -41,25 +66,31 @@
 // Disable gpu-accelerated 2d canvas.
 const char kDisableAccelerated2dCanvas[]    = "disable-accelerated-2d-canvas";
 
-// Disable antialiasing on 2d canvas.
-const char kDisable2dCanvasAntialiasing[]   = "disable-canvas-aa";
-
-// Enable experimental canvas features, e.g. canvas 2D context attributes
-const char kEnableExperimentalCanvasFeatures[]
-                                        = "enable-experimental-canvas-features";
-
 // Disables accelerated compositing.
 const char kDisableAcceleratedCompositing[] = "disable-accelerated-compositing";
 
+// Disables accelerated compositing for backgrounds of root layers with
+// background-attachment: fixed.
+const char kDisableAcceleratedFixedRootBackground[] =
+    "disable-accelerated-fixed-root-background";
+
 // Disables the hardware acceleration of 3D CSS and animation.
 const char kDisableAcceleratedLayers[]      = "disable-accelerated-layers";
 
+// Disables accelerated compositing for overflow scroll.
+const char kDisableAcceleratedOverflowScroll[] =
+    "disable-accelerated-overflow-scroll";
+
 // Disables the hardware acceleration of plugins.
 const char kDisableAcceleratedPlugins[]     = "disable-accelerated-plugins";
 
 // Disables GPU accelerated video display.
 const char kDisableAcceleratedVideo[]       = "disable-accelerated-video";
 
+// Disables hardware acceleration of video decode, where available.
+const char kDisableAcceleratedVideoDecode[] =
+    "disable-accelerated-video-decode";
+
 // Disables the alternate window station for the renderer.
 const char kDisableAltWinstation[]          = "disable-winsta";
 
@@ -74,9 +105,24 @@
 // users with many windows/tabs and lots of memory.
 const char kDisableBackingStoreLimit[]      = "disable-backing-store-limit";
 
+// Enables browser plugin compositing experiment.
+const char kDisableBrowserPluginCompositing[] =
+    "disable-browser-plugin-compositing";
+
+// See comment for kEnableCompositingForFixedPosition.
+const char kDisableCompositingForFixedPosition[] =
+     "disable-fixed-position-compositing";
+
+// See comment for kEnableCompositingForTransition.
+const char kDisableCompositingForTransition[] =
+     "disable-transition-compositing";
+
 // Disables HTML5 DB support.
 const char kDisableDatabases[]              = "disable-databases";
 
+// Disables delegated renderer.
+const char kDisableDelegatedRenderer[]      = "disable-delegated-renderer";
+
 // Disables desktop notifications (default enabled on windows).
 const char kDisableDesktopNotifications[]   = "disable-desktop-notifications";
 
@@ -86,28 +132,40 @@
 // Disable experimental WebGL support.
 const char kDisableExperimentalWebGL[]      = "disable-webgl";
 
-// Blacklist the GPU for accelerated compositing.
-const char kBlacklistAcceleratedCompositing[] =
-    "blacklist-accelerated-compositing";
-
-// Blacklist the GPU for WebGL.
-const char kBlacklistWebGL[]                = "blacklist-webgl";
-
 // Disable FileSystem API.
 const char kDisableFileSystem[]             = "disable-file-system";
 
+const char kDisableFixedPositionCreatesStackingContext[]
+    = "disable-fixed-position-creates-stacking-context";
+
 // Disable 3D inside of flapper.
 const char kDisableFlash3d[]                = "disable-flash-3d";
 
 // Disable Stage3D inside of flapper.
 const char kDisableFlashStage3d[]           = "disable-flash-stage3d";
 
+// This flag disables force compositing mode and prevents it from being enabled
+// via field trials.
+const char kDisableForceCompositingMode[]   = "disable-force-compositing-mode";
+
+// Disable the JavaScript Full Screen API.
+const char kDisableFullScreen[]             = "disable-fullscreen";
+
 // Suppresses support for the Geolocation javascript API.
 const char kDisableGeolocation[]            = "disable-geolocation";
 
+const char kDisableGestureTapHighlight[]    = "disable-gesture-tap-highlight";
+
 // Disable GL multisampling.
 const char kDisableGLMultisampling[]        = "disable-gl-multisampling";
 
+// Disables GPU hardware acceleration.  If software renderer is not in place,
+// then the GPU process won't launch.
+const char kDisableGpu[]                    = "disable-gpu";
+
+// Prevent the compositor from using its GPU implementation.
+const char kDisableGpuCompositing[]         = "disable-gpu-compositing";
+
 // 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";
@@ -115,41 +173,34 @@
 // Disable the GPU process sandbox.
 const char kDisableGpuSandbox[]             = "disable-gpu-sandbox";
 
-// Reduces the GPU process sandbox to be less strict.
-const char kReduceGpuSandbox[]              = "reduce-gpu-sandbox";
+// Disable the thread that crashes the GPU process if it stops responding to
+// messages.
+const char kDisableGpuWatchdog[]            = "disable-gpu-watchdog";
 
 // Suppresses hang monitor dialogs in renderer processes.  This may allow slow
 // unload handlers on a page to prevent the tab from closing, but the Task
 // Manager can be used to terminate the offending process in this case.
 const char kDisableHangMonitor[]            = "disable-hang-monitor";
 
-// Disables HTML-based desktop notifications.
-const char kDisableHTMLNotifications[]      = "disable-html-notifications";
-
 // Disable the RenderThread's HistogramCustomizer.
 const char kDisableHistogramCustomizer[]    = "disable-histogram-customizer";
 
+// Disables HTML-based desktop notifications.
+const char kDisableHTMLNotifications[]      = "disable-html-notifications";
+
 // Disable the use of an ImageTransportSurface. This means the GPU process
 // will present the rendered page rather than the browser process.
 const char kDisableImageTransportSurface[]  = "disable-image-transport-surface";
 
-// Use hardware gpu, if available, for tests.
-const char kUseGpuInTests[]                 = "use-gpu-in-tests";
-
-// Disables GPU hardware acceleration.  If software renderer is not in place,
-// then the GPU process won't launch.
-const char kDisableGpu[]                    = "disable-gpu";
-
-// Disable the thread that crashes the GPU process if it stops responding to
-// messages.
-const char kDisableGpuWatchdog[]            = "disable-gpu-watchdog";
-
 // Prevent Java from running.
 const char kDisableJava[]                   = "disable-java";
 
 // Don't execute JavaScript (browser JS like the new tab page still runs).
 const char kDisableJavaScript[]             = "disable-javascript";
 
+// Disables prefixed Encrypted Media API (e.g. webkitGenerateKeyRequest()).
+const char kDisableLegacyEncryptedMedia[] = "disable-legacy-encrypted-media";
+
 // Disable LocalStorage.
 const char kDisableLocalStorage[]           = "disable-local-storage";
 
@@ -157,13 +208,20 @@
 // builds.
 const char kDisableLogging[]                = "disable-logging";
 
-// Enables displaying net log events on the command line, or writing the events
-// to a separate file if a file name is given.
-const char kLogNetLog[]                     = "log-net-log";
+// Disable Pepper3D.
+const char kDisablePepper3d[]               = "disable-pepper-3d";
+
+// Disables compositor-accelerated touch-screen pinch gestures.
+const char kDisablePinch[]                  = "disable-pinch";
 
 // Prevent plugins from running.
 const char kDisablePlugins[]                = "disable-plugins";
 
+// Disable discovering third-party plug-ins. Effectively loading only
+// ones shipped with the browser plus third-party ones as specified by
+// --extra-plugin-dir and --load-plugin switches.
+const char kDisablePluginsDiscovery[]       = "disable-plugins-discovery";
+
 // Disables remote web font support. SVG font should always work whether this
 // option is specified or not.
 const char kDisableRemoteFonts[]            = "disable-remote-fonts";
@@ -171,12 +229,6 @@
 // Turns off the accessibility in the renderer.
 const char kDisableRendererAccessibility[]  = "disable-renderer-accessibility";
 
-// Disable False Start in SSL and TLS connections.
-const char kDisableSSLFalseStart[]          = "disable-ssl-false-start";
-
-// Disable smooth scrolling for testing.
-const char kDisableSmoothScrolling[]        = "disable-smooth-scrolling";
-
 // Disable the seccomp filter sandbox (seccomp-bpf) (Linux only).
 const char kDisableSeccompFilterSandbox[]   = "disable-seccomp-filter-sandbox";
 
@@ -192,60 +244,33 @@
 // Disables site-specific tailoring to compatibility issues in WebKit.
 const char kDisableSiteSpecificQuirks[]     = "disable-site-specific-quirks";
 
+// Disable smooth scrolling for testing.
+const char kDisableSmoothScrolling[]        = "disable-smooth-scrolling";
+
+// Disables the use of a 3D software rasterizer.
+const char kDisableSoftwareRasterizer[]     = "disable-software-rasterizer";
+
 // Disables speech input.
 const char kDisableSpeechInput[]            = "disable-speech-input";
 
-// Specifies the request key for the continuous speech recognition webservice.
-const char kSpeechRecognitionWebserviceKey[] = "speech-service-key";
+// Disable False Start in SSL and TLS connections.
+const char kDisableSSLFalseStart[]          = "disable-ssl-false-start";
 
-// Enables the synthesis part of the Web Speech API.
-const char kEnableSpeechSynthesis[]          = "enable-speech-synthesis";
+// Disable multithreaded GPU compositing of web content.
+const char kDisableThreadedCompositing[]     = "disable-threaded-compositing";
 
-#if defined(OS_ANDROID)
-// WebRTC is enabled by default on Android.
-const char kDisableWebRTC[]                 = "disable-webrtc";
-
-// Enable the recognition part of the Web Speech API.
-const char kEnableSpeechRecognition[]       = "enable-speech-recognition";
-
-#endif
+// Disables the threaded HTML parser in WebKit
+const char kDisableThreadedHTMLParser[]     = "disable-threaded-html-parser";
 
 // Disable web audio API.
 const char kDisableWebAudio[]               = "disable-webaudio";
 
-#if defined(ENABLE_WEBRTC)
-// Enables WebRTC AEC recordings.
-const char kEnableWebRtcAecRecordings[]     = "enable-webrtc-aec-recordings";
-
-// Enable WebRTC DataChannels SCTP wire protocol support.
-const char kEnableSCTPDataChannels[]        = "enable-sctp-data-channels";
-
-// Disable WebRTC device enumeration.
-const char kDisableDeviceEnumeration[]        = "disable-device-enumeration";
-
-#endif
-
-// Enable WebRTC to open TCP server sockets.
-const char kEnableWebRtcTcpServerSocket[]   = "enable-webrtc-tcp-server-socket";
-
-// Enables HW decode acceleration for WebRTC.
-const char kEnableWebRtcHWDecoding[]        = "enable-webrtc-hw-decoding";
-
-// Enable CSS Transitions / Animations on the Web Animations model.
-const char kEnableWebAnimationsCSS[]        = "enable-web-animations-css";
-
-// Enable SVG Animations on the Web Animations model.
-const char kEnableWebAnimationsSVG[]        = "enable-web-animations-svg";
-
-// Enables Web MIDI API.
-const char kEnableWebMIDI[]                 = "enable-web-midi";
+// Disables prefixed Media Source API (i.e., the WebKitMediaSource object).
+const char kDisableWebKitMediaSource[]      = "disable-webkit-media-source";
 
 // Don't enforce the same-origin policy. (Used by people testing their sites.)
 const char kDisableWebSecurity[]            = "disable-web-security";
 
-// Enable an experimental WebSocket implementation.
-const char kEnableExperimentalWebSocket[] = "enable-experimental-websocket";
-
 // Disables WebKit's XSSAuditor. The XSSAuditor mitigates reflective XSS.
 const char kDisableXSSAuditor[]             = "disable-xss-auditor";
 
@@ -255,16 +280,24 @@
 // based tests.
 const char kDomAutomationController[]       = "dom-automation";
 
-// Specifies if the |StatsCollectionController| needs to be bound in the
-// renderer. This binding happens on per-frame basis and hence can potentially
-// be a performance bottleneck. One should only enable it when running a test
-// that needs to access the provided statistics.
-const char kStatsCollectionController[] =
-    "enable-stats-collection-bindings";
-
 // Enable gpu-accelerated SVG/W3C filters.
 const char kEnableAcceleratedFilters[]      = "enable-accelerated-filters";
 
+// Enables accelerated compositing for backgrounds of root layers with
+// background-attachment: fixed. Requires kForceCompositingMode.
+const char kEnableAcceleratedFixedRootBackground[] =
+    "enable-accelerated-fixed-root-background";
+
+// Enables accelerated compositing for overflow scroll. Promotes eligible
+// overflow:scroll elements to layers to enable accelerated scrolling for them.
+const char kEnableAcceleratedOverflowScroll[] =
+    "enable-accelerated-overflow-scroll";
+
+// Enables accelerated compositing for scrollable frames for accelerated
+// scrolling for them. Requires kForceCompositingMode.
+const char kEnableAcceleratedScrollableFrames[] =
+     "enable-accelerated-scrollable-frames";
+
 // Turns on extremely verbose logging of accessibility events.
 const char kEnableAccessibilityLogging[]    = "enable-accessibility-logging";
 
@@ -272,11 +305,13 @@
 //
 // TODO(miu): Remove --enable-audible-notifications once the feature goes
 // live.  http://crbug.com/178934
-const char kEnableAudibleNotifications[]   = "enable-audible-notifications";
+const char kEnableAudibleNotifications[]    = "enable-audible-notifications";
 
-// Enables browser plugin compositing experiment.
-const char kDisableBrowserPluginCompositing[] =
-    "disable-browser-plugin-compositing";
+// Use a begin frame signal from browser to renderer to schedule rendering.
+const char kEnableBeginFrameScheduling[]    = "enable-begin-frame-scheduling";
+
+// Synchronize delivery and response of input events to and from the renderer.
+const char kEnableBrowserInputController[]  = "enable-browser-input-controller";
 
 // Enables browser plugin for all types of pages.
 const char kEnableBrowserPluginForAllViewTypes[] =
@@ -286,7 +321,12 @@
 // kEnableBrowserPluginGuestViews must also be set at this time.
 const char kEnableBrowserPluginDragDrop[]   = "enable-browser-plugin-drag-drop";
 
-// Enable/Disable the creation of compositing layers for fixed position
+// Enables accelerated scrolling by the compositor for frames. Requires
+// kForceCompositingMode and kEnableAcceleratedScrollableFrames.
+const char kEnableCompositedScrollingForFrames[] =
+     "enable-composited-scrolling-for-frames";
+
+// Enable the creation of compositing layers for fixed position
 // elements. Three options are needed to support four possible scenarios:
 //  1. Default (disabled)
 //  2. Enabled always (to allow dogfooding)
@@ -298,10 +338,6 @@
 // override Option #4.
 const char kEnableCompositingForFixedPosition[] =
      "enable-fixed-position-compositing";
-const char kDisableCompositingForFixedPosition[] =
-     "disable-fixed-position-compositing";
-const char kEnableHighDpiCompositingForFixedPosition[] =
-     "enable-high-dpi-fixed-position-compositing";
 
 // Enable/Disable the creation of compositing layers for RenderLayers with a
 // transition on a property that supports accelerated animation (that is,
@@ -312,14 +348,12 @@
 //  3. Disabled always.
 const char kEnableCompositingForTransition[] =
      "enable-transition-compositing";
-const char kDisableCompositingForTransition[] =
-     "disable-transition-compositing";
 
 // Enables CSS3 custom filters
 const char kEnableCssShaders[]              = "enable-css-shaders";
 
-// Disables delegated renderer.
-const char kDisableDelegatedRenderer[]      = "disable-delegated-renderer";
+// Defer image decoding in WebKit until painting.
+const char kEnableDeferredImageDecoding[]   = "enable-deferred-image-decoding";
 
 // Enables delegated renderer.
 const char kEnableDelegatedRenderer[]       = "enable-delegated-renderer";
@@ -327,40 +361,33 @@
 // Enables device motion events.
 const char kEnableDeviceMotion[]            = "enable-device-motion";
 
-#if defined(OS_ANDROID)
-// Disables device motion events.
-const char kDisableDeviceMotion[]           = "disable-device-motion";
-#endif
-
 // Enables restarting interrupted downloads.
 const char kEnableDownloadResumption[]      = "enable-download-resumption";
 
+// Enables support for Encrypted Media Extensions (e.g. MediaKeys).
+const char kEnableEncryptedMedia[] = "enable-encrypted-media";
+
+// Enable experimental canvas features, e.g. canvas 2D context attributes
+const char kEnableExperimentalCanvasFeatures[] =
+    "enable-experimental-canvas-features";
+
 // Enables Web Platform features that are in development.
 const char kEnableExperimentalWebPlatformFeatures[] =
     "enable-experimental-web-platform-features";
 
-// Enables the CSS multicol implementation that uses the regions implementation.
-const char kEnableRegionBasedColumns[] =
-    "enable-region-based-columns";
-
-// Disables the threaded HTML parser in WebKit
-const char kDisableThreadedHTMLParser[]     = "disable-threaded-html-parser";
+// Enable an experimental WebSocket implementation.
+const char kEnableExperimentalWebSocket[]   = "enable-experimental-websocket";
 
 // By default, a page is laid out to fill the entire width of the window.
 // This flag fixes the layout of the page to a default of 980 CSS pixels,
 // or to a specified width and height using --enable-fixed-layout=w,h
 const char kEnableFixedLayout[]             = "enable-fixed-layout";
 
-// Disable the JavaScript Full Screen API.
-const char kDisableFullScreen[]             = "disable-fullscreen";
-
-// Enable Text Service Framework(TSF) for text inputting instead of IMM32. This
-// flag is ignored on Metro environment.
-const char kEnableTextServicesFramework[] = "enable-text-services-framework";
+const char kEnableFixedPositionCreatesStackingContext[]
+    = "enable-fixed-position-creates-stacking-context";
 
 // Enable Gesture Tap Highlight
-const char kEnableGestureTapHighlight[]    = "enable-gesture-tap-highlight";
-const char kDisableGestureTapHighlight[]   = "disable-gesture-tap-highlight";
+const char kEnableGestureTapHighlight[]     = "enable-gesture-tap-highlight";
 
 // Enables the GPU benchmarking extension
 const char kEnableGpuBenchmarking[]         = "enable-gpu-benchmarking";
@@ -368,34 +395,22 @@
 // Enables TRACE for GL calls in the renderer.
 const char kEnableGpuClientTracing[]        = "enable-gpu-client-tracing";
 
+// See comment for kEnableCompositingForFixedPosition.
+const char kEnableHighDpiCompositingForFixedPosition[] =
+     "enable-high-dpi-fixed-position-compositing";
+
+// Enable HTML Imports
+extern const char kEnableHTMLImports[]      = "enable-html-imports";
+
 // Enables support for inband text tracks in media content.
-const char kEnableInbandTextTracks[] = "enable-inband-text-tracks";
-
-// Enables the memory benchmarking extension
-const char kEnableMemoryBenchmarking[]      = "enable-memory-benchmarking";
-
-// Enables the Skia benchmarking extension
-const char kEnableSkiaBenchmarking[]         = "enable-skia-benchmarking";
+const char kEnableInbandTextTracks[]        = "enable-inband-text-tracks";
 
 // Force logging to be enabled.  Logging is disabled by default in release
 // builds.
 const char kEnableLogging[]                 = "enable-logging";
 
-// Disables prefixed Media Source API (i.e., the WebKitMediaSource object).
-const char kDisableWebKitMediaSource[]      = "disable-webkit-media-source";
-
-// Enables support for Encrypted Media Extensions (e.g. MediaKeys).
-const char kEnableEncryptedMedia[] = "enable-encrypted-media";
-
-// Disables prefixed Encrypted Media API (e.g. webkitGenerateKeyRequest()).
-const char kDisableLegacyEncryptedMedia[] = "disable-legacy-encrypted-media";
-
-// Use fake device for MediaStream to replace actual camera and microphone.
-const char kUseFakeDeviceForMediaStream[] = "use-fake-device-for-media-stream";
-
-// Bypass the media stream infobar by selecting the default device for media
-// streams (e.g. WebRTC). Works with --use-fake-device-for-media-stream.
-const char kUseFakeUIForMediaStream[]     = "use-fake-ui-for-media-stream";
+// Enables the memory benchmarking extension
+const char kEnableMemoryBenchmarking[]      = "enable-memory-benchmarking";
 
 // On Windows, converts the page to the currently-installed monitor profile.
 // This does NOT enable color management for images. The source is still
@@ -406,13 +421,15 @@
 // http://crbug.com/260005
 const char kEnableNewMediaInternals[]       = "enable-new-media-internals";
 
-// Enables compositor-accelerated touch-screen pinch gestures.
-const char kEnablePinch[]                   = "enable-pinch";
-const char kDisablePinch[]                  = "disable-pinch";
-
 // Enables use of cache if offline, even if it's stale
 const char kEnableOfflineCacheAccess[]      = "enable-offline-cache-access";
 
+// Forward overscroll event data from the renderer to the browser.
+const char kEnableOverscrollNotifications[] = "enable-overscroll-notifications";
+
+// Enables compositor-accelerated touch-screen pinch gestures.
+const char kEnablePinch[]                   = "enable-pinch";
+
 // Enable caching of pre-parsed JS script data.  See http://crbug.com/32407.
 const char kEnablePreparsedJsCaching[]      = "enable-preparsed-js-caching";
 
@@ -425,23 +442,32 @@
 const char kEnablePruneGpuCommandBuffers[] =
     "enable-prune-gpu-command-buffers";
 
-// Enable screen capturing support for MediaStream API.
-const char kEnableUserMediaScreenCapturing[] =
-    "enable-usermedia-screen-capturing";
-
-// Enables TLS cached info extension.
-const char kEnableSSLCachedInfo[]  = "enable-ssl-cached-info";
+// Enables the CSS multicol implementation that uses the regions implementation.
+const char kEnableRegionBasedColumns[] =
+    "enable-region-based-columns";
 
 // Cause the OS X sandbox write to syslog every time an access to a resource
 // is denied by the sandbox.
 const char kEnableSandboxLogging[]          = "enable-sandbox-logging";
 
-// Enable spatial navigation
-const char kEnableSpatialNavigation[]       = "enable-spatial-navigation";
+// Enables the Skia benchmarking extension
+const char kEnableSkiaBenchmarking[]        = "enable-skia-benchmarking";
 
 // On platforms that support it, enables smooth scroll animation.
 const char kEnableSmoothScrolling[]         = "enable-smooth-scrolling";
 
+// Allow the compositor to use its software implementation if GL fails.
+const char kEnableSoftwareCompositing[]     = "enable-software-compositing";
+
+// Enable spatial navigation
+const char kEnableSpatialNavigation[]       = "enable-spatial-navigation";
+
+// Enables the synthesis part of the Web Speech API.
+const char kEnableSpeechSynthesis[]         = "enable-speech-synthesis";
+
+// Enables TLS cached info extension.
+const char kEnableSSLCachedInfo[]           = "enable-ssl-cached-info";
+
 // Enables StatsTable, logging statistics to a global named shared memory table.
 const char kEnableStatsTable[]              = "enable-stats-table";
 
@@ -457,29 +483,51 @@
 // cookies on cross-site requests.
 const char kEnableStrictSiteIsolation[]     = "enable-strict-site-isolation";
 
-// Enable multithreaded GPU compositing of web content.
-const char kEnableThreadedCompositing[]     = "enable-threaded-compositing";
-
-// Allow GL contexts to be automatically virtualized (shared between command
-// buffer clients) if they are compatible.
-const char kEnableVirtualGLContexts[]       = "enable-virtual-gl-contexts";
-
-// Disable multithreaded GPU compositing of web content.
-const char kDisableThreadedCompositing[]     = "disable-threaded-compositing";
-
 // Enable use of experimental TCP sockets API for sending data in the
 // SYN packet.
 const char kEnableTcpFastOpen[]             = "enable-tcp-fastopen";
 
-// Disables hardware acceleration of video decode, where available.
-const char kDisableAcceleratedVideoDecode[] =
-    "disable-accelerated-video-decode";
+// Enable Text Service Framework(TSF) for text inputting instead of IMM32. This
+// flag is ignored on Metro environment.
+const char kEnableTextServicesFramework[]   = "enable-text-services-framework";
+
+// Enable multithreaded GPU compositing of web content.
+const char kEnableThreadedCompositing[]     = "enable-threaded-compositing";
+
+// Enable screen capturing support for MediaStream API.
+const char kEnableUserMediaScreenCapturing[] =
+    "enable-usermedia-screen-capturing";
 
 // Enables the use of the viewport meta tag, which allows
 // pages to control aspects of their own layout. This also turns on touch-screen
 // pinch gestures.
 const char kEnableViewport[]                = "enable-viewport";
 
+// Allow GL contexts to be automatically virtualized (shared between command
+// buffer clients) if they are compatible.
+const char kEnableVirtualGLContexts[]       = "enable-virtual-gl-contexts";
+
+// Enables moving cursor by word in visual order.
+const char kEnableVisualWordMovement[]      = "enable-visual-word-movement";
+
+// Enable the Vtune profiler support.
+const char kEnableVtune[]                   = "enable-vtune-support";
+
+// Enable CSS Transitions / Animations on the Web Animations model.
+const char kEnableWebAnimationsCSS[]        = "enable-web-animations-css";
+
+// Enable SVG Animations on the Web Animations model.
+const char kEnableWebAnimationsSVG[]        = "enable-web-animations-svg";
+
+// Enables WebGL extensions not yet approved by the community.
+const char kEnableWebGLDraftExtensions[] = "enable-webgl-draft-extensions";
+
+// Enables Web MIDI API.
+const char kEnableWebMIDI[]                 = "enable-web-midi";
+
+// Enable WebRTC to open TCP server sockets.
+const char kEnableWebRtcTcpServerSocket[]   = "enable-webrtc-tcp-server-socket";
+
 // Enables experimental features for the geolocation API.
 // Current features:
 // - CoreLocation support for Mac OS X 10.6
@@ -487,14 +535,13 @@
 // - Location platform support for Windows 7
 const char kExperimentalLocationFeatures[]  = "experimental-location-features";
 
+// Load NPAPI plugins from the specified directory.
+const char kExtraPluginDir[]                = "extra-plugin-dir";
+
 // If accelerated compositing is supported, always enter compositing mode for
 // the base layer even when compositing is not strictly required.
 const char kForceCompositingMode[]          = "force-compositing-mode";
 
-// This flag disables force compositing mode and prevents it from being enabled
-// via field trials.
-const char kDisableForceCompositingMode[]   = "disable-force-compositing-mode";
-
 // Some field trials may be randomized in the browser, and the randomly selected
 // outcome needs to be propagated to the renderer. For instance, this is used
 // to modify histograms recorded in the renderer, or to get the renderer to
@@ -510,12 +557,6 @@
 // overrides this if present.
 const char kForceRendererAccessibility[]    = "force-renderer-accessibility";
 
-// Allow the compositor to use its software implementation if GL fails.
-const char kEnableSoftwareCompositing[] = "enable-software-compositing";
-
-// Prevent the compositor from using its GPU implementation.
-const char kDisableGpuCompositing[] = "disable-gpu-compositing";
-
 // Passes gpu device_id from browser process to GPU process.
 const char kGpuDeviceID[]                   = "gpu-device-id";
 
@@ -541,12 +582,6 @@
 // Passes gpu vendor_id from browser process to GPU process.
 const char kGpuVendorID[]                   = "gpu-vendor-id";
 
-#if defined(OS_ANDROID)
-// Don't display any scrollbars. This is useful for Android WebView where
-// the system manages the scrollbars instead.
-const char kHideScrollbars[]                = "hide-scrollbars";
-#endif
-
 // These mappings only apply to the host resolver.
 const char kHostResolverRules[]             = "host-resolver-rules";
 
@@ -565,24 +600,24 @@
 // Specifies the flags passed to JS engine
 const char kJavaScriptFlags[]               = "js-flags";
 
-// Load NPAPI plugins from the specified directory.
-const char kExtraPluginDir[]                = "extra-plugin-dir";
-
 // Load an NPAPI plugin from the specified path.
 const char kLoadPlugin[]                    = "load-plugin";
 
-// Disable discovering third-party plug-ins. Effectively loading only
-// ones shipped with the browser plus third-party ones as specified by
-// --extra-plugin-dir and --load-plugin switches.
-const char kDisablePluginsDiscovery[]       = "disable-plugins-discovery";
-
 // Sets the minimum log level. Valid values are from 0 to 3:
 // INFO = 0, WARNING = 1, LOG_ERROR = 2, LOG_FATAL = 3.
 const char kLoggingLevel[]                  = "log-level";
 
+// Enables displaying net log events on the command line, or writing the events
+// to a separate file if a file name is given.
+const char kLogNetLog[]                     = "log-net-log";
+
 // Make plugin processes log their sent and received messages to VLOG(1).
 const char kLogPluginMessages[]             = "log-plugin-messages";
 
+// Sets the width and height above which a composited layer will get tiled.
+const char kMaxUntiledLayerHeight[]         = "max-untiled-layer-height";
+const char kMaxUntiledLayerWidth[]          = "max-untiled-layer-width";
+
 // Sample memory usage with high frequency and store the results to the
 // Renderer.Memory histogram. Used in memory tests.
 const char kMemoryMetrics[]                 = "memory-metrics";
@@ -597,13 +632,11 @@
 // Disables the sandbox for all process types that are normally sandboxed.
 const char kNoSandbox[]                     = "no-sandbox";
 
-// Enables the sandboxed processes to run without a job object assigned to them.
-// This flag is required to allow Chrome to run in RemoteApps or Citrix. This
-// flag can reduce the security of the sandboxed processes and allow them to do
-// certain API calls like shut down Windows or access the clipboard. Also we
-// lose the chance to kill some processes until the outer job that owns them
-// finishes.
-const char kAllowNoSandboxJob[]             = "allow-no-sandbox-job";
+// Enables or disables history navigation in response to horizontal overscroll.
+// Set the value to '1' to enable the feature, and set to '0' to disable.
+// Defaults to enabled.
+const char kOverscrollHistoryNavigation[] =
+    "overscroll-history-navigation";
 
 // Specifies a command that should be used to launch the plugin process.  Useful
 // for running the plugin process through purify or quantify.  Ex:
@@ -622,6 +655,9 @@
 // Argument to the process type that indicates a PPAPI broker process type.
 const char kPpapiBrokerProcess[]            = "ppapi-broker";
 
+// "Command-line" arguments for the PPAPI Flash; used for debugging options.
+const char kPpapiFlashArgs[]                = "ppapi-flash-args";
+
 // Runs PPAPI (Pepper) plugins in-process.
 const char kPpapiInProcess[]                = "ppapi-in-process";
 
@@ -651,17 +687,16 @@
 // renderer or plugin host.  If it's empty, it's the browser.
 const char kProcessType[]                   = "type";
 
+// Reduces the GPU process sandbox to be less strict.
+const char kReduceGpuSandbox[]              = "reduce-gpu-sandbox";
+
 // Register Pepper plugins (see pepper_plugin_registry.cc for its format).
 const char kRegisterPepperPlugins[]         = "register-pepper-plugins";
 
+
 // Enables remote debug over HTTP on the specified port.
 const char kRemoteDebuggingPort[]           = "remote-debugging-port";
 
-#if defined(OS_ANDROID)
-// Enables remote debug over HTTP on the specified socket name.
-const char kRemoteDebuggingSocketName[]     = "remote-debugging-socket-name";
-#endif
-
 // Causes the renderer process to throw an assertion on launch.
 const char kRendererAssertTest[]            = "renderer-assert-test";
 
@@ -672,9 +707,6 @@
 // Causes the process to run as renderer instead of as browser.
 const char kRendererProcess[]               = "renderer";
 
-// Enable the Vtune profiler support.
-const char kEnableVtune[]                   = "enable-vtune-support";
-
 // Overrides the default/calculated limit to the number of renderer processes.
 // Very high values for this setting can lead to high memory/resource usage
 // or instability.
@@ -683,24 +715,10 @@
 // Causes the renderer process to display a dialog on launch.
 const char kRendererStartupDialog[]         = "renderer-startup-dialog";
 
-// Enables accelerated compositing for overflow scroll. Promotes eligible
-// overflow:scroll elements to layers to enable accelerated scrolling for them.
-const char kEnableAcceleratedOverflowScroll[] =
-    "enable-accelerated-overflow-scroll";
-
-// Disables accelerated compositing for overflow scroll.
-const char kDisableAcceleratedOverflowScroll[] =
-    "disable-accelerated-overflow-scroll";
-
-// Enables accelerated compositing for scrollable frames for accelerated
-// scrolling for them. Requires kForceCompositingMode.
-const char kEnableAcceleratedScrollableFrames[] =
-     "enable-accelerated-scrollable-frames";
-
-// Enables accelerated scrolling by the compositor for frames. Requires
-// kForceCompositingMode and kEnableAcceleratedScrollableFrames.
-const char kEnableCompositedScrollingForFrames[] =
-     "enable-composited-scrolling-for-frames";
+// Enables or disables scroll end effect in response to vertical overscroll.
+// Set the value to '1' to enable the feature, and set to '0' to disable.
+// Defaults to disabled.
+const char kScrollEndEffect[] = "scroll-end-effect";
 
 // Visibly render a border around paint rects in the web page to help debug
 // and study painting behavior.
@@ -734,24 +752,35 @@
 // content. The switch is intended only for tests.
 const char kSkipGpuDataLoading[]            = "skip-gpu-data-loading";
 
+// Specifies the request key for the continuous speech recognition webservice.
+const char kSpeechRecognitionWebserviceKey[] = "speech-service-key";
+
+// Specifies if the |StatsCollectionController| needs to be bound in the
+// renderer. This binding happens on per-frame basis and hence can potentially
+// be a performance bottleneck. One should only enable it when running a test
+// that needs to access the provided statistics.
+const char kStatsCollectionController[] =
+    "enable-stats-collection-bindings";
+
+// Upscale defaults to "good".
+const char kTabCaptureDownscaleQuality[]    = "tab-capture-downscale-quality";
+
 // Scaling quality for capturing tab. Should be one of "fast", "good" or "best".
 // One flag for upscaling, one for downscaling.
 // Upscale defaults to "best".
 const char kTabCaptureUpscaleQuality[]      = "tab-capture-upscale-quality";
-// Upscale defaults to "good".
-const char kTabCaptureDownscaleQuality[]    = "tab-capture-downscale-quality";
 
 // GestureTapDown events are deferred by this many miillseconds before
 // sending them to the renderer.
 const char kTapDownDeferralTimeMs[]         = "tap-down-deferral-time";
 
-// Runs the security test for the renderer sandbox.
-const char kTestSandbox[]                   = "test-sandbox";
-
 // Allows for forcing socket connections to http/https to use fixed ports.
 const char kTestingFixedHttpPort[]          = "testing-fixed-http-port";
 const char kTestingFixedHttpsPort[]         = "testing-fixed-https-port";
 
+// Runs the security test for the renderer sandbox.
+const char kTestSandbox[]                   = "test-sandbox";
+
 // Causes TRACE_EVENT flags to be recorded from startup. Optionally, can
 // specify the specific trace categories to include (e.g.
 // --trace-startup=base,net) otherwise, all events are recorded. Setting this
@@ -761,6 +790,11 @@
 // supported in the base-only TraceLog component).
 const char kTraceStartup[]                  = "trace-startup";
 
+// Sets the time in seconds until startup tracing ends. If omitted a default of
+// 5 seconds is used. Has no effect without --trace-startup, or if
+// --startup-trace-file=none was supplied.
+const char kTraceStartupDuration[]          = "trace-startup-duration";
+
 // If supplied, sets the file which startup tracing will be stored into, if
 // omitted the default will be used "chrometrace.log" in the current directory.
 // Has no effect unless --trace-startup is also supplied.
@@ -770,15 +804,25 @@
 // all events since startup.
 const char kTraceStartupFile[]              = "trace-startup-file";
 
-// Sets the time in seconds until startup tracing ends. If omitted a default of
-// 5 seconds is used. Has no effect without --trace-startup, or if
-// --startup-trace-file=none was supplied.
-const char kTraceStartupDuration[]          = "trace-startup-duration";
+
 
 // Prioritizes the UI's command stream in the GPU process
 extern const char kUIPrioritizeInGpuProcess[] =
     "ui-prioritize-in-gpu-process";
 
+// Use fake device for MediaStream to replace actual camera and microphone.
+const char kUseFakeDeviceForMediaStream[] = "use-fake-device-for-media-stream";
+
+// Bypass the media stream infobar by selecting the default device for media
+// streams (e.g. WebRTC). Works with --use-fake-device-for-media-stream.
+const char kUseFakeUIForMediaStream[]     = "use-fake-ui-for-media-stream";
+
+// Use hardware gpu, if available, for tests.
+const char kUseGpuInTests[]                 = "use-gpu-in-tests";
+
+// Set when Chromium should use a mobile user agent.
+const char kUseMobileUserAgent[] = "use-mobile-user-agent";
+
 // A string used to override the default user agent with a custom one.
 const char kUserAgent[]                     = "user-agent";
 
@@ -815,25 +859,50 @@
 // Causes the process to run as a renderer zygote.
 const char kZygoteProcess[]                 = "zygote";
 
-// Enables moving cursor by word in visual order.
-const char kEnableVisualWordMovement[]      = "enable-visual-word-movement";
+#if defined(ENABLE_WEBRTC)
+// Disable WebRTC device enumeration.
+const char kDisableDeviceEnumeration[]        = "disable-device-enumeration";
 
-// Set when Chromium should use a mobile user agent.
-const char kUseMobileUserAgent[] = "use-mobile-user-agent";
+// Enable WebRTC DataChannels SCTP wire protocol support.
+const char kEnableSCTPDataChannels[]        = "enable-sctp-data-channels";
+
+// Enables WebRTC AEC recordings.
+const char kEnableWebRtcAecRecordings[]     = "enable-webrtc-aec-recordings";
+
+// Enables HW decode acceleration for WebRTC.
+const char kEnableWebRtcHWDecoding[]        = "enable-webrtc-hw-decoding";
+
+#endif
 
 #if defined(OS_ANDROID)
-// Disable history logging for media elements.
-const char kDisableMediaHistoryLogging[]    = "disable-media-history";
+// Disables device motion events.
+const char kDisableDeviceMotion[]           = "disable-device-motion";
 
 // Disable user gesture requirement for media playback.
 const char kDisableGestureRequirementForMediaPlayback[] =
     "disable-gesture-requirement-for-media-playback";
 
-// The telephony region (ISO country code) to use in phone number detection.
-const char kNetworkCountryIso[] = "network-country-iso";
+// Disable history logging for media elements.
+const char kDisableMediaHistoryLogging[]    = "disable-media-history";
 
 // Disable overscroll edge effects like those found in Android views.
 const char kDisableOverscrollEdgeEffect[] = "disable-overscroll-edge-effect";
+
+// WebRTC is enabled by default on Android.
+const char kDisableWebRTC[]                 = "disable-webrtc";
+
+// Enable the recognition part of the Web Speech API.
+const char kEnableSpeechRecognition[]       = "enable-speech-recognition";
+
+// Don't display any scrollbars. This is useful for Android WebView where
+// the system manages the scrollbars instead.
+const char kHideScrollbars[]                = "hide-scrollbars";
+
+// The telephony region (ISO country code) to use in phone number detection.
+const char kNetworkCountryIso[] = "network-country-iso";
+
+// Enables remote debug over HTTP on the specified socket name.
+const char kRemoteDebuggingSocketName[]     = "remote-debugging-socket-name";
 #endif
 
 #if defined(OS_CHROMEOS)
@@ -841,11 +910,6 @@
 const char kDisablePanelFitting[]           = "disable-panel-fitting";
 #endif
 
-#if defined(OS_POSIX)
-// Causes the child processes to cleanly exit via calling exit().
-const char kChildCleanExit[]                = "child-clean-exit";
-#endif
-
 #if defined(OS_MACOSX) && !defined(OS_IOS)
 const char kDisableCarbonInterposing[]      = "disable-carbon-interposing";
 
@@ -853,58 +917,16 @@
 const char kUseCoreAnimation[]              = "use-core-animation";
 #endif
 
-// Disables the use of a 3D software rasterizer.
-const char kDisableSoftwareRasterizer[]     = "disable-software-rasterizer";
+#if defined(OS_POSIX)
+// Causes the child processes to cleanly exit via calling exit().
+const char kChildCleanExit[]                = "child-clean-exit";
+#endif
 
 #if defined(USE_AURA)
 // Forces usage of the test compositor. Needed to run ui tests on bots.
 extern const char kTestCompositor[]         = "test-compositor";
 #endif
 
-// Sets the tile size used by composited layers.
-const char kDefaultTileWidth[]              = "default-tile-width";
-const char kDefaultTileHeight[]             = "default-tile-height";
-
-// Sets the width and height above which a composited layer will get tiled.
-const char kMaxUntiledLayerWidth[]          = "max-untiled-layer-width";
-const char kMaxUntiledLayerHeight[]         = "max-untiled-layer-height";
-
-const char kEnableFixedPositionCreatesStackingContext[]
-    = "enable-fixed-position-creates-stacking-context";
-const char kDisableFixedPositionCreatesStackingContext[]
-    = "disable-fixed-position-creates-stacking-context";
-
-// Defer image decoding in WebKit until painting.
-const char kEnableDeferredImageDecoding[] = "enable-deferred-image-decoding";
-
-// Use a begin frame signal from browser to renderer to schedule rendering.
-const char kEnableBeginFrameScheduling[] = "enable-begin-frame-scheduling";
-
-// Synchronize delivery and response of input events to and from the renderer.
-const char kEnableBrowserInputController[] = "enable-browser-input-controller";
-
-// Enables or disables history navigation in response to horizontal overscroll.
-// Set the value to '1' to enable the feature, and set to '0' to disable.
-// Defaults to enabled.
-const char kOverscrollHistoryNavigation[] =
-    "overscroll-history-navigation";
-
-// Enables or disables scroll end effect in response to vertical overscroll.
-// Set the value to '1' to enable the feature, and set to '0' to disable.
-// Defaults to disabled.
-const char kScrollEndEffect[] = "scroll-end-effect";
-
-// Forward overscroll event data from the renderer to the browser.
-const char kEnableOverscrollNotifications[] = "enable-overscroll-notifications";
-
-// Enables WebGL extensions not yet approved by the community.
-const char kEnableWebGLDraftExtensions[] = "enable-webgl-draft-extensions";
-
-// Enables/disables accelerated compositing for backgrounds of root layers with
-// background-attachment: fixed. Requires kForceCompositingMode.
-const char kDisableAcceleratedFixedRootBackground[] =
-    "disable-accelerated-fixed-root-background";
-const char kEnableAcceleratedFixedRootBackground[] =
-    "enable-accelerated-fixed-root-background";
+// 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 9124de1..a4852d5 100644
--- a/content/public/common/content_switches.h
+++ b/content/public/common/content_switches.h
@@ -12,148 +12,154 @@
 
 namespace switches {
 
+// All switches in alphabetical order. The switches should be documented
+// alongside the definition of their values in the .cc file.
 CONTENT_EXPORT extern const char kAllowFileAccessFromFiles[];
+CONTENT_EXPORT extern const char kAllowNoSandboxJob[];
 extern const char kAllowSandboxDebugging[];
 extern const char kAllowWebUICompositing[];
-extern const char kAuditHandles[];
 extern const char kAuditAllHandles[];
+extern const char kAuditHandles[];
+CONTENT_EXPORT extern const char kBlacklistAcceleratedCompositing[];
+CONTENT_EXPORT extern const char kBlacklistWebGL[];
 CONTENT_EXPORT extern const char kBrowserAssertTest[];
 CONTENT_EXPORT extern const char kBrowserCrashTest[];
 CONTENT_EXPORT extern const char kBrowserSubprocessPath[];
+extern const char kDebugPluginLoading[];
+extern const char kDefaultTileWidth[];
+extern const char kDefaultTileHeight[];
 CONTENT_EXPORT extern const char kDisable2dCanvasAntialiasing[];
-CONTENT_EXPORT extern const char kEnableExperimentalCanvasFeatures[];
 CONTENT_EXPORT extern const char kDisable3DAPIs[];
 CONTENT_EXPORT extern const char kDisableAccelerated2dCanvas[];
 CONTENT_EXPORT extern const char kDisableAcceleratedCompositing[];
+CONTENT_EXPORT extern const char kDisableAcceleratedFixedRootBackground[];
 CONTENT_EXPORT extern const char kDisableAcceleratedLayers[];
+extern const char kDisableAcceleratedOverflowScroll[];
 CONTENT_EXPORT extern const char kDisableAcceleratedPlugins[];
 CONTENT_EXPORT extern const char kDisableAcceleratedVideo[];
+CONTENT_EXPORT extern const char kDisableAcceleratedVideoDecode[];
 CONTENT_EXPORT extern const char kDisableAltWinstation[];
 CONTENT_EXPORT extern const char kDisableApplicationCache[];
 CONTENT_EXPORT extern const char kDisableAudio[];
 extern const char kDisableBackingStoreLimit[];
+CONTENT_EXPORT extern const char kDisableBrowserPluginCompositing[];
+CONTENT_EXPORT extern const char kDisableCompositingForFixedPosition[];
+CONTENT_EXPORT extern const char kDisableCompositingForTransition[];
 CONTENT_EXPORT extern const char kDisableDatabases[];
+CONTENT_EXPORT extern const char kDisableDelegatedRenderer[];
 extern const char kDisableDesktopNotifications[];
 CONTENT_EXPORT extern const char kDisableDeviceOrientation[];
 CONTENT_EXPORT extern const char kDisableExperimentalWebGL[];
-CONTENT_EXPORT extern const char kBlacklistAcceleratedCompositing[];
-CONTENT_EXPORT extern const char kBlacklistWebGL[];
 extern const char kDisableFileSystem[];
+CONTENT_EXPORT extern const char kDisableFixedPositionCreatesStackingContext[];
 CONTENT_EXPORT extern const char kDisableFlash3d[];
 CONTENT_EXPORT extern const char kDisableFlashStage3d[];
 CONTENT_EXPORT extern const char kDisableForceCompositingMode[];
+CONTENT_EXPORT extern const char kDisableFullScreen[];
 extern const char kDisableGeolocation[];
-CONTENT_EXPORT extern const char kUseGpuInTests[];
-extern const char kDisableGpu[];
+CONTENT_EXPORT extern const char kDisableGestureTapHighlight[];
 CONTENT_EXPORT extern const char kDisableGLMultisampling[];
+extern const char kDisableGpu[];
+CONTENT_EXPORT extern const char kDisableGpuCompositing[];
 CONTENT_EXPORT extern const char kDisableGpuProcessPrelaunch[];
 extern const char kDisableGpuSandbox[];
-extern const char kReduceGpuSandbox[];
-CONTENT_EXPORT extern const char kDisableGpuCompositing[];
 extern const char kDisableGpuWatchdog[];
 CONTENT_EXPORT extern const char kDisableHangMonitor[];
-CONTENT_EXPORT extern const char kDisableHTMLNotifications[];
 extern const char kDisableHistogramCustomizer[];
+CONTENT_EXPORT extern const char kDisableHTMLNotifications[];
 extern const char kDisableImageTransportSurface[];
 CONTENT_EXPORT extern const char kDisableJava[];
 CONTENT_EXPORT extern const char kDisableJavaScript[];
+extern const char kDisableLegacyEncryptedMedia[];
 CONTENT_EXPORT extern const char kDisableLocalStorage[];
 CONTENT_EXPORT extern const char kDisableLogging[];
-CONTENT_EXPORT extern const char kLogNetLog[];
-CONTENT_EXPORT extern const char kDisableSmoothScrolling[];
+extern const char kDisablePepper3d[];
+extern const char kDisablePinch[];
 CONTENT_EXPORT extern const char kDisablePlugins[];
+CONTENT_EXPORT extern const char kDisablePluginsDiscovery[];
 extern const char kDisableRemoteFonts[];
 extern const char kDisableRendererAccessibility[];
-extern const char kDisableSSLFalseStart[];
 extern const char kDisableSeccompFilterSandbox[];
 extern const char kDisableSessionStorage[];
 extern const char kDisableSetuidSandbox[];
 extern const char kDisableSharedWorkers[];
 extern const char kDisableSiteSpecificQuirks[];
+CONTENT_EXPORT extern const char kDisableSmoothScrolling[];
+CONTENT_EXPORT extern const char kDisableSoftwareRasterizer[];
 CONTENT_EXPORT extern const char kDisableSpeechInput[];
-extern const char kSpeechRecognitionWebserviceKey[];
-CONTENT_EXPORT extern const char kEnableSpeechSynthesis[];
-#if defined(OS_ANDROID)
-CONTENT_EXPORT extern const char kDisableWebRTC[];
-CONTENT_EXPORT extern const char kEnableSpeechRecognition[];
-#endif
+extern const char kDisableSSLFalseStart[];
+CONTENT_EXPORT extern const char kDisableThreadedCompositing[];
+CONTENT_EXPORT extern const char kDisableThreadedHTMLParser[];
 CONTENT_EXPORT extern const char kDisableWebAudio[];
-#if defined(ENABLE_WEBRTC)
-CONTENT_EXPORT extern const char kDisableDeviceEnumeration[];
-CONTENT_EXPORT extern const char kEnableSCTPDataChannels[];
-extern const char kEnableWebRtcAecRecordings[];
-extern const char kEnableWebRtcHWDecoding[];
-#endif
-extern const char kEnableWebRtcTcpServerSocket[];
-extern const char kEnableWebAnimationsCSS[];
-extern const char kEnableWebAnimationsSVG[];
-extern const char kEnableWebMIDI[];
+extern const char kDisableWebKitMediaSource[];
 extern const char kDisableWebSecurity[];
-extern const char kEnableExperimentalWebSocket[];
 extern const char kDisableXSSAuditor[];
 CONTENT_EXPORT extern const char kDomAutomationController[];
-CONTENT_EXPORT extern const char kStatsCollectionController[];
 CONTENT_EXPORT extern const char kEnableAcceleratedFilters[];
+CONTENT_EXPORT extern const char kEnableAcceleratedFixedRootBackground[];
+extern const char kEnableAcceleratedOverflowScroll[];
+extern const char kEnableAcceleratedScrollableFrames[];
 extern const char kEnableAccessibilityLogging[];
 extern const char kEnableAudibleNotifications[];
-CONTENT_EXPORT extern const char kDisableBrowserPluginCompositing[];
+CONTENT_EXPORT extern const char kEnableBeginFrameScheduling[];
+CONTENT_EXPORT extern const char kEnableBrowserInputController[];
 CONTENT_EXPORT extern const char kEnableBrowserPluginForAllViewTypes[];
 CONTENT_EXPORT extern const char kEnableBrowserPluginDragDrop[];
+extern const char kEnableCompositedScrollingForFrames[];
 CONTENT_EXPORT extern const char kEnableCompositingForFixedPosition[];
-CONTENT_EXPORT extern const char kEnableHighDpiCompositingForFixedPosition[];
-CONTENT_EXPORT extern const char kDisableCompositingForFixedPosition[];
 CONTENT_EXPORT extern const char kEnableCompositingForTransition[];
-CONTENT_EXPORT extern const char kDisableCompositingForTransition[];
 CONTENT_EXPORT extern const char kEnableCssShaders[];
-CONTENT_EXPORT extern const char kDisableDelegatedRenderer[];
+CONTENT_EXPORT extern const char kEnableDeferredImageDecoding[];
 CONTENT_EXPORT extern const char kEnableDelegatedRenderer[];
 CONTENT_EXPORT extern const char kEnableDeviceMotion[];
-#if defined(OS_ANDROID)
-CONTENT_EXPORT extern const char kDisableDeviceMotion[];
-#endif
 CONTENT_EXPORT extern const char kEnableDownloadResumption[];
+extern const char kEnableEncryptedMedia[];
+CONTENT_EXPORT extern const char kEnableExperimentalCanvasFeatures[];
 CONTENT_EXPORT extern const char kEnableExperimentalWebPlatformFeatures[];
-CONTENT_EXPORT extern const char kEnableRegionBasedColumns[];
-CONTENT_EXPORT extern const char kDisableThreadedHTMLParser[];
+extern const char kEnableExperimentalWebSocket[];
 CONTENT_EXPORT extern const char kEnableFixedLayout[];
-CONTENT_EXPORT extern const char kDisableFullScreen[];
-CONTENT_EXPORT extern const char kEnableTextServicesFramework[];
+CONTENT_EXPORT extern const char kEnableFixedPositionCreatesStackingContext[];
 CONTENT_EXPORT extern const char kEnableGestureTapHighlight[];
-CONTENT_EXPORT extern const char kDisableGestureTapHighlight[];
 extern const char kEnableGpuBenchmarking[];
 extern const char kEnableGpuClientTracing[];
+CONTENT_EXPORT extern const char kEnableHighDpiCompositingForFixedPosition[];
+extern const char kEnableHTMLImports[];
 CONTENT_EXPORT extern const char kEnableInbandTextTracks[];
-extern const char kEnableMemoryBenchmarking[];
-extern const char kEnableSkiaBenchmarking[];
 CONTENT_EXPORT extern const char kEnableLogging[];
-extern const char kDisableWebKitMediaSource[];
-extern const char kEnableEncryptedMedia[];
-extern const char kDisableLegacyEncryptedMedia[];
-CONTENT_EXPORT extern const char kUseFakeDeviceForMediaStream[];
-CONTENT_EXPORT extern const char kUseFakeUIForMediaStream[];
+extern const char kEnableMemoryBenchmarking[];
 extern const char kEnableMonitorProfile[];
 extern const char kEnableNewMediaInternals[];
-extern const char kEnableUserMediaScreenCapturing[];
-extern const char kEnablePinch[];
 CONTENT_EXPORT extern const char kEnableOfflineCacheAccess[];
-extern const char kDisablePinch[];
+CONTENT_EXPORT extern const char kEnableOverscrollNotifications[];
+extern const char kEnablePinch[];
 extern const char kEnablePreparsedJsCaching[];
 CONTENT_EXPORT extern const char kEnablePrivilegedWebGLExtensions[];
 extern const char kEnablePruneGpuCommandBuffers[];
-extern const char kEnableSSLCachedInfo[];
+CONTENT_EXPORT extern const char kEnableRegionBasedColumns[];
 extern const char kEnableSandboxLogging[];
-extern const char kEnableSpatialNavigation[];
-CONTENT_EXPORT extern const char kEnableSoftwareCompositing[];
+extern const char kEnableSkiaBenchmarking[];
 CONTENT_EXPORT extern const char kEnableSmoothScrolling[];
+CONTENT_EXPORT extern const char kEnableSoftwareCompositing[];
+extern const char kEnableSpatialNavigation[];
+CONTENT_EXPORT extern const char kEnableSpeechSynthesis[];
+extern const char kEnableSSLCachedInfo[];
 CONTENT_EXPORT extern const char kEnableStatsTable[];
 extern const char kEnableStrictSiteIsolation[];
-CONTENT_EXPORT extern const char kEnableThreadedCompositing[];
-CONTENT_EXPORT extern const char kDisableThreadedCompositing[];
-extern const char kEnableVirtualGLContexts[];
 CONTENT_EXPORT extern const char kEnableTcpFastOpen[];
-CONTENT_EXPORT extern const char kDisableAcceleratedVideoDecode[];
+CONTENT_EXPORT extern const char kEnableTextServicesFramework[];
+CONTENT_EXPORT extern const char kEnableThreadedCompositing[];
+extern const char kEnableUserMediaScreenCapturing[];
 extern const char kEnableViewport[];
+extern const char kEnableVirtualGLContexts[];
+extern const char kEnableVisualWordMovement[];
+CONTENT_EXPORT extern const char kEnableVtune[];
+extern const char kEnableWebAnimationsCSS[];
+extern const char kEnableWebAnimationsSVG[];
+CONTENT_EXPORT extern const char kEnableWebGLDraftExtensions[];
+extern const char kEnableWebMIDI[];
+extern const char kEnableWebRtcTcpServerSocket[];
 CONTENT_EXPORT extern const char kExperimentalLocationFeatures[];
+CONTENT_EXPORT extern const char kExtraPluginDir[];
 CONTENT_EXPORT extern const char kForceCompositingMode[];
 extern const char kForceFieldTrials[];
 CONTENT_EXPORT extern const char kForceRendererAccessibility[];
@@ -165,30 +171,29 @@
 extern const char kGpuSandboxAllowSysVShm[];
 extern const char kGpuStartupDialog[];
 extern const char kGpuVendorID[];
-#if defined(OS_ANDROID)
-CONTENT_EXPORT extern const char kHideScrollbars[];
-#endif
 CONTENT_EXPORT extern const char kHostResolverRules[];
 CONTENT_EXPORT extern const char kIgnoreCertificateErrors[];
 CONTENT_EXPORT extern const char kIgnoreGpuBlacklist[];
 extern const char kInProcessGPU[];
 extern const char kInProcessPlugins[];
 CONTENT_EXPORT extern const char kJavaScriptFlags[];
-CONTENT_EXPORT extern const char kExtraPluginDir[];
 extern const char kLoadPlugin[];
-CONTENT_EXPORT extern const char kDisablePluginsDiscovery[];
 CONTENT_EXPORT extern const char kLoggingLevel[];
+CONTENT_EXPORT extern const char kLogNetLog[];
 extern const char kLogPluginMessages[];
+extern const char kMaxUntiledLayerHeight[];
+extern const char kMaxUntiledLayerWidth[];
 extern const char kMemoryMetrics[];
 CONTENT_EXPORT extern const char kMuteAudio[];
 CONTENT_EXPORT extern const char kNoReferrers[];
 CONTENT_EXPORT extern const char kNoSandbox[];
-CONTENT_EXPORT extern const char kAllowNoSandboxJob[];
+CONTENT_EXPORT extern const char kOverscrollHistoryNavigation[];
 extern const char kPluginLauncher[];
 CONTENT_EXPORT extern const char kPluginPath[];
 CONTENT_EXPORT extern const char kPluginProcess[];
 extern const char kPluginStartupDialog[];
 CONTENT_EXPORT extern const char kPpapiBrokerProcess[];
+extern const char kPpapiFlashArgs[];
 CONTENT_EXPORT extern const char kPpapiInProcess[];
 extern const char kPpapiPluginLauncher[];
 CONTENT_EXPORT extern const char kPpapiPluginProcess[];
@@ -196,36 +201,36 @@
 CONTENT_EXPORT extern const char kProcessPerSite[];
 CONTENT_EXPORT extern const char kProcessPerTab[];
 CONTENT_EXPORT extern const char kProcessType[];
+extern const char kReduceGpuSandbox[];
 CONTENT_EXPORT extern const char kRegisterPepperPlugins[];
 CONTENT_EXPORT extern const char kRemoteDebuggingPort[];
-#if defined(OS_ANDROID)
-CONTENT_EXPORT extern const char kRemoteDebuggingSocketName[];
-#endif
 CONTENT_EXPORT extern const char kRendererAssertTest[];
 extern const char kRendererCmdPrefix[];
 CONTENT_EXPORT extern const char kRendererProcess[];
-CONTENT_EXPORT extern const char kEnableVtune[];
 extern const char kRendererProcessLimit[];
 extern const char kRendererStartupDialog[];
-extern const char kEnableAcceleratedOverflowScroll[];
-extern const char kDisableAcceleratedOverflowScroll[];
-extern const char kEnableAcceleratedScrollableFrames[];
-extern const char kEnableCompositedScrollingForFrames[];
+CONTENT_EXPORT extern const char kScrollEndEffect[];
 extern const char kShowPaintRects[];
 CONTENT_EXPORT extern const char kSimulateTouchScreenWithMouse[];
 CONTENT_EXPORT extern const char kSingleProcess[];
 CONTENT_EXPORT extern const char kSitePerProcess[];
 CONTENT_EXPORT extern const char kSkipGpuDataLoading[];
-extern const char kTabCaptureUpscaleQuality[];
+extern const char kSpeechRecognitionWebserviceKey[];
+CONTENT_EXPORT extern const char kStatsCollectionController[];
 extern const char kTabCaptureDownscaleQuality[];
+extern const char kTabCaptureUpscaleQuality[];
 extern const char kTapDownDeferralTimeMs[];
-CONTENT_EXPORT extern const char kTestSandbox[];
 CONTENT_EXPORT extern const char kTestingFixedHttpPort[];
 CONTENT_EXPORT extern const char kTestingFixedHttpsPort[];
+CONTENT_EXPORT extern const char kTestSandbox[];
 extern const char kTraceStartup[];
-extern const char kTraceStartupFile[];
 extern const char kTraceStartupDuration[];
+extern const char kTraceStartupFile[];
 CONTENT_EXPORT extern const char kUIPrioritizeInGpuProcess[];
+CONTENT_EXPORT extern const char kUseFakeDeviceForMediaStream[];
+CONTENT_EXPORT extern const char kUseFakeUIForMediaStream[];
+CONTENT_EXPORT extern const char kUseGpuInTests[];
+CONTENT_EXPORT extern const char kUseMobileUserAgent[];
 CONTENT_EXPORT extern const char kUserAgent[];
 extern const char kUtilityCmdPrefix[];
 CONTENT_EXPORT extern const char kUtilityProcess[];
@@ -236,51 +241,45 @@
 CONTENT_EXPORT extern const char kWorkerProcess[];
 CONTENT_EXPORT extern const char kZygoteCmdPrefix[];
 CONTENT_EXPORT extern const char kZygoteProcess[];
-CONTENT_EXPORT extern const char kDisableSoftwareRasterizer[];
-extern const char kDefaultTileWidth[];
-extern const char kDefaultTileHeight[];
-extern const char kMaxUntiledLayerWidth[];
-extern const char kMaxUntiledLayerHeight[];
-CONTENT_EXPORT extern const char kEnableFixedPositionCreatesStackingContext[];
-CONTENT_EXPORT extern const char kDisableFixedPositionCreatesStackingContext[];
-CONTENT_EXPORT extern const char kEnableDeferredImageDecoding[];
-CONTENT_EXPORT extern const char kEnableBeginFrameScheduling[];
-CONTENT_EXPORT extern const char kEnableBrowserInputController[];
 
-extern const char kEnableVisualWordMovement[];
-CONTENT_EXPORT extern const char kUseMobileUserAgent[];
+#if defined(ENABLE_WEBRTC)
+CONTENT_EXPORT extern const char kDisableDeviceEnumeration[];
+CONTENT_EXPORT extern const char kEnableSCTPDataChannels[];
+extern const char kEnableWebRtcAecRecordings[];
+extern const char kEnableWebRtcHWDecoding[];
+#endif
 
 #if defined(OS_ANDROID)
-extern const char kDisableMediaHistoryLogging[];
+CONTENT_EXPORT extern const char kDisableDeviceMotion[];
 CONTENT_EXPORT extern const char kDisableGestureRequirementForMediaPlayback[];
-extern const char kNetworkCountryIso[];
+extern const char kDisableMediaHistoryLogging[];
 CONTENT_EXPORT extern const char kDisableOverscrollEdgeEffect[];
+CONTENT_EXPORT extern const char kDisableWebRTC[];
+CONTENT_EXPORT extern const char kEnableSpeechRecognition[];
+CONTENT_EXPORT extern const char kHideScrollbars[];
+extern const char kNetworkCountryIso[];
+CONTENT_EXPORT extern const char kRemoteDebuggingSocketName[];
 #endif
 
 #if defined(OS_CHROMEOS)
 CONTENT_EXPORT extern const char kDisablePanelFitting[];
 #endif
 
-#if defined(OS_POSIX)
-extern const char kChildCleanExit[];
-#endif
-
 #if defined(OS_MACOSX) && !defined(OS_IOS)
 extern const char kDisableCarbonInterposing[];
 extern const char kUseCoreAnimation[];
 #endif
 
+#if defined(OS_POSIX)
+extern const char kChildCleanExit[];
+#endif
+
 #if defined(USE_AURA)
 CONTENT_EXPORT extern const char kTestCompositor[];
 #endif
 
-CONTENT_EXPORT extern const char kOverscrollHistoryNavigation[];
-CONTENT_EXPORT extern const char kScrollEndEffect[];
-CONTENT_EXPORT extern const char kEnableOverscrollNotifications[];
-CONTENT_EXPORT extern const char kEnableWebGLDraftExtensions[];
-
-CONTENT_EXPORT extern const char kDisableAcceleratedFixedRootBackground[];
-CONTENT_EXPORT extern const char kEnableAcceleratedFixedRootBackground[];
+// 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).
 
 }  // namespace switches
 
diff --git a/content/public/common/desktop_media_id.cc b/content/public/common/desktop_media_id.cc
new file mode 100644
index 0000000..82ebe9c
--- /dev/null
+++ b/content/public/common/desktop_media_id.cc
@@ -0,0 +1,41 @@
+// 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/public/common/desktop_media_id.h"
+
+namespace content {
+
+// static
+DesktopMediaID DesktopMediaID::Parse(const std::string& str) {
+  if (str == "screen")
+    return DesktopMediaID(TYPE_SCREEN, 0);
+
+  std::string window_prefix("window:");
+  if (StartsWithASCII(str, window_prefix, true)) {
+    int64 id;
+    if (!base::StringToInt64(str.substr(window_prefix.size()), &id))
+      return DesktopMediaID(TYPE_NONE, 0);
+    return DesktopMediaID(TYPE_WINDOW, id);
+  }
+
+  return DesktopMediaID(TYPE_NONE, 0);
+}
+
+std::string DesktopMediaID::ToString() {
+  switch (type) {
+    case TYPE_NONE:
+      NOTREACHED();
+      return std::string();
+
+    case TYPE_SCREEN:
+      return "screen";
+
+    case TYPE_WINDOW:
+      return "window:" + base::Int64ToString(id);
+  }
+  NOTREACHED();
+  return std::string();
+}
+
+}  // namespace content
diff --git a/content/public/common/desktop_media_id.h b/content/public/common/desktop_media_id.h
new file mode 100644
index 0000000..a863872
--- /dev/null
+++ b/content/public/common/desktop_media_id.h
@@ -0,0 +1,57 @@
+// 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_PUBLIC_COMMON_DESKTOP_MEDIA_ID_H_
+#define CONTENT_PUBLIC_COMMON_DESKTOP_MEDIA_ID_H_
+
+#include <string>
+
+#include "base/basictypes.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/strings/string_util.h"
+#include "content/common/content_export.h"
+
+namespace content {
+
+// Type used to identify desktop media sources. It's converted to string and
+// stored in MediaStreamRequest::requested_video_device_id .
+struct CONTENT_EXPORT DesktopMediaID {
+ public:
+  enum Type {
+    TYPE_NONE,
+    TYPE_SCREEN,
+    TYPE_WINDOW,
+  };
+  typedef intptr_t Id;
+
+  static DesktopMediaID Parse(const std::string& str);
+
+  DesktopMediaID()
+      : type(TYPE_NONE),
+        id(0) {
+  }
+  DesktopMediaID(Type type, Id id)
+      : type(type),
+        id(id) {
+  }
+
+  // Operators so that DesktopMediaID can be used with STL containers.
+  bool operator<(const DesktopMediaID& other) const {
+    return type < other.type || (type == other.type && id < other.id);
+  }
+  bool operator==(const DesktopMediaID& other) const {
+    return type == other.type && id == other.id;
+  }
+
+  bool is_null() { return type == TYPE_NONE; }
+
+  std::string ToString();
+
+  Type type;
+  Id id;
+};
+
+}  // namespace content
+
+#endif  // CONTENT_PUBLIC_COMMON_DESKTOP_MEDIA_ID_H_
diff --git a/content/public/common/media_stream_request.cc b/content/public/common/media_stream_request.cc
index 2c2f9d8..e3ad35b 100644
--- a/content/public/common/media_stream_request.cc
+++ b/content/public/common/media_stream_request.cc
@@ -17,8 +17,7 @@
 bool IsVideoMediaType(MediaStreamType type) {
   return (type == content::MEDIA_DEVICE_VIDEO_CAPTURE ||
           type == content::MEDIA_TAB_VIDEO_CAPTURE ||
-          type == content::MEDIA_SCREEN_VIDEO_CAPTURE ||
-          type == content::MEDIA_WINDOW_VIDEO_CAPTURE);
+          type == content::MEDIA_DESKTOP_VIDEO_CAPTURE);
 }
 
 MediaStreamDevice::MediaStreamDevice() : type(MEDIA_NO_SERVICE) {}
diff --git a/content/public/common/media_stream_request.h b/content/public/common/media_stream_request.h
index d01e7a8..cbbf232d1 100644
--- a/content/public/common/media_stream_request.h
+++ b/content/public/common/media_stream_request.h
@@ -26,14 +26,18 @@
   MEDIA_DEVICE_VIDEO_CAPTURE,
 
   // Mirroring of a browser tab.
+  //
+  // TODO(serygeu): Remove these values and use MEDIA_DESKTOP_VIDEO_CAPTURE and
+  // MEDIA_DESKTOP_AUDIO_CAPTURE.
   MEDIA_TAB_AUDIO_CAPTURE,
   MEDIA_TAB_VIDEO_CAPTURE,
 
   // Desktop media sources.
-  MEDIA_SCREEN_VIDEO_CAPTURE,
-  MEDIA_WINDOW_VIDEO_CAPTURE,
+  MEDIA_DESKTOP_VIDEO_CAPTURE,
 
   // Capture system audio (post-mix loopback stream).
+  //
+  // TODO(sergeyu): Replace with MEDIA_DESKTOP_AUDIO_CAPTURE.
   MEDIA_SYSTEM_AUDIO_CAPTURE,
 
   NUM_MEDIA_TYPES
diff --git a/content/public/common/url_constants.cc b/content/public/common/url_constants.cc
index d8936c5..71ab648 100644
--- a/content/public/common/url_constants.cc
+++ b/content/public/common/url_constants.cc
@@ -22,12 +22,12 @@
 const char kHttpScheme[] = "http";
 const char kHttpsScheme[] = "https";
 const char kJavaScriptScheme[] = "javascript";
-const char kMailToScheme[] = "mailto";
-const char kMetadataScheme[] = "metadata";
 }  // namespace chrome
 
 namespace content {
 
+const char kMailToScheme[] = "mailto";
+const char kMetadataScheme[] = "metadata";
 const char kSwappedOutScheme[] = "swappedout";
 const char kViewSourceScheme[] = "view-source";
 
diff --git a/content/public/common/url_constants.h b/content/public/common/url_constants.h
index 541f4c6..ef17684 100644
--- a/content/public/common/url_constants.h
+++ b/content/public/common/url_constants.h
@@ -28,12 +28,12 @@
 CONTENT_EXPORT extern const char kHttpScheme[];
 CONTENT_EXPORT extern const char kHttpsScheme[];
 CONTENT_EXPORT extern const char kJavaScriptScheme[];
-CONTENT_EXPORT extern const char kMailToScheme[];
-CONTENT_EXPORT extern const char kMetadataScheme[];
 }  // namespace chrome
 
 namespace content {
 
+CONTENT_EXPORT extern const char kMailToScheme[];
+CONTENT_EXPORT extern const char kMetadataScheme[];
 CONTENT_EXPORT extern const char kSwappedOutScheme[];
 CONTENT_EXPORT extern const char kViewSourceScheme[];
 
diff --git a/content/public/renderer/content_renderer_client.cc b/content/public/renderer/content_renderer_client.cc
index a94fb2d..c190f09 100644
--- a/content/public/renderer/content_renderer_client.cc
+++ b/content/public/renderer/content_renderer_client.cc
@@ -138,7 +138,7 @@
 
 bool ContentRendererClient::ShouldOverridePageVisibilityState(
     const RenderView* render_view,
-    WebKit::WebPageVisibilityState* override_state) const {
+    WebKit::WebPageVisibilityState* override_state) {
   return false;
 }
 
@@ -163,17 +163,22 @@
   return NULL;
 }
 
+bool ContentRendererClient::IsExternalPepperPlugin(
+    const std::string& module_name) {
+  return false;
+}
+
 bool ContentRendererClient::IsPluginAllowedToCallRequestOSFileHandle(
-    WebKit::WebPluginContainer* container) const {
+    WebKit::WebPluginContainer* container) {
   return false;
 }
 
 bool ContentRendererClient::AllowBrowserPlugin(
-    WebKit::WebPluginContainer* container) const {
+    WebKit::WebPluginContainer* container) {
   return false;
 }
 
-bool ContentRendererClient::AllowPepperMediaStreamAPI(const GURL& url) const {
+bool ContentRendererClient::AllowPepperMediaStreamAPI(const GURL& url) {
   return false;
 }
 
diff --git a/content/public/renderer/content_renderer_client.h b/content/public/renderer/content_renderer_client.h
index 7730927..a00e1a9 100644
--- a/content/public/renderer/content_renderer_client.h
+++ b/content/public/renderer/content_renderer_client.h
@@ -209,7 +209,7 @@
   virtual WebKit::WebPrescientNetworking* GetPrescientNetworking();
   virtual bool ShouldOverridePageVisibilityState(
       const RenderView* render_view,
-      WebKit::WebPageVisibilityState* override_state) const;
+      WebKit::WebPageVisibilityState* override_state);
 
   // Return true if the GetCookie request will be handled by the embedder.
   // Cookies are returned in the cookie parameter.
@@ -229,16 +229,20 @@
   virtual const void* CreatePPAPIInterface(
       const std::string& interface_name);
 
+  // Returns true if the given Pepper plugin is external (requiring special
+  // startup steps).
+  virtual bool IsExternalPepperPlugin(const std::string& module_name);
+
   // Returns true if plugin living in the container can use
   // pp::FileIO::RequestOSFileHandle.
   virtual bool IsPluginAllowedToCallRequestOSFileHandle(
-      WebKit::WebPluginContainer* container) const;
+      WebKit::WebPluginContainer* container);
 
   // Returns whether BrowserPlugin should be allowed within the |container|.
-  virtual bool AllowBrowserPlugin(WebKit::WebPluginContainer* container) const;
+  virtual bool AllowBrowserPlugin(WebKit::WebPluginContainer* container);
 
   // Returns true if the page at |url| can use Pepper MediaStream APIs.
-  virtual bool AllowPepperMediaStreamAPI(const GURL& url) const;
+  virtual bool AllowPepperMediaStreamAPI(const GURL& url);
 };
 
 }  // namespace content
diff --git a/content/public/renderer/pepper_plugin_instance.h b/content/public/renderer/pepper_plugin_instance.h
index 211752d..c7741a2 100644
--- a/content/public/renderer/pepper_plugin_instance.h
+++ b/content/public/renderer/pepper_plugin_instance.h
@@ -56,11 +56,6 @@
   // Returns the location of this module.
   virtual base::FilePath GetModulePath() = 0;
 
-  // Returns a reference to a file with the given path.
-  // The returned object will have a refcount of 0 (just like "new").
-  virtual PP_Resource CreateExternalFileReference(
-      const base::FilePath& external_file_path) = 0;
-
   // Creates a PPB_ImageData given a Skia image.
   virtual PP_Resource CreateImage(gfx::ImageSkia* source_image,
                                   float scale) = 0;
@@ -92,7 +87,6 @@
   virtual int32_t Navigate(const ppapi::URLRequestInfoData& request,
                            const char* target,
                            bool from_user_action) = 0;
-
 };
 
 }  // namespace content
diff --git a/content/public/renderer/renderer_ppapi_host.h b/content/public/renderer/renderer_ppapi_host.h
index 329961e..36d6273 100644
--- a/content/public/renderer/renderer_ppapi_host.h
+++ b/content/public/renderer/renderer_ppapi_host.h
@@ -47,6 +47,11 @@
  public:
   // Returns the RendererPpapiHost associated with the given PP_Instance,
   // or NULL if the instance is invalid.
+  //
+  // Do NOT use this when dealing with the "NaCl trusted plugin". That plugin
+  // and the "untrusted plugin" (the NaCl application) that will be loaded
+  // share a PP_Instance, and the RendererPpapiHost* for the "untrusted plugin"
+  // will be returned after we switch the proxy on.
   CONTENT_EXPORT static RendererPpapiHost* GetForPPInstance(
       PP_Instance instance);
 
diff --git a/content/public/test/mock_download_manager.cc b/content/public/test/mock_download_manager.cc
index 12485b2..ef5a9f5 100644
--- a/content/public/test/mock_download_manager.cc
+++ b/content/public/test/mock_download_manager.cc
@@ -17,6 +17,8 @@
     const GURL& referrer_url,
     const base::Time& start_time,
     const base::Time& end_time,
+    const std::string& etag,
+    const std::string& last_modified,
     int64 received_bytes,
     int64 total_bytes,
     DownloadItem::DownloadState state,
@@ -46,6 +48,8 @@
       referrer_url(rhs.referrer_url),
       start_time(rhs.start_time),
       end_time(rhs.end_time),
+      etag(rhs.etag),
+      last_modified(rhs.last_modified),
       received_bytes(rhs.received_bytes),
       total_bytes(rhs.total_bytes),
       state(rhs.state),
@@ -64,6 +68,8 @@
           referrer_url == rhs.referrer_url &&
           start_time == rhs.start_time &&
           end_time == rhs.end_time &&
+          etag == rhs.etag &&
+          last_modified == rhs.last_modified &&
           received_bytes == rhs.received_bytes &&
           total_bytes == rhs.total_bytes &&
           state == rhs.state &&
@@ -91,6 +97,8 @@
     const GURL& referrer_url,
     const base::Time& start_time,
     const base::Time& end_time,
+    const std::string& etag,
+    const std::string& last_modified,
     int64 received_bytes,
     int64 total_bytes,
     DownloadItem::DownloadState state,
@@ -99,8 +107,8 @@
     bool opened) {
   CreateDownloadItemAdapter adapter(
       id, current_path, target_path, url_chain, referrer_url, start_time,
-      end_time, received_bytes, total_bytes, state, danger_type,
-      interrupt_reason, opened);
+      end_time, etag, last_modified, received_bytes, total_bytes, state,
+      danger_type, interrupt_reason, opened);
   return MockCreateDownloadItem(adapter);
 }
 
diff --git a/content/public/test/mock_download_manager.h b/content/public/test/mock_download_manager.h
index 9f090a9..fdcf9d6 100644
--- a/content/public/test/mock_download_manager.h
+++ b/content/public/test/mock_download_manager.h
@@ -33,6 +33,8 @@
     GURL referrer_url;
     base::Time start_time;
     base::Time end_time;
+    std::string etag;
+    std::string last_modified;
     int64 received_bytes;
     int64 total_bytes;
     DownloadItem::DownloadState state;
@@ -48,6 +50,8 @@
       const GURL& referrer_url,
       const base::Time& start_time,
       const base::Time& end_time,
+      const std::string& etag,
+      const std::string& last_modified,
       int64 received_bytes,
       int64 total_bytes,
       DownloadItem::DownloadState state,
@@ -99,6 +103,8 @@
       const GURL& referrer_url,
       const base::Time& start_time,
       const base::Time& end_time,
+      const std::string& etag,
+      const std::string& last_modified,
       int64 received_bytes,
       int64 total_bytes,
       DownloadItem::DownloadState state,
diff --git a/content/renderer/all_rendering_benchmarks.cc b/content/renderer/all_rendering_benchmarks.cc
deleted file mode 100644
index 14280f3..0000000
--- a/content/renderer/all_rendering_benchmarks.cc
+++ /dev/null
@@ -1,290 +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/renderer/all_rendering_benchmarks.h"
-
-#include <algorithm>
-#include <string>
-#include <vector>
-
-#include "base/bind.h"
-#include "base/callback.h"
-#include "base/compiler_specific.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/time/time.h"
-#include "content/renderer/rendering_benchmark.h"
-#include "skia/ext/platform_canvas.h"
-#include "third_party/skia/include/core/SkPicture.h"
-#include "third_party/skia/include/utils/SkNullCanvas.h"
-#include "third_party/WebKit/public/platform/WebRect.h"
-#include "third_party/WebKit/public/platform/WebSize.h"
-#include "third_party/WebKit/public/web/WebViewBenchmarkSupport.h"
-
-using base::TimeDelta;
-using base::TimeTicks;
-using WebKit::WebSize;
-using WebKit::WebCanvas;
-using WebKit::WebViewBenchmarkSupport;
-using WebKit::WebRect;
-using std::vector;
-
-namespace {
-
-// This is a base class for timing the painting of the current webpage to
-// custom WebCanvases.
-class CustomPaintBenchmark
-    : public content::RenderingBenchmark,
-      public WebViewBenchmarkSupport::PaintClient {
- public:
-  CustomPaintBenchmark(const std::string& name,
-                       WebViewBenchmarkSupport::PaintMode paint_mode)
-      : content::RenderingBenchmark(name),
-        paint_mode_(paint_mode) { }
-
-  virtual WebCanvas* willPaint(const WebSize& size) OVERRIDE {
-    WebCanvas* canvas = createCanvas(size);
-    before_time_ = TimeTicks::HighResNow();
-    return canvas;
-  }
-
-  virtual void didPaint(WebCanvas* canvas) OVERRIDE {
-    paint_time_total_ += (TimeTicks::HighResNow() - before_time_);
-    delete canvas;
-  }
-
-  virtual double Run(WebViewBenchmarkSupport* support) OVERRIDE {
-    paint_time_total_ = TimeDelta();
-    support->paint(this, paint_mode_);
-    return paint_time_total_.InMillisecondsF();
-  }
-
- private:
-  virtual WebCanvas* createCanvas(const WebSize& size) = 0;
-
-  TimeTicks before_time_;
-  TimeDelta paint_time_total_;
-  const WebViewBenchmarkSupport::PaintMode paint_mode_;
-};
-
-class BitmapCanvasPaintBenchmark : public CustomPaintBenchmark {
- public:
-  BitmapCanvasPaintBenchmark(const std::string& name,
-                             WebViewBenchmarkSupport::PaintMode paint_mode)
-      : CustomPaintBenchmark(name, paint_mode) { }
-
- private:
-  virtual WebCanvas* createCanvas(const WebSize& size) OVERRIDE {
-    return skia::CreateBitmapCanvas(size.width, size.height, false);
-  }
-};
-
-class CanvasCountBenchmark
-    : public content::RenderingBenchmark,
-      public WebViewBenchmarkSupport::PaintClient {
- public:
-  CanvasCountBenchmark(const std::string& name,
-                       WebViewBenchmarkSupport::PaintMode paint_mode)
-      : content::RenderingBenchmark(name),
-        canvas_count_(0),
-        paint_mode_(paint_mode) { }
-
-  virtual WebCanvas* willPaint(const WebSize& size) OVERRIDE {
-    ++canvas_count_;
-    return SkCreateNullCanvas();
-  }
-
-  virtual void didPaint(WebCanvas* canvas) OVERRIDE {
-    delete canvas;
-  }
-
-  virtual double Run(WebViewBenchmarkSupport* support) OVERRIDE {
-    canvas_count_ = 0;
-    support->paint(this, paint_mode_);
-    return canvas_count_;
-  }
- private:
-  int canvas_count_;
-  const WebViewBenchmarkSupport::PaintMode paint_mode_;
-};
-
-class NullCanvasPaintBenchmark : public CustomPaintBenchmark {
- public:
-  NullCanvasPaintBenchmark(const std::string& name,
-                           WebViewBenchmarkSupport::PaintMode paint_mode)
-      : CustomPaintBenchmark(name, paint_mode) { }
-
- private:
-  virtual WebCanvas* createCanvas(const WebSize& size) OVERRIDE {
-    return SkCreateNullCanvas();
-  }
-};
-
-class SkPicturePaintBenchmark : public CustomPaintBenchmark {
- public:
-  SkPicturePaintBenchmark(const std::string& name,
-                          WebViewBenchmarkSupport::PaintMode paint_mode)
-      : CustomPaintBenchmark(name, paint_mode) { }
-
-  virtual void didPaint(WebCanvas* canvas) OVERRIDE {
-    DCHECK(picture_.getRecordingCanvas() == canvas);
-    picture_.endRecording();
-    CustomPaintBenchmark::didPaint(NULL);
-  }
-
- private:
-  virtual WebCanvas* createCanvas(const WebSize& size) OVERRIDE {
-    return picture_.beginRecording(size.width, size.height);
-  }
-
-  SkPicture picture_;
-};
-
-// Base class for timing the replaying of the SkPicture into canvases.
-class TiledReplayBenchmark
-    : public content::RenderingBenchmark,
-      public WebViewBenchmarkSupport::PaintClient {
- public:
-  TiledReplayBenchmark(const std::string& name,
-                       WebViewBenchmarkSupport::PaintMode paint_mode)
-      : RenderingBenchmark(name),
-        paint_mode_(paint_mode) {}
-
-  virtual WebCanvas* willPaint(const WebSize& size) OVERRIDE {
-    return picture_.beginRecording(size.width, size.height);
-  }
-
-  virtual void didPaint(WebCanvas* canvas) OVERRIDE {
-    DCHECK(picture_.getRecordingCanvas() == canvas);
-    picture_.endRecording();
-
-    const vector<WebRect> repaint_tiles = GetRepaintTiles(
-        WebSize(picture_.width(), picture_.height()));
-
-    vector<WebRect>::const_iterator it;
-    for (it = repaint_tiles.begin(); it != repaint_tiles.end(); ++it) {
-      WebRect tile = *it;
-      scoped_ptr<WebCanvas> canvas(
-          skia::CreateBitmapCanvas(tile.width, tile.height, false));
-      TimeTicks before_time = TimeTicks::HighResNow();
-      canvas->translate(-tile.x, -tile.y);
-      picture_.draw(canvas.get());
-      paint_time_total_ += (TimeTicks::HighResNow() - before_time);
-    }
-  }
-
-  virtual double Run(WebViewBenchmarkSupport* support) OVERRIDE {
-    paint_time_total_ = TimeDelta();
-    support->paint(this, paint_mode_);
-    return paint_time_total_.InMillisecondsF();
-  }
-
- private:
-  virtual vector<WebRect> GetRepaintTiles(const WebSize& layer_size) const = 0;
-
-  TimeDelta paint_time_total_;
-  SkPicture picture_;
-  const WebViewBenchmarkSupport::PaintMode paint_mode_;
-};
-
-class SquareTiledReplayBenchmark : public TiledReplayBenchmark {
- public:
-  SquareTiledReplayBenchmark(const std::string& name,
-                             WebViewBenchmarkSupport::PaintMode paint_mode,
-                             int tile_size)
-      : TiledReplayBenchmark(name, paint_mode),
-        tile_size_(tile_size) {
-    CHECK_GT(tile_size, 0);
-  }
-
- private:
-  virtual vector<WebRect> GetRepaintTiles(
-      const WebSize& layer_size) const OVERRIDE {
-    vector<WebRect> tiles;
-    for (int x = 0; x < layer_size.width; x += tile_size_) {
-      for (int y = 0; y < layer_size.height; y += tile_size_) {
-        int width = std::min(layer_size.width - x, tile_size_);
-        int height = std::min(layer_size.height - y, tile_size_);
-        tiles.push_back(WebRect(x, y, width, height));
-      }
-    }
-    return tiles;
-  }
-
-  int tile_size_;
-};
-
-class LayerWidthTiledReplayBenchmark : public TiledReplayBenchmark {
- public:
-  LayerWidthTiledReplayBenchmark(const std::string& name,
-                                 WebViewBenchmarkSupport::PaintMode paint_mode,
-                                 int tile_height)
-      : TiledReplayBenchmark(name, paint_mode),
-        tile_height_(tile_height) {
-    CHECK_GT(tile_height, 0);
-  }
-
- private:
-  virtual vector<WebRect> GetRepaintTiles(
-      const WebSize& layer_size) const OVERRIDE {
-    vector<WebRect> tiles;
-    for (int y = 0; y < layer_size.height; y += tile_height_) {
-      int height = std::min(layer_size.height - y, tile_height_);
-      tiles.push_back(WebRect(0, y, layer_size.width, height));
-    }
-    return tiles;
-  }
-
-  int tile_height_;
-};
-
-}  // anonymous namespace
-
-namespace content {
-
-ScopedVector<RenderingBenchmark> AllRenderingBenchmarks() {
-  ScopedVector<RenderingBenchmark> benchmarks;
-  benchmarks.push_back(new BitmapCanvasPaintBenchmark(
-      "PaintEverythingToBitmapMs",
-      WebViewBenchmarkSupport::PaintModeEverything));
-  benchmarks.push_back(new NullCanvasPaintBenchmark(
-      "PaintEverythingToNullCanvasMs",
-      WebViewBenchmarkSupport::PaintModeEverything));
-  benchmarks.push_back(new CanvasCountBenchmark(
-      "LayerCount",
-      WebViewBenchmarkSupport::PaintModeEverything));
-  benchmarks.push_back(new SkPicturePaintBenchmark(
-      "PaintEverythingToSkPictureMs",
-      WebViewBenchmarkSupport::PaintModeEverything));
-  benchmarks.push_back(new SquareTiledReplayBenchmark(
-      "RepaintEverythingTo256x256BitmapMs",
-      WebViewBenchmarkSupport::PaintModeEverything,
-      256));
-  benchmarks.push_back(new SquareTiledReplayBenchmark(
-      "RepaintEverythingTo128x128BitmapMs",
-      WebViewBenchmarkSupport::PaintModeEverything,
-      128));
-  benchmarks.push_back(new SquareTiledReplayBenchmark(
-      "RepaintEverythingTo512x512BitmapMs",
-      WebViewBenchmarkSupport::PaintModeEverything,
-      512));
-  benchmarks.push_back(new LayerWidthTiledReplayBenchmark(
-      "RepaintEverythingToLayerWidthx256BitmapMs",
-      WebViewBenchmarkSupport::PaintModeEverything,
-      256));
-  benchmarks.push_back(new LayerWidthTiledReplayBenchmark(
-      "RepaintEverythingToLayerWidthx128BitmapMs",
-      WebViewBenchmarkSupport::PaintModeEverything,
-      128));
-  benchmarks.push_back(new LayerWidthTiledReplayBenchmark(
-      "RepaintEverythingToLayerWidthx64BitmapMs",
-      WebViewBenchmarkSupport::PaintModeEverything,
-      64));
-  benchmarks.push_back(new LayerWidthTiledReplayBenchmark(
-      "RepaintEverythingToLayerWidthx512BitmapMs",
-      WebViewBenchmarkSupport::PaintModeEverything,
-      512));
-  return benchmarks.Pass();
-}
-
-}  // namespace content
diff --git a/content/renderer/all_rendering_benchmarks.h b/content/renderer/all_rendering_benchmarks.h
deleted file mode 100644
index b19dca3..0000000
--- a/content/renderer/all_rendering_benchmarks.h
+++ /dev/null
@@ -1,19 +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_RENDERER_ALL_RENDERING_BENCHMARKS_H_
-#define CONTENT_RENDERER_ALL_RENDERING_BENCHMARKS_H_
-
-#include <vector>
-
-#include "base/memory/scoped_vector.h"
-
-namespace content {
-class RenderingBenchmark;
-
-ScopedVector<RenderingBenchmark> AllRenderingBenchmarks();
-
-}  // namespace content
-
-#endif  // CONTENT_RENDERER_ALL_RENDERING_BENCHMARKS_H_
diff --git a/content/renderer/browser_plugin/browser_plugin.cc b/content/renderer/browser_plugin/browser_plugin.cc
index 186743e..f0483dd 100644
--- a/content/renderer/browser_plugin/browser_plugin.cc
+++ b/content/renderer/browser_plugin/browser_plugin.cc
@@ -23,6 +23,7 @@
 #include "content/renderer/drop_data_builder.h"
 #include "content/renderer/render_process_impl.h"
 #include "content/renderer/render_thread_impl.h"
+#include "content/renderer/sad_plugin.h"
 #include "content/renderer/v8_value_converter_impl.h"
 #include "skia/ext/platform_canvas.h"
 #include "third_party/WebKit/public/platform/WebRect.h"
@@ -37,7 +38,6 @@
 #include "third_party/WebKit/public/web/WebScriptSource.h"
 #include "third_party/WebKit/public/web/WebView.h"
 #include "ui/base/keycodes/keyboard_codes.h"
-#include "webkit/plugins/sad_plugin.h"
 
 #if defined (OS_WIN)
 #include "base/sys_info.h"
@@ -1091,7 +1091,7 @@
     // content_shell does not have the sad plugin bitmap, so we'll paint black
     // instead to make it clear that something went wrong.
     if (sad_guest_) {
-      webkit::PaintSadPlugin(canvas, plugin_rect_, *sad_guest_);
+      PaintSadPlugin(canvas, plugin_rect_, *sad_guest_);
       return;
     }
   }
diff --git a/content/renderer/browser_plugin/browser_plugin_browsertest.cc b/content/renderer/browser_plugin/browser_plugin_browsertest.cc
index c8e5123..1ad07e9 100644
--- a/content/renderer/browser_plugin/browser_plugin_browsertest.cc
+++ b/content/renderer/browser_plugin/browser_plugin_browsertest.cc
@@ -60,8 +60,8 @@
   }
   virtual ~TestContentRendererClient() {
   }
-  virtual bool AllowBrowserPlugin(WebKit::WebPluginContainer* container) const
-      OVERRIDE {
+  virtual bool AllowBrowserPlugin(
+      WebKit::WebPluginContainer* container) OVERRIDE {
     // Allow BrowserPlugin for tests.
     return true;
   }
diff --git a/content/renderer/gpu/gpu_benchmarking_extension.cc b/content/renderer/gpu/gpu_benchmarking_extension.cc
index 43d557d..a274d0d 100644
--- a/content/renderer/gpu/gpu_benchmarking_extension.cc
+++ b/content/renderer/gpu/gpu_benchmarking_extension.cc
@@ -14,7 +14,6 @@
 #include "content/common/browser_rendering_stats.h"
 #include "content/common/gpu/gpu_rendering_stats.h"
 #include "content/public/renderer/render_thread.h"
-#include "content/renderer/all_rendering_benchmarks.h"
 #include "content/renderer/gpu/render_widget_compositor.h"
 #include "content/renderer/render_view_impl.h"
 #include "content/renderer/rendering_benchmark.h"
@@ -213,10 +212,6 @@
           "  native function SmoothScrollSendsTouch();"
           "  return SmoothScrollSendsTouch();"
           "};"
-          "chrome.gpuBenchmarking.runRenderingBenchmarks = function(filter) {"
-          "  native function RunRenderingBenchmarks();"
-          "  return RunRenderingBenchmarks(filter);"
-          "};"
           "chrome.gpuBenchmarking.beginWindowSnapshotPNG = function(callback) {"
           "  native function BeginWindowSnapshotPNG();"
           "  BeginWindowSnapshotPNG(callback);"
@@ -240,8 +235,6 @@
       return v8::FunctionTemplate::New(BeginSmoothScroll);
     if (name->Equals(v8::String::New("SmoothScrollSendsTouch")))
       return v8::FunctionTemplate::New(SmoothScrollSendsTouch);
-    if (name->Equals(v8::String::New("RunRenderingBenchmarks")))
-      return v8::FunctionTemplate::New(RunRenderingBenchmarks);
     if (name->Equals(v8::String::New("BeginWindowSnapshotPNG")))
       return v8::FunctionTemplate::New(BeginWindowSnapshotPNG);
     if (name->Equals(v8::String::New("ClearImageCache")))
@@ -451,62 +444,6 @@
     args.GetReturnValue().Set(true);
   }
 
-  static void RunRenderingBenchmarks(
-      const v8::FunctionCallbackInfo<v8::Value>& args) {
-    // For our name filter, the argument can be undefined or null to run
-    // all benchmarks, or a string for filtering by name.
-    if (!args.Length() ||
-        (!args[0]->IsString() &&
-         !(args[0]->IsNull() || args[0]->IsUndefined()))) {
-      return;
-    }
-
-    std::string name_filter;
-    if (args[0]->IsNull() || args[0]->IsUndefined()) {
-      name_filter = "";
-    } else {
-      char filter[256];
-      args[0]->ToString()->WriteUtf8(filter, sizeof(filter)-1);
-      name_filter = std::string(filter);
-    }
-
-    WebFrame* web_frame = WebFrame::frameForCurrentContext();
-    if (!web_frame)
-      return;
-
-    WebView* web_view = web_frame->view();
-    if (!web_view)
-      return;
-
-    WebViewBenchmarkSupport* support = web_view->benchmarkSupport();
-    if (!support)
-      return;
-
-    ScopedVector<RenderingBenchmark> benchmarks = AllRenderingBenchmarks();
-
-    v8::Handle<v8::Array> results = v8::Array::New(0);
-    ScopedVector<RenderingBenchmark>::const_iterator it;
-    for (it = benchmarks.begin(); it != benchmarks.end(); it++) {
-      RenderingBenchmark* benchmark = *it;
-      const std::string& name = benchmark->name();
-      if (name_filter != "" &&
-          std::string::npos == name.find(name_filter)) {
-        continue;
-      }
-      benchmark->SetUp(support);
-      double result = benchmark->Run(support);
-      benchmark->TearDown(support);
-
-      v8::Handle<v8::Object> result_object = v8::Object::New();
-      result_object->Set(v8::String::New("benchmark", 9),
-                         v8::String::New(name.c_str(), -1));
-      result_object->Set(v8::String::New("result", 6), v8::Number::New(result));
-      results->Set(results->Length(), result_object);
-    }
-
-    args.GetReturnValue().Set(results);
-  }
-
   static void OnSnapshotCompleted(CallbackAndContext* callback_and_context,
                                   const gfx::Size& size,
                                   const std::vector<unsigned char>& png) {
diff --git a/content/renderer/gpu/input_handler_proxy.cc b/content/renderer/gpu/input_handler_proxy.cc
index 1d9bb07..1f88e62 100644
--- a/content/renderer/gpu/input_handler_proxy.cc
+++ b/content/renderer/gpu/input_handler_proxy.cc
@@ -173,10 +173,11 @@
     DCHECK(expect_scroll_update_end_);
     expect_scroll_update_end_ = false;
 #endif
+    input_handler_->ScrollEnd();
+
     if (!gesture_scroll_on_impl_thread_)
       return DID_NOT_HANDLE;
 
-    input_handler_->ScrollEnd();
     gesture_scroll_on_impl_thread_ = false;
     return DID_HANDLE;
   } else if (event.type == WebInputEvent::GesturePinchBegin) {
diff --git a/content/renderer/gpu/input_handler_proxy_unittest.cc b/content/renderer/gpu/input_handler_proxy_unittest.cc
index ca3e2cf..3e8b8c8 100644
--- a/content/renderer/gpu/input_handler_proxy_unittest.cc
+++ b/content/renderer/gpu/input_handler_proxy_unittest.cc
@@ -238,6 +238,7 @@
 
   gesture_.type = WebInputEvent::GestureScrollEnd;
   gesture_.data.scrollUpdate.deltaY = 0;
+  EXPECT_CALL(mock_input_handler_, ScrollEnd()).WillOnce(testing::Return());
   EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
 }
 
@@ -246,7 +247,7 @@
   // Instead, we should get a DROP_EVENT result, indicating
   // that we could determine that there's nothing that could scroll or otherwise
   // react to this gesture sequence and thus we should drop the whole gesture
-  // sequence on the floor.
+  // sequence on the floor, except for the ScrollEnd.
   expected_disposition_ = InputHandlerProxy::DROP_EVENT;
   VERIFY_AND_RESET_MOCKS();
 
@@ -255,6 +256,11 @@
 
   gesture_.type = WebInputEvent::GestureScrollBegin;
   EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
+
+  expected_disposition_ = InputHandlerProxy::DID_NOT_HANDLE;
+  gesture_.type = WebInputEvent::GestureScrollEnd;
+  EXPECT_CALL(mock_input_handler_, ScrollEnd()).WillOnce(testing::Return());
+  EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
 }
 
 TEST_F(InputHandlerProxyTest, GesturePinch) {
@@ -359,6 +365,8 @@
 
   gesture_.type = WebInputEvent::GestureScrollEnd;
   gesture_.data.scrollUpdate.deltaY = 0;
+  EXPECT_CALL(mock_input_handler_, ScrollEnd())
+      .WillOnce(testing::Return());
   EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
 }
 
diff --git a/content/renderer/media/android/stream_texture_factory_android.cc b/content/renderer/media/android/stream_texture_factory_android.cc
deleted file mode 100644
index a2e2c5f..0000000
--- a/content/renderer/media/android/stream_texture_factory_android.cc
+++ /dev/null
@@ -1,109 +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/renderer/media/android/stream_texture_factory_android.h"
-
-#include "content/common/gpu/client/gpu_channel_host.h"
-#include "content/common/gpu/gpu_messages.h"
-#include "third_party/WebKit/public/platform/WebGraphicsContext3D.h"
-#include "ui/gfx/size.h"
-
-namespace content {
-
-StreamTextureProxy::StreamTextureProxy(StreamTextureHost* host)
-    : host_(host), client_(NULL) {
-  host->SetListener(this);
-}
-
-StreamTextureProxy::~StreamTextureProxy() {}
-
-void StreamTextureProxy::Release() {
-  SetClient(NULL);
-  if (loop_.get() && loop_.get() != base::MessageLoopProxy::current())
-    loop_->DeleteSoon(FROM_HERE, this);
-  else
-    delete this;
-}
-
-void StreamTextureProxy::SetClient(cc::VideoFrameProvider::Client* client) {
-  base::AutoLock lock(client_lock_);
-  client_ = client;
-}
-
-void StreamTextureProxy::BindToCurrentThread(int stream_id) {
-  loop_ = base::MessageLoopProxy::current();
-  host_->Initialize(stream_id);
-}
-
-void StreamTextureProxy::OnFrameAvailable() {
-  base::AutoLock lock(client_lock_);
-  if (client_)
-    client_->DidReceiveFrame();
-}
-
-void StreamTextureProxy::OnMatrixChanged(const float matrix[16]) {
-  base::AutoLock lock(client_lock_);
-  if (client_)
-    client_->DidUpdateMatrix(matrix);
-}
-
-StreamTextureFactory::StreamTextureFactory(
-    WebKit::WebGraphicsContext3D* context,
-    GpuChannelHost* channel,
-    int view_id)
-    : context_(context), channel_(channel), view_id_(view_id) {
-  DCHECK(context_);
-  DCHECK(channel);
-}
-
-StreamTextureFactory::~StreamTextureFactory() {}
-
-StreamTextureProxy* StreamTextureFactory::CreateProxy() {
-  DCHECK(channel_.get());
-  StreamTextureHost* host = new StreamTextureHost(channel_.get());
-  return new StreamTextureProxy(host);
-}
-
-void StreamTextureFactory::EstablishPeer(int32 stream_id, int player_id) {
-  DCHECK(channel_.get());
-  channel_->Send(
-      new GpuChannelMsg_EstablishStreamTexture(stream_id, view_id_, player_id));
-}
-
-unsigned StreamTextureFactory::CreateStreamTexture(
-    unsigned texture_target,
-    unsigned* texture_id,
-    gpu::Mailbox* texture_mailbox,
-    unsigned* texture_mailbox_sync_point) {
-  unsigned stream_id = 0;
-  if (context_->makeContextCurrent()) {
-    *texture_id = context_->createTexture();
-    stream_id = context_->createStreamTextureCHROMIUM(*texture_id);
-
-    context_->genMailboxCHROMIUM(texture_mailbox->name);
-    context_->bindTexture(texture_target, *texture_id);
-    context_->produceTextureCHROMIUM(texture_target, texture_mailbox->name);
-
-    context_->flush();
-    *texture_mailbox_sync_point = context_->insertSyncPoint();
-  }
-  return stream_id;
-}
-
-void StreamTextureFactory::DestroyStreamTexture(unsigned texture_id) {
-  if (context_->makeContextCurrent()) {
-    // TODO(sievers): Make the destroyStreamTexture implicit when the last
-    // texture referencing it is lost.
-    context_->destroyStreamTextureCHROMIUM(texture_id);
-    context_->deleteTexture(texture_id);
-    context_->flush();
-  }
-}
-
-void StreamTextureFactory::SetStreamTextureSize(
-    int32 stream_id, const gfx::Size& size) {
-  channel_->Send(new GpuChannelMsg_SetStreamTextureSize(stream_id, size));
-}
-
-}  // namespace content
diff --git a/content/renderer/media/android/stream_texture_factory_android.h b/content/renderer/media/android/stream_texture_factory_android.h
index f496348..d41d857 100644
--- a/content/renderer/media/android/stream_texture_factory_android.h
+++ b/content/renderer/media/android/stream_texture_factory_android.h
@@ -7,51 +7,33 @@
 
 #include "base/memory/scoped_ptr.h"
 #include "cc/layers/video_frame_provider.h"
-#include "content/renderer/gpu/stream_texture_host_android.h"
 #include "gpu/command_buffer/common/mailbox.h"
-
-namespace WebKit {
-class WebGraphicsContext3D;
-}
+#include "ui/gfx/size.h"
 
 namespace content {
 
 // The proxy class for the gpu thread to notify the compositor thread
 // when a new video frame is available.
-class StreamTextureProxy : public StreamTextureHost::Listener {
+class StreamTextureProxy {
  public:
-  explicit StreamTextureProxy(StreamTextureHost* host);
-  virtual ~StreamTextureProxy();
+  virtual ~StreamTextureProxy() {}
 
   // Initialize and bind to the current thread, which becomes the thread that
   // a connected client will receive callbacks on.
-  void BindToCurrentThread(int32 stream_id);
+  virtual void BindToCurrentThread(int32 stream_id) = 0;
 
-  bool IsBoundToThread() { return loop_.get() != NULL; }
+  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.
-  void SetClient(cc::VideoFrameProvider::Client* client);
+  virtual void SetClient(cc::VideoFrameProvider::Client* client) = 0;
 
-  // StreamTextureHost::Listener implementation:
-  virtual void OnFrameAvailable() OVERRIDE;
-  virtual void OnMatrixChanged(const float matrix[16]) OVERRIDE;
+  // Causes this instance to be deleted on the thread it is bound to.
+  virtual void Release() = 0;
 
   struct Deleter {
     inline void operator()(StreamTextureProxy* ptr) const { ptr->Release(); }
   };
-
- private:
-  // Causes this instance to be deleted on the thread it is bound to.
-  void Release();
-
-  scoped_ptr<StreamTextureHost> host_;
-  scoped_refptr<base::MessageLoopProxy> loop_;
-
-  base::Lock client_lock_;
-  cc::VideoFrameProvider::Client* client_;
-
-  DISALLOW_IMPLICIT_CONSTRUCTORS(StreamTextureProxy);
 };
 
 typedef scoped_ptr<StreamTextureProxy, StreamTextureProxy::Deleter>
@@ -60,43 +42,34 @@
 // Factory class for managing stream textures.
 class StreamTextureFactory {
  public:
-  StreamTextureFactory(WebKit::WebGraphicsContext3D* context,
-                       GpuChannelHost* channel,
-                       int view_id);
-  ~StreamTextureFactory();
+  virtual ~StreamTextureFactory() {}
 
   // Create the StreamTextureProxy object.
-  StreamTextureProxy* CreateProxy();
+  virtual StreamTextureProxy* CreateProxy() = 0;
 
   // Send an IPC message to the browser process to request a java surface
   // object for the given stream_id. After the the surface is created,
   // it will be passed back to the WebMediaPlayerAndroid object identified by
   // the player_id.
-  void EstablishPeer(int32 stream_id, int player_id);
+  virtual void EstablishPeer(int32 stream_id, int player_id) = 0;
 
   // Create the streamTexture and return the stream Id and create a client-side
   // texture id to refer to the streamTexture. The texture id is produced into
   // a mailbox so it can be used to ship in a VideoFrame, with a sync point for
   // when the mailbox can be accessed.
-  unsigned CreateStreamTexture(
+  virtual unsigned CreateStreamTexture(
       unsigned texture_target,
       unsigned* texture_id,
       gpu::Mailbox* texture_mailbox,
-      unsigned* texture_mailbox_sync_point);
+      unsigned* texture_mailbox_sync_point) = 0;
 
   // Destroy the streamTexture for the given texture id, as well as the
   // client side texture.
-  void DestroyStreamTexture(unsigned texture_id);
+  virtual void DestroyStreamTexture(unsigned texture_id) = 0;
 
   // Set the streamTexture size for the given stream Id.
-  void SetStreamTextureSize(int32 texture_id, const gfx::Size& size);
-
- private:
-  WebKit::WebGraphicsContext3D* context_;
-  scoped_refptr<GpuChannelHost> channel_;
-  int view_id_;
-
-  DISALLOW_IMPLICIT_CONSTRUCTORS(StreamTextureFactory);
+  virtual void SetStreamTextureSize(int32 texture_id,
+                                    const gfx::Size& size) = 0;
 };
 
 }  // namespace content
diff --git a/content/renderer/media/android/stream_texture_factory_android_impl.cc b/content/renderer/media/android/stream_texture_factory_android_impl.cc
new file mode 100644
index 0000000..721b680
--- /dev/null
+++ b/content/renderer/media/android/stream_texture_factory_android_impl.cc
@@ -0,0 +1,140 @@
+// 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/renderer/media/android/stream_texture_factory_android_impl.h"
+
+#include "content/common/gpu/client/gpu_channel_host.h"
+#include "content/common/gpu/gpu_messages.h"
+#include "content/renderer/gpu/stream_texture_host_android.h"
+#include "third_party/WebKit/public/platform/WebGraphicsContext3D.h"
+#include "ui/gfx/size.h"
+
+namespace content {
+
+namespace {
+
+class StreamTextureProxyImpl : public StreamTextureProxy,
+                               public StreamTextureHost::Listener {
+ public:
+  explicit StreamTextureProxyImpl(StreamTextureHost* host);
+  virtual ~StreamTextureProxyImpl();
+
+  // 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;
+
+  // StreamTextureHost::Listener implementation:
+  virtual void OnFrameAvailable() OVERRIDE;
+  virtual void OnMatrixChanged(const float matrix[16]) OVERRIDE;
+
+ private:
+  scoped_ptr<StreamTextureHost> host_;
+  scoped_refptr<base::MessageLoopProxy> loop_;
+
+  base::Lock client_lock_;
+  cc::VideoFrameProvider::Client* client_;
+
+  DISALLOW_IMPLICIT_CONSTRUCTORS(StreamTextureProxyImpl);
+};
+
+StreamTextureProxyImpl::StreamTextureProxyImpl(StreamTextureHost* host)
+    : host_(host), client_(NULL) {
+  host->SetListener(this);
+}
+
+StreamTextureProxyImpl::~StreamTextureProxyImpl() {}
+
+void StreamTextureProxyImpl::Release() {
+  SetClient(NULL);
+  if (loop_.get() && loop_.get() != base::MessageLoopProxy::current())
+    loop_->DeleteSoon(FROM_HERE, this);
+  else
+    delete this;
+}
+
+void StreamTextureProxyImpl::SetClient(cc::VideoFrameProvider::Client* client) {
+  base::AutoLock lock(client_lock_);
+  client_ = client;
+}
+
+void StreamTextureProxyImpl::BindToCurrentThread(int stream_id) {
+  loop_ = base::MessageLoopProxy::current();
+  host_->Initialize(stream_id);
+}
+
+void StreamTextureProxyImpl::OnFrameAvailable() {
+  base::AutoLock lock(client_lock_);
+  if (client_)
+    client_->DidReceiveFrame();
+}
+
+void StreamTextureProxyImpl::OnMatrixChanged(const float matrix[16]) {
+  base::AutoLock lock(client_lock_);
+  if (client_)
+    client_->DidUpdateMatrix(matrix);
+}
+
+}  // namespace
+
+StreamTextureFactoryImpl::StreamTextureFactoryImpl(
+    WebKit::WebGraphicsContext3D* context,
+    GpuChannelHost* channel,
+    int view_id)
+    : context_(context), channel_(channel), view_id_(view_id) {
+  DCHECK(context_);
+  DCHECK(channel);
+}
+
+StreamTextureFactoryImpl::~StreamTextureFactoryImpl() {}
+
+StreamTextureProxy* StreamTextureFactoryImpl::CreateProxy() {
+  DCHECK(channel_.get());
+  StreamTextureHost* host = new StreamTextureHost(channel_.get());
+  return new StreamTextureProxyImpl(host);
+}
+
+void StreamTextureFactoryImpl::EstablishPeer(int32 stream_id, int player_id) {
+  DCHECK(channel_.get());
+  channel_->Send(
+      new GpuChannelMsg_EstablishStreamTexture(stream_id, view_id_, player_id));
+}
+
+unsigned StreamTextureFactoryImpl::CreateStreamTexture(
+    unsigned texture_target,
+    unsigned* texture_id,
+    gpu::Mailbox* texture_mailbox,
+    unsigned* texture_mailbox_sync_point) {
+  unsigned stream_id = 0;
+  if (context_->makeContextCurrent()) {
+    *texture_id = context_->createTexture();
+    stream_id = context_->createStreamTextureCHROMIUM(*texture_id);
+
+    context_->genMailboxCHROMIUM(texture_mailbox->name);
+    context_->bindTexture(texture_target, *texture_id);
+    context_->produceTextureCHROMIUM(texture_target, texture_mailbox->name);
+
+    context_->flush();
+    *texture_mailbox_sync_point = context_->insertSyncPoint();
+  }
+  return stream_id;
+}
+
+void StreamTextureFactoryImpl::DestroyStreamTexture(unsigned texture_id) {
+  if (context_->makeContextCurrent()) {
+    // TODO(sievers): Make the destroyStreamTexture implicit when the last
+    // texture referencing it is lost.
+    context_->destroyStreamTextureCHROMIUM(texture_id);
+    context_->deleteTexture(texture_id);
+    context_->flush();
+  }
+}
+
+void StreamTextureFactoryImpl::SetStreamTextureSize(
+    int32 stream_id, const gfx::Size& size) {
+  channel_->Send(new GpuChannelMsg_SetStreamTextureSize(stream_id, size));
+}
+
+}  // namespace content
diff --git a/content/renderer/media/android/stream_texture_factory_android_impl.h b/content/renderer/media/android/stream_texture_factory_android_impl.h
new file mode 100644
index 0000000..20aacdd
--- /dev/null
+++ b/content/renderer/media/android/stream_texture_factory_android_impl.h
@@ -0,0 +1,47 @@
+// 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_RENDERER_MEDIA_ANDROID_STREAM_TEXTURE_FACTORY_ANDROID_IMPL_H_
+#define CONTENT_RENDERER_MEDIA_ANDROID_STREAM_TEXTURE_FACTORY_ANDROID_IMPL_H_
+
+#include "content/renderer/media/android/stream_texture_factory_android.h"
+
+namespace WebKit {
+class WebGraphicsContext3D;
+}
+
+namespace content {
+
+class GpuChannelHost;
+
+class StreamTextureFactoryImpl : public StreamTextureFactory {
+ public:
+  StreamTextureFactoryImpl(WebKit::WebGraphicsContext3D* context,
+                           GpuChannelHost* channel,
+                           int view_id);
+  virtual ~StreamTextureFactoryImpl();
+
+  // StreamTextureFactory implementation.
+  virtual StreamTextureProxy* CreateProxy() OVERRIDE;
+  virtual void EstablishPeer(int32 stream_id, int player_id) OVERRIDE;
+  virtual unsigned CreateStreamTexture(
+      unsigned texture_target,
+      unsigned* texture_id,
+      gpu::Mailbox* texture_mailbox,
+      unsigned* texture_mailbox_sync_point) OVERRIDE;
+  virtual void DestroyStreamTexture(unsigned texture_id) OVERRIDE;
+  virtual void SetStreamTextureSize(int32 texture_id,
+                                    const gfx::Size& size) OVERRIDE;
+
+ private:
+  WebKit::WebGraphicsContext3D* context_;
+  scoped_refptr<GpuChannelHost> channel_;
+  int view_id_;
+
+  DISALLOW_IMPLICIT_CONSTRUCTORS(StreamTextureFactoryImpl);
+};
+
+}  // namespace content
+
+#endif  // CONTENT_RENDERER_MEDIA_ANDROID_STREAM_TEXTURE_FACTORY_ANDROID_IMPL_H_
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
new file mode 100644
index 0000000..88878d5
--- /dev/null
+++ b/content/renderer/media/android/stream_texture_factory_android_synchronous_impl.cc
@@ -0,0 +1,34 @@
+// 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/renderer/media/android/stream_texture_factory_android_synchronous_impl.h"
+
+namespace content {
+
+StreamTextureFactorySynchronousImpl::StreamTextureFactorySynchronousImpl() {}
+StreamTextureFactorySynchronousImpl::~StreamTextureFactorySynchronousImpl() {}
+
+StreamTextureProxy* StreamTextureFactorySynchronousImpl::CreateProxy() {
+  return NULL;
+}
+
+void StreamTextureFactorySynchronousImpl::EstablishPeer(int32 stream_id,
+                                                        int player_id) {}
+
+unsigned StreamTextureFactorySynchronousImpl::CreateStreamTexture(
+    unsigned texture_target,
+    unsigned* texture_id,
+    gpu::Mailbox* texture_mailbox,
+    unsigned* texture_mailbox_sync_point) {
+  return 0;
+}
+
+void StreamTextureFactorySynchronousImpl::DestroyStreamTexture(
+    unsigned texture_id) {}
+
+void StreamTextureFactorySynchronousImpl::SetStreamTextureSize(
+    int32 texture_id,
+    const gfx::Size& size) {}
+
+}  // namespace content
diff --git a/content/renderer/media/android/stream_texture_factory_android_synchronous_impl.h b/content/renderer/media/android/stream_texture_factory_android_synchronous_impl.h
new file mode 100644
index 0000000..52fc65a
--- /dev/null
+++ b/content/renderer/media/android/stream_texture_factory_android_synchronous_impl.h
@@ -0,0 +1,35 @@
+// 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_RENDERER_MEDIA_ANDROID_STREAM_TEXTURE_FACTORY_ANDROID_SYNCHRONOUS_IMPL_H_
+#define CONTENT_RENDERER_MEDIA_ANDROID_STREAM_TEXTURE_FACTORY_ANDROID_SYNCHRONOUS_IMPL_H_
+
+#include "content/renderer/media/android/stream_texture_factory_android.h"
+
+namespace content {
+
+// Factory for when using synchronous compositor in Android WebView.
+class StreamTextureFactorySynchronousImpl : public StreamTextureFactory {
+ public:
+  StreamTextureFactorySynchronousImpl();
+  virtual ~StreamTextureFactorySynchronousImpl();
+
+  virtual StreamTextureProxy* CreateProxy() OVERRIDE;
+  virtual void EstablishPeer(int32 stream_id, int player_id) OVERRIDE;
+  virtual unsigned CreateStreamTexture(
+      unsigned texture_target,
+      unsigned* texture_id,
+      gpu::Mailbox* texture_mailbox,
+      unsigned* texture_mailbox_sync_point) OVERRIDE;
+  virtual void DestroyStreamTexture(unsigned texture_id) OVERRIDE;
+  virtual void SetStreamTextureSize(int32 texture_id,
+                                    const gfx::Size& size) OVERRIDE;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(StreamTextureFactorySynchronousImpl);
+};
+
+}  // namespace content
+
+#endif  // CONTENT_RENDERER_MEDIA_ANDROID_STREAM_TEXTURE_FACTORY_ANDROID_SYNCHRONOUS_IMPL_H_
diff --git a/content/renderer/media/crypto/content_decryption_module_factory.cc b/content/renderer/media/crypto/content_decryption_module_factory.cc
index 3ce22f3..9310101 100644
--- a/content/renderer/media/crypto/content_decryption_module_factory.cc
+++ b/content/renderer/media/crypto/content_decryption_module_factory.cc
@@ -6,7 +6,7 @@
 
 #include "base/logging.h"
 #include "content/renderer/media/crypto/key_systems.h"
-#include "media/crypto/aes_decryptor.h"
+#include "media/cdm/aes_decryptor.h"
 
 #if defined(ENABLE_PEPPER_CDMS)
 #include "content/renderer/media/crypto/ppapi_decryptor.h"
diff --git a/content/renderer/media/media_stream_dependency_factory.cc b/content/renderer/media/media_stream_dependency_factory.cc
index 7f5e64a..304a818 100644
--- a/content/renderer/media/media_stream_dependency_factory.cc
+++ b/content/renderer/media/media_stream_dependency_factory.cc
@@ -286,7 +286,7 @@
         source_data->device_info().device.type ==
             content::MEDIA_TAB_VIDEO_CAPTURE ||
         source_data->device_info().device.type ==
-            content::MEDIA_SCREEN_VIDEO_CAPTURE;
+            content::MEDIA_DESKTOP_VIDEO_CAPTURE;
     source_data->SetVideoSource(
         CreateLocalVideoSource(source_data->device_info().session_id,
                                is_screencast,
@@ -551,8 +551,8 @@
             web_frame);
 
   PeerConnectionIdentityService* identity_service =
-      new PeerConnectionIdentityService(GURL(web_frame->document().url().spec())
-                                            .GetOrigin());
+      PeerConnectionIdentityService::Create(
+          GURL(web_frame->document().url().spec()).GetOrigin());
 
   return pc_factory_->CreatePeerConnection(ice_servers,
                                            constraints,
diff --git a/content/renderer/media/media_stream_dispatcher.cc b/content/renderer/media/media_stream_dispatcher.cc
index 80b3473..cc241fa 100644
--- a/content/renderer/media/media_stream_dispatcher.cc
+++ b/content/renderer/media/media_stream_dispatcher.cc
@@ -244,6 +244,8 @@
                         OnStreamGenerated)
     IPC_MESSAGE_HANDLER(MediaStreamMsg_StreamGenerationFailed,
                         OnStreamGenerationFailed)
+    IPC_MESSAGE_HANDLER(MediaStreamMsg_StopGeneratedStream,
+                        OnStopGeneratedStream)
     IPC_MESSAGE_HANDLER(MediaStreamMsg_DevicesEnumerated,
                         OnDevicesEnumerated)
     IPC_MESSAGE_HANDLER(MediaStreamMsg_DevicesEnumerationFailed,
@@ -302,6 +304,20 @@
   }
 }
 
+void MediaStreamDispatcher::OnStopGeneratedStream(const std::string& label) {
+  DCHECK(main_loop_->BelongsToCurrentThread());
+  LabelStreamMap::iterator it = label_stream_map_.find(label);
+  if (it == label_stream_map_.end())
+    return;
+
+  if (it->second.handler.get()) {
+    it->second.handler->OnStopGeneratedStream(label);
+    DVLOG(1) << "MediaStreamDispatcher::OnStopGeneratedStream("
+             << label << ")\n";
+  }
+  label_stream_map_.erase(it);
+}
+
 void MediaStreamDispatcher::OnDevicesEnumerated(
     int request_id,
     const std::string& label,
diff --git a/content/renderer/media/media_stream_dispatcher.h b/content/renderer/media/media_stream_dispatcher.h
index 3562a02..aa8f345 100644
--- a/content/renderer/media/media_stream_dispatcher.h
+++ b/content/renderer/media/media_stream_dispatcher.h
@@ -146,6 +146,7 @@
       const StreamDeviceInfoArray& audio_array,
       const StreamDeviceInfoArray& video_array);
   void OnStreamGenerationFailed(int request_id);
+  void OnStopGeneratedStream(const std::string& label);
   void OnDevicesEnumerated(
       int request_id,
       const std::string& label,
diff --git a/content/renderer/media/media_stream_dispatcher_eventhandler.h b/content/renderer/media/media_stream_dispatcher_eventhandler.h
index c489607..7a0803a 100644
--- a/content/renderer/media/media_stream_dispatcher_eventhandler.h
+++ b/content/renderer/media/media_stream_dispatcher_eventhandler.h
@@ -25,6 +25,9 @@
   // to the requested devices or no device is available.
   virtual void OnStreamGenerationFailed(int request_id) = 0;
 
+  // The user has requested to stop a media stream.
+  virtual void OnStopGeneratedStream(const std::string& label) = 0;
+
   // A new list of devices have been enumerated.
   virtual void OnDevicesEnumerated(
       int request_id,
diff --git a/content/renderer/media/media_stream_dispatcher_unittest.cc b/content/renderer/media/media_stream_dispatcher_unittest.cc
index b5e46be..300bfe3 100644
--- a/content/renderer/media/media_stream_dispatcher_unittest.cc
+++ b/content/renderer/media/media_stream_dispatcher_unittest.cc
@@ -50,6 +50,10 @@
     request_id_ = request_id;
   }
 
+  virtual void OnStopGeneratedStream(const std::string& label) OVERRIDE {
+    label_ = label;
+  }
+
   virtual void OnDevicesEnumerated(
       int request_id,
       const StreamDeviceInfoArray& device_array) OVERRIDE {
diff --git a/content/renderer/media/media_stream_impl.cc b/content/renderer/media/media_stream_impl.cc
index abe68a2..5edc4cc 100644
--- a/content/renderer/media/media_stream_impl.cc
+++ b/content/renderer/media/media_stream_impl.cc
@@ -10,6 +10,7 @@
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
+#include "content/public/common/desktop_media_id.h"
 #include "content/renderer/media/media_stream_audio_renderer.h"
 #include "content/renderer/media/media_stream_dependency_factory.h"
 #include "content/renderer/media/media_stream_dispatcher.h"
@@ -71,7 +72,9 @@
           user_media_request.videoConstraints(),
           kMediaStreamSourceId, true);
     } else if (video_stream_source == kMediaStreamSourceScreen) {
-      options->video_type = content::MEDIA_SCREEN_VIDEO_CAPTURE;
+      options->video_type = content::MEDIA_DESKTOP_VIDEO_CAPTURE;
+      options->video_device_id =
+          DesktopMediaID(DesktopMediaID::TYPE_SCREEN, 0).ToString();
     }
   }
 }
@@ -373,6 +376,24 @@
   DeleteUserMediaRequestInfo(request_info);
 }
 
+// Callback from MediaStreamDispatcher.
+// The user has requested to stop the media stream.
+void MediaStreamImpl::OnStopGeneratedStream(const std::string& label) {
+  DCHECK(CalledOnValidThread());
+  DVLOG(1) << "MediaStreamImpl::OnStopGeneratedStream(" << label << ")";
+
+  UserMediaRequestInfo* user_media_request = FindUserMediaRequestInfo(label);
+  if (user_media_request) {
+    // No need to call media_stream_dispatcher_->StopStream() because the
+    // request has come from the browser process.
+    StopLocalAudioTrack(user_media_request->web_stream);
+    DeleteUserMediaRequestInfo(user_media_request);
+  } else {
+    DVLOG(1) << "MediaStreamImpl::OnStopGeneratedStream: the stream has "
+             << "already been stopped.";
+  }
+}
+
 // Callback from MediaStreamDependencyFactory when the sources in |web_stream|
 // have been generated.
 void MediaStreamImpl::OnCreateNativeSourcesComplete(
diff --git a/content/renderer/media/media_stream_impl.h b/content/renderer/media/media_stream_impl.h
index ee506cc..1cd4479 100644
--- a/content/renderer/media/media_stream_impl.h
+++ b/content/renderer/media/media_stream_impl.h
@@ -73,6 +73,7 @@
       const StreamDeviceInfoArray& audio_array,
       const StreamDeviceInfoArray& video_array) OVERRIDE;
   virtual void OnStreamGenerationFailed(int request_id) OVERRIDE;
+  virtual void OnStopGeneratedStream(const std::string& label) OVERRIDE;
   virtual void OnDevicesEnumerated(
       int request_id,
       const StreamDeviceInfoArray& device_array) OVERRIDE;
diff --git a/content/renderer/media/peer_connection_identity_service.cc b/content/renderer/media/peer_connection_identity_service.cc
index f7bc856..904eb41 100644
--- a/content/renderer/media/peer_connection_identity_service.cc
+++ b/content/renderer/media/peer_connection_identity_service.cc
@@ -9,8 +9,17 @@
 
 namespace content {
 
-PeerConnectionIdentityService::PeerConnectionIdentityService(const GURL& origin)
-    : origin_(origin), pending_observer_(NULL), pending_request_id_(0) {}
+PeerConnectionIdentityService* PeerConnectionIdentityService::Create(
+    const GURL& origin) {
+// The crypto APIs needed for generating identities are not implenented for
+// OPENSSL yet (crbug/91512). So returning NULL in that case.
+// TODO(jiayl): remove the #if once the crypto APIs are implemented for OPENSSL.
+#if defined(USE_OPENSSL)
+  return NULL;
+#else
+  return new PeerConnectionIdentityService(origin);
+#endif  // defined(USE_OPENSSL)
+}
 
 PeerConnectionIdentityService::~PeerConnectionIdentityService() {
   if (pending_observer_)
@@ -39,6 +48,9 @@
   return true;
 }
 
+PeerConnectionIdentityService::PeerConnectionIdentityService(const GURL& origin)
+    : origin_(origin), pending_observer_(NULL), pending_request_id_(0) {}
+
 void PeerConnectionIdentityService::OnIdentityReady(
     const std::string& certificate,
     const std::string& private_key) {
diff --git a/content/renderer/media/peer_connection_identity_service.h b/content/renderer/media/peer_connection_identity_service.h
index a5092e3..fa0b16a 100644
--- a/content/renderer/media/peer_connection_identity_service.h
+++ b/content/renderer/media/peer_connection_identity_service.h
@@ -19,7 +19,8 @@
 class PeerConnectionIdentityService
     : public webrtc::DTLSIdentityServiceInterface {
  public:
-  explicit PeerConnectionIdentityService(const GURL& origin);
+  static PeerConnectionIdentityService* Create(const GURL& origin);
+
   virtual ~PeerConnectionIdentityService();
 
   // webrtc::DTLSIdentityServiceInterface implementation.
@@ -29,6 +30,8 @@
       webrtc::DTLSIdentityRequestObserver* observer) OVERRIDE;
 
  private:
+  explicit PeerConnectionIdentityService(const GURL& origin);
+
   void OnIdentityReady(const std::string& certificate,
                        const std::string& private_key);
   void OnRequestFailed(int error);
diff --git a/content/renderer/media/rtc_video_decoder.cc b/content/renderer/media/rtc_video_decoder.cc
index e89cad9..12904f1 100644
--- a/content/renderer/media/rtc_video_decoder.cc
+++ b/content/renderer/media/rtc_video_decoder.cc
@@ -95,11 +95,14 @@
 
 RTCVideoDecoder::~RTCVideoDecoder() {
   DVLOG(2) << "~RTCVideoDecoder";
-  // Remove |this| from the observer if vda thread is alive.
-  if (vda_loop_proxy_->BelongsToCurrentThread())
+  // Destroy VDA and remove |this| from the observer if this is vda thread.
+  if (vda_loop_proxy_->BelongsToCurrentThread()) {
     base::MessageLoop::current()->RemoveDestructionObserver(this);
-  // VDA should have been destroyed.
-  DCHECK(!vda_);
+    DestroyVDA();
+  } else {
+    // VDA should have been destroyed in WillDestroyCurrentMessageLoop.
+    DCHECK(!vda_);
+  }
 
   // Delete all shared memories.
   STLDeleteElements(&available_shm_segments_);
@@ -231,19 +234,9 @@
 
 int32_t RTCVideoDecoder::Release() {
   DVLOG(2) << "Release";
-  base::AutoLock auto_lock(lock_);
-  if (state_ == UNINITIALIZED) {
-    LOG(ERROR) << "Decoder not initialized.";
-    return WEBRTC_VIDEO_CODEC_UNINITIALIZED;
-  }
-  if (next_bitstream_buffer_id_ != 0)
-    reset_bitstream_buffer_id_ = next_bitstream_buffer_id_ - 1;
-  else
-    reset_bitstream_buffer_id_ = ID_LAST;
-  factories_->Abort();
-  vda_loop_proxy_->PostTask(
-      FROM_HERE, base::Bind(&RTCVideoDecoder::DestroyVDA, weak_this_));
-  return WEBRTC_VIDEO_CODEC_OK;
+  // Do not destroy VDA because WebRTC can call InitDecode and start decoding
+  // again.
+  return Reset();
 }
 
 int32_t RTCVideoDecoder::Reset() {
@@ -367,7 +360,7 @@
       width, height, width, (width + 1) / 2, (width + 1) / 2);
   decoded_image.set_timestamp(timestamp);
 
-  // Invoke decode callback. WebRTC expects no frame callback after Release.
+  // Invoke decode callback. WebRTC expects no callback after Reset or Release.
   {
     base::AutoLock auto_lock(lock_);
     DCHECK(decode_complete_callback_ != NULL);
@@ -659,6 +652,8 @@
   if (vda_)
     vda_.release()->Destroy();
   DestroyTextures();
+  base::AutoLock auto_lock(lock_);
+  state_ = UNINITIALIZED;
 }
 
 scoped_ptr<RTCVideoDecoder::SHMBuffer> RTCVideoDecoder::GetSHM_Locked(
diff --git a/content/renderer/media/rtc_video_decoder_unittest.cc b/content/renderer/media/rtc_video_decoder_unittest.cc
index e23e91b..2ffeb3e 100644
--- a/content/renderer/media/rtc_video_decoder_unittest.cc
+++ b/content/renderer/media/rtc_video_decoder_unittest.cc
@@ -20,6 +20,7 @@
 
 namespace content {
 
+// TODO(wuchengli): add MockSharedMemroy so more functions can be tested.
 class RTCVideoDecoderTest : public ::testing::Test,
                             webrtc::DecodedImageCallback {
  public:
@@ -53,8 +54,6 @@
   virtual void TearDown() OVERRIDE {
     VLOG(2) << "TearDown";
     if (vda_thread_.IsRunning()) {
-      if (rtc_decoder_)
-        rtc_decoder_->Release();
       RunUntilIdle();  // Wait until all callbascks complete.
       vda_loop_proxy_->DeleteSoon(FROM_HERE, rtc_decoder_.release());
       // Make sure the decoder is released before stopping the thread.
@@ -152,6 +151,17 @@
 
 TEST_F(RTCVideoDecoderTest, ReleaseReturnsOk) {
   Initialize();
+  EXPECT_CALL(*mock_vda_, Reset())
+      .WillOnce(Invoke(this, &RTCVideoDecoderTest::NotifyResetDone));
+  EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, rtc_decoder_->Release());
+}
+
+TEST_F(RTCVideoDecoderTest, InitDecodeAfterRelease) {
+  EXPECT_CALL(*mock_vda_, Reset())
+      .WillRepeatedly(Invoke(this, &RTCVideoDecoderTest::NotifyResetDone));
+  Initialize();
+  EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, rtc_decoder_->Release());
+  Initialize();
   EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, rtc_decoder_->Release());
 }
 
diff --git a/content/renderer/media/webmediaplayer_impl.cc b/content/renderer/media/webmediaplayer_impl.cc
index 1343bc6..227d0cf 100644
--- a/content/renderer/media/webmediaplayer_impl.cc
+++ b/content/renderer/media/webmediaplayer_impl.cc
@@ -1061,8 +1061,8 @@
         base::Bind(&LogMediaSourceError, media_log_));
     demuxer_.reset(chunk_demuxer_);
 
-#if !defined(OS_CHROMEOS) || !defined(ARCH_CPU_X86_FAMILY)
-    // Disable GpuVideoDecoder creation on platforms other than CrOS x86 until
+#if !defined(OS_CHROMEOS)
+    // Disable GpuVideoDecoder creation on platforms other than CrOS until
     // they support codec config changes.
     // TODO(acolwell): Remove this once http://crbug.com/151045 is fixed.
     gpu_factories_ = NULL;
diff --git a/content/renderer/npapi/webplugin_delegate_proxy.cc b/content/renderer/npapi/webplugin_delegate_proxy.cc
index f1da1d8..fe807dd 100644
--- a/content/renderer/npapi/webplugin_delegate_proxy.cc
+++ b/content/renderer/npapi/webplugin_delegate_proxy.cc
@@ -30,11 +30,13 @@
 #include "content/child/npapi/npobject_util.h"
 #include "content/child/npapi/webplugin.h"
 #include "content/child/plugin_messages.h"
+#include "content/common/content_constants_internal.h"
 #include "content/common/view_messages.h"
 #include "content/public/renderer/content_renderer_client.h"
 #include "content/renderer/npapi/plugin_channel_host.h"
 #include "content/renderer/render_thread_impl.h"
 #include "content/renderer/render_view_impl.h"
+#include "content/renderer/sad_plugin.h"
 #include "ipc/ipc_channel_handle.h"
 #include "net/base/mime_util.h"
 #include "skia/ext/platform_canvas.h"
@@ -51,8 +53,6 @@
 #include "ui/gfx/skia_util.h"
 #include "webkit/common/cursors/webcursor.h"
 #include "webkit/glue/webkit_glue.h"
-#include "webkit/plugins/plugin_constants.h"
-#include "webkit/plugins/sad_plugin.h"
 
 #if defined(OS_POSIX)
 #include "ipc/ipc_channel_posix.h"
@@ -681,7 +681,11 @@
   // If the plugin is no longer connected (channel crashed) draw a crashed
   // plugin bitmap
   if (!channel_host_.get() || !channel_host_->channel_valid()) {
-    PaintSadPlugin(canvas, rect);
+    // Lazily load the sad plugin image.
+    if (!sad_plugin_)
+      sad_plugin_ = GetContentClient()->renderer()->GetSadPluginBitmap();
+    if (sad_plugin_)
+      PaintSadPlugin(canvas, plugin_rect_, *sad_plugin_);
     return;
   }
 
@@ -1011,15 +1015,6 @@
     *cookies = plugin_->GetCookies(url, first_party_for_cookies);
 }
 
-void WebPluginDelegateProxy::PaintSadPlugin(WebKit::WebCanvas* native_context,
-                                            const gfx::Rect& rect) {
-  // Lazily load the sad plugin image.
-  if (!sad_plugin_)
-    sad_plugin_ = GetContentClient()->renderer()->GetSadPluginBitmap();
-  if (sad_plugin_)
-    webkit::PaintSadPlugin(native_context, plugin_rect_, *sad_plugin_);
-}
-
 void WebPluginDelegateProxy::CopyFromBackBufferToFrontBuffer(
     const gfx::Rect& rect) {
 #if defined(OS_MACOSX)
diff --git a/content/renderer/npapi/webplugin_delegate_proxy.h b/content/renderer/npapi/webplugin_delegate_proxy.h
index 7c7b0ae..a40da83 100644
--- a/content/renderer/npapi/webplugin_delegate_proxy.h
+++ b/content/renderer/npapi/webplugin_delegate_proxy.h
@@ -181,9 +181,6 @@
   // Helper function that sends the UpdateGeometry message.
   void SendUpdateGeometry(bool bitmaps_changed);
 
-  // Draw a graphic indicating a crashed plugin.
-  void PaintSadPlugin(WebKit::WebCanvas* canvas, const gfx::Rect& rect);
-
   // Copies the given rectangle from the back-buffer transport_stores_ bitmap to
   // the front-buffer transport_stores_ bitmap.
   void CopyFromBackBufferToFrontBuffer(const gfx::Rect& rect);
diff --git a/content/renderer/npapi/webplugin_impl.cc b/content/renderer/npapi/webplugin_impl.cc
index ae71c44..21e80b6 100644
--- a/content/renderer/npapi/webplugin_impl.cc
+++ b/content/renderer/npapi/webplugin_impl.cc
@@ -13,10 +13,12 @@
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
 #include "cc/layers/io_surface_layer.h"
+#include "content/child/appcache/web_application_cache_host_impl.h"
 #include "content/child/npapi/plugin_host.h"
 #include "content/child/npapi/plugin_instance.h"
 #include "content/child/npapi/webplugin_delegate_impl.h"
 #include "content/common/view_messages.h"
+#include "content/public/common/content_constants.h"
 #include "content/public/renderer/content_renderer_client.h"
 #include "content/renderer/npapi/webplugin_delegate_proxy.h"
 #include "content/renderer/render_process.h"
@@ -49,11 +51,8 @@
 #include "url/gurl.h"
 #include "url/url_util.h"
 #include "webkit/child/multipart_response_delegate.h"
-#include "webkit/plugins/plugin_constants.h"
-#include "webkit/renderer/appcache/web_application_cache_host_impl.h"
 #include "webkit/renderer/compositor_bindings/web_layer_impl.h"
 
-using appcache::WebApplicationCacheHostImpl;
 using WebKit::WebCanvas;
 using WebKit::WebConsoleMessage;
 using WebKit::WebCookieJar;
diff --git a/content/renderer/pepper/audio_helper.cc b/content/renderer/pepper/audio_helper.cc
index 2bbe991..0dae997 100644
--- a/content/renderer/pepper/audio_helper.cc
+++ b/content/renderer/pepper/audio_helper.cc
@@ -79,7 +79,7 @@
 }
 
 void AudioHelper::SetCreateCallback(
-    scoped_refptr< ::ppapi::TrackedCallback> create_callback) {
+    scoped_refptr<ppapi::TrackedCallback> create_callback) {
   DCHECK(!TrackedCallback::IsPending(create_callback_));
   create_callback_ = create_callback;
 }
diff --git a/content/renderer/pepper/audio_helper.h b/content/renderer/pepper/audio_helper.h
index 8b04c84..a111325 100644
--- a/content/renderer/pepper/audio_helper.h
+++ b/content/renderer/pepper/audio_helper.h
@@ -27,7 +27,7 @@
                      base::SyncSocket::Handle socket);
 
   void SetCreateCallback(
-      scoped_refptr< ::ppapi::TrackedCallback> create_callback);
+      scoped_refptr<ppapi::TrackedCallback> create_callback);
 
  protected:
   // TODO(viettrungluu): This is all very poorly thought out. Refactor.
@@ -42,7 +42,7 @@
                                base::SyncSocket::Handle socket_handle) = 0;
 
  private:
-  scoped_refptr< ::ppapi::TrackedCallback> create_callback_;
+  scoped_refptr<ppapi::TrackedCallback> create_callback_;
 
   // When a create callback is being issued, these will save the info for
   // querying from the callback. The proxy uses this to get the handles to the
diff --git a/content/renderer/pepper/content_decryptor_delegate.cc b/content/renderer/pepper/content_decryptor_delegate.cc
index 22c3aff..94d8928 100644
--- a/content/renderer/pepper/content_decryptor_delegate.cc
+++ b/content/renderer/pepper/content_decryptor_delegate.cc
@@ -823,7 +823,9 @@
   scoped_refptr<media::VideoFrame> decoded_frame =
       media::VideoFrame::WrapExternalYuvData(
           media::VideoFrame::YV12,
-          frame_size, gfx::Rect(frame_size), natural_size_,
+          frame_size,
+          gfx::Rect(frame_size),
+          natural_size_,
           frame_info->strides[PP_DECRYPTEDFRAMEPLANES_Y],
           frame_info->strides[PP_DECRYPTEDFRAMEPLANES_U],
           frame_info->strides[PP_DECRYPTEDFRAMEPLANES_V],
@@ -832,10 +834,10 @@
           frame_data + frame_info->plane_offsets[PP_DECRYPTEDFRAMEPLANES_V],
           base::TimeDelta::FromMicroseconds(
               frame_info->tracking_info.timestamp),
-          ppb_buffer->shared_memory()->handle(),
           media::BindToLoop(
               base::MessageLoopProxy::current(),
-              base::Bind(&BufferNoLongerNeeded, ppb_buffer,
+              base::Bind(&BufferNoLongerNeeded,
+                         ppb_buffer,
                          base::Bind(&ContentDecryptorDelegate::FreeBuffer,
                                     weak_this_,
                                     frame_info->tracking_info.buffer_id))));
diff --git a/content/renderer/pepper/event_conversion.cc b/content/renderer/pepper/event_conversion.cc
index 8020d5a..6c02bd0 100644
--- a/content/renderer/pepper/event_conversion.cc
+++ b/content/renderer/pepper/event_conversion.cc
@@ -609,7 +609,7 @@
 // Generate a coherent sequence of input events to simulate a user event.
 // From src/third_party/WebKit/Tools/DumpRenderTree/chromium/EventSender.cpp.
 std::vector<linked_ptr<WebInputEvent> > CreateSimulatedWebInputEvents(
-    const ::ppapi::InputEventData& event,
+    const ppapi::InputEventData& event,
     int plugin_x,
     int plugin_y) {
   std::vector<linked_ptr<WebInputEvent> > events;
diff --git a/content/renderer/pepper/event_conversion.h b/content/renderer/pepper/event_conversion.h
index 05bdda8..edaa730 100644
--- a/content/renderer/pepper/event_conversion.h
+++ b/content/renderer/pepper/event_conversion.h
@@ -28,18 +28,17 @@
 // The generated events will be filled into the given vector. On failure, no
 // events will ge generated and the vector will be empty.
 void CreateInputEventData(const WebKit::WebInputEvent& event,
-                          std::vector< ::ppapi::InputEventData >* pp_events);
+                          std::vector<ppapi::InputEventData >* pp_events);
 
 // Creates a WebInputEvent from the given PP_InputEvent.  If it fails, returns
 // NULL.  The caller owns the created object on success.
-WebKit::WebInputEvent* CreateWebInputEvent(
-    const ::ppapi::InputEventData& event);
+WebKit::WebInputEvent* CreateWebInputEvent(const ppapi::InputEventData& event);
 
 // Creates an array of WebInputEvents to make the given event look like a user
 // input event on all platforms. |plugin_x| and |plugin_y| should be the
 // coordinates of a point within the plugin's area on the page.
 std::vector<linked_ptr<WebKit::WebInputEvent> > CreateSimulatedWebInputEvents(
-    const ::ppapi::InputEventData& event,
+    const ppapi::InputEventData& event,
     int plugin_x,
     int plugin_y);
 
diff --git a/content/renderer/pepper/host_array_buffer_var.h b/content/renderer/pepper/host_array_buffer_var.h
index 9388c4e..9ba1d7c 100644
--- a/content/renderer/pepper/host_array_buffer_var.h
+++ b/content/renderer/pepper/host_array_buffer_var.h
@@ -14,7 +14,7 @@
 namespace content {
 
 // Represents a host-side ArrayBufferVar.
-class HostArrayBufferVar : public ::ppapi::ArrayBufferVar {
+class HostArrayBufferVar : public ppapi::ArrayBufferVar {
  public:
   explicit HostArrayBufferVar(uint32 size_in_bytes);
   explicit HostArrayBufferVar(const WebKit::WebArrayBuffer& buffer);
diff --git a/content/renderer/pepper/host_globals.cc b/content/renderer/pepper/host_globals.cc
index dac943b..64a989c 100644
--- a/content/renderer/pepper/host_globals.cc
+++ b/content/renderer/pepper/host_globals.cc
@@ -11,6 +11,7 @@
 #include "base/rand_util.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/task_runner.h"
+#include "content/public/common/content_switches.h"
 #include "content/renderer/pepper/pepper_plugin_instance_impl.h"
 #include "content/renderer/pepper/plugin_module.h"
 #include "content/renderer/render_thread_impl.h"
@@ -22,7 +23,6 @@
 #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 "webkit/plugins/plugin_switches.h"
 
 using ppapi::CheckIdType;
 using ppapi::MakeTypedId;
@@ -77,15 +77,15 @@
 HostGlobals* HostGlobals::host_globals_ = NULL;
 
 HostGlobals::HostGlobals()
-    : ::ppapi::PpapiGlobals(),
+    : ppapi::PpapiGlobals(),
       resource_tracker_(ResourceTracker::SINGLE_THREADED) {
   DCHECK(!host_globals_);
   host_globals_ = this;
 }
 
 HostGlobals::HostGlobals(
-    ::ppapi::PpapiGlobals::PerThreadForTest per_thread_for_test)
-    : ::ppapi::PpapiGlobals(per_thread_for_test),
+    ppapi::PpapiGlobals::PerThreadForTest per_thread_for_test)
+    : ppapi::PpapiGlobals(per_thread_for_test),
       resource_tracker_(ResourceTracker::SINGLE_THREADED) {
   DCHECK(!host_globals_);
 }
@@ -95,15 +95,15 @@
   host_globals_ = NULL;
 }
 
-::ppapi::ResourceTracker* HostGlobals::GetResourceTracker() {
+ppapi::ResourceTracker* HostGlobals::GetResourceTracker() {
   return &resource_tracker_;
 }
 
-::ppapi::VarTracker* HostGlobals::GetVarTracker() {
+ppapi::VarTracker* HostGlobals::GetVarTracker() {
   return &host_var_tracker_;
 }
 
-::ppapi::CallbackTracker* HostGlobals::GetCallbackTrackerForInstance(
+ppapi::CallbackTracker* HostGlobals::GetCallbackTrackerForInstance(
     PP_Instance instance) {
   InstanceMap::iterator found = instance_map_.find(instance);
   if (found == instance_map_.end())
@@ -111,13 +111,13 @@
   return found->second->module()->GetCallbackTracker().get();
 }
 
-::ppapi::thunk::PPB_Instance_API* HostGlobals::GetInstanceAPI(
+ppapi::thunk::PPB_Instance_API* HostGlobals::GetInstanceAPI(
     PP_Instance instance) {
   // The InstanceAPI is just implemented by the PluginInstance object.
   return GetInstance(instance);
 }
 
-::ppapi::thunk::ResourceCreationAPI* HostGlobals::GetResourceCreationAPI(
+ppapi::thunk::ResourceCreationAPI* HostGlobals::GetResourceCreationAPI(
     PP_Instance pp_instance) {
   PepperPluginInstanceImpl* instance = GetInstance(pp_instance);
   if (!instance)
@@ -189,7 +189,7 @@
   return RenderThreadImpl::current()->GetFileThreadMessageLoopProxy().get();
 }
 
-::ppapi::MessageLoopShared* HostGlobals::GetCurrentMessageLoop() {
+ppapi::MessageLoopShared* HostGlobals::GetCurrentMessageLoop() {
   return NULL;
 }
 
@@ -205,7 +205,7 @@
   PP_Module new_module;
   do {
     new_module = MakeTypedId(static_cast<PP_Module>(base::RandUint64()),
-                             ::ppapi::PP_ID_TYPE_MODULE);
+                             ppapi::PP_ID_TYPE_MODULE);
   } while (!new_module ||
            module_map_.find(new_module) != module_map_.end());
   module_map_[new_module] = module;
@@ -213,7 +213,7 @@
 }
 
 void HostGlobals::ModuleDeleted(PP_Module module) {
-  DLOG_IF(ERROR, !CheckIdType(module, ::ppapi::PP_ID_TYPE_MODULE))
+  DLOG_IF(ERROR, !CheckIdType(module, ppapi::PP_ID_TYPE_MODULE))
       << module << " is not a PP_Module.";
   ModuleMap::iterator found = module_map_.find(module);
   if (found == module_map_.end()) {
@@ -224,7 +224,7 @@
 }
 
 PluginModule* HostGlobals::GetModule(PP_Module module) {
-  DLOG_IF(ERROR, !CheckIdType(module, ::ppapi::PP_ID_TYPE_MODULE))
+  DLOG_IF(ERROR, !CheckIdType(module, ppapi::PP_ID_TYPE_MODULE))
       << module << " is not a PP_Module.";
   ModuleMap::iterator found = module_map_.find(module);
   if (found == module_map_.end())
@@ -242,7 +242,7 @@
   PP_Instance new_instance;
   do {
     new_instance = MakeTypedId(static_cast<PP_Instance>(base::RandUint64()),
-                               ::ppapi::PP_ID_TYPE_INSTANCE);
+                               ppapi::PP_ID_TYPE_INSTANCE);
   } while (!new_instance ||
            instance_map_.find(new_instance) != instance_map_.end() ||
            !instance->module()->ReserveInstanceID(new_instance));
@@ -265,7 +265,7 @@
 }
 
 PepperPluginInstanceImpl* HostGlobals::GetInstance(PP_Instance instance) {
-  DLOG_IF(ERROR, !CheckIdType(instance, ::ppapi::PP_ID_TYPE_INSTANCE))
+  DLOG_IF(ERROR, !CheckIdType(instance, ppapi::PP_ID_TYPE_INSTANCE))
       << instance << " is not a PP_Instance.";
   InstanceMap::iterator found = instance_map_.find(instance);
   if (found == instance_map_.end())
diff --git a/content/renderer/pepper/host_globals.h b/content/renderer/pepper/host_globals.h
index f48eb05..2f67b9e 100644
--- a/content/renderer/pepper/host_globals.h
+++ b/content/renderer/pepper/host_globals.h
@@ -17,10 +17,10 @@
 class PepperPluginInstanceImpl;
 class PluginModule;
 
-class HostGlobals : public ::ppapi::PpapiGlobals {
+class HostGlobals : public ppapi::PpapiGlobals {
  public:
   HostGlobals();
-  explicit HostGlobals(::ppapi::PpapiGlobals::PerThreadForTest);
+  explicit HostGlobals(ppapi::PpapiGlobals::PerThreadForTest);
   virtual ~HostGlobals();
 
   // Getter for the global singleton. Generally, you should use
@@ -32,13 +32,13 @@
   }
 
   // PpapiGlobals implementation.
-  virtual ::ppapi::ResourceTracker* GetResourceTracker() OVERRIDE;
-  virtual ::ppapi::VarTracker* GetVarTracker() OVERRIDE;
-  virtual ::ppapi::CallbackTracker* GetCallbackTrackerForInstance(
+  virtual ppapi::ResourceTracker* GetResourceTracker() OVERRIDE;
+  virtual ppapi::VarTracker* GetVarTracker() OVERRIDE;
+  virtual ppapi::CallbackTracker* GetCallbackTrackerForInstance(
       PP_Instance instance) OVERRIDE;
-  virtual ::ppapi::thunk::PPB_Instance_API* GetInstanceAPI(
+  virtual ppapi::thunk::PPB_Instance_API* GetInstanceAPI(
       PP_Instance instance) OVERRIDE;
-  virtual ::ppapi::thunk::ResourceCreationAPI* GetResourceCreationAPI(
+  virtual ppapi::thunk::ResourceCreationAPI* GetResourceCreationAPI(
       PP_Instance instance) OVERRIDE;
   virtual PP_Module GetModuleForInstance(PP_Instance instance) OVERRIDE;
   virtual std::string GetCmdLine() OVERRIDE;
@@ -52,7 +52,7 @@
                                       PP_LogLevel level,
                                       const std::string& source,
                                       const std::string& value) OVERRIDE;
-  virtual ::ppapi::MessageLoopShared* GetCurrentMessageLoop() OVERRIDE;
+  virtual ppapi::MessageLoopShared* GetCurrentMessageLoop() OVERRIDE;
   virtual base::TaskRunner* GetFileTaskRunner(PP_Instance instance) OVERRIDE;
 
   HostVarTracker* host_var_tracker() {
@@ -96,7 +96,7 @@
 
   static HostGlobals* host_globals_;
 
-  ::ppapi::ResourceTracker resource_tracker_;
+  ppapi::ResourceTracker resource_tracker_;
   HostVarTracker host_var_tracker_;
 
   // Tracks all live instances and their associated object.
diff --git a/content/renderer/pepper/host_var_tracker.cc b/content/renderer/pepper/host_var_tracker.cc
index 9b9ebda..71a568a 100644
--- a/content/renderer/pepper/host_var_tracker.cc
+++ b/content/renderer/pepper/host_var_tracker.cc
@@ -122,7 +122,7 @@
   instance_map_.erase(found_instance);
 }
 
-void HostVarTracker::ForceReleaseNPObject(::ppapi::NPObjectVar* object_var) {
+void HostVarTracker::ForceReleaseNPObject(ppapi::NPObjectVar* object_var) {
   object_var->InstanceDeleted();
   VarMap::iterator iter = live_vars_.find(object_var->GetExistingVarID());
   if (iter == live_vars_.end()) {
diff --git a/content/renderer/pepper/host_var_tracker.h b/content/renderer/pepper/host_var_tracker.h
index 290e858..5abdbff 100644
--- a/content/renderer/pepper/host_var_tracker.h
+++ b/content/renderer/pepper/host_var_tracker.h
@@ -31,7 +31,7 @@
 
 // Adds NPObject var tracking to the standard PPAPI VarTracker for use in the
 // renderer.
-class HostVarTracker : public ::ppapi::VarTracker {
+class HostVarTracker : public ppapi::VarTracker {
  public:
   HostVarTracker();
   virtual ~HostVarTracker();
@@ -40,14 +40,14 @@
   // NPObject and get the NPObjectVar corresponding to it. This Add/Remove
   // function is called by the NPObjectVar when it is created and
   // destroyed.
-  void AddNPObjectVar(::ppapi::NPObjectVar* object_var);
-  void RemoveNPObjectVar(::ppapi::NPObjectVar* object_var);
+  void AddNPObjectVar(ppapi::NPObjectVar* object_var);
+  void RemoveNPObjectVar(ppapi::NPObjectVar* object_var);
 
   // Looks up a previously registered NPObjectVar for the given NPObject and
   // instance. Returns NULL if there is no NPObjectVar corresponding to the
   // given NPObject for the given instance. See AddNPObjectVar above.
-  ::ppapi::NPObjectVar* NPObjectVarForNPObject(PP_Instance instance,
-                                               NPObject* np_object);
+  ppapi::NPObjectVar* NPObjectVarForNPObject(PP_Instance instance,
+                                             NPObject* np_object);
 
   // Returns the number of NPObjectVar's associated with the given instance.
   // Returns 0 if the instance isn't known.
@@ -67,17 +67,16 @@
 
  private:
   // VarTracker private implementation.
-  virtual ::ppapi::ArrayBufferVar* CreateArrayBuffer(
+  virtual ppapi::ArrayBufferVar* CreateArrayBuffer(
       uint32 size_in_bytes) OVERRIDE;
-  virtual ::ppapi::ArrayBufferVar* CreateShmArrayBuffer(
+  virtual ppapi::ArrayBufferVar* CreateShmArrayBuffer(
       uint32 size_in_bytes, base::SharedMemoryHandle handle) OVERRIDE;
 
   // Clear the reference count of the given object and remove it from
   // live_vars_.
-  void ForceReleaseNPObject(::ppapi::NPObjectVar* object_var);
+  void ForceReleaseNPObject(ppapi::NPObjectVar* object_var);
 
-  typedef std::map<NPObject*, ::ppapi::NPObjectVar*>
-      NPObjectToNPObjectVarMap;
+  typedef std::map<NPObject*, ppapi::NPObjectVar*> NPObjectToNPObjectVarMap;
 
   // Lists all known NPObjects, first indexed by the corresponding instance,
   // then by the NPObject*. This allows us to look up an NPObjectVar given
diff --git a/content/renderer/pepper/host_var_tracker_unittest.cc b/content/renderer/pepper/host_var_tracker_unittest.cc
index 693d63f..0c4d00d 100644
--- a/content/renderer/pepper/host_var_tracker_unittest.cc
+++ b/content/renderer/pepper/host_var_tracker_unittest.cc
@@ -120,8 +120,8 @@
   }
 
   // Remove both of the refs we made above.
-  ::ppapi::VarTracker* var_tracker =
-      ::ppapi::PpapiGlobals::Get()->GetVarTracker();
+  ppapi::VarTracker* var_tracker =
+      ppapi::PpapiGlobals::Get()->GetVarTracker();
   var_tracker->ReleaseVar(static_cast<int32_t>(pp_object2.value.as_id));
   var_tracker->ReleaseVar(static_cast<int32_t>(pp_object1.value.as_id));
 
diff --git a/content/renderer/pepper/mock_resource.h b/content/renderer/pepper/mock_resource.h
index fc6d0a8..d7a09c3 100644
--- a/content/renderer/pepper/mock_resource.h
+++ b/content/renderer/pepper/mock_resource.h
@@ -12,10 +12,10 @@
 // Tests can derive from this to implement special test-specific resources.
 // It's assumed that a test will only need one mock resource, so it can
 // static_cast to get its own implementation.
-class MockResource : public ::ppapi::Resource {
+class MockResource : public ppapi::Resource {
  public:
   MockResource(PP_Instance instance)
-      : Resource(::ppapi::OBJECT_IS_IMPL, instance) {}
+      : Resource(ppapi::OBJECT_IS_IMPL, instance) {}
 
  private:
   virtual ~MockResource() {}
diff --git a/content/renderer/pepper/npapi_glue.cc b/content/renderer/pepper/npapi_glue.cc
index 96e0bb0..124d03d 100644
--- a/content/renderer/pepper/npapi_glue.cc
+++ b/content/renderer/pepper/npapi_glue.cc
@@ -292,7 +292,7 @@
 }
 
 PPVarArrayFromNPVariantArray::~PPVarArrayFromNPVariantArray() {
-  ::ppapi::VarTracker* var_tracker = PpapiGlobals::Get()->GetVarTracker();
+  ppapi::VarTracker* var_tracker = PpapiGlobals::Get()->GetVarTracker();
   for (size_t i = 0; i < size_; i++)
     var_tracker->ReleaseVar(array_[i]);
 }
@@ -343,7 +343,7 @@
   if (!has_exception()) {
     has_exception_ = true;
     if (exception_) {
-      *exception_ = ::ppapi::StringVar::StringToPPVar(message, strlen(message));
+      *exception_ = ppapi::StringVar::StringToPPVar(message, strlen(message));
     }
   }
 }
diff --git a/content/renderer/pepper/pepper_browser_connection.cc b/content/renderer/pepper/pepper_browser_connection.cc
index 3032576..00c6cd6 100644
--- a/content/renderer/pepper/pepper_browser_connection.cc
+++ b/content/renderer/pepper/pepper_browser_connection.cc
@@ -34,9 +34,10 @@
   IPC_BEGIN_MESSAGE_MAP(PepperBrowserConnection, msg)
     IPC_MESSAGE_HANDLER(PpapiHostMsg_CreateResourceHostFromHostReply,
                         OnMsgCreateResourceHostFromHostReply)
+    IPC_MESSAGE_HANDLER(PpapiHostMsg_FileRef_GetInfoForRendererReply,
+                        OnMsgFileRefGetInfoReply)
     IPC_MESSAGE_UNHANDLED(handled = false)
   IPC_END_MESSAGE_MAP()
-
   return handled;
 }
 
@@ -101,10 +102,7 @@
 
 void PepperBrowserConnection::OnMsgFileRefGetInfoReply(
     int32_t sequence_number,
-    const std::vector<PP_Resource>& resources,
-    const std::vector<PP_FileSystemType>& types,
-    const std::vector<std::string>& file_system_url_specs,
-    const std::vector<base::FilePath>& external_paths) {
+    const std::vector<ppapi::FileRefDetailedInfo>& infos) {
   // Check that the message is destined for the plugin this object is associated
   // with.
   std::map<int32_t, FileRefGetInfoCallback>::iterator it =
@@ -112,7 +110,7 @@
   if (it != get_info_map_.end()) {
     FileRefGetInfoCallback callback = it->second;
     get_info_map_.erase(it);
-    callback.Run(resources, types, file_system_url_specs, external_paths);
+    callback.Run(infos);
   } else {
     NOTREACHED();
   }
diff --git a/content/renderer/pepper/pepper_browser_connection.h b/content/renderer/pepper/pepper_browser_connection.h
index 9fde7d2..d058a32 100644
--- a/content/renderer/pepper/pepper_browser_connection.h
+++ b/content/renderer/pepper/pepper_browser_connection.h
@@ -15,6 +15,7 @@
 #include "ppapi/c/pp_file_info.h"
 #include "ppapi/c/pp_instance.h"
 #include "ppapi/c/pp_resource.h"
+#include "ppapi/shared_impl/file_ref_detailed_info.h"
 
 namespace content {
 
@@ -28,10 +29,7 @@
  public:
   typedef base::Callback<void(int)> PendingResourceIDCallback;
   typedef base::Callback<void(
-      const std::vector<PP_Resource>&,
-      const std::vector<PP_FileSystemType>&,
-      const std::vector<std::string>&,
-      const std::vector<base::FilePath>&)> FileRefGetInfoCallback;
+      const std::vector<ppapi::FileRefDetailedInfo>&)> FileRefGetInfoCallback;
 
   explicit PepperBrowserConnection(RenderView* render_view);
   virtual ~PepperBrowserConnection();
@@ -71,10 +69,7 @@
                                             int pending_resource_host_id);
   void OnMsgFileRefGetInfoReply(
       int32_t sequence_number,
-      const std::vector<PP_Resource>& resources,
-      const std::vector<PP_FileSystemType>& types,
-      const std::vector<std::string>& file_system_url_specs,
-      const std::vector<base::FilePath>& external_paths);
+      const std::vector<ppapi::FileRefDetailedInfo>& infos);
 
   // Return the next sequence number.
   int32_t GetNextSequence();
diff --git a/content/renderer/pepper/pepper_device_enumeration_host_helper.h b/content/renderer/pepper/pepper_device_enumeration_host_helper.h
index 424475b..5773845 100644
--- a/content/renderer/pepper/pepper_device_enumeration_host_helper.h
+++ b/content/renderer/pepper/pepper_device_enumeration_host_helper.h
@@ -43,7 +43,7 @@
     typedef base::Callback<
         void (int /* request_id */,
               bool /* succeeded */,
-              const std::vector< ::ppapi::DeviceRefData>& /* devices */)>
+              const std::vector<ppapi::DeviceRefData>& /* devices */)>
         EnumerateDevicesCallback;
 
     // Enumerates devices of the specified type. The request ID passed into the
diff --git a/content/renderer/pepper/pepper_file_chooser_host.cc b/content/renderer/pepper/pepper_file_chooser_host.cc
index 1229d17..bdf9cd8 100644
--- a/content/renderer/pepper/pepper_file_chooser_host.cc
+++ b/content/renderer/pepper/pepper_file_chooser_host.cc
@@ -7,13 +7,11 @@
 #include "base/files/file_path.h"
 #include "base/strings/utf_string_conversions.h"
 #include "content/public/renderer/renderer_ppapi_host.h"
-#include "content/renderer/pepper/ppb_file_ref_impl.h"
 #include "content/renderer/render_view_impl.h"
 #include "ppapi/c/pp_errors.h"
 #include "ppapi/host/dispatch_host_message.h"
 #include "ppapi/host/ppapi_host.h"
 #include "ppapi/proxy/ppapi_messages.h"
-#include "ppapi/proxy/ppb_file_ref_proxy.h"
 #include "third_party/WebKit/public/platform/WebCString.h"
 #include "third_party/WebKit/public/platform/WebString.h"
 #include "third_party/WebKit/public/platform/WebVector.h"
@@ -81,7 +79,9 @@
     PP_Resource resource)
     : ResourceHost(host->GetPpapiHost(), instance, resource),
       renderer_ppapi_host_(host),
-      handler_(NULL) {
+      num_pending_file_resources_(0),
+      handler_(NULL),
+      weak_factory_(this) {
 }
 
 PepperFileChooserHost::~PepperFileChooserHost() {
@@ -98,29 +98,30 @@
 
 void PepperFileChooserHost::StoreChosenFiles(
     const std::vector<ChosenFileInfo>& files) {
-  std::vector<ppapi::PPB_FileRef_CreateInfo> chosen_files;
+  num_pending_file_resources_ = files.size();
   for (size_t i = 0; i < files.size(); i++) {
 #if defined(OS_WIN)
     base::FilePath file_path(UTF8ToWide(files[i].path));
 #else
     base::FilePath file_path(files[i].path);
 #endif
-
-    PPB_FileRef_Impl* ref = PPB_FileRef_Impl::CreateExternal(
-        pp_instance(), file_path, files[i].display_name);
-    ppapi::PPB_FileRef_CreateInfo create_info;
-    ppapi::proxy::PPB_FileRef_Proxy::SerializeFileRef(ref->GetReference(),
-                                                      &create_info);
-    chosen_files.push_back(create_info);
+    renderer_ppapi_host_->CreateBrowserResourceHost(
+        pp_instance(),
+        PpapiHostMsg_FileRef_CreateExternal(file_path),
+        base::Bind(&PepperFileChooserHost::DidCreateResourceHost,
+                   weak_factory_.GetWeakPtr(),
+                   file_path,
+                   files[i].display_name));
   }
 
-  reply_context_.params.set_result(
-      (chosen_files.size() > 0) ? PP_OK : PP_ERROR_USERCANCEL);
-  host()->SendReply(reply_context_,
-                    PpapiPluginMsg_FileChooser_ShowReply(chosen_files));
-
-  reply_context_ = ppapi::host::ReplyMessageContext();
-  handler_ = NULL;  // Handler deletes itself.
+  if (files.empty()) {
+    reply_context_.params.set_result(PP_ERROR_USERCANCEL);
+    std::vector<ppapi::FileRefCreateInfo> chosen_files;
+    host()->SendReply(reply_context_,
+                      PpapiPluginMsg_FileChooser_ShowReply(chosen_files));
+    reply_context_ = ppapi::host::ReplyMessageContext();
+    handler_ = NULL;  // Handler deletes itself.
+  }
 }
 
 int32_t PepperFileChooserHost::OnShow(
@@ -167,5 +168,22 @@
   return PP_OK_COMPLETIONPENDING;
 }
 
+void PepperFileChooserHost::DidCreateResourceHost(
+    const base::FilePath& file_path,
+    const std::string& display_name,
+    int32_t id) {
+  num_pending_file_resources_--;
+  ppapi::FileRefCreateInfo info = ppapi::MakeExternalFileRefCreateInfo(
+      file_path, display_name, id);
+  chosen_files_.push_back(info);
+  if (num_pending_file_resources_ == 0) {
+    reply_context_.params.set_result(PP_OK);
+    host()->SendReply(reply_context_,
+                      PpapiPluginMsg_FileChooser_ShowReply(chosen_files_));
+    reply_context_ = ppapi::host::ReplyMessageContext();
+    handler_ = NULL;  // Handler deletes itself.
+  }
+}
+
 }  // namespace content
 
diff --git a/content/renderer/pepper/pepper_file_chooser_host.h b/content/renderer/pepper/pepper_file_chooser_host.h
index af27768..d837460 100644
--- a/content/renderer/pepper/pepper_file_chooser_host.h
+++ b/content/renderer/pepper/pepper_file_chooser_host.h
@@ -15,6 +15,10 @@
 #include "ppapi/host/resource_host.h"
 #include "ppapi/proxy/resource_message_params.h"
 
+namespace ppapi {
+struct FileRefCreateInfo;
+}
+
 namespace content {
 
 class RendererPpapiHost;
@@ -51,12 +55,21 @@
                  const std::string& suggested_file_name,
                  const std::vector<std::string>& accept_mime_types);
 
+  void DidCreateResourceHost(const base::FilePath& file_path,
+                             const std::string& display_name,
+                             int32_t id);
+
   // Non-owning pointer.
   RendererPpapiHost* renderer_ppapi_host_;
 
+  int num_pending_file_resources_;
+  std::vector<ppapi::FileRefCreateInfo> chosen_files_;
+
   ppapi::host::ReplyMessageContext reply_context_;
   CompletionHandler* handler_;
 
+  base::WeakPtrFactory<PepperFileChooserHost> weak_factory_;
+
   DISALLOW_COPY_AND_ASSIGN(PepperFileChooserHost);
 };
 
diff --git a/content/renderer/pepper/pepper_file_chooser_host_unittest.cc b/content/renderer/pepper/pepper_file_chooser_host_unittest.cc
index b228cd7..c8cf9f6 100644
--- a/content/renderer/pepper/pepper_file_chooser_host_unittest.cc
+++ b/content/renderer/pepper/pepper_file_chooser_host_unittest.cc
@@ -18,7 +18,6 @@
 #include "ppapi/proxy/resource_message_params.h"
 #include "ppapi/proxy/resource_message_test_sink.h"
 #include "ppapi/shared_impl/ppapi_permissions.h"
-#include "ppapi/shared_impl/ppb_file_ref_shared.h"
 #include "ppapi/shared_impl/resource_tracker.h"
 #include "ppapi/shared_impl/test_globals.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -65,70 +64,11 @@
 
 }  // namespace
 
-TEST_F(PepperFileChooserHostTest, Show) {
-  PP_Resource pp_resource = 123;
-
-  MockRendererPpapiHost host(view_, pp_instance());
-  PepperFileChooserHost chooser(&host, pp_instance(), pp_resource);
-
-  // Say there's a user gesture.
-  host.set_has_user_gesture(true);
-
-  std::vector<std::string> accept;
-  accept.push_back("text/plain");
-  PpapiHostMsg_FileChooser_Show show_msg(false, false, std::string(), accept);
-
-  ppapi::proxy::ResourceMessageCallParams call_params(pp_resource, 0);
-  ppapi::host::HostMessageContext context(call_params);
-  int32 result = chooser.OnResourceMessageReceived(show_msg, &context);
-  EXPECT_EQ(PP_OK_COMPLETIONPENDING, result);
-
-  // The render view should have sent a chooser request to the browser
-  // (caught by the render thread's test message sink).
-  const IPC::Message* msg = render_thread_->sink().GetUniqueMessageMatching(
-      ViewHostMsg_RunFileChooser::ID);
-  ASSERT_TRUE(msg);
-  ViewHostMsg_RunFileChooser::Schema::Param call_msg_param;
-  ASSERT_TRUE(ViewHostMsg_RunFileChooser::Read(msg, &call_msg_param));
-  const FileChooserParams& chooser_params = call_msg_param.a;
-
-  // Basic validation of request.
-  EXPECT_EQ(FileChooserParams::Open, chooser_params.mode);
-  ASSERT_EQ(1u, chooser_params.accept_types.size());
-  EXPECT_EQ(accept[0], UTF16ToUTF8(chooser_params.accept_types[0]));
-
-  // Send a chooser reply to the render view. Note our reply path has to have a
-  // path separator so we include both a Unix and a Windows one.
-  ui::SelectedFileInfo selected_info;
-  selected_info.display_name = FILE_PATH_LITERAL("Hello, world");
-  selected_info.local_path = base::FilePath(FILE_PATH_LITERAL("myp\\ath/foo"));
-  std::vector<ui::SelectedFileInfo> selected_info_vector;
-  selected_info_vector.push_back(selected_info);
-  RenderViewImpl* view_impl = static_cast<RenderViewImpl*>(view_);
-  ViewMsg_RunFileChooserResponse response(view_impl->routing_id(),
-                                          selected_info_vector);
-  EXPECT_TRUE(view_impl->OnMessageReceived(response));
-
-  // This should have sent the Pepper reply to our test sink.
-  ppapi::proxy::ResourceMessageReplyParams reply_params;
-  IPC::Message reply_msg;
-  ASSERT_TRUE(host.sink().GetFirstResourceReplyMatching(
-      PpapiPluginMsg_FileChooser_ShowReply::ID, &reply_params, &reply_msg));
-
-  // Basic validation of reply.
-  EXPECT_EQ(call_params.sequence(), reply_params.sequence());
-  EXPECT_EQ(PP_OK, reply_params.result());
-  PpapiPluginMsg_FileChooser_ShowReply::Schema::Param reply_msg_param;
-  ASSERT_TRUE(PpapiPluginMsg_FileChooser_ShowReply::Read(&reply_msg,
-                                                         &reply_msg_param));
-  const std::vector<ppapi::PPB_FileRef_CreateInfo>& chooser_results =
-      reply_msg_param.a;
-  ASSERT_EQ(1u, chooser_results.size());
-  // Note path is empty because this is an external filesystem.
-  EXPECT_EQ(std::string(), chooser_results[0].path);
-  EXPECT_EQ(FilePathToUTF8(selected_info.display_name),
-            chooser_results[0].name);
-}
+// TODO(teravest): Write a good test for the "Show" interface of FileChooser.
+// We can't do this very easily today because we need direct access to the
+// RenderViewImpl, but also need renderer and browser instances fully set up.
+// This is was caused by the "new" FileRef refactor, which moved FileRef
+// hosting to the browser. http://crbug.com/270322
 
 TEST_F(PepperFileChooserHostTest, NoUserGesture) {
   PP_Resource pp_resource = 123;
diff --git a/content/renderer/pepper/pepper_file_io_host.cc b/content/renderer/pepper/pepper_file_io_host.cc
index 5a6d40c..0431b1c 100644
--- a/content/renderer/pepper/pepper_file_io_host.cc
+++ b/content/renderer/pepper/pepper_file_io_host.cc
@@ -17,11 +17,14 @@
 #include "content/public/common/content_client.h"
 #include "content/public/renderer/content_renderer_client.h"
 #include "content/renderer/pepper/host_globals.h"
+#include "content/renderer/pepper/pepper_browser_connection.h"
 #include "content/renderer/pepper/pepper_plugin_instance_impl.h"
-#include "content/renderer/pepper/ppb_file_ref_impl.h"
+#include "content/renderer/pepper/plugin_module.h"
 #include "content/renderer/pepper/quota_file_io.h"
+#include "content/renderer/pepper/renderer_ppapi_host_impl.h"
 #include "content/renderer/render_thread_impl.h"
 #include "ppapi/c/pp_errors.h"
+#include "ppapi/c/ppb_file_io.h"
 #include "ppapi/host/dispatch_host_message.h"
 #include "ppapi/host/ppapi_host.h"
 #include "ppapi/proxy/ppapi_messages.h"
@@ -36,17 +39,9 @@
 using ppapi::PPTimeToTime;
 using ppapi::host::ReplyMessageContext;
 using ppapi::thunk::EnterResourceNoLock;
-using ppapi::thunk::PPB_FileRef_API;
 
 namespace {
 
-// The maximum size we'll support reading in one chunk. The renderer process
-// must allocate a buffer sized according to the request of the plugin. To
-// keep things from getting out of control, we cap the read size to this value.
-// This should generally be OK since the API specifies that it may perform a
-// partial read.
-static const int32_t kMaxReadSize = 32 * 1024 * 1024;  // 32MB
-
 typedef base::Callback<void (base::PlatformFileError)> PlatformGeneralCallback;
 
 int32_t ErrorOrByteNumber(int32_t pp_error, int32_t byte_number) {
@@ -142,6 +137,8 @@
                                    PP_Instance instance,
                                    PP_Resource resource)
     : ResourceHost(host->GetPpapiHost(), instance, resource),
+      renderer_ppapi_host_(host),
+      plugin_instance_(HostGlobals::Get()->GetInstance(instance)),
       file_(base::kInvalidPlatformFileValue),
       file_system_type_(PP_FILESYSTEMTYPE_INVALID),
       quota_policy_(quota::kQuotaLimitTypeUnknown),
@@ -163,12 +160,8 @@
   IPC_BEGIN_MESSAGE_MAP(PepperFileIOHost, msg)
     PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_FileIO_Open,
                                       OnHostMsgOpen)
-    PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(PpapiHostMsg_FileIO_Query,
-                                        OnHostMsgQuery)
     PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_FileIO_Touch,
                                       OnHostMsgTouch)
-    PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_FileIO_Read,
-                                      OnHostMsgRead)
     PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_FileIO_Write,
                                       OnHostMsgWrite)
     PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_FileIO_SetLength,
@@ -233,70 +226,71 @@
   // FileSystemDispatcher so it can handle doing the security check.
   int platform_file_flags = 0;
   open_flags_ = open_flags;
-  if (!::ppapi::PepperFileOpenFlagsToPlatformFileFlags(open_flags,
-                                                       &platform_file_flags)) {
+  if (!ppapi::PepperFileOpenFlagsToPlatformFileFlags(open_flags,
+                                                     &platform_file_flags)) {
     return PP_ERROR_BADARGUMENT;
   }
 
-  EnterResourceNoLock<PPB_FileRef_API> enter(file_ref_resource, true);
-  if (enter.failed())
-    return PP_ERROR_BADRESOURCE;
+  RenderView* render_view =
+      renderer_ppapi_host_->GetRenderViewForInstance(pp_instance());
+  PepperBrowserConnection* browser_connection =
+      PepperBrowserConnection::Get(render_view);
+  int child_process_id = plugin_instance_->module()->GetPluginChildId();
 
-  PPB_FileRef_API* file_ref_api = enter.object();
-  PP_FileSystemType type = file_ref_api->GetFileSystemType();
-  if (type != PP_FILESYSTEMTYPE_LOCALPERSISTENT &&
-      type != PP_FILESYSTEMTYPE_LOCALTEMPORARY &&
-      type != PP_FILESYSTEMTYPE_EXTERNAL &&
-      type != PP_FILESYSTEMTYPE_ISOLATED)
-    return PP_ERROR_FAILED;
-  file_system_type_ = type;
+  // Explicitly set child_process_id to 0 if we're running in process. This is
+  // necessary in the case where we're a host for a resource in "the trusted
+  // NaCl plugin". In that case, we may have already done work for the
+  // untrusted plugin, and the call above will give a non-zero
+  // child_process_id.
+  if (renderer_ppapi_host_->IsRunningInProcess())
+    child_process_id = 0;
 
-  PPB_FileRef_Impl* file_ref = static_cast<PPB_FileRef_Impl*>(file_ref_api);
-  if (file_ref->HasValidFileSystem()) {
-    file_system_url_ = file_ref->GetFileSystemURL();
+  std::vector<PP_Resource> resources;
+  resources.push_back(file_ref_resource);
+  browser_connection->SendBrowserFileRefGetInfo(
+      child_process_id,
+      resources,
+      base::Bind(&PepperFileIOHost::DidGetFileRefInfo,
+                 weak_factory_.GetWeakPtr(),
+                 context->MakeReplyMessageContext(),
+                 platform_file_flags));
+  state_manager_.SetPendingOperation(FileIOStateManager::OPERATION_EXCLUSIVE);
+  return PP_OK_COMPLETIONPENDING;
+}
 
+void PepperFileIOHost::DidGetFileRefInfo(
+    ppapi::host::ReplyMessageContext reply_context,
+    int platform_file_flags,
+    const std::vector<ppapi::FileRefDetailedInfo>& infos) {
+  if (infos.size() != 1) {
+    reply_context.params.set_result(PP_ERROR_FAILED);
+    host()->SendReply(reply_context,
+                      PpapiPluginMsg_FileIO_OpenReply());
+    return;
+  }
+
+  file_system_type_ = infos[0].file_system_type;
+  if (file_system_type_ != PP_FILESYSTEMTYPE_EXTERNAL) {
+    file_system_url_ = GURL(infos[0].file_system_url_spec);
     FileSystemDispatcher* file_system_dispatcher =
         ChildThread::current()->file_system_dispatcher();
+
     AsyncOpenFileSystemURLCallback callback = base::Bind(
         &PepperFileIOHost::ExecutePlatformOpenFileSystemURLCallback,
         weak_factory_.GetWeakPtr(),
-        context->MakeReplyMessageContext());
+        reply_context);
     file_system_dispatcher->OpenFile(
         file_system_url_, platform_file_flags,
         base::Bind(&DidOpenFileSystemURL, callback),
         base::Bind(&DidFailOpenFileSystemURL, callback));
   } else {
-    if (file_system_type_ != PP_FILESYSTEMTYPE_EXTERNAL)
-      return PP_ERROR_FAILED;
     int message_id = pending_async_open_files_.Add(new AsyncOpenFileCallback(
         base::Bind(&PepperFileIOHost::ExecutePlatformOpenFileCallback,
                     weak_factory_.GetWeakPtr(),
-                    context->MakeReplyMessageContext())));
+                    reply_context)));
     RenderThreadImpl::current()->Send(new ViewHostMsg_AsyncOpenPepperFile(
-        routing_id_, file_ref->GetSystemPath(), open_flags, message_id));
+        routing_id_, infos[0].external_path, open_flags_, message_id));
   }
-
-  state_manager_.SetPendingOperation(FileIOStateManager::OPERATION_EXCLUSIVE);
-  return PP_OK_COMPLETIONPENDING;
-}
-
-int32_t PepperFileIOHost::OnHostMsgQuery(
-    ppapi::host::HostMessageContext* context) {
-  int32_t rv = state_manager_.CheckOperationState(
-      FileIOStateManager::OPERATION_EXCLUSIVE, true);
-  if (rv != PP_OK)
-    return rv;
-
-  if (!base::FileUtilProxy::GetFileInfoFromPlatformFile(
-          RenderThreadImpl::current()->GetFileThreadMessageLoopProxy().get(),
-          file_,
-          base::Bind(&PepperFileIOHost::ExecutePlatformQueryCallback,
-                     weak_factory_.GetWeakPtr(),
-                     context->MakeReplyMessageContext())))
-    return PP_ERROR_FAILED;
-
-  state_manager_.SetPendingOperation(FileIOStateManager::OPERATION_EXCLUSIVE);
-  return PP_OK_COMPLETIONPENDING;
 }
 
 int32_t PepperFileIOHost::OnHostMsgTouch(
@@ -338,39 +332,6 @@
   return PP_OK_COMPLETIONPENDING;
 }
 
-int32_t PepperFileIOHost::OnHostMsgRead(
-    ppapi::host::HostMessageContext* context,
-    int64_t offset,
-    int32_t max_read_length) {
-  int32_t rv = state_manager_.CheckOperationState(
-      FileIOStateManager::OPERATION_READ, true);
-  if (rv != PP_OK)
-    return rv;
-
-  // Validate max_read_length before allocating below. This value is coming from
-  // the untrusted plugin.
-  if (max_read_length < 0) {
-    ReplyMessageContext reply_context = context->MakeReplyMessageContext();
-    reply_context.params.set_result(PP_ERROR_FAILED);
-    host()->SendReply(reply_context,
-                      PpapiPluginMsg_FileIO_ReadReply(std::string()));
-    return PP_OK_COMPLETIONPENDING;
-  }
-
-  if (!base::FileUtilProxy::Read(
-          RenderThreadImpl::current()->GetFileThreadMessageLoopProxy().get(),
-          file_,
-          offset,
-          max_read_length,
-          base::Bind(&PepperFileIOHost::ExecutePlatformReadCallback,
-                     weak_factory_.GetWeakPtr(),
-                     context->MakeReplyMessageContext())))
-    return PP_ERROR_FAILED;
-
-  state_manager_.SetPendingOperation(FileIOStateManager::OPERATION_READ);
-  return PP_OK_COMPLETIONPENDING;
-}
-
 int32_t PepperFileIOHost::OnHostMsgWrite(
     ppapi::host::HostMessageContext* context,
     int64_t offset,
@@ -520,16 +481,13 @@
       quota_policy_ != quota::kQuotaLimitTypeUnlimited)
     return PP_ERROR_FAILED;
 
-  RendererPpapiHost* renderer_ppapi_host =
-      RendererPpapiHost::GetForPPInstance(pp_instance());
-
   // Whitelist to make it privately accessible.
   if (!GetContentClient()->renderer()->IsPluginAllowedToCallRequestOSFileHandle(
-          renderer_ppapi_host->GetContainerForInstance(pp_instance())))
+          renderer_ppapi_host_->GetContainerForInstance(pp_instance())))
     return PP_ERROR_NOACCESS;
 
   IPC::PlatformFileForTransit file =
-      renderer_ppapi_host->ShareHandleWithRemote(file_, false);
+      renderer_ppapi_host_->ShareHandleWithRemote(file_, false);
   if (file == IPC::InvalidPlatformFileForTransit())
     return PP_ERROR_FAILED;
   ppapi::host::ReplyMessageContext reply_context =
@@ -565,7 +523,7 @@
     ppapi::host::ReplyMessageContext reply_context,
     base::PlatformFileError error_code) {
   reply_context.params.set_result(
-      ::ppapi::PlatformFileErrorToPepperError(error_code));
+      ppapi::PlatformFileErrorToPepperError(error_code));
   host()->SendReply(reply_context, PpapiPluginMsg_FileIO_GeneralReply());
   state_manager_.SetOperationFinished();
 }
@@ -574,7 +532,7 @@
     ppapi::host::ReplyMessageContext reply_context,
     base::PlatformFileError error_code,
     base::PassPlatformFile file) {
-  int32_t pp_error = ::ppapi::PlatformFileErrorToPepperError(error_code);
+  int32_t pp_error = ppapi::PlatformFileErrorToPepperError(error_code);
   if (pp_error == PP_OK)
     state_manager_.SetOpenSucceed();
 
@@ -582,11 +540,26 @@
   file_ = file.ReleaseValue();
 
   DCHECK(!quota_file_io_.get());
-  if (file_ != base::kInvalidPlatformFileValue &&
-      (file_system_type_ == PP_FILESYSTEMTYPE_LOCALTEMPORARY ||
-       file_system_type_ == PP_FILESYSTEMTYPE_LOCALPERSISTENT)) {
-    quota_file_io_.reset(new QuotaFileIO(
-        new QuotaFileIODelegate, file_, file_system_url_, file_system_type_));
+  if (file_ != base::kInvalidPlatformFileValue) {
+    if (file_system_type_ == PP_FILESYSTEMTYPE_LOCALTEMPORARY ||
+        file_system_type_ == PP_FILESYSTEMTYPE_LOCALPERSISTENT) {
+      quota_file_io_.reset(new QuotaFileIO(
+          new QuotaFileIODelegate, file_, file_system_url_, file_system_type_));
+    }
+
+    IPC::PlatformFileForTransit file_for_transit =
+        renderer_ppapi_host_->ShareHandleWithRemote(file_, false);
+    if (!(file_for_transit == IPC::InvalidPlatformFileForTransit())) {
+      // Send the file descriptor to the plugin process. This is used in the
+      // plugin for any file operations that can be done there.
+      // IMPORTANT: Clear PP_FILEOPENFLAG_WRITE and PP_FILEOPENFLAG_APPEND so
+      // the plugin can't write and so bypass our quota checks.
+      int32_t no_write_flags =
+          open_flags_ & ~(PP_FILEOPENFLAG_WRITE | PP_FILEOPENFLAG_APPEND);
+      ppapi::proxy::SerializedHandle file_handle;
+      file_handle.set_file_handle(file_for_transit, no_write_flags);
+      reply_context.params.AppendHandle(file_handle);
+    }
   }
 
   reply_context.params.set_result(pp_error);
@@ -606,36 +579,6 @@
   ExecutePlatformOpenFileCallback(reply_context, error_code, file);
 }
 
-void PepperFileIOHost::ExecutePlatformQueryCallback(
-    ppapi::host::ReplyMessageContext reply_context,
-    base::PlatformFileError error_code,
-    const base::PlatformFileInfo& file_info) {
-  PP_FileInfo pp_info;
-  ppapi::PlatformFileInfoToPepperFileInfo(file_info, file_system_type_,
-                                          &pp_info);
-
-  int32_t pp_error = ::ppapi::PlatformFileErrorToPepperError(error_code);
-  reply_context.params.set_result(pp_error);
-  host()->SendReply(reply_context,
-                    PpapiPluginMsg_FileIO_QueryReply(pp_info));
-  state_manager_.SetOperationFinished();
-}
-
-void PepperFileIOHost::ExecutePlatformReadCallback(
-    ppapi::host::ReplyMessageContext reply_context,
-    base::PlatformFileError error_code,
-    const char* data, int bytes_read) {
-  int32_t pp_error = ::ppapi::PlatformFileErrorToPepperError(error_code);
-
-  // Only send the amount of data in the string that was actually read.
-  std::string buffer;
-  if (pp_error == PP_OK)
-    buffer.append(data, bytes_read);
-  reply_context.params.set_result(ErrorOrByteNumber(pp_error, bytes_read));
-  host()->SendReply(reply_context, PpapiPluginMsg_FileIO_ReadReply(buffer));
-  state_manager_.SetOperationFinished();
-}
-
 void PepperFileIOHost::ExecutePlatformWriteCallback(
     ppapi::host::ReplyMessageContext reply_context,
     base::PlatformFileError error_code,
@@ -643,7 +586,7 @@
   // On the plugin side, the callback expects a parameter with different meaning
   // depends on whether is negative or not. It is the result here. We translate
   // for the callback.
-  int32_t pp_error = ::ppapi::PlatformFileErrorToPepperError(error_code);
+  int32_t pp_error = ppapi::PlatformFileErrorToPepperError(error_code);
   reply_context.params.set_result(ErrorOrByteNumber(pp_error, bytes_written));
   host()->SendReply(reply_context, PpapiPluginMsg_FileIO_GeneralReply());
   state_manager_.SetOperationFinished();
diff --git a/content/renderer/pepper/pepper_file_io_host.h b/content/renderer/pepper/pepper_file_io_host.h
index 1d3dbbd..1680406 100644
--- a/content/renderer/pepper/pepper_file_io_host.h
+++ b/content/renderer/pepper/pepper_file_io_host.h
@@ -19,6 +19,7 @@
 #include "ppapi/host/host_message_context.h"
 #include "ppapi/host/resource_host.h"
 #include "ppapi/shared_impl/file_io_state_manager.h"
+#include "ppapi/shared_impl/file_ref_detailed_info.h"
 #include "ppapi/thunk/ppb_file_ref_api.h"
 #include "url/gurl.h"
 #include "webkit/common/quota/quota_types.h"
@@ -26,6 +27,7 @@
 using ppapi::host::ReplyMessageContext;
 
 namespace content {
+class PepperPluginInstanceImpl;
 class QuotaFileIO;
 
 class PepperFileIOHost : public ppapi::host::ResourceHost,
@@ -57,13 +59,9 @@
   int32_t OnHostMsgOpen(ppapi::host::HostMessageContext* context,
                         PP_Resource file_ref_resource,
                         int32_t open_flags);
-  int32_t OnHostMsgQuery(ppapi::host::HostMessageContext* context);
   int32_t OnHostMsgTouch(ppapi::host::HostMessageContext* context,
                          PP_Time last_access_time,
                          PP_Time last_modified_time);
-  int32_t OnHostMsgRead(ppapi::host::HostMessageContext* context,
-                        int64_t offset,
-                        int32_t bytes_to_read);
   int32_t OnHostMsgWrite(ppapi::host::HostMessageContext* context,
                          int64_t offset,
                          const std::string& buffer);
@@ -83,6 +81,11 @@
   int32_t OnHostMsgWillSetLength(ppapi::host::HostMessageContext* context,
                                  int64_t length);
 
+  void DidGetFileRefInfo(
+      ppapi::host::ReplyMessageContext reply_context,
+      int flags,
+      const std::vector<ppapi::FileRefDetailedInfo>& infos);
+
   // Callback handlers. These mostly convert the PlatformFileError to the
   // PP_Error code and send back the reply. Note that the argument
   // ReplyMessageContext is copied so that we have a closure containing all
@@ -108,6 +111,8 @@
                                     base::PlatformFileError error_code,
                                     int bytes_written);
 
+  RendererPpapiHost* renderer_ppapi_host_;
+  PepperPluginInstanceImpl* plugin_instance_;
   base::PlatformFile file_;
 
   // The file system type specified in the Open() call. This will be
diff --git a/content/renderer/pepper/pepper_in_process_resource_creation.cc b/content/renderer/pepper/pepper_in_process_resource_creation.cc
index 3732583..cb10ff2 100644
--- a/content/renderer/pepper/pepper_in_process_resource_creation.cc
+++ b/content/renderer/pepper/pepper_in_process_resource_creation.cc
@@ -19,6 +19,7 @@
 #include "ppapi/proxy/ext_crx_file_system_private_resource.h"
 #include "ppapi/proxy/file_chooser_resource.h"
 #include "ppapi/proxy/file_io_resource.h"
+#include "ppapi/proxy/file_ref_resource.h"
 #include "ppapi/proxy/file_system_resource.h"
 #include "ppapi/proxy/graphics_2d_resource.h"
 #include "ppapi/proxy/ppapi_messages.h"
@@ -85,6 +86,15 @@
       instance))->GetReference();
 }
 
+PP_Resource PepperInProcessResourceCreation::CreateFileRef(
+    PP_Instance instance,
+    const ppapi::FileRefCreateInfo& create_info) {
+  return ppapi::proxy::FileRefResource::CreateFileRef(
+      host_impl_->in_process_router()->GetPluginConnection(instance),
+      instance,
+      create_info);
+}
+
 PP_Resource PepperInProcessResourceCreation::CreateFileSystem(
     PP_Instance instance,
     PP_FileSystemType type) {
@@ -127,7 +137,7 @@
     PP_Instance instance) {
   return (new ppapi::proxy::URLRequestInfoResource(
       host_impl_->in_process_router()->GetPluginConnection(instance),
-      instance, ::ppapi::URLRequestInfoData()))->GetReference();
+      instance, ppapi::URLRequestInfoData()))->GetReference();
 }
 
 PP_Resource PepperInProcessResourceCreation::CreateWebSocket(
diff --git a/content/renderer/pepper/pepper_in_process_resource_creation.h b/content/renderer/pepper/pepper_in_process_resource_creation.h
index 985ae09..847aac1 100644
--- a/content/renderer/pepper/pepper_in_process_resource_creation.h
+++ b/content/renderer/pepper/pepper_in_process_resource_creation.h
@@ -49,6 +49,9 @@
       PP_FileChooserMode_Dev mode,
       const PP_Var& accept_types) OVERRIDE;
   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 CreateGraphics2D(
diff --git a/content/renderer/pepper/pepper_media_device_manager.cc b/content/renderer/pepper/pepper_media_device_manager.cc
index ede9796..3531816 100644
--- a/content/renderer/pepper/pepper_media_device_manager.cc
+++ b/content/renderer/pepper/pepper_media_device_manager.cc
@@ -152,6 +152,9 @@
 void PepperMediaDeviceManager::OnStreamGenerationFailed(int request_id) {
 }
 
+void PepperMediaDeviceManager::OnStopGeneratedStream(const std::string& label) {
+}
+
 void PepperMediaDeviceManager::OnDevicesEnumerated(
     int request_id,
     const StreamDeviceInfoArray& device_array) {
diff --git a/content/renderer/pepper/pepper_media_device_manager.h b/content/renderer/pepper/pepper_media_device_manager.h
index dd1d9d5..67d8976 100644
--- a/content/renderer/pepper/pepper_media_device_manager.h
+++ b/content/renderer/pepper/pepper_media_device_manager.h
@@ -60,6 +60,7 @@
       const StreamDeviceInfoArray& audio_device_array,
       const StreamDeviceInfoArray& video_device_array) OVERRIDE;
   virtual void OnStreamGenerationFailed(int request_id) OVERRIDE;
+  virtual void OnStopGeneratedStream(const std::string& label) OVERRIDE;
   virtual void OnDevicesEnumerated(
       int request_id,
       const StreamDeviceInfoArray& device_array) OVERRIDE;
diff --git a/content/renderer/pepper/pepper_plugin_instance_impl.cc b/content/renderer/pepper/pepper_plugin_instance_impl.cc
index 310ebe8..1ba473b 100644
--- a/content/renderer/pepper/pepper_plugin_instance_impl.cc
+++ b/content/renderer/pepper/pepper_plugin_instance_impl.cc
@@ -16,6 +16,7 @@
 #include "base/strings/utf_string_conversions.h"
 #include "base/time/time.h"
 #include "cc/layers/texture_layer.h"
+#include "content/common/content_constants_internal.h"
 #include "content/public/common/page_zoom.h"
 #include "content/public/renderer/content_renderer_client.h"
 #include "content/renderer/pepper/common.h"
@@ -35,7 +36,6 @@
 #include "content/renderer/pepper/plugin_module.h"
 #include "content/renderer/pepper/plugin_object.h"
 #include "content/renderer/pepper/ppb_buffer_impl.h"
-#include "content/renderer/pepper/ppb_file_ref_impl.h"
 #include "content/renderer/pepper/ppb_graphics_3d_impl.h"
 #include "content/renderer/pepper/ppb_image_data_impl.h"
 #include "content/renderer/pepper/ppp_pdf.h"
@@ -45,6 +45,7 @@
 #include "content/renderer/render_thread_impl.h"
 #include "content/renderer/render_view_impl.h"
 #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"
@@ -110,8 +111,6 @@
 #include "ui/gfx/rect_conversions.h"
 #include "ui/gfx/scoped_ns_graphics_context_save_gstate_mac.h"
 #include "v8/include/v8.h"
-#include "webkit/plugins/plugin_constants.h"
-#include "webkit/plugins/sad_plugin.h"
 #include "webkit/renderer/compositor_bindings/web_layer_impl.h"
 
 #if defined(OS_MACOSX)
@@ -373,14 +372,14 @@
                                       plugin_url);
 }
 
-PepperPluginInstanceImpl::NaClDocumentLoader::NaClDocumentLoader()
+PepperPluginInstanceImpl::ExternalDocumentLoader::ExternalDocumentLoader()
     : finished_loading_(false) {
 }
 
-PepperPluginInstanceImpl::NaClDocumentLoader::~NaClDocumentLoader(){
+PepperPluginInstanceImpl::ExternalDocumentLoader::~ExternalDocumentLoader() {
 }
 
-void PepperPluginInstanceImpl::NaClDocumentLoader::ReplayReceivedData(
+void PepperPluginInstanceImpl::ExternalDocumentLoader::ReplayReceivedData(
     WebURLLoaderClient* document_loader) {
   for (std::list<std::string>::iterator it = data_.begin();
        it != data_.end(); ++it) {
@@ -396,7 +395,7 @@
   }
 }
 
-void PepperPluginInstanceImpl::NaClDocumentLoader::didReceiveData(
+void PepperPluginInstanceImpl::ExternalDocumentLoader::didReceiveData(
     WebURLLoader* loader,
     const char* data,
     int data_length,
@@ -404,14 +403,14 @@
   data_.push_back(std::string(data, data_length));
 }
 
-void PepperPluginInstanceImpl::NaClDocumentLoader::didFinishLoading(
+void PepperPluginInstanceImpl::ExternalDocumentLoader::didFinishLoading(
     WebURLLoader* loader,
     double finish_time) {
   DCHECK(!finished_loading_);
   finished_loading_ = true;
 }
 
-void PepperPluginInstanceImpl::NaClDocumentLoader::didFail(
+void PepperPluginInstanceImpl::ExternalDocumentLoader::didFail(
     WebURLLoader* loader,
     const WebURLError& error) {
   DCHECK(!error_.get());
@@ -419,7 +418,7 @@
 }
 
 PepperPluginInstanceImpl::GamepadImpl::GamepadImpl()
-    : Resource(::ppapi::Resource::Untracked()) {
+    : Resource(ppapi::Resource::Untracked()) {
 }
 
 PepperPluginInstanceImpl::GamepadImpl::~GamepadImpl() {
@@ -435,13 +434,13 @@
   WebKit::WebGamepads webkit_data;
   RenderThreadImpl::current()->SampleGamepads(&webkit_data);
   ConvertWebKitGamepadData(
-      *reinterpret_cast<const ::ppapi::WebKitGamepads*>(&webkit_data), data);
+      *reinterpret_cast<const ppapi::WebKitGamepads*>(&webkit_data), data);
 }
 
 PepperPluginInstanceImpl::PepperPluginInstanceImpl(
     RenderViewImpl* render_view,
     PluginModule* module,
-    ::ppapi::PPP_Instance_Combined* instance_interface,
+    ppapi::PPP_Instance_Combined* instance_interface,
     WebPluginContainer* container,
     const GURL& plugin_url)
     : render_view_(render_view),
@@ -488,7 +487,7 @@
       selection_anchor_(0),
       pending_user_gesture_(0.0),
       document_loader_(NULL),
-      nacl_document_load_(false),
+      external_document_load_(false),
       npp_(new NPP_t),
       isolate_(v8::Isolate::GetCurrent()) {
   pp_instance_ = HostGlobals::Get()->AddInstance(this);
@@ -517,11 +516,9 @@
   RendererPpapiHostImpl* host_impl = module_->renderer_ppapi_host();
   resource_creation_ = host_impl->CreateInProcessResourceCreationAPI(this);
 
-  // TODO(bbudge) remove this when the trusted NaCl plugin has been removed.
-  // We must defer certain plugin events for NaCl instances since we switch
-  // from the in-process to the out-of-process proxy after instantiating them.
-  if (module->name() == "Native Client")
-    nacl_document_load_ = true;
+  if (GetContentClient()->renderer() &&  // NULL in unit tests.
+      GetContentClient()->renderer()->IsExternalPepperPlugin(module->name()))
+    external_document_load_ = true;
 }
 
 PepperPluginInstanceImpl::~PepperPluginInstanceImpl() {
@@ -609,7 +606,7 @@
     if (!sad_plugin_)  // Lazily initialize bitmap.
       sad_plugin_ = GetContentClient()->renderer()->GetSadPluginBitmap();
     if (sad_plugin_)
-      webkit::PaintSadPlugin(canvas, plugin_rect, *sad_plugin_);
+      PaintSadPlugin(canvas, plugin_rect, *sad_plugin_);
     return;
   }
 
@@ -671,7 +668,7 @@
   UnSetAndDeleteLockTargetAdapter();
 }
 
-static void SetGPUHistogram(const ::ppapi::Preferences& prefs,
+static void SetGPUHistogram(const ppapi::Preferences& prefs,
                             const std::vector<std::string>& arg_names,
                             const std::vector<std::string>& arg_values) {
   // Calculate a histogram to let us determine how likely people are to try to
@@ -732,12 +729,12 @@
 bool PepperPluginInstanceImpl::HandleDocumentLoad(
     const WebKit::WebURLResponse& response) {
   DCHECK(!document_loader_);
-  if (nacl_document_load_) {
-    // The NaCl proxy isn't available, so save the response and record document
-    // load notifications for later replay.
-    nacl_document_response_ = response;
-    nacl_document_loader_.reset(new NaClDocumentLoader());
-    document_loader_ = nacl_document_loader_.get();
+  if (external_document_load_) {
+    // The external proxy isn't available, so save the response and record
+    // document load notifications for later replay.
+    external_document_response_ = response;
+    external_document_loader_.reset(new ExternalDocumentLoader());
+    document_loader_ = external_document_loader_.get();
     return true;
   }
 
@@ -770,6 +767,7 @@
   DCHECK(pending_host_id);
 
   DataFromWebURLResponse(
+      host_impl,
       pp_instance(),
       response,
       base::Bind(&PepperPluginInstanceImpl::DidDataFromWebURLResponse,
@@ -809,9 +807,9 @@
       !(input_event_mask_ & event_class))
     return false;
 
-  ::ppapi::InputEventData event;
+  ppapi::InputEventData event;
   event.event_type = type;
-  event.event_time_stamp = ::ppapi::TimeTicksToPPTimeTicks(
+  event.event_time_stamp = ppapi::TimeTicksToPPTimeTicks(
       base::TimeTicks::Now());
 
   // Convert UTF16 text to UTF8 with offset conversion.
@@ -862,7 +860,7 @@
   else
     handled = true;  // Unfiltered events are assumed to be handled.
   scoped_refptr<PPB_InputEvent_Shared> event_resource(
-      new PPB_InputEvent_Shared(::ppapi::OBJECT_IS_IMPL, pp_instance(), event));
+      new PPB_InputEvent_Shared(ppapi::OBJECT_IS_IMPL, pp_instance(), event));
   handled |= PP_ToBool(plugin_input_event_interface_->HandleInputEvent(
       pp_instance(), event_resource->pp_resource()));
   return handled;
@@ -963,7 +961,7 @@
     if ((filtered_input_event_mask_ & event_class) ||
         (input_event_mask_ & event_class)) {
       // Actually send the event.
-      std::vector< ::ppapi::InputEventData > events;
+      std::vector< ppapi::InputEventData > events;
       CreateInputEventData(event, &events);
 
       // Allow the user gesture to be pending after the plugin handles the
@@ -971,7 +969,7 @@
       // gesture after processing has finished here.
       if (WebUserGestureIndicator::isProcessingUserGesture()) {
         pending_user_gesture_ =
-            ::ppapi::EventTimeToPPTimeTicks(event.timeStampSeconds);
+            ppapi::EventTimeToPPTimeTicks(event.timeStampSeconds);
         pending_user_gesture_token_ =
             WebUserGestureIndicator::currentUserGestureToken();
         pending_user_gesture_token_.setOutOfProcess();
@@ -984,7 +982,7 @@
         else
           rv = true;  // Unfiltered events are assumed to be handled.
         scoped_refptr<PPB_InputEvent_Shared> event_resource(
-            new PPB_InputEvent_Shared(::ppapi::OBJECT_IS_IMPL,
+            new PPB_InputEvent_Shared(ppapi::OBJECT_IS_IMPL,
                                       pp_instance(), events[i]));
 
         rv |= PP_ToBool(plugin_input_event_interface_->HandleInputEvent(
@@ -1327,7 +1325,7 @@
 
 bool PepperPluginInstanceImpl::LoadPrintInterface() {
   // Only check for the interface if the plugin has dev permission.
-  if (!module_->permissions().HasPermission(::ppapi::PERMISSION_DEV))
+  if (!module_->permissions().HasPermission(ppapi::PERMISSION_DEV))
     return false;
   if (!plugin_print_interface_) {
     plugin_print_interface_ = static_cast<const PPP_Printing_Dev*>(
@@ -1338,7 +1336,7 @@
 
 bool PepperPluginInstanceImpl::LoadPrivateInterface() {
   // Only check for the interface if the plugin has private permission.
-  if (!module_->permissions().HasPermission(::ppapi::PERMISSION_PRIVATE))
+  if (!module_->permissions().HasPermission(ppapi::PERMISSION_PRIVATE))
     return false;
   if (!plugin_private_interface_) {
     plugin_private_interface_ = static_cast<const PPP_Instance_Private*>(
@@ -1447,7 +1445,7 @@
   last_sent_view_data_ = view_data_;
   ScopedPPResource resource(
       ScopedPPResource::PassRef(),
-      (new PPB_View_Shared(::ppapi::OBJECT_IS_IMPL,
+      (new PPB_View_Shared(ppapi::OBJECT_IS_IMPL,
                            pp_instance(), view_data_))->GetReference());
 
   instance_interface_->DidChangeView(pp_instance(), resource,
@@ -1670,7 +1668,7 @@
   if (is_mouselock_pending && !IsMouseLocked()) {
     if (!IsProcessingUserGesture() &&
         !module_->permissions().HasPermission(
-            ::ppapi::PERMISSION_BYPASS_USER_GESTURE)) {
+            ppapi::PERMISSION_BYPASS_USER_GESTURE)) {
       lock_mouse_callback_->Run(PP_ERROR_NO_USER_GESTURE);
     } else {
       // Open a user gesture here so the Webkit user gesture checks will succeed
@@ -1703,7 +1701,7 @@
 bool PepperPluginInstanceImpl::PrintPDFOutput(PP_Resource print_output,
                                               WebKit::WebCanvas* canvas) {
 #if defined(ENABLE_PRINTING)
-  ::ppapi::thunk::EnterResourceNoLock<PPB_Buffer_API> enter(print_output, true);
+  ppapi::thunk::EnterResourceNoLock<PPB_Buffer_API> enter(print_output, true);
   if (enter.failed())
     return false;
 
@@ -1850,8 +1848,7 @@
 }
 
 bool PepperPluginInstanceImpl::IsProcessingUserGesture() {
-  PP_TimeTicks now =
-      ::ppapi::TimeTicksToPPTimeTicks(base::TimeTicks::Now());
+  PP_TimeTicks now = ppapi::TimeTicksToPPTimeTicks(base::TimeTicks::Now());
   // Give a lot of slack so tests won't be flaky.
   const PP_TimeTicks kUserGestureDurationInSeconds = 10.0;
   return pending_user_gesture_token_.hasGestures() &&
@@ -1973,7 +1970,7 @@
   TRACE_EVENT0("ppapi", "PepperPluginInstanceImpl::BindGraphics");
   // The Graphics3D instance can't be destroyed until we call
   // UpdateLayer().
-  scoped_refptr< ::ppapi::Resource> old_graphics = bound_graphics_3d_.get();
+  scoped_refptr<ppapi::Resource> old_graphics = bound_graphics_3d_.get();
   if (bound_graphics_3d_.get()) {
     bound_graphics_3d_->BindToInstance(false);
     bound_graphics_3d_ = NULL;
@@ -2242,25 +2239,25 @@
   return PP_TRUE;
 }
 
-::ppapi::Resource* PepperPluginInstanceImpl::GetSingletonResource(
+ppapi::Resource* PepperPluginInstanceImpl::GetSingletonResource(
     PP_Instance instance,
-    ::ppapi::SingletonResourceID id) {
+    ppapi::SingletonResourceID id) {
   // Flash APIs and some others aren't implemented in-process.
   switch (id) {
-    case ::ppapi::BROKER_SINGLETON_ID:
-    case ::ppapi::BROWSER_FONT_SINGLETON_ID:
-    case ::ppapi::CRX_FILESYSTEM_SINGLETON_ID:
-    case ::ppapi::EXTENSIONS_COMMON_SINGLETON_ID:
-    case ::ppapi::FLASH_CLIPBOARD_SINGLETON_ID:
-    case ::ppapi::FLASH_FILE_SINGLETON_ID:
-    case ::ppapi::FLASH_FULLSCREEN_SINGLETON_ID:
-    case ::ppapi::FLASH_SINGLETON_ID:
-    case ::ppapi::NETWORK_PROXY_SINGLETON_ID:
-    case ::ppapi::PDF_SINGLETON_ID:
-    case ::ppapi::TRUETYPE_FONT_SINGLETON_ID:
+    case ppapi::BROKER_SINGLETON_ID:
+    case ppapi::BROWSER_FONT_SINGLETON_ID:
+    case ppapi::CRX_FILESYSTEM_SINGLETON_ID:
+    case ppapi::EXTENSIONS_COMMON_SINGLETON_ID:
+    case ppapi::FLASH_CLIPBOARD_SINGLETON_ID:
+    case ppapi::FLASH_FILE_SINGLETON_ID:
+    case ppapi::FLASH_FULLSCREEN_SINGLETON_ID:
+    case ppapi::FLASH_SINGLETON_ID:
+    case ppapi::NETWORK_PROXY_SINGLETON_ID:
+    case ppapi::PDF_SINGLETON_ID:
+    case ppapi::TRUETYPE_FONT_SINGLETON_ID:
       NOTIMPLEMENTED();
       return NULL;
-    case ::ppapi::GAMEPAD_SINGLETON_ID:
+    case ppapi::GAMEPAD_SINGLETON_ID:
       return gamepad_impl_.get();
   }
 
@@ -2450,7 +2447,7 @@
 
   WebElement plugin_element = container()->element();
   GURL document_url = plugin_element.document().baseURL();
-  return ::ppapi::PPB_URLUtil_Shared::GenerateURLReturn(
+  return ppapi::PPB_URLUtil_Shared::GenerateURLReturn(
       document_url.Resolve(relative_string->value()),
       components);
 }
@@ -2490,15 +2487,15 @@
     PP_Instance instance,
     PP_URLComponents_Dev* components) {
   WebKit::WebDocument document = container()->element().document();
-  return ::ppapi::PPB_URLUtil_Shared::GenerateURLReturn(document.url(),
-                                                        components);
+  return ppapi::PPB_URLUtil_Shared::GenerateURLReturn(document.url(),
+                                                      components);
 }
 
 PP_Var PepperPluginInstanceImpl::GetPluginInstanceURL(
     PP_Instance instance,
     PP_URLComponents_Dev* components) {
-  return ::ppapi::PPB_URLUtil_Shared::GenerateURLReturn(plugin_url_,
-                                                        components);
+  return ppapi::PPB_URLUtil_Shared::GenerateURLReturn(plugin_url_,
+                                                      components);
 }
 
 PP_ExternalPluginResult PepperPluginInstanceImpl::ResetAsProxied(
@@ -2557,16 +2554,16 @@
   view_change_weak_ptr_factory_.InvalidateWeakPtrs();
   SendDidChangeView();
 
-  DCHECK(nacl_document_load_);
-  nacl_document_load_ = false;
-  if (!nacl_document_response_.isNull()) {
+  DCHECK(external_document_load_);
+  external_document_load_ = false;
+  if (!external_document_response_.isNull()) {
     document_loader_ = NULL;
     // Pass the response to the new proxy.
-    HandleDocumentLoad(nacl_document_response_);
-    nacl_document_response_ = WebKit::WebURLResponse();
+    HandleDocumentLoad(external_document_response_);
+    external_document_response_ = WebKit::WebURLResponse();
     // Replay any document load events we've received to the real loader.
-    nacl_document_loader_->ReplayReceivedData(document_loader_);
-    nacl_document_loader_.reset(NULL);
+    external_document_loader_->ReplayReceivedData(document_loader_);
+    external_document_loader_.reset(NULL);
   }
 
   return PP_EXTERNAL_PLUGIN_OK;
@@ -2598,7 +2595,7 @@
   return container_;
 }
 
-::ppapi::VarTracker* PepperPluginInstanceImpl::GetVarTracker() {
+ppapi::VarTracker* PepperPluginInstanceImpl::GetVarTracker() {
   return HostGlobals::Get()->GetVarTracker();
 }
 
@@ -2610,13 +2607,6 @@
   return module_->path();
 }
 
-PP_Resource PepperPluginInstanceImpl::CreateExternalFileReference(
-    const base::FilePath& external_file_path) {
-  PPB_FileRef_Impl* ref = PPB_FileRef_Impl::CreateExternal(
-      pp_instance(), external_file_path, "");
-  return ref->GetReference();
-}
-
 PP_Resource PepperPluginInstanceImpl::CreateImage(gfx::ImageSkia* source_image,
                                                   float scale) {
   ui::ScaleFactor scale_factor = ui::GetScaleFactorFromScale(scale);
@@ -2651,7 +2641,7 @@
 
 PP_ExternalPluginResult PepperPluginInstanceImpl::SwitchToOutOfProcessProxy(
     const base::FilePath& file_path,
-    ::ppapi::PpapiPermissions permissions,
+    ppapi::PpapiPermissions permissions,
     const IPC::ChannelHandle& channel_handle,
     base::ProcessId plugin_pid,
     int plugin_child_id) {
@@ -2739,7 +2729,7 @@
 }
 
 int32_t PepperPluginInstanceImpl::Navigate(
-    const ::ppapi::URLRequestInfoData& request,
+    const ppapi::URLRequestInfoData& request,
     const char* target,
     bool from_user_action) {
   if (!container_)
@@ -2750,11 +2740,15 @@
   if (!frame)
     return PP_ERROR_FAILED;
 
-  ::ppapi::URLRequestInfoData completed_request = request;
+  ppapi::URLRequestInfoData completed_request = request;
 
   WebURLRequest web_request;
-  if (!CreateWebURLRequest(&completed_request, frame, &web_request))
+  if (!CreateWebURLRequest(pp_instance_,
+                           &completed_request,
+                           frame,
+                           &web_request)) {
     return PP_ERROR_FAILED;
+  }
   web_request.setFirstPartyForCookies(document.firstPartyForCookies());
   web_request.setHasUserGesture(from_user_action);
 
diff --git a/content/renderer/pepper/pepper_plugin_instance_impl.h b/content/renderer/pepper/pepper_plugin_instance_impl.h
index ad63881..930c55a 100644
--- a/content/renderer/pepper/pepper_plugin_instance_impl.h
+++ b/content/renderer/pepper/pepper_plugin_instance_impl.h
@@ -114,7 +114,7 @@
     : public base::RefCounted<PepperPluginInstanceImpl>,
       public base::SupportsWeakPtr<PepperPluginInstanceImpl>,
       public NON_EXPORTED_BASE(PepperPluginInstance),
-      public ::ppapi::PPB_Instance_Shared {
+      public ppapi::PPB_Instance_Shared {
  public:
   // Create and return a PepperPluginInstanceImpl object which supports the most
   // recent version of PPP_Instance possible by querying the given
@@ -135,7 +135,7 @@
   // nonzero.
   PP_Instance pp_instance() const { return pp_instance_; }
 
-  ::ppapi::thunk::ResourceCreationAPI& resource_creation() {
+  ppapi::thunk::ResourceCreationAPI& resource_creation() {
     return *resource_creation_.get();
   }
 
@@ -170,7 +170,7 @@
 
   // PPB_Instance and PPB_Instance_Private implementation.
   bool full_frame() const { return full_frame_; }
-  const ::ppapi::ViewData& view_data() const { return view_data_; }
+  const ppapi::ViewData& view_data() const { return view_data_; }
 
   // PPP_Instance and PPP_Instance_Private.
   bool Initialize(const std::vector<std::string>& arg_names,
@@ -320,13 +320,13 @@
 
   // Simulates an input event to the plugin by passing it down to WebKit,
   // which sends it back up to the plugin as if it came from the user.
-  void SimulateInputEvent(const ::ppapi::InputEventData& input_event);
+  void SimulateInputEvent(const ppapi::InputEventData& input_event);
 
   // Simulates an IME event at the level of RenderView which sends it back up to
   // the plugin as if it came from the user.
-  bool SimulateIMEEvent(const ::ppapi::InputEventData& input_event);
+  bool SimulateIMEEvent(const ppapi::InputEventData& input_event);
   void SimulateImeSetCompositionEvent(
-      const ::ppapi::InputEventData& input_event);
+      const ppapi::InputEventData& input_event);
 
   // The document loader is valid when the plugin is "full-frame" and in this
   // case is non-NULL as long as the corresponding loader resource is alive.
@@ -344,16 +344,14 @@
   // PluginInstance implementation
   virtual RenderView* GetRenderView() OVERRIDE;
   virtual WebKit::WebPluginContainer* GetContainer() OVERRIDE;
-  virtual ::ppapi::VarTracker* GetVarTracker() OVERRIDE;
+  virtual ppapi::VarTracker* GetVarTracker() OVERRIDE;
   virtual const GURL& GetPluginURL() OVERRIDE;
   virtual base::FilePath GetModulePath() OVERRIDE;
-  virtual PP_Resource CreateExternalFileReference(
-      const base::FilePath& external_file_path) OVERRIDE;
   virtual PP_Resource CreateImage(gfx::ImageSkia* source_image,
                                   float scale) OVERRIDE;
   virtual PP_ExternalPluginResult SwitchToOutOfProcessProxy(
       const base::FilePath& file_path,
-      ::ppapi::PpapiPermissions permissions,
+      ppapi::PpapiPermissions permissions,
       const IPC::ChannelHandle& channel_handle,
       base::ProcessId plugin_pid,
       int plugin_child_id) OVERRIDE;
@@ -361,7 +359,7 @@
   virtual bool IsFullPagePlugin() OVERRIDE;
   virtual void FlashSetFullscreen(bool fullscreen, bool delay_report) OVERRIDE;
   virtual bool IsRectTopmost(const gfx::Rect& rect) OVERRIDE;
-  virtual int32_t Navigate(const ::ppapi::URLRequestInfoData& request,
+  virtual int32_t Navigate(const ppapi::URLRequestInfoData& request,
                            const char* target,
                            bool from_user_action) OVERRIDE;
 
@@ -369,7 +367,7 @@
   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 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;
@@ -391,8 +389,8 @@
                                 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 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,
@@ -410,7 +408,7 @@
                             const PP_Point* hot_spot) OVERRIDE;
   virtual int32_t LockMouse(
       PP_Instance instance,
-      scoped_refptr< ::ppapi::TrackedCallback> callback) OVERRIDE;
+      scoped_refptr<ppapi::TrackedCallback> callback) OVERRIDE;
   virtual void UnlockMouse(PP_Instance instance) OVERRIDE;
   virtual void SetTextInputType(PP_Instance instance,
                                 PP_TextInput_Type type) OVERRIDE;
@@ -504,11 +502,11 @@
   virtual ~PepperPluginInstanceImpl();
 
   // Class to record document load notifications and play them back once the
-  // real document loader becomes available. Used only by NaCl instances.
-  class NaClDocumentLoader : public WebKit::WebURLLoaderClient {
+  // real document loader becomes available. Used only by external instances.
+  class ExternalDocumentLoader : public WebKit::WebURLLoaderClient {
    public:
-    NaClDocumentLoader();
-    virtual ~NaClDocumentLoader();
+    ExternalDocumentLoader();
+    virtual ~ExternalDocumentLoader();
 
     void ReplayReceivedData(WebURLLoaderClient* document_loader);
 
@@ -530,12 +528,12 @@
 
   // Implements PPB_Gamepad_API. This is just to avoid having an excessive
   // number of interfaces implemented by PepperPluginInstanceImpl.
-  class GamepadImpl : public ::ppapi::thunk::PPB_Gamepad_API,
-                      public ::ppapi::Resource {
+  class GamepadImpl : public ppapi::thunk::PPB_Gamepad_API,
+                      public ppapi::Resource {
    public:
     GamepadImpl();
     // Resource implementation.
-    virtual ::ppapi::thunk::PPB_Gamepad_API* AsPPB_Gamepad_API() OVERRIDE;
+    virtual ppapi::thunk::PPB_Gamepad_API* AsPPB_Gamepad_API() OVERRIDE;
     virtual void Sample(PP_Instance instance,
                         PP_GamepadsSampleData* data) OVERRIDE;
    private:
@@ -548,7 +546,7 @@
   // for member initialization.
   PepperPluginInstanceImpl(RenderViewImpl* render_view,
                            PluginModule* module,
-                           ::ppapi::PPP_Instance_Combined* instance_interface,
+                           ppapi::PPP_Instance_Combined* instance_interface,
                            WebKit::WebPluginContainer* container,
                            const GURL& plugin_url);
 
@@ -644,12 +642,12 @@
 
   RenderViewImpl* render_view_;
   scoped_refptr<PluginModule> module_;
-  scoped_ptr< ::ppapi::PPP_Instance_Combined> instance_interface_;
+  scoped_ptr<ppapi::PPP_Instance_Combined> instance_interface_;
   // If this is the NaCl plugin, we create a new module when we switch to the
   // IPC-based PPAPI proxy. Store the original module and instance interface
   // so we can shut down properly.
   scoped_refptr<PluginModule> original_module_;
-  scoped_ptr< ::ppapi::PPP_Instance_Combined> original_instance_interface_;
+  scoped_ptr<ppapi::PPP_Instance_Combined> original_instance_interface_;
 
   PP_Instance pp_instance_;
 
@@ -667,10 +665,10 @@
   bool full_frame_;
 
   // Stores the current state of the plugin view.
-  ::ppapi::ViewData view_data_;
+  ppapi::ViewData view_data_;
   // The last state sent to the plugin. It is only valid after
   // |sent_initial_did_change_view_| is set to true.
-  ::ppapi::ViewData last_sent_view_data_;
+  ppapi::ViewData last_sent_view_data_;
 
   // Indicates if we've ever sent a didChangeView to the plugin. This ensures we
   // always send an initial notification, even if the position and clip are the
@@ -699,7 +697,7 @@
   int find_identifier_;
 
   // Helper object that creates resources.
-  scoped_ptr< ::ppapi::thunk::ResourceCreationAPI> resource_creation_;
+  scoped_ptr<ppapi::thunk::ResourceCreationAPI> resource_creation_;
 
   // The plugin-provided interfaces.
   // When adding PPP interfaces, make sure to reset them in ResetAsProxied.
@@ -742,7 +740,7 @@
   // An array of page ranges.
   std::vector<PP_PrintPageNumberRange_Dev> ranges_;
 
-  scoped_refptr< ::ppapi::Resource> gamepad_impl_;
+  scoped_refptr<ppapi::Resource> gamepad_impl_;
 
   // The plugin print interface.
   const PPP_Printing_Dev* plugin_print_interface_;
@@ -816,7 +814,7 @@
   size_t selection_caret_;
   size_t selection_anchor_;
 
-  scoped_refptr< ::ppapi::TrackedCallback> lock_mouse_callback_;
+  scoped_refptr<ppapi::TrackedCallback> lock_mouse_callback_;
 
   // Track pending user gestures so out-of-process plugins can respond to
   // a user gesture after it has been processed.
@@ -830,10 +828,10 @@
 
   // Non-owning pointer to the document loader, if any.
   WebKit::WebURLLoaderClient* document_loader_;
-  // State for deferring document loads. Used only by NaCl instances.
-  WebKit::WebURLResponse nacl_document_response_;
-  scoped_ptr<NaClDocumentLoader> nacl_document_loader_;
-  bool nacl_document_load_;
+  // State for deferring document loads. Used only by external instances.
+  WebKit::WebURLResponse external_document_response_;
+  scoped_ptr<ExternalDocumentLoader> external_document_loader_;
+  bool external_document_load_;
 
   // The ContentDecryptorDelegate forwards PPP_ContentDecryptor_Private
   // calls and handles PPB_ContentDecryptor_Private calls.
diff --git a/content/renderer/pepper/pepper_url_loader_host.cc b/content/renderer/pepper/pepper_url_loader_host.cc
index 8343f19..60bb467 100644
--- a/content/renderer/pepper/pepper_url_loader_host.cc
+++ b/content/renderer/pepper/pepper_url_loader_host.cc
@@ -250,8 +250,12 @@
   if (!frame)
     return PP_ERROR_FAILED;
   WebURLRequest web_request;
-  if (!CreateWebURLRequest(&filled_in_request_data, frame, &web_request))
+  if (!CreateWebURLRequest(pp_instance(),
+                           &filled_in_request_data,
+                           frame,
+                           &web_request)) {
     return PP_ERROR_FAILED;
+  }
   web_request.setRequestorProcessID(renderer_ppapi_host_->GetPluginPID());
 
   WebURLLoaderOptions options;
@@ -389,6 +393,7 @@
     pending_response_ = true;
 
     DataFromWebURLResponse(
+        renderer_ppapi_host_,
         pp_instance(),
         response,
         base::Bind(&PepperURLLoaderHost::DidDataFromWebURLResponse,
diff --git a/content/renderer/pepper/pepper_url_request_unittest.cc b/content/renderer/pepper/pepper_url_request_unittest.cc
index 20e7f92..05ca764 100644
--- a/content/renderer/pepper/pepper_url_request_unittest.cc
+++ b/content/renderer/pepper/pepper_url_request_unittest.cc
@@ -64,7 +64,7 @@
     test_globals_.GetResourceTracker()->DidCreateInstance(pp_instance_);
 
     // This resource doesn't do IPC, so a null connection is fine.
-    info_ = new URLRequestInfoResource(::ppapi::proxy::Connection(),
+    info_ = new URLRequestInfoResource(ppapi::proxy::Connection(),
                                        pp_instance_,
                                        URLRequestInfoData());
   }
@@ -77,7 +77,7 @@
   bool GetDownloadToFile() {
     WebURLRequest web_request;
     URLRequestInfoData data = info_->GetData();
-    if (!CreateWebURLRequest(&data, GetMainFrame(), &web_request))
+    if (!CreateWebURLRequest(pp_instance_, &data, GetMainFrame(), &web_request))
       return false;
     return web_request.downloadToFile();
   }
@@ -85,7 +85,7 @@
   WebCString GetURL() {
     WebURLRequest web_request;
     URLRequestInfoData data = info_->GetData();
-    if (!CreateWebURLRequest(&data, GetMainFrame(), &web_request))
+    if (!CreateWebURLRequest(pp_instance_, &data, GetMainFrame(), &web_request))
       return WebCString();
     return web_request.url().spec();
   }
@@ -93,7 +93,7 @@
   WebString GetMethod() {
     WebURLRequest web_request;
     URLRequestInfoData data = info_->GetData();
-    if (!CreateWebURLRequest(&data, GetMainFrame(), &web_request))
+    if (!CreateWebURLRequest(pp_instance_, &data, GetMainFrame(), &web_request))
       return WebString();
     return web_request.httpMethod();
   }
@@ -101,7 +101,7 @@
   WebString GetHeaderValue(const char* field) {
     WebURLRequest web_request;
     URLRequestInfoData data = info_->GetData();
-    if (!CreateWebURLRequest(&data, GetMainFrame(), &web_request))
+    if (!CreateWebURLRequest(pp_instance_, &data, GetMainFrame(), &web_request))
       return WebString();
     return web_request.httpHeaderField(WebString::fromUTF8(field));
   }
@@ -116,14 +116,14 @@
   PP_Instance pp_instance_;
 
   // Needs to be alive for resource tracking to work.
-  ::ppapi::TestGlobals test_globals_;
+  ppapi::TestGlobals test_globals_;
 
   scoped_refptr<URLRequestInfoResource> info_;
 };
 
 TEST_F(URLRequestInfoTest, GetInterface) {
   const PPB_URLRequestInfo* request_info =
-      ::ppapi::thunk::GetPPB_URLRequestInfo_1_0_Thunk();
+      ppapi::thunk::GetPPB_URLRequestInfo_1_0_Thunk();
   EXPECT_TRUE(request_info);
   EXPECT_TRUE(request_info->Create);
   EXPECT_TRUE(request_info->IsURLRequestInfo);
diff --git a/content/renderer/pepper/pepper_video_capture_host.cc b/content/renderer/pepper/pepper_video_capture_host.cc
index 191f430..5f90099 100644
--- a/content/renderer/pepper/pepper_video_capture_host.cc
+++ b/content/renderer/pepper/pepper_video_capture_host.cc
@@ -176,7 +176,7 @@
   // for sending below.
   std::vector<HostResource> buffer_host_resources;
   buffers_.reserve(buffer_count_hint_);
-  ::ppapi::ResourceTracker* tracker =
+  ppapi::ResourceTracker* tracker =
       HostGlobals::Get()->GetResourceTracker();
   ppapi::proxy::HostDispatcher* dispatcher =
       ppapi::proxy::HostDispatcher::GetForInstance(pp_instance());
@@ -330,7 +330,7 @@
 }
 
 void PepperVideoCaptureHost::ReleaseBuffers() {
-  ::ppapi::ResourceTracker* tracker = HostGlobals::Get()->GetResourceTracker();
+  ppapi::ResourceTracker* tracker = HostGlobals::Get()->GetResourceTracker();
   for (size_t i = 0; i < buffers_.size(); ++i) {
     buffers_[i].buffer->Unmap();
     tracker->ReleaseResource(buffers_[i].buffer->pp_resource());
diff --git a/content/renderer/pepper/pepper_webplugin_impl.cc b/content/renderer/pepper/pepper_webplugin_impl.cc
index e86c191..acbe838 100644
--- a/content/renderer/pepper/pepper_webplugin_impl.cc
+++ b/content/renderer/pepper/pepper_webplugin_impl.cc
@@ -120,7 +120,7 @@
     container_->clearScriptObjects();
 
   if (instance_.get()) {
-    ::ppapi::PpapiGlobals::Get()->GetVarTracker()->ReleaseVar(instance_object_);
+    ppapi::PpapiGlobals::Get()->GetVarTracker()->ReleaseVar(instance_object_);
     instance_object_ = PP_MakeUndefined();
     instance_->Delete();
     instance_ = NULL;
diff --git a/content/renderer/pepper/plugin_module.cc b/content/renderer/pepper/plugin_module.cc
index 6ccad4d..7a06929 100644
--- a/content/renderer/pepper/plugin_module.cc
+++ b/content/renderer/pepper/plugin_module.cc
@@ -138,7 +138,6 @@
 #include "ppapi/thunk/enter.h"
 #include "ppapi/thunk/ppb_graphics_2d_api.h"
 #include "ppapi/thunk/thunk.h"
-#include "webkit/plugins/plugin_switches.h"
 
 using ppapi::InputEventData;
 using ppapi::PpapiGlobals;
@@ -306,7 +305,7 @@
   // TODO(brettw) put these in a hash map for better performance.
   #define UNPROXIED_IFACE(api_name, iface_str, iface_struct) \
       if (strcmp(name, iface_str) == 0) \
-        return ::ppapi::thunk::Get##iface_struct##_Thunk();
+        return ppapi::thunk::Get##iface_struct##_Thunk();
   #define PROXIED_IFACE(api_name, iface_str, iface_struct) \
       UNPROXIED_IFACE(api_name, iface_str, iface_struct)
 
@@ -403,8 +402,8 @@
 
 PluginModule::PluginModule(const std::string& name,
                            const base::FilePath& path,
-                           const ::ppapi::PpapiPermissions& perms)
-    : callback_tracker_(new ::ppapi::CallbackTracker),
+                           const ppapi::PpapiPermissions& perms)
+    : callback_tracker_(new ppapi::CallbackTracker),
       is_in_destructor_(false),
       is_crashed_(false),
       broker_(NULL),
@@ -590,7 +589,7 @@
   instances_.erase(instance);
 }
 
-scoped_refptr< ::ppapi::CallbackTracker> PluginModule::GetCallbackTracker() {
+scoped_refptr<ppapi::CallbackTracker> PluginModule::GetCallbackTracker() {
   return callback_tracker_;
 }
 
diff --git a/content/renderer/pepper/plugin_module.h b/content/renderer/pepper/plugin_module.h
index 835e387..daadf3c 100644
--- a/content/renderer/pepper/plugin_module.h
+++ b/content/renderer/pepper/plugin_module.h
@@ -72,7 +72,7 @@
   // tracks which modules are alive.
   PluginModule(const std::string& name,
                const base::FilePath& path,
-               const ::ppapi::PpapiPermissions& perms);
+               const ppapi::PpapiPermissions& perms);
 
   // Sets the given class as being associated with this module. It will be
   // deleted when the module is destroyed. You can only set it once, subsequent
@@ -136,7 +136,7 @@
 
   const std::string& name() const { return name_; }
   const base::FilePath& path() const { return path_; }
-  const ::ppapi::PpapiPermissions& permissions() const { return permissions_; }
+  const ppapi::PpapiPermissions& permissions() const { return permissions_; }
 
   PepperPluginInstanceImpl* CreateInstance(
       RenderViewImpl* render_view,
@@ -161,7 +161,7 @@
   void InstanceCreated(PepperPluginInstanceImpl* instance);
   void InstanceDeleted(PepperPluginInstanceImpl* instance);
 
-  scoped_refptr< ::ppapi::CallbackTracker> GetCallbackTracker();
+  scoped_refptr<ppapi::CallbackTracker> GetCallbackTracker();
 
   // Called when running out of process and the plugin crashed. This will
   // release relevant resources and update all affected instances.
@@ -228,7 +228,7 @@
 
   // Tracker for completion callbacks, used mainly to ensure that all callbacks
   // are properly aborted on module shutdown.
-  scoped_refptr< ::ppapi::CallbackTracker> callback_tracker_;
+  scoped_refptr<ppapi::CallbackTracker> callback_tracker_;
 
   PP_Module pp_module_;
 
@@ -263,7 +263,7 @@
   const std::string name_;
   const base::FilePath path_;
 
-  ::ppapi::PpapiPermissions permissions_;
+  ppapi::PpapiPermissions permissions_;
 
   // Non-owning pointers to all instances associated with this module. When
   // there are no more instances, this object should be deleted.
diff --git a/content/renderer/pepper/plugin_object.cc b/content/renderer/pepper/plugin_object.cc
index 62346f5..7746846 100644
--- a/content/renderer/pepper/plugin_object.cc
+++ b/content/renderer/pepper/plugin_object.cc
@@ -214,7 +214,7 @@
 
   // Release the PP_Var that the plugin allocated. On success, they will all
   // be converted to NPVariants, and on failure, we want them to just go away.
-  ::ppapi::VarTracker* var_tracker = PpapiGlobals::Get()->GetVarTracker();
+  ppapi::VarTracker* var_tracker = PpapiGlobals::Get()->GetVarTracker();
   for (uint32_t i = 0; i < property_count; ++i)
     var_tracker->ReleaseVar(properties[i]);
   free(properties);
diff --git a/content/renderer/pepper/ppapi_unittest.cc b/content/renderer/pepper/ppapi_unittest.cc
index 28112aa..f46eb6b 100644
--- a/content/renderer/pepper/ppapi_unittest.cc
+++ b/content/renderer/pepper/ppapi_unittest.cc
@@ -79,8 +79,8 @@
 
   // Initialize the mock module.
   module_ = new PluginModule("Mock plugin", base::FilePath(),
-                             ::ppapi::PpapiPermissions());
-  ::ppapi::PpapiGlobals::Get()->ResetMainThreadMessageLoopForTesting();
+                             ppapi::PpapiPermissions());
+  ppapi::PpapiGlobals::Get()->ResetMainThreadMessageLoopForTesting();
   PepperPluginInfo::EntryPoints entry_points;
   entry_points.get_interface = &MockGetInterface;
   entry_points.initialize_module = &MockInitializeModule;
diff --git a/content/renderer/pepper/ppb_audio_impl.cc b/content/renderer/pepper/ppb_audio_impl.cc
index 3f1baca..45a9254 100644
--- a/content/renderer/pepper/ppb_audio_impl.cc
+++ b/content/renderer/pepper/ppb_audio_impl.cc
@@ -29,7 +29,7 @@
 // PPB_Audio_Impl --------------------------------------------------------------
 
 PPB_Audio_Impl::PPB_Audio_Impl(PP_Instance instance)
-    : Resource(::ppapi::OBJECT_IS_IMPL, instance),
+    : Resource(ppapi::OBJECT_IS_IMPL, instance),
       audio_(NULL),
       sample_frame_count_(0) {
 }
diff --git a/content/renderer/pepper/ppb_audio_impl.h b/content/renderer/pepper/ppb_audio_impl.h
index 62a4dd2..d5b9b45 100644
--- a/content/renderer/pepper/ppb_audio_impl.h
+++ b/content/renderer/pepper/ppb_audio_impl.h
@@ -23,8 +23,8 @@
 
 // Some of the backend functionality of this class is implemented by the
 // PPB_Audio_Shared so it can be shared with the proxy.
-class PPB_Audio_Impl : public ::ppapi::Resource,
-                       public ::ppapi::PPB_Audio_Shared,
+class PPB_Audio_Impl : public ppapi::Resource,
+                       public ppapi::PPB_Audio_Shared,
                        public AudioHelper {
  public:
   // Trusted initialization. You must call Init after this.
@@ -46,7 +46,7 @@
             void* user_data);
 
   // Resource overrides.
-  virtual ::ppapi::thunk::PPB_Audio_API* AsPPB_Audio_API() OVERRIDE;
+  virtual ppapi::thunk::PPB_Audio_API* AsPPB_Audio_API() OVERRIDE;
 
   // PPB_Audio_API implementation.
   virtual PP_Resource GetCurrentConfig() OVERRIDE;
@@ -54,7 +54,7 @@
   virtual PP_Bool StopPlayback() OVERRIDE;
   virtual int32_t Open(
       PP_Resource config_id,
-      scoped_refptr< ::ppapi::TrackedCallback> create_callback) OVERRIDE;
+      scoped_refptr<ppapi::TrackedCallback> create_callback) OVERRIDE;
   virtual int32_t GetSyncSocket(int* sync_socket) OVERRIDE;
   virtual int32_t GetSharedMemory(int* shm_handle, uint32_t* shm_size) OVERRIDE;
 
@@ -67,7 +67,7 @@
                                base::SyncSocket::Handle socket) OVERRIDE;
 
   // AudioConfig used for creating this Audio object. We own a ref.
-  ::ppapi::ScopedPPResource config_;
+  ppapi::ScopedPPResource config_;
 
   // PluginDelegate audio object that we delegate audio IPC through. We don't
   // own this pointer but are responsible for calling Shutdown on it.
diff --git a/content/renderer/pepper/ppb_broker_impl.cc b/content/renderer/pepper/ppb_broker_impl.cc
index 3eab94e..f68d257 100644
--- a/content/renderer/pepper/ppb_broker_impl.cc
+++ b/content/renderer/pepper/ppb_broker_impl.cc
@@ -28,7 +28,7 @@
 // PPB_Broker_Impl ------------------------------------------------------
 
 PPB_Broker_Impl::PPB_Broker_Impl(PP_Instance instance)
-    : Resource(::ppapi::OBJECT_IS_IMPL, instance),
+    : Resource(ppapi::OBJECT_IS_IMPL, instance),
       broker_(NULL),
       connect_callback_(),
       pipe_handle_(PlatformFileToInt(base::kInvalidPlatformFileValue)),
diff --git a/content/renderer/pepper/ppb_broker_impl.h b/content/renderer/pepper/ppb_broker_impl.h
index 6cd3829..0e77218 100644
--- a/content/renderer/pepper/ppb_broker_impl.h
+++ b/content/renderer/pepper/ppb_broker_impl.h
@@ -25,19 +25,19 @@
 namespace content {
 class PepperBroker;
 
-class PPB_Broker_Impl : public ::ppapi::Resource,
-                        public ::ppapi::thunk::PPB_Broker_API,
+class PPB_Broker_Impl : public ppapi::Resource,
+                        public ppapi::thunk::PPB_Broker_API,
                         public IPC::Listener,
                         public base::SupportsWeakPtr<PPB_Broker_Impl> {
  public:
   explicit PPB_Broker_Impl(PP_Instance instance);
 
   // Resource override.
-  virtual ::ppapi::thunk::PPB_Broker_API* AsPPB_Broker_API() OVERRIDE;
+  virtual ppapi::thunk::PPB_Broker_API* AsPPB_Broker_API() OVERRIDE;
 
   // PPB_BrokerTrusted implementation.
   virtual int32_t Connect(
-      scoped_refptr< ::ppapi::TrackedCallback> connect_callback) OVERRIDE;
+      scoped_refptr<ppapi::TrackedCallback> connect_callback) OVERRIDE;
   virtual int32_t GetHandle(int32_t* handle) OVERRIDE;
 
   // Returns the URL of the document this plug-in runs in. This is necessary to
@@ -61,7 +61,7 @@
   PepperBroker* broker_;
 
   // Callback invoked from BrokerConnected.
-  scoped_refptr< ::ppapi::TrackedCallback> connect_callback_;
+  scoped_refptr<ppapi::TrackedCallback> connect_callback_;
 
   // Pipe handle for the plugin instance to use to communicate with the broker.
   // Never owned by this object.
diff --git a/content/renderer/pepper/ppb_buffer_impl.cc b/content/renderer/pepper/ppb_buffer_impl.cc
index 7c6ec83..4b806b9 100644
--- a/content/renderer/pepper/ppb_buffer_impl.cc
+++ b/content/renderer/pepper/ppb_buffer_impl.cc
@@ -15,12 +15,12 @@
 #include "ppapi/c/pp_instance.h"
 #include "ppapi/c/pp_resource.h"
 
-using ::ppapi::thunk::PPB_Buffer_API;
+using ppapi::thunk::PPB_Buffer_API;
 
 namespace content {
 
 PPB_Buffer_Impl::PPB_Buffer_Impl(PP_Instance instance)
-    : Resource(::ppapi::OBJECT_IS_IMPL, instance),
+    : Resource(ppapi::OBJECT_IS_IMPL, instance),
       size_(0),
       map_count_(0) {
 }
diff --git a/content/renderer/pepper/ppb_buffer_impl.h b/content/renderer/pepper/ppb_buffer_impl.h
index ba042d6..7652622 100644
--- a/content/renderer/pepper/ppb_buffer_impl.h
+++ b/content/renderer/pepper/ppb_buffer_impl.h
@@ -14,8 +14,8 @@
 
 namespace content {
 
-class PPB_Buffer_Impl : public ::ppapi::Resource,
-                        public ::ppapi::thunk::PPB_Buffer_API {
+class PPB_Buffer_Impl : public ppapi::Resource,
+                        public ppapi::thunk::PPB_Buffer_API {
  public:
   static PP_Resource Create(PP_Instance instance, uint32_t size);
   static scoped_refptr<PPB_Buffer_Impl> CreateResource(PP_Instance instance,
@@ -27,7 +27,7 @@
   uint32_t size() const { return size_; }
 
   // Resource overrides.
-  virtual ::ppapi::thunk::PPB_Buffer_API* AsPPB_Buffer_API() OVERRIDE;
+  virtual ppapi::thunk::PPB_Buffer_API* AsPPB_Buffer_API() OVERRIDE;
 
   // PPB_Buffer_API implementation.
   virtual PP_Bool Describe(uint32_t* size_in_bytes) OVERRIDE;
@@ -55,7 +55,7 @@
 // mapped state in the destructor.
 class BufferAutoMapper {
  public:
-  explicit BufferAutoMapper(::ppapi::thunk::PPB_Buffer_API* api);
+  explicit BufferAutoMapper(ppapi::thunk::PPB_Buffer_API* api);
   ~BufferAutoMapper();
 
   // Will be NULL on failure to map.
@@ -63,7 +63,7 @@
   uint32_t size() { return size_; }
 
  private:
-  ::ppapi::thunk::PPB_Buffer_API* api_;
+  ppapi::thunk::PPB_Buffer_API* api_;
 
   bool needs_unmap_;
 
diff --git a/content/renderer/pepper/ppb_file_ref_impl.cc b/content/renderer/pepper/ppb_file_ref_impl.cc
deleted file mode 100644
index b50cbde..0000000
--- a/content/renderer/pepper/ppb_file_ref_impl.cc
+++ /dev/null
@@ -1,555 +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/renderer/pepper/ppb_file_ref_impl.h"
-
-#include "base/files/file_util_proxy.h"
-#include "base/platform_file.h"
-#include "base/strings/string_util.h"
-#include "base/strings/utf_string_conversions.h"
-#include "content/child/fileapi/file_system_dispatcher.h"
-#include "content/common/view_messages.h"
-#include "content/renderer/pepper/common.h"
-#include "content/renderer/pepper/pepper_file_system_host.h"
-#include "content/renderer/pepper/plugin_module.h"
-#include "content/renderer/pepper/renderer_ppapi_host_impl.h"
-#include "content/renderer/render_thread_impl.h"
-#include "net/base/escape.h"
-#include "ppapi/c/pp_errors.h"
-#include "ppapi/c/ppb_file_io.h"
-#include "ppapi/host/ppapi_host.h"
-#include "ppapi/shared_impl/file_type_conversion.h"
-#include "ppapi/shared_impl/time_conversion.h"
-#include "ppapi/shared_impl/var.h"
-#include "ppapi/thunk/enter.h"
-#include "ppapi/thunk/ppb_file_system_api.h"
-#include "url/gurl.h"
-#include "webkit/common/fileapi/directory_entry.h"
-#include "webkit/common/fileapi/file_system_util.h"
-
-using ppapi::HostResource;
-using ppapi::PPB_FileRef_CreateInfo;
-using ppapi::PPTimeToTime;
-using ppapi::StringVar;
-using ppapi::TrackedCallback;
-using ppapi::thunk::EnterResourceNoLock;
-using ppapi::thunk::PPB_FileRef_API;
-using ppapi::thunk::PPB_FileSystem_API;
-
-namespace content {
-
-namespace {
-
-bool IsValidLocalPath(const std::string& path) {
-  // The path must start with '/'
-  if (path.empty() || path[0] != '/')
-    return false;
-
-  // The path must contain valid UTF-8 characters.
-  if (!IsStringUTF8(path))
-    return false;
-
-#if defined(OS_WIN)
-  base::FilePath::StringType path_win(path.begin(), path.end());
-  base::FilePath file_path(path_win);
-#else
-  base::FilePath file_path(path);
-#endif
-  if (file_path.ReferencesParent())
-    return false;
-
-  return true;
-}
-
-void TrimTrailingSlash(std::string* path) {
-  // If this path ends with a slash, then normalize it away unless path is the
-  // root path.
-  if (path->size() > 1 && path->at(path->size() - 1) == '/')
-    path->erase(path->size() - 1, 1);
-}
-
-std::string GetNameForExternalFilePath(const base::FilePath& in_path) {
-  const base::FilePath::StringType& path = in_path.value();
-  size_t pos = path.rfind(base::FilePath::kSeparators[0]);
-  CHECK(pos != base::FilePath::StringType::npos);
-#if defined(OS_WIN)
-  return WideToUTF8(path.substr(pos + 1));
-#elif defined(OS_POSIX)
-  return path.substr(pos + 1);
-#else
-#error "Unsupported platform."
-#endif
-}
-
-std::string GetNameForVirtualFilePath(const std::string& path) {
-  if (path.size() == 1 && path[0] == '/')
-    return path;
-
-  // There should always be a leading slash at least!
-  size_t pos = path.rfind('/');
-  CHECK(pos != std::string::npos);
-  return path.substr(pos + 1);
-}
-
-void IgnoreCloseCallback(base::PlatformFileError error_code) {
-}
-
-void PlatformFileInfoToPPFileInfo(
-    const base::PlatformFileInfo& file_info,
-    PP_FileSystemType file_system_type,
-    PP_FileInfo* info) {
-  DCHECK(info);
-  ::ppapi::PlatformFileInfoToPepperFileInfo(file_info, file_system_type, info);
-}
-
-void GetFileInfoCallback(
-    scoped_refptr<base::TaskRunner> task_runner,
-    base::PlatformFile file,
-    linked_ptr<PP_FileInfo> info,
-    scoped_refptr<TrackedCallback> callback,
-    base::PlatformFileError error_code,
-    const base::PlatformFileInfo& file_info) {
-  base::FileUtilProxy::Close(
-      task_runner.get(), file, base::Bind(&IgnoreCloseCallback));
-
-  if (!TrackedCallback::IsPending(callback))
-    return;
-
-  int32_t pp_error = ::ppapi::PlatformFileErrorToPepperError(error_code);
-  if (pp_error != PP_OK) {
-    callback->Run(pp_error);
-    return;
-  }
-
-  PlatformFileInfoToPPFileInfo(
-      file_info, PP_FILESYSTEMTYPE_EXTERNAL, info.get());
-
-  callback->Run(PP_OK);
-}
-
-void QueryCallback(scoped_refptr<base::TaskRunner> task_runner,
-                   linked_ptr<PP_FileInfo> info,
-                   scoped_refptr<TrackedCallback> callback,
-                   base::PlatformFileError error_code,
-                   base::PassPlatformFile passed_file) {
-  if (!TrackedCallback::IsPending(callback))
-    return;
-
-  int32_t pp_error = ::ppapi::PlatformFileErrorToPepperError(error_code);
-  if (pp_error != PP_OK) {
-    callback->Run(pp_error);
-    return;
-  }
-  base::PlatformFile file = passed_file.ReleaseValue();
-
-  if (!base::FileUtilProxy::GetFileInfoFromPlatformFile(
-          task_runner.get(),
-          file,
-          base::Bind(
-              &GetFileInfoCallback, task_runner, file, info, callback))) {
-    base::FileUtilProxy::Close(
-        task_runner.get(), file, base::Bind(&IgnoreCloseCallback));
-    callback->Run(PP_ERROR_FAILED);
-  }
-}
-
-void DidReadMetadata(
-    scoped_refptr< ::ppapi::TrackedCallback> callback,
-    linked_ptr<PP_FileInfo> info,
-    PP_FileSystemType file_system_type,
-    const base::PlatformFileInfo& file_info) {
-  if (!TrackedCallback::IsPending(callback))
-    return;
-
-  PlatformFileInfoToPPFileInfo(file_info, file_system_type, info.get());
-  callback->Run(PP_OK);
-}
-
-void DidReadDirectory(
-    scoped_refptr< ::ppapi::TrackedCallback> callback,
-    PPB_FileRef_Impl* dir_ref,
-    linked_ptr<std::vector< ::ppapi::PPB_FileRef_CreateInfo> > dir_files,
-    linked_ptr<std::vector<PP_FileType> > dir_file_types,
-    const std::vector<fileapi::DirectoryEntry>& entries,
-    bool has_more) {
-  if (!TrackedCallback::IsPending(callback))
-    return;
-
-  // The current filesystem backend always returns false.
-  DCHECK(!has_more);
-
-  DCHECK(dir_ref);
-  DCHECK(dir_files.get());
-  DCHECK(dir_file_types.get());
-
-  std::string dir_path = dir_ref->GetCreateInfo().path;
-  if (dir_path.empty() || dir_path[dir_path.size() - 1] != '/')
-    dir_path += '/';
-
-  for (size_t i = 0; i < entries.size(); ++i) {
-    const fileapi::DirectoryEntry& entry = entries[i];
-    scoped_refptr<PPB_FileRef_Impl> file_ref(PPB_FileRef_Impl::CreateInternal(
-        dir_ref->pp_instance(),
-        dir_ref->file_system_resource(),
-        dir_path + fileapi::FilePathToString(base::FilePath(entry.name))));
-    dir_files->push_back(file_ref->GetCreateInfo());
-    dir_file_types->push_back(
-        entry.is_directory ? PP_FILETYPE_DIRECTORY : PP_FILETYPE_REGULAR);
-    // Add a ref count on behalf of the plugin side.
-    file_ref->GetReference();
-  }
-  CHECK_EQ(dir_files->size(), dir_file_types->size());
-
-  callback->Run(PP_OK);
-}
-
-void DidFinishFileOperation(
-    scoped_refptr< ::ppapi::TrackedCallback> callback,
-    base::PlatformFileError error_code) {
-  if (callback->completed())
-    return;
-  callback->Run(::ppapi::PlatformFileErrorToPepperError(error_code));
-}
-
-}  // namespace
-
-PPB_FileRef_Impl::PPB_FileRef_Impl(const PPB_FileRef_CreateInfo& info,
-                                   PP_Resource file_system)
-    : PPB_FileRef_Shared(::ppapi::OBJECT_IS_IMPL, info),
-      file_system_(file_system),
-      external_file_system_path_(),
-      routing_id_(MSG_ROUTING_NONE) {
-  if (RenderThreadImpl::current()) {  // NULL in tests.
-    routing_id_ = RenderThreadImpl::current()->GenerateRoutingID();
-    ChildThread::current()->AddRoute(routing_id_, this);
-  }
-}
-
-PPB_FileRef_Impl::PPB_FileRef_Impl(const PPB_FileRef_CreateInfo& info,
-                                   const base::FilePath& external_file_path)
-    : PPB_FileRef_Shared(::ppapi::OBJECT_IS_IMPL, info),
-      file_system_(),
-      external_file_system_path_(external_file_path),
-      routing_id_(MSG_ROUTING_NONE) {
-  if (RenderThreadImpl::current()) {  // NULL in tests.
-    routing_id_ = RenderThreadImpl::current()->GenerateRoutingID();
-    ChildThread::current()->AddRoute(routing_id_, this);
-  }
-}
-
-PPB_FileRef_Impl::~PPB_FileRef_Impl() {
-  if (RenderThreadImpl::current())
-    ChildThread::current()->RemoveRoute(routing_id_);
-}
-
-// static
-PPB_FileRef_Impl* PPB_FileRef_Impl::CreateInternal(PP_Instance instance,
-                                                   PP_Resource pp_file_system,
-                                                   const std::string& path) {
-  PepperFileSystemHost* fs_host = GetFileSystemHostInternal(
-      instance, pp_file_system);
-  if (!fs_host)
-    return 0;
-
-  PP_FileSystemType type = fs_host->GetType();
-  if (type != PP_FILESYSTEMTYPE_LOCALPERSISTENT &&
-      type != PP_FILESYSTEMTYPE_LOCALTEMPORARY &&
-      type != PP_FILESYSTEMTYPE_EXTERNAL &&
-      type != PP_FILESYSTEMTYPE_ISOLATED)
-    return 0;
-
-  PPB_FileRef_CreateInfo info;
-  info.resource = HostResource::MakeInstanceOnly(instance);
-  info.file_system_plugin_resource = pp_file_system;
-  info.file_system_type = type;
-
-  // Validate the path.
-  info.path = path;
-  if (!IsValidLocalPath(info.path))
-    return 0;
-  TrimTrailingSlash(&info.path);
-
-  info.name = GetNameForVirtualFilePath(info.path);
-
-  PPB_FileRef_Impl* file_ref = new PPB_FileRef_Impl(info, pp_file_system);
-
-  RendererPpapiHostImpl* renderer_host =
-      RendererPpapiHostImpl::GetForPPInstance(instance);
-  if (renderer_host && renderer_host->IsRunningInProcess())
-    file_ref->AddFileSystemRefCount();
-  return file_ref;
-}
-
-// static
-PPB_FileRef_Impl* PPB_FileRef_Impl::CreateExternal(
-    PP_Instance instance,
-    const base::FilePath& external_file_path,
-    const std::string& display_name) {
-  PPB_FileRef_CreateInfo info;
-  info.resource = HostResource::MakeInstanceOnly(instance);
-  info.file_system_plugin_resource = 0;
-  info.file_system_type = PP_FILESYSTEMTYPE_EXTERNAL;
-  if (display_name.empty())
-    info.name = GetNameForExternalFilePath(external_file_path);
-  else
-    info.name = display_name;
-
-  return new PPB_FileRef_Impl(info, external_file_path);
-}
-
-PP_Resource PPB_FileRef_Impl::GetParent() {
-  if (GetFileSystemType() == PP_FILESYSTEMTYPE_EXTERNAL)
-    return 0;
-
-  const std::string& virtual_path = GetCreateInfo().path;
-
-  // There should always be a leading slash at least!
-  size_t pos = virtual_path.rfind('/');
-  CHECK(pos != std::string::npos);
-
-  // If the path is "/foo", then we want to include the slash.
-  if (pos == 0)
-    pos++;
-  std::string parent_path = virtual_path.substr(0, pos);
-
-  scoped_refptr<PPB_FileRef_Impl> parent_ref(
-      CreateInternal(pp_instance(), file_system_, parent_path));
-  if (!parent_ref.get())
-    return 0;
-  return parent_ref->GetReference();
-}
-
-int32_t PPB_FileRef_Impl::MakeDirectory(
-    PP_Bool make_ancestors,
-    scoped_refptr<TrackedCallback> callback) {
-  if (!IsValidNonExternalFileSystem())
-    return PP_ERROR_NOACCESS;
-
-  FileSystemDispatcher* file_system_dispatcher =
-      ChildThread::current()->file_system_dispatcher();
-  file_system_dispatcher->CreateDirectory(
-      GetFileSystemURL(), false /* exclusive */, PP_ToBool(make_ancestors),
-      base::Bind(&DidFinishFileOperation, callback));
-  return PP_OK_COMPLETIONPENDING;
-}
-
-int32_t PPB_FileRef_Impl::Touch(PP_Time last_access_time,
-                                PP_Time last_modified_time,
-                                scoped_refptr<TrackedCallback> callback) {
-  if (!IsValidNonExternalFileSystem())
-    return PP_ERROR_NOACCESS;
-
-  FileSystemDispatcher* file_system_dispatcher =
-      ChildThread::current()->file_system_dispatcher();
-  file_system_dispatcher->TouchFile(
-      GetFileSystemURL(),
-      PPTimeToTime(last_access_time),
-      PPTimeToTime(last_modified_time),
-      base::Bind(&DidFinishFileOperation, callback));
-  return PP_OK_COMPLETIONPENDING;
-}
-
-int32_t PPB_FileRef_Impl::Delete(scoped_refptr<TrackedCallback> callback) {
-  if (!IsValidNonExternalFileSystem())
-    return PP_ERROR_NOACCESS;
-
-  FileSystemDispatcher* file_system_dispatcher =
-      ChildThread::current()->file_system_dispatcher();
-  file_system_dispatcher->Remove(
-      GetFileSystemURL(),
-      false /* recursive */,
-      base::Bind(&DidFinishFileOperation, callback));
-  return PP_OK_COMPLETIONPENDING;
-}
-
-int32_t PPB_FileRef_Impl::Rename(PP_Resource new_pp_file_ref,
-                                 scoped_refptr<TrackedCallback> callback) {
-  EnterResourceNoLock<PPB_FileRef_API> enter(new_pp_file_ref, true);
-  if (enter.failed())
-    return PP_ERROR_BADRESOURCE;
-  PPB_FileRef_Impl* new_file_ref =
-      static_cast<PPB_FileRef_Impl*>(enter.object());
-
-  if (!IsValidNonExternalFileSystem() ||
-      file_system_ != new_file_ref->file_system_)
-    return PP_ERROR_NOACCESS;
-
-  // TODO(viettrungluu): Also cancel when the new file ref is destroyed?
-  // http://crbug.com/67624
-  FileSystemDispatcher* file_system_dispatcher =
-      ChildThread::current()->file_system_dispatcher();
-  file_system_dispatcher->Move(
-      GetFileSystemURL(), new_file_ref->GetFileSystemURL(),
-      base::Bind(&DidFinishFileOperation, callback));
-  return PP_OK_COMPLETIONPENDING;
-}
-
-PP_Var PPB_FileRef_Impl::GetAbsolutePath() {
-  if (GetFileSystemType() != PP_FILESYSTEMTYPE_EXTERNAL)
-    return GetPath();
-  if (!external_path_var_.get()) {
-    external_path_var_ =
-        new StringVar(external_file_system_path_.AsUTF8Unsafe());
-  }
-  return external_path_var_->GetPPVar();
-}
-
-base::FilePath PPB_FileRef_Impl::GetSystemPath() const {
-  if (GetFileSystemType() != PP_FILESYSTEMTYPE_EXTERNAL) {
-    NOTREACHED();
-    return base::FilePath();
-  }
-  return external_file_system_path_;
-}
-
-GURL PPB_FileRef_Impl::GetFileSystemURL() const {
-  if (GetFileSystemType() != PP_FILESYSTEMTYPE_LOCALPERSISTENT &&
-      GetFileSystemType() != PP_FILESYSTEMTYPE_LOCALTEMPORARY &&
-      GetFileSystemType() != PP_FILESYSTEMTYPE_EXTERNAL &&
-      GetFileSystemType() != PP_FILESYSTEMTYPE_ISOLATED) {
-    NOTREACHED();
-    return GURL();
-  }
-
-  const std::string& virtual_path = GetCreateInfo().path;
-  CHECK(!virtual_path.empty());  // Should always be at least "/".
-
-  // Since |virtual_path_| starts with a '/', it looks like an absolute path.
-  // We need to trim off the '/' before calling Resolve, as FileSystem URLs
-  // start with a storage type identifier that looks like a path segment.
-
-  PepperFileSystemHost* host = GetFileSystemHost();
-  if (!host)
-    return GURL();
-
-  return GURL(host->GetRootUrl()).Resolve(net::EscapePath(
-      virtual_path.substr(1)));
-}
-
-bool PPB_FileRef_Impl::OnMessageReceived(const IPC::Message& msg) {
-  bool handled = true;
-  IPC_BEGIN_MESSAGE_MAP(PPB_FileRef_Impl, msg)
-    IPC_MESSAGE_HANDLER(ViewMsg_AsyncOpenPepperFile_ACK, OnAsyncFileOpened)
-    IPC_MESSAGE_UNHANDLED(handled = false)
-  IPC_END_MESSAGE_MAP()
-  return handled;
-}
-
-void PPB_FileRef_Impl::OnAsyncFileOpened(
-    base::PlatformFileError error_code,
-    IPC::PlatformFileForTransit file_for_transit,
-    int message_id) {
-  AsyncOpenFileCallback* callback =
-      pending_async_open_files_.Lookup(message_id);
-  DCHECK(callback);
-  pending_async_open_files_.Remove(message_id);
-
-  base::PlatformFile file =
-      IPC::PlatformFileForTransitToPlatformFile(file_for_transit);
-  callback->Run(error_code, base::PassPlatformFile(&file));
-  // Make sure we won't leak file handle if the requester has died.
-  if (file != base::kInvalidPlatformFileValue) {
-    base::FileUtilProxy::Close(
-        RenderThreadImpl::current()->GetFileThreadMessageLoopProxy().get(),
-        file,
-        base::FileUtilProxy::StatusCallback());
-  }
-  delete callback;
-}
-
-bool PPB_FileRef_Impl::IsValidNonExternalFileSystem() const {
-  PepperFileSystemHost* host = GetFileSystemHost();
-  return HasValidFileSystem() && host &&
-      host->GetType() != PP_FILESYSTEMTYPE_EXTERNAL;
-}
-
-bool PPB_FileRef_Impl::HasValidFileSystem() const {
-  PepperFileSystemHost* host = GetFileSystemHost();
-  return host && host->IsOpened();
-}
-
-int32_t PPB_FileRef_Impl::Query(PP_FileInfo* info,
-                                scoped_refptr<TrackedCallback> callback) {
-  NOTREACHED();
-  return PP_ERROR_FAILED;
-}
-
-int32_t PPB_FileRef_Impl::QueryInHost(
-    linked_ptr<PP_FileInfo> info,
-    scoped_refptr<TrackedCallback> callback) {
-  if (!file_system_) {
-    // External file system
-    // We have to do something totally different for external file systems.
-
-    // TODO(teravest): Use the SequencedWorkerPool instead.
-    scoped_refptr<base::TaskRunner> task_runner =
-        RenderThreadImpl::current()->GetFileThreadMessageLoopProxy();
-
-    int message_id = pending_async_open_files_.Add(new AsyncOpenFileCallback(
-        base::Bind(&QueryCallback, task_runner, info, callback)));
-    RenderThreadImpl::current()->Send(new ViewHostMsg_AsyncOpenPepperFile(
-        routing_id_,
-        GetSystemPath(),
-        PP_FILEOPENFLAG_READ,
-        message_id));
-  } else {
-    // Non-external file system
-    if (!HasValidFileSystem())
-      return PP_ERROR_NOACCESS;
-
-    PP_FileSystemType file_system_type = GetFileSystemHost()->GetType();
-    FileSystemDispatcher* file_system_dispatcher =
-        ChildThread::current()->file_system_dispatcher();
-    file_system_dispatcher->ReadMetadata(
-        GetFileSystemURL(),
-        base::Bind(&DidReadMetadata, callback, info, file_system_type),
-        base::Bind(&DidFinishFileOperation, callback));
-  }
-  return PP_OK_COMPLETIONPENDING;
-}
-
-int32_t PPB_FileRef_Impl::ReadDirectoryEntries(
-    const PP_ArrayOutput& output,
-    scoped_refptr<TrackedCallback> callback) {
-  NOTREACHED();
-  return PP_ERROR_FAILED;
-}
-
-int32_t PPB_FileRef_Impl::ReadDirectoryEntriesInHost(
-    linked_ptr<std::vector< ::ppapi::PPB_FileRef_CreateInfo> > files,
-    linked_ptr<std::vector<PP_FileType> > file_types,
-    scoped_refptr<TrackedCallback> callback) {
-  if (!IsValidNonExternalFileSystem())
-    return PP_ERROR_NOACCESS;
-
-  // TODO(yzshen): Passing base::Unretained(this) to the callback could
-  // be dangerous.
-  FileSystemDispatcher* file_system_dispatcher =
-      ChildThread::current()->file_system_dispatcher();
-  file_system_dispatcher->ReadDirectory(
-      GetFileSystemURL(),
-      base::Bind(&DidReadDirectory,
-                 callback, base::Unretained(this), files, file_types),
-      base::Bind(&DidFinishFileOperation, callback));
-  return PP_OK_COMPLETIONPENDING;
-}
-
-PepperFileSystemHost* PPB_FileRef_Impl::GetFileSystemHost() const {
-  return GetFileSystemHostInternal(pp_instance(), file_system_);
-}
-
-PepperFileSystemHost* PPB_FileRef_Impl::GetFileSystemHostInternal(
-    PP_Instance instance, PP_Resource resource) {
-  const ppapi::host::PpapiHost* ppapi_host =
-      RendererPpapiHost::GetForPPInstance(instance)->GetPpapiHost();
-  if (!resource || !ppapi_host)
-    return NULL;
-  ppapi::host::ResourceHost* resource_host =
-      ppapi_host->GetResourceHost(resource);
-  if (resource_host && resource_host->IsFileSystemHost())
-    return static_cast<PepperFileSystemHost*>(resource_host);
-  return NULL;
-}
-
-}  // namespace content
diff --git a/content/renderer/pepper/ppb_file_ref_impl.h b/content/renderer/pepper/ppb_file_ref_impl.h
deleted file mode 100644
index 2dde933..0000000
--- a/content/renderer/pepper/ppb_file_ref_impl.h
+++ /dev/null
@@ -1,155 +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_RENDERER_PEPPER_PPB_FILE_REF_IMPL_H_
-#define CONTENT_RENDERER_PEPPER_PPB_FILE_REF_IMPL_H_
-
-#include <string>
-#include <vector>
-
-#include "base/callback_forward.h"
-#include "base/files/file_path.h"
-#include "base/id_map.h"
-#include "base/memory/linked_ptr.h"
-#include "base/platform_file.h"
-#include "ipc/ipc_listener.h"
-#include "ipc/ipc_platform_file.h"
-#include "ppapi/c/pp_file_info.h"
-#include "ppapi/c/ppb_file_ref.h"
-#include "ppapi/shared_impl/ppb_file_ref_shared.h"
-#include "ppapi/shared_impl/scoped_pp_resource.h"
-#include "ppapi/shared_impl/var.h"
-#include "url/gurl.h"
-
-namespace ppapi {
-namespace host {
-class ResourceHost;
-}
-}
-
-namespace content {
-
-using ::ppapi::StringVar;
-
-class PepperFileSystemHost;
-
-class PPB_FileRef_Impl : public ::ppapi::PPB_FileRef_Shared,
-                         public IPC::Listener {
- public:
-  PPB_FileRef_Impl(const ::ppapi::PPB_FileRef_CreateInfo& info,
-                   PP_Resource file_system);
-  PPB_FileRef_Impl(const ::ppapi::PPB_FileRef_CreateInfo& info,
-                   const base::FilePath& external_file_path);
-
-  // The returned object will have a refcount of 0 (just like "new").
-  static PPB_FileRef_Impl* CreateInternal(PP_Instance instance,
-                                          PP_Resource pp_file_system,
-                                          const std::string& path);
-
-  // The returned object will have a refcount of 0 (just like "new").
-  static PPB_FileRef_Impl* CreateExternal(
-      PP_Instance instance,
-      const base::FilePath& external_file_path,
-      const std::string& display_name);
-
-  // PPB_FileRef_API implementation (not provided by PPB_FileRef_Shared).
-  virtual PP_Resource GetParent() OVERRIDE;
-  virtual int32_t MakeDirectory(
-      PP_Bool make_ancestors,
-      scoped_refptr< ::ppapi::TrackedCallback> callback) OVERRIDE;
-  virtual int32_t Touch(
-      PP_Time last_access_time,
-      PP_Time last_modified_time,
-      scoped_refptr< ::ppapi::TrackedCallback> callback) OVERRIDE;
-  virtual int32_t Delete(
-      scoped_refptr< ::ppapi::TrackedCallback> callback) OVERRIDE;
-  virtual int32_t Rename(
-      PP_Resource new_file_ref,
-      scoped_refptr< ::ppapi::TrackedCallback> callback) OVERRIDE;
-  virtual int32_t Query(
-      PP_FileInfo* info,
-      scoped_refptr< ::ppapi::TrackedCallback> callback) OVERRIDE;
-  virtual int32_t ReadDirectoryEntries(
-      const PP_ArrayOutput& output,
-      scoped_refptr< ::ppapi::TrackedCallback> callback) OVERRIDE;
-  virtual int32_t QueryInHost(
-      linked_ptr<PP_FileInfo> info,
-      scoped_refptr< ::ppapi::TrackedCallback> callback) OVERRIDE;
-  virtual int32_t ReadDirectoryEntriesInHost(
-      linked_ptr<std::vector< ::ppapi::PPB_FileRef_CreateInfo> > files,
-      linked_ptr<std::vector<PP_FileType> > file_types,
-      scoped_refptr< ::ppapi::TrackedCallback> callback) OVERRIDE;
-  virtual PP_Var GetAbsolutePath() OVERRIDE;
-
-  PP_Resource file_system_resource() const { return file_system_; }
-
-  // Returns the system path corresponding to this file. Valid only for
-  // external filesystems.
-  base::FilePath GetSystemPath() const;
-
-  // Returns the FileSystem API URL corresponding to this file.
-  GURL GetFileSystemURL() const;
-
-  // Checks if file ref has file system instance and if the instance is opened.
-  bool HasValidFileSystem() const;
-
-  void AddFileSystemRefCount() {
-    file_system_ref_ = file_system_;
-  }
-
- private:
-  virtual ~PPB_FileRef_Impl();
-
-  // IPC::Listener implementation.
-  virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
-
-  void OnAsyncFileOpened(
-      base::PlatformFileError error_code,
-      IPC::PlatformFileForTransit file_for_transit,
-      int message_id);
-
-  // Many mutation functions are allow only to non-external filesystems, This
-  // function returns true if the filesystem is opened and isn't external as an
-  // access check for these functions.
-  bool IsValidNonExternalFileSystem() const;
-
-  PepperFileSystemHost* GetFileSystemHost() const;
-  static PepperFileSystemHost* GetFileSystemHostInternal(
-      PP_Instance instance, PP_Resource resource);
-
-  // 0 for external filesystems.  This is a plugin side resource that we don't
-  // hold a reference here, so file_system_ could be destroyed earlier than
-  // this object.  Right now we checked the existance in plugin delegate before
-  // use.  But it's better to hold a reference once we migrate FileRef to the
-  // new design.
-  PP_Resource file_system_;
-
-  // Holds a reference of FileSystem when running in process.  See
-  // PPB_FileRef_Proxy for corresponding code for out-of-process mode.  Note
-  // that this ScopedPPResource is only expected to be used when running in
-  // process (since PPB_FileRef_Proxy takes care of out-of-process case).
-  // Also note that this workaround will be no longer needed after FileRef
-  // refactoring.
-  ::ppapi::ScopedPPResource file_system_ref_;
-
-  // Used only for external filesystems.
-  base::FilePath external_file_system_path_;
-
-  // Lazily initialized var created from the external path. This is so we can
-  // return the identical string object every time it is requested.
-  scoped_refptr<StringVar> external_path_var_;
-
-  int routing_id_;
-
-  typedef base::Callback<void (base::PlatformFileError, base::PassPlatformFile)>
-      AsyncOpenFileCallback;
-
-  IDMap<AsyncOpenFileCallback> pending_async_open_files_;
-
-  DISALLOW_COPY_AND_ASSIGN(PPB_FileRef_Impl);
-};
-
-}  // namespace content
-
-#endif  // CONTENT_RENDERER_PEPPER_PPB_FILE_REF_IMPL_H_
diff --git a/content/renderer/pepper/ppb_flash_message_loop_impl.cc b/content/renderer/pepper/ppb_flash_message_loop_impl.cc
index c13ecb8..ff2abc4 100644
--- a/content/renderer/pepper/ppb_flash_message_loop_impl.cc
+++ b/content/renderer/pepper/ppb_flash_message_loop_impl.cc
@@ -43,7 +43,7 @@
 };
 
 PPB_Flash_MessageLoop_Impl::PPB_Flash_MessageLoop_Impl(PP_Instance instance)
-    : Resource(::ppapi::OBJECT_IS_IMPL, instance),
+    : Resource(ppapi::OBJECT_IS_IMPL, instance),
       state_(new State()) {
 }
 
diff --git a/content/renderer/pepper/ppb_flash_message_loop_impl.h b/content/renderer/pepper/ppb_flash_message_loop_impl.h
index 4bd303d..981a7da 100644
--- a/content/renderer/pepper/ppb_flash_message_loop_impl.h
+++ b/content/renderer/pepper/ppb_flash_message_loop_impl.h
@@ -14,13 +14,13 @@
 namespace content {
 
 class PPB_Flash_MessageLoop_Impl
-    : public ::ppapi::Resource,
-      public ::ppapi::thunk::PPB_Flash_MessageLoop_API {
+    : public ppapi::Resource,
+      public ppapi::thunk::PPB_Flash_MessageLoop_API {
  public:
   static PP_Resource Create(PP_Instance instance);
 
   // Resource.
-  virtual ::ppapi::thunk::PPB_Flash_MessageLoop_API*
+  virtual ppapi::thunk::PPB_Flash_MessageLoop_API*
       AsPPB_Flash_MessageLoop_API() OVERRIDE;
 
   // PPB_Flash_MessageLoop_API implementation.
diff --git a/content/renderer/pepper/ppb_gpu_blacklist_private_impl.cc b/content/renderer/pepper/ppb_gpu_blacklist_private_impl.cc
index 7649cae..8db33bd 100644
--- a/content/renderer/pepper/ppb_gpu_blacklist_private_impl.cc
+++ b/content/renderer/pepper/ppb_gpu_blacklist_private_impl.cc
@@ -6,7 +6,7 @@
 
 #include "base/command_line.h"
 #include "base/logging.h"
-#include "webkit/plugins/plugin_switches.h"
+#include "content/public/common/content_switches.h"
 
 // todo(nfullagar): Remove this private interface when the SRPC proxy is
 // permanently disabled.
diff --git a/content/renderer/pepper/ppb_graphics_3d_impl.cc b/content/renderer/pepper/ppb_graphics_3d_impl.cc
index 6587781..b48d68a 100644
--- a/content/renderer/pepper/ppb_graphics_3d_impl.cc
+++ b/content/renderer/pepper/ppb_graphics_3d_impl.cc
@@ -8,6 +8,7 @@
 #include "base/command_line.h"
 #include "base/message_loop/message_loop.h"
 #include "base/strings/utf_string_conversions.h"
+#include "content/public/common/content_switches.h"
 #include "content/renderer/pepper/host_globals.h"
 #include "content/renderer/pepper/pepper_platform_context_3d.h"
 #include "content/renderer/pepper/pepper_plugin_instance_impl.h"
@@ -23,7 +24,6 @@
 #include "third_party/WebKit/public/web/WebFrame.h"
 #include "third_party/WebKit/public/web/WebPluginContainer.h"
 #include "webkit/common/webpreferences.h"
-#include "webkit/plugins/plugin_switches.h"
 
 using ppapi::thunk::EnterResourceNoLock;
 using ppapi::thunk::PPB_Graphics3D_API;
@@ -72,8 +72,7 @@
 PP_Bool PPB_Graphics3D_Impl::IsGpuBlacklisted() {
   CommandLine* command_line = CommandLine::ForCurrentProcess();
   if (command_line)
-    return PP_FromBool(
-        command_line->HasSwitch(switches::kDisablePepper3d));
+    return PP_FromBool(command_line->HasSwitch(switches::kDisablePepper3d));
   return PP_TRUE;
 }
 
diff --git a/content/renderer/pepper/ppb_graphics_3d_impl.h b/content/renderer/pepper/ppb_graphics_3d_impl.h
index e00695a..3e1c797 100644
--- a/content/renderer/pepper/ppb_graphics_3d_impl.h
+++ b/content/renderer/pepper/ppb_graphics_3d_impl.h
@@ -12,7 +12,7 @@
 namespace content {
 class PlatformContext3D;
 
-class PPB_Graphics3D_Impl : public ::ppapi::PPB_Graphics3D_Shared {
+class PPB_Graphics3D_Impl : public ppapi::PPB_Graphics3D_Shared {
  public:
   static PP_Resource Create(PP_Instance instance,
                             PP_Resource share_context,
diff --git a/content/renderer/pepper/ppb_image_data_impl.cc b/content/renderer/pepper/ppb_image_data_impl.cc
index e79e83c..9ea83d5 100644
--- a/content/renderer/pepper/ppb_image_data_impl.cc
+++ b/content/renderer/pepper/ppb_image_data_impl.cc
@@ -21,13 +21,13 @@
 #include "third_party/skia/include/core/SkColorPriv.h"
 #include "ui/surface/transport_dib.h"
 
-using ::ppapi::thunk::PPB_ImageData_API;
+using ppapi::thunk::PPB_ImageData_API;
 
 namespace content {
 
 PPB_ImageData_Impl::PPB_ImageData_Impl(PP_Instance instance,
                                        PPB_ImageData_Shared::ImageDataType type)
-    : Resource(::ppapi::OBJECT_IS_IMPL, instance),
+    : Resource(ppapi::OBJECT_IS_IMPL, instance),
       format_(PP_IMAGEDATAFORMAT_BGRA_PREMUL),
       width_(0),
       height_(0) {
diff --git a/content/renderer/pepper/ppb_image_data_impl.h b/content/renderer/pepper/ppb_image_data_impl.h
index ee05b5a..a16bbfa 100644
--- a/content/renderer/pepper/ppb_image_data_impl.h
+++ b/content/renderer/pepper/ppb_image_data_impl.h
@@ -25,9 +25,9 @@
 namespace content {
 
 class CONTENT_EXPORT PPB_ImageData_Impl
-    : public ::ppapi::Resource,
-      public ::ppapi::PPB_ImageData_Shared,
-      public NON_EXPORTED_BASE(::ppapi::thunk::PPB_ImageData_API) {
+    : public ppapi::Resource,
+      public ppapi::PPB_ImageData_Shared,
+      public NON_EXPORTED_BASE(ppapi::thunk::PPB_ImageData_API) {
  public:
   // We delegate most of our implementation to a back-end class that either uses
   // a PlatformCanvas (for most trusted stuff) or bare shared memory (for use by
@@ -76,7 +76,7 @@
   TransportDIB* GetTransportDIB() const;
 
   // Resource override.
-  virtual ::ppapi::thunk::PPB_ImageData_API* AsPPB_ImageData_API() OVERRIDE;
+  virtual ppapi::thunk::PPB_ImageData_API* AsPPB_ImageData_API() OVERRIDE;
 
   // PPB_ImageData_API implementation.
   virtual PP_Bool Describe(PP_ImageDataDesc* desc) OVERRIDE;
diff --git a/content/renderer/pepper/ppb_network_monitor_private_impl.cc b/content/renderer/pepper/ppb_network_monitor_private_impl.cc
index d43c8f0..a616a2c 100644
--- a/content/renderer/pepper/ppb_network_monitor_private_impl.cc
+++ b/content/renderer/pepper/ppb_network_monitor_private_impl.cc
@@ -44,7 +44,7 @@
     PP_Instance instance,
     PPB_NetworkMonitor_Callback callback,
     void* user_data)
-    : Resource(::ppapi::OBJECT_IS_IMPL, instance),
+    : Resource(ppapi::OBJECT_IS_IMPL, instance),
       callback_(callback),
       user_data_(user_data),
       started_(false) {
@@ -66,7 +66,7 @@
   return result->GetReference();
 }
 
-::ppapi::thunk::PPB_NetworkMonitor_Private_API*
+ppapi::thunk::PPB_NetworkMonitor_Private_API*
 PPB_NetworkMonitor_Private_Impl::AsPPB_NetworkMonitor_Private_API() {
   return this;
 }
@@ -78,14 +78,14 @@
 
 void PPB_NetworkMonitor_Private_Impl::OnNetworkListChanged(
     const net::NetworkInterfaceList& list) {
-  ::ppapi::NetworkList list_copy(list.size());
+  ppapi::NetworkList list_copy(list.size());
   for (size_t i = 0; i < list.size(); ++i) {
-    ::ppapi::NetworkInfo& network = list_copy.at(i);
+    ppapi::NetworkInfo& network = list_copy.at(i);
     network.name = list[i].name;
 
     network.addresses.resize(
-        1, ::ppapi::NetAddressPrivateImpl::kInvalidNetAddress);
-    bool result = ::ppapi::NetAddressPrivateImpl::IPEndPointToNetAddress(
+        1, ppapi::NetAddressPrivateImpl::kInvalidNetAddress);
+    bool result = ppapi::NetAddressPrivateImpl::IPEndPointToNetAddress(
         list[i].address, 0, &(network.addresses[0]));
     DCHECK(result);
 
@@ -97,11 +97,11 @@
     network.display_name = list[i].name;
     network.mtu = 0;
   }
-  scoped_refptr< ::ppapi::NetworkListStorage> list_storage(
-      new ::ppapi::NetworkListStorage(list_copy));
+  scoped_refptr<ppapi::NetworkListStorage> list_storage(
+      new ppapi::NetworkListStorage(list_copy));
   PP_Resource list_resource =
-      ::ppapi::PPB_NetworkList_Private_Shared::Create(
-          ::ppapi::OBJECT_IS_IMPL, pp_instance(), list_storage);
+      ppapi::PPB_NetworkList_Private_Shared::Create(
+          ppapi::OBJECT_IS_IMPL, pp_instance(), list_storage);
   callback_(user_data_, list_resource);
 }
 
diff --git a/content/renderer/pepper/ppb_network_monitor_private_impl.h b/content/renderer/pepper/ppb_network_monitor_private_impl.h
index 678ee40..317e145 100644
--- a/content/renderer/pepper/ppb_network_monitor_private_impl.h
+++ b/content/renderer/pepper/ppb_network_monitor_private_impl.h
@@ -15,15 +15,15 @@
 namespace content {
 
 class PPB_NetworkMonitor_Private_Impl
-    : public ::ppapi::Resource,
-      public ::ppapi::thunk::PPB_NetworkMonitor_Private_API,
+    : public ppapi::Resource,
+      public ppapi::thunk::PPB_NetworkMonitor_Private_API,
       public content::NetworkListObserver {
  public:
   static PP_Resource Create(PP_Instance instance,
                             PPB_NetworkMonitor_Callback callback,
                             void* user_data);
 
-  virtual ::ppapi::thunk::PPB_NetworkMonitor_Private_API*
+  virtual ppapi::thunk::PPB_NetworkMonitor_Private_API*
       AsPPB_NetworkMonitor_Private_API() OVERRIDE;
 
   // NetworkListObserver interface.
diff --git a/content/renderer/pepper/ppb_proxy_impl.cc b/content/renderer/pepper/ppb_proxy_impl.cc
index a9d99f3..cdae3ac 100644
--- a/content/renderer/pepper/ppb_proxy_impl.cc
+++ b/content/renderer/pepper/ppb_proxy_impl.cc
@@ -25,7 +25,7 @@
 }
 
 PP_Instance GetInstanceForResource(PP_Resource resource) {
-  ::ppapi::Resource* obj =
+  ppapi::Resource* obj =
       PpapiGlobals::Get()->GetResourceTracker()->GetResource(resource);
   if (!obj)
     return 0;
diff --git a/content/renderer/pepper/ppb_scrollbar_impl.cc b/content/renderer/pepper/ppb_scrollbar_impl.cc
index e3da676..fb01c59 100644
--- a/content/renderer/pepper/ppb_scrollbar_impl.cc
+++ b/content/renderer/pepper/ppb_scrollbar_impl.cc
@@ -151,7 +151,7 @@
 }
 
 PP_Bool PPB_Scrollbar_Impl::HandleEventInternal(
-    const ::ppapi::InputEventData& data) {
+    const ppapi::InputEventData& data) {
   scoped_ptr<WebInputEvent> web_input_event(CreateWebInputEvent(data));
   if (!web_input_event.get() || !scrollbar_)
     return PP_FALSE;
diff --git a/content/renderer/pepper/ppb_scrollbar_impl.h b/content/renderer/pepper/ppb_scrollbar_impl.h
index 559c303..eb7906b 100644
--- a/content/renderer/pepper/ppb_scrollbar_impl.h
+++ b/content/renderer/pepper/ppb_scrollbar_impl.h
@@ -19,7 +19,7 @@
 namespace content {
 
 class PPB_Scrollbar_Impl : public PPB_Widget_Impl,
-                           public ::ppapi::thunk::PPB_Scrollbar_API,
+                           public ppapi::thunk::PPB_Scrollbar_API,
                            public WebKit::WebPluginScrollbarClient {
  public:
   static PP_Resource Create(PP_Instance instance, bool vertical);
@@ -47,7 +47,7 @@
   virtual PP_Bool PaintInternal(const gfx::Rect& rect,
                                 PPB_ImageData_Impl* image) OVERRIDE;
   virtual PP_Bool HandleEventInternal(
-      const ::ppapi::InputEventData& data) OVERRIDE;
+      const ppapi::InputEventData& data) OVERRIDE;
   virtual void SetLocationInternal(const PP_Rect* location) OVERRIDE;
 
   // WebKit::WebPluginScrollbarClient implementation.
diff --git a/content/renderer/pepper/ppb_tcp_socket_private_impl.cc b/content/renderer/pepper/ppb_tcp_socket_private_impl.cc
index 13f36a2..2b47e64 100644
--- a/content/renderer/pepper/ppb_tcp_socket_private_impl.cc
+++ b/content/renderer/pepper/ppb_tcp_socket_private_impl.cc
@@ -17,7 +17,7 @@
     PP_Instance instance,
     uint32 socket_id,
     int routing_id)
-    : ::ppapi::TCPSocketPrivateImpl(instance, socket_id),
+    : ppapi::TCPSocketPrivateImpl(instance, socket_id),
       routing_id_(routing_id) {
   ChildThread::current()->AddRoute(routing_id, this);
 }
@@ -79,7 +79,7 @@
 
 void PPB_TCPSocket_Private_Impl::SendSetOption(
     PP_TCPSocket_Option name,
-    const ::ppapi::SocketOptionData& value) {
+    const ppapi::SocketOptionData& value) {
   RenderThreadImpl::current()->Send(
       new PpapiHostMsg_PPBTCPSocket_SetOption(socket_id_, name, value));
 }
diff --git a/content/renderer/pepper/ppb_tcp_socket_private_impl.h b/content/renderer/pepper/ppb_tcp_socket_private_impl.h
index ae53a6e..2ac6981 100644
--- a/content/renderer/pepper/ppb_tcp_socket_private_impl.h
+++ b/content/renderer/pepper/ppb_tcp_socket_private_impl.h
@@ -13,7 +13,7 @@
 
 namespace content {
 
-class PPB_TCPSocket_Private_Impl : public ::ppapi::TCPSocketPrivateImpl,
+class PPB_TCPSocket_Private_Impl : public ppapi::TCPSocketPrivateImpl,
                                    public IPC::Listener {
  public:
   static PP_Resource CreateResource(PP_Instance instance);
@@ -30,7 +30,7 @@
   virtual void SendWrite(const std::string& buffer) OVERRIDE;
   virtual void SendDisconnect() OVERRIDE;
   virtual void SendSetOption(PP_TCPSocket_Option name,
-                             const ::ppapi::SocketOptionData& value) OVERRIDE;
+                             const ppapi::SocketOptionData& value) OVERRIDE;
 
  private:
   PPB_TCPSocket_Private_Impl(PP_Instance instance,
diff --git a/content/renderer/pepper/ppb_var_deprecated_impl.cc b/content/renderer/pepper/ppb_var_deprecated_impl.cc
index c5353cf..23472fa 100644
--- a/content/renderer/pepper/ppb_var_deprecated_impl.cc
+++ b/content/renderer/pepper/ppb_var_deprecated_impl.cc
@@ -412,10 +412,10 @@
 // static
 const PPB_Var_Deprecated* PPB_Var_Deprecated_Impl::GetVarDeprecatedInterface() {
   static const PPB_Var_Deprecated var_deprecated_interface = {
-    ::ppapi::PPB_Var_Shared::GetVarInterface1_0()->AddRef,
-    ::ppapi::PPB_Var_Shared::GetVarInterface1_0()->Release,
-    ::ppapi::PPB_Var_Shared::GetVarInterface1_0()->VarFromUtf8,
-    ::ppapi::PPB_Var_Shared::GetVarInterface1_0()->VarToUtf8,
+    ppapi::PPB_Var_Shared::GetVarInterface1_0()->AddRef,
+    ppapi::PPB_Var_Shared::GetVarInterface1_0()->Release,
+    ppapi::PPB_Var_Shared::GetVarInterface1_0()->VarFromUtf8,
+    ppapi::PPB_Var_Shared::GetVarInterface1_0()->VarToUtf8,
     &HasPropertyDeprecated,
     &HasMethodDeprecated,
     &GetProperty,
diff --git a/content/renderer/pepper/ppb_video_decoder_impl.h b/content/renderer/pepper/ppb_video_decoder_impl.h
index f716ecd..d9b195b 100644
--- a/content/renderer/pepper/ppb_video_decoder_impl.h
+++ b/content/renderer/pepper/ppb_video_decoder_impl.h
@@ -29,7 +29,7 @@
 class PlatformContext3D;
 class PlatformVideoDecoder;
 
-class PPB_VideoDecoder_Impl : public ::ppapi::PPB_VideoDecoder_Shared,
+class PPB_VideoDecoder_Impl : public ppapi::PPB_VideoDecoder_Shared,
                               public media::VideoDecodeAccelerator::Client {
  public:
   // See PPB_VideoDecoder_Dev::Create.  Returns 0 on failure to create &
@@ -41,14 +41,14 @@
   // PPB_VideoDecoder_API implementation.
   virtual int32_t Decode(
       const PP_VideoBitstreamBuffer_Dev* bitstream_buffer,
-      scoped_refptr< ::ppapi::TrackedCallback> callback) OVERRIDE;
+      scoped_refptr<ppapi::TrackedCallback> callback) OVERRIDE;
   virtual void AssignPictureBuffers(
       uint32_t no_of_buffers, const PP_PictureBuffer_Dev* buffers) OVERRIDE;
   virtual void ReusePictureBuffer(int32_t picture_buffer_id) OVERRIDE;
   virtual int32_t Flush(
-      scoped_refptr< ::ppapi::TrackedCallback> callback) OVERRIDE;
+      scoped_refptr<ppapi::TrackedCallback> callback) OVERRIDE;
   virtual int32_t Reset(
-      scoped_refptr< ::ppapi::TrackedCallback> callback) OVERRIDE;
+      scoped_refptr<ppapi::TrackedCallback> callback) OVERRIDE;
   virtual void Destroy() OVERRIDE;
 
   // media::VideoDecodeAccelerator::Client implementation.
diff --git a/content/renderer/pepper/ppb_widget_impl.cc b/content/renderer/pepper/ppb_widget_impl.cc
index eaeae43..494eec7 100644
--- a/content/renderer/pepper/ppb_widget_impl.cc
+++ b/content/renderer/pepper/ppb_widget_impl.cc
@@ -21,7 +21,7 @@
 namespace content {
 
 PPB_Widget_Impl::PPB_Widget_Impl(PP_Instance instance)
-    : Resource(::ppapi::OBJECT_IS_IMPL, instance),
+    : Resource(ppapi::OBJECT_IS_IMPL, instance),
       scale_(1.0f) {
   memset(&location_, 0, sizeof(location_));
 }
diff --git a/content/renderer/pepper/ppb_widget_impl.h b/content/renderer/pepper/ppb_widget_impl.h
index 5a5ef0d..66139ca 100644
--- a/content/renderer/pepper/ppb_widget_impl.h
+++ b/content/renderer/pepper/ppb_widget_impl.h
@@ -22,13 +22,13 @@
 
 class PPB_ImageData_Impl;
 
-class PPB_Widget_Impl : public ::ppapi::Resource,
-                        public ::ppapi::thunk::PPB_Widget_API {
+class PPB_Widget_Impl : public ppapi::Resource,
+                        public ppapi::thunk::PPB_Widget_API {
  public:
   explicit PPB_Widget_Impl(PP_Instance instance);
 
   // Resource overrides.
-  virtual ::ppapi::thunk::PPB_Widget_API* AsPPB_Widget_API() OVERRIDE;
+  virtual ppapi::thunk::PPB_Widget_API* AsPPB_Widget_API() OVERRIDE;
 
   // PPB_WidgetAPI implementation.
   virtual PP_Bool Paint(const PP_Rect* rect, PP_Resource ) OVERRIDE;
@@ -45,7 +45,7 @@
 
   virtual PP_Bool PaintInternal(const gfx::Rect& rect,
                                 PPB_ImageData_Impl* image) = 0;
-  virtual PP_Bool HandleEventInternal(const ::ppapi::InputEventData& data) = 0;
+  virtual PP_Bool HandleEventInternal(const ppapi::InputEventData& data) = 0;
   virtual void SetLocationInternal(const PP_Rect* location) = 0;
 
   PP_Rect location() const { return location_; }
diff --git a/content/renderer/pepper/ppb_x509_certificate_private_impl.cc b/content/renderer/pepper/ppb_x509_certificate_private_impl.cc
index 6c287a3..c580e71 100644
--- a/content/renderer/pepper/ppb_x509_certificate_private_impl.cc
+++ b/content/renderer/pepper/ppb_x509_certificate_private_impl.cc
@@ -11,7 +11,7 @@
 
 PPB_X509Certificate_Private_Impl::PPB_X509Certificate_Private_Impl(
     PP_Instance instance) :
-  PPB_X509Certificate_Private_Shared(::ppapi::OBJECT_IS_IMPL, instance) {
+  PPB_X509Certificate_Private_Shared(ppapi::OBJECT_IS_IMPL, instance) {
 }
 
 // static
@@ -22,7 +22,7 @@
 
 bool PPB_X509Certificate_Private_Impl::ParseDER(
     const std::vector<char>& der,
-    ::ppapi::PPB_X509Certificate_Fields* result) {
+    ppapi::PPB_X509Certificate_Fields* result) {
   bool succeeded = false;
   RenderThreadImpl::current()->Send(
       new PpapiHostMsg_PPBX509Certificate_ParseDER(der, &succeeded, result));
diff --git a/content/renderer/pepper/ppb_x509_certificate_private_impl.h b/content/renderer/pepper/ppb_x509_certificate_private_impl.h
index 76438c9..0f10ec0 100644
--- a/content/renderer/pepper/ppb_x509_certificate_private_impl.h
+++ b/content/renderer/pepper/ppb_x509_certificate_private_impl.h
@@ -17,12 +17,12 @@
 namespace content {
 
 class PPB_X509Certificate_Private_Impl :
-    public ::ppapi::PPB_X509Certificate_Private_Shared {
+    public ppapi::PPB_X509Certificate_Private_Shared {
  public:
   PPB_X509Certificate_Private_Impl(PP_Instance instance);
   static PP_Resource CreateResource(PP_Instance instance);
   virtual bool ParseDER(const std::vector<char>& der,
-                        ::ppapi::PPB_X509Certificate_Fields* result) OVERRIDE;
+                        ppapi::PPB_X509Certificate_Fields* result) OVERRIDE;
 
  private:
   virtual ~PPB_X509Certificate_Private_Impl();
diff --git a/content/renderer/pepper/renderer_ppapi_host_impl.cc b/content/renderer/pepper/renderer_ppapi_host_impl.cc
index cd1d6dd..dd78352 100644
--- a/content/renderer/pepper/renderer_ppapi_host_impl.cc
+++ b/content/renderer/pepper/renderer_ppapi_host_impl.cc
@@ -114,10 +114,10 @@
   return instance->module()->renderer_ppapi_host();
 }
 
-scoped_ptr< ::ppapi::thunk::ResourceCreationAPI>
+scoped_ptr<ppapi::thunk::ResourceCreationAPI>
 RendererPpapiHostImpl::CreateInProcessResourceCreationAPI(
     PepperPluginInstanceImpl* instance) {
-  return scoped_ptr< ::ppapi::thunk::ResourceCreationAPI>(
+  return scoped_ptr<ppapi::thunk::ResourceCreationAPI>(
       new PepperInProcessResourceCreation(this, instance));
 }
 
diff --git a/content/renderer/pepper/renderer_ppapi_host_impl.h b/content/renderer/pepper/renderer_ppapi_host_impl.h
index 4ef47bd..935f38d 100644
--- a/content/renderer/pepper/renderer_ppapi_host_impl.h
+++ b/content/renderer/pepper/renderer_ppapi_host_impl.h
@@ -68,7 +68,7 @@
   // host impl should outlive the returned pointer. Since the resource
   // creation object is associated with the instance, this will generally
   // happen automatically.
-  scoped_ptr< ::ppapi::thunk::ResourceCreationAPI>
+  scoped_ptr<ppapi::thunk::ResourceCreationAPI>
       CreateInProcessResourceCreationAPI(PepperPluginInstanceImpl* instance);
 
   PepperPluginInstanceImpl* GetPluginInstanceImpl(PP_Instance instance) const;
diff --git a/content/renderer/pepper/resource_creation_impl.cc b/content/renderer/pepper/resource_creation_impl.cc
index d2ddd30..cddc891 100644
--- a/content/renderer/pepper/resource_creation_impl.cc
+++ b/content/renderer/pepper/resource_creation_impl.cc
@@ -8,7 +8,6 @@
 #include "content/renderer/pepper/ppb_audio_impl.h"
 #include "content/renderer/pepper/ppb_broker_impl.h"
 #include "content/renderer/pepper/ppb_buffer_impl.h"
-#include "content/renderer/pepper/ppb_file_ref_impl.h"
 #include "content/renderer/pepper/ppb_flash_message_loop_impl.h"
 #include "content/renderer/pepper/ppb_graphics_3d_impl.h"
 #include "content/renderer/pepper/ppb_image_data_impl.h"
@@ -50,8 +49,8 @@
     PP_Instance instance,
     PP_AudioSampleRate sample_rate,
     uint32_t sample_frame_count) {
-  return ::ppapi::PPB_AudioConfig_Shared::Create(
-      ::ppapi::OBJECT_IS_IMPL, instance, sample_rate, sample_frame_count);
+  return ppapi::PPB_AudioConfig_Shared::Create(
+      ppapi::OBJECT_IS_IMPL, instance, sample_rate, sample_frame_count);
 }
 
 PP_Resource ResourceCreationImpl::CreateAudioTrusted(
@@ -72,22 +71,6 @@
   return PPB_Buffer_Impl::Create(instance, size);
 }
 
-PP_Resource ResourceCreationImpl::CreateFileRef(
-    PP_Instance instance,
-    PP_Resource file_system,
-    const char* path) {
-  PPB_FileRef_Impl* res = PPB_FileRef_Impl::CreateInternal(
-      instance, file_system, path);
-  return res ? res->GetReference() : 0;
-}
-
-PP_Resource ResourceCreationImpl::CreateFileRef(
-    const ::ppapi::PPB_FileRef_CreateInfo& serialized) {
-  // When we're in-process, the host resource in the create info *is* the
-  // resource, so we don't need to do anything.
-  return serialized.resource.host_resource();
-}
-
 PP_Resource ResourceCreationImpl::CreateFlashDRM(PP_Instance instance) {
   return 0;  // Not supported in-process.
 }
@@ -138,7 +121,7 @@
     const PP_Size* size,
     PP_Bool init_to_zero) {
   return PPB_ImageData_Impl::Create(instance,
-                                    ::ppapi::PPB_ImageData_Shared::PLATFORM,
+                                    ppapi::PPB_ImageData_Shared::PLATFORM,
                                     format, *size, init_to_zero);
 }
 
@@ -148,7 +131,7 @@
     const PP_Size* size,
     PP_Bool init_to_zero) {
   return PPB_ImageData_Impl::Create(instance,
-                                    ::ppapi::PPB_ImageData_Shared::SIMPLE,
+                                    ppapi::PPB_ImageData_Shared::SIMPLE,
                                     format, *size, init_to_zero);
 }
 
@@ -163,7 +146,7 @@
     uint32_t selection_start,
     uint32_t selection_end) {
   return PPB_InputEvent_Shared::CreateIMEInputEvent(
-      ::ppapi::OBJECT_IS_IMPL, instance, type, time_stamp, text, segment_number,
+      ppapi::OBJECT_IS_IMPL, instance, type, time_stamp, text, segment_number,
       segment_offsets, target_segment, selection_start, selection_end);
 }
 
@@ -181,7 +164,7 @@
     uint32_t key_code,
     struct PP_Var character_text) {
   return PPB_InputEvent_Shared::CreateKeyboardInputEvent(
-      ::ppapi::OBJECT_IS_IMPL, instance, type, time_stamp, modifiers, key_code,
+      ppapi::OBJECT_IS_IMPL, instance, type, time_stamp, modifiers, key_code,
       character_text);
 }
 
@@ -195,7 +178,7 @@
     int32_t click_count,
     const PP_Point* mouse_movement) {
   return PPB_InputEvent_Shared::CreateMouseInputEvent(
-      ::ppapi::OBJECT_IS_IMPL, instance, type, time_stamp, modifiers,
+      ppapi::OBJECT_IS_IMPL, instance, type, time_stamp, modifiers,
       mouse_button, mouse_position, click_count, mouse_movement);
 }
 
@@ -223,7 +206,7 @@
     PP_TimeTicks time_stamp,
     uint32_t modifiers) {
   return PPB_InputEvent_Shared::CreateTouchInputEvent(
-      ::ppapi::OBJECT_IS_IMPL, instance, type, time_stamp, modifiers);
+      ppapi::OBJECT_IS_IMPL, instance, type, time_stamp, modifiers);
 }
 
 PP_Resource ResourceCreationImpl::CreateNetworkMonitor(
@@ -247,7 +230,7 @@
     const PP_Resource elements[],
     uint32_t size) {
   PPB_ResourceArray_Shared* object = new PPB_ResourceArray_Shared(
-      ::ppapi::OBJECT_IS_IMPL, instance, elements, size);
+      ppapi::OBJECT_IS_IMPL, instance, elements, size);
   return object->GetReference();
 }
 
@@ -301,7 +284,7 @@
     const PP_FloatPoint* wheel_ticks,
     PP_Bool scroll_by_page) {
   return PPB_InputEvent_Shared::CreateWheelInputEvent(
-      ::ppapi::OBJECT_IS_IMPL, instance, time_stamp, modifiers,
+      ppapi::OBJECT_IS_IMPL, instance, time_stamp, modifiers,
       wheel_delta, wheel_ticks, scroll_by_page);
 }
 
diff --git a/content/renderer/pepper/resource_creation_impl.h b/content/renderer/pepper/resource_creation_impl.h
index 7d09822..30ddf63 100644
--- a/content/renderer/pepper/resource_creation_impl.h
+++ b/content/renderer/pepper/resource_creation_impl.h
@@ -17,7 +17,7 @@
 // "old-style" resources are handled here. See
 // content/renderer/pepper/pepper_in_process_resource_creation.h for functions
 // that implement "new-style" resources.
-class ResourceCreationImpl : public ::ppapi::thunk::ResourceCreationAPI {
+class ResourceCreationImpl : public ppapi::thunk::ResourceCreationAPI {
  public:
   explicit ResourceCreationImpl(PepperPluginInstanceImpl* instance);
   virtual ~ResourceCreationImpl();
@@ -35,11 +35,6 @@
   virtual PP_Resource CreateBroker(PP_Instance instance) OVERRIDE;
   virtual PP_Resource CreateBuffer(PP_Instance instance,
                                    uint32_t size) OVERRIDE;
-  virtual PP_Resource CreateFileRef(PP_Instance instance,
-                                    PP_Resource file_system,
-                                    const char* path) OVERRIDE;
-  virtual PP_Resource CreateFileRef(
-      const ::ppapi::PPB_FileRef_CreateInfo& serialized) OVERRIDE;
   virtual PP_Resource CreateFlashDRM(PP_Instance instance) OVERRIDE;
   virtual PP_Resource CreateFlashFontFile(
       PP_Instance instance,
diff --git a/content/renderer/pepper/url_request_info_util.cc b/content/renderer/pepper/url_request_info_util.cc
index 9f13fe0..5b3786b 100644
--- a/content/renderer/pepper/url_request_info_util.cc
+++ b/content/renderer/pepper/url_request_info_util.cc
@@ -8,10 +8,13 @@
 #include "base/strings/string_util.h"
 #include "content/common/fileapi/file_system_messages.h"
 #include "content/renderer/pepper/common.h"
+#include "content/renderer/pepper/host_globals.h"
+#include "content/renderer/pepper/pepper_plugin_instance_impl.h"
 #include "content/renderer/pepper/plugin_module.h"
-#include "content/renderer/pepper/ppb_file_ref_impl.h"
 #include "content/renderer/render_thread_impl.h"
 #include "net/http/http_util.h"
+#include "ppapi/proxy/ppapi_messages.h"
+#include "ppapi/shared_impl/file_ref_detailed_info.h"
 #include "ppapi/shared_impl/url_request_info_data.h"
 #include "ppapi/shared_impl/var.h"
 #include "ppapi/thunk/enter.h"
@@ -25,10 +28,9 @@
 #include "url/url_util.h"
 #include "webkit/child/weburlrequest_extradata_impl.h"
 
-using ppapi::URLRequestInfoData;
 using ppapi::Resource;
+using ppapi::URLRequestInfoData;
 using ppapi::thunk::EnterResourceNoLock;
-using ppapi::thunk::PPB_FileRef_API;
 using WebKit::WebData;
 using WebKit::WebHTTPBody;
 using WebKit::WebString;
@@ -43,32 +45,23 @@
 // Appends the file ref given the Resource pointer associated with it to the
 // given HTTP body, returning true on success.
 bool AppendFileRefToBody(
-    Resource* file_ref_resource,
+    const ppapi::FileRefDetailedInfo& file_info,
     int64_t start_offset,
     int64_t number_of_bytes,
     PP_Time expected_last_modified_time,
     WebHTTPBody *http_body) {
-  // Get the underlying file ref impl.
-  if (!file_ref_resource)
-    return false;
-  PPB_FileRef_API* file_ref_api = file_ref_resource->AsPPB_FileRef_API();
-  if (!file_ref_api)
-    return false;
-  const PPB_FileRef_Impl* file_ref =
-      static_cast<PPB_FileRef_Impl*>(file_ref_api);
-
   base::FilePath platform_path;
-  switch (file_ref->GetFileSystemType()) {
+  switch (file_info.file_system_type) {
     case PP_FILESYSTEMTYPE_LOCALTEMPORARY:
     case PP_FILESYSTEMTYPE_LOCALPERSISTENT:
       // TODO(kinuko): remove this sync IPC when we fully support
       // AppendURLRange for FileSystem URL.
       RenderThreadImpl::current()->Send(
           new FileSystemHostMsg_SyncGetPlatformPath(
-              file_ref->GetFileSystemURL(), &platform_path));
+              GURL(file_info.file_system_url_spec), &platform_path));
       break;
     case PP_FILESYSTEMTYPE_EXTERNAL:
-      platform_path = file_ref->GetSystemPath();
+      platform_path = file_info.external_path;
       break;
     default:
       NOTREACHED();
@@ -84,7 +77,7 @@
 // Checks that the request data is valid. Returns false on failure. Note that
 // method and header validation is done by the URL loader when the request is
 // opened, and any access errors are returned asynchronously.
-bool ValidateURLRequestData(const ::ppapi::URLRequestInfoData& data) {
+bool ValidateURLRequestData(const URLRequestInfoData& data) {
   if (data.prefetch_buffer_lower_threshold < 0 ||
       data.prefetch_buffer_upper_threshold < 0 ||
       data.prefetch_buffer_upper_threshold <=
@@ -94,33 +87,16 @@
   return true;
 }
 
-// Ensures that the file_ref members of the given request info data are
-// populated from the resource IDs. Returns true on success.
-bool EnsureFileRefObjectsPopulated(::ppapi::URLRequestInfoData* data) {
-  // Get the Resource objects for any file refs with only host resource (this
-  // is the state of the request as it comes off IPC).
-  for (size_t i = 0; i < data->body.size(); ++i) {
-    URLRequestInfoData::BodyItem& item = data->body[i];
-    if (item.is_file && !item.file_ref.get()) {
-      EnterResourceNoLock<PPB_FileRef_API> enter(
-          item.file_ref_host_resource.host_resource(), false);
-      if (!enter.succeeded())
-        return false;
-      item.file_ref = enter.resource();
-    }
-  }
-  return true;
-}
-
 }  // namespace
 
-bool CreateWebURLRequest(::ppapi::URLRequestInfoData* data,
+bool CreateWebURLRequest(PP_Instance instance,
+                         URLRequestInfoData* data,
                          WebFrame* frame,
                          WebURLRequest* dest) {
   // In the out-of-process case, we've received the URLRequestInfoData
   // from the untrusted plugin and done no validation on it. We need to be
   // sure it's not being malicious by checking everything for consistency.
-  if (!ValidateURLRequestData(*data) || !EnsureFileRefObjectsPopulated(data))
+  if (!ValidateURLRequestData(*data))
     return false;
 
   dest->initialize();
@@ -145,19 +121,44 @@
     }
   }
 
+  // Get file information for FileRefs inside BodyItems.
+  std::vector<PP_Resource> resources;
+  for (size_t i = 0; i < data->body.size(); ++i) {
+    const URLRequestInfoData::BodyItem& item = data->body[i];
+    if (item.is_file)
+      resources.push_back(item.file_ref_pp_resource);
+  }
+  std::vector<ppapi::FileRefDetailedInfo> infos;
+
+  if (!resources.empty()) {
+    PepperPluginInstanceImpl* instance_impl =
+        HostGlobals::Get()->GetInstance(instance);
+    int child_process_id = instance_impl->module()->GetPluginChildId();
+    // The routing id is automatically populated for us when set to 0.
+    RenderThreadImpl::current()->Send(
+        new PpapiHostMsg_FileRef_SyncGetInfoForRenderer(
+            0, child_process_id, resources, &infos));
+    if (infos.size() != resources.size())
+      return false;
+  }
+
   // Append the upload data.
   if (!data->body.empty()) {
     WebHTTPBody http_body;
     http_body.initialize();
+    int file_index = 0;
     for (size_t i = 0; i < data->body.size(); ++i) {
       const URLRequestInfoData::BodyItem& item = data->body[i];
       if (item.is_file) {
-        if (!AppendFileRefToBody(item.file_ref.get(),
+        if (item.file_ref_pp_resource != infos[file_index].resource)
+          return false;
+        if (!AppendFileRefToBody(infos[file_index],
                                  item.start_offset,
                                  item.number_of_bytes,
                                  item.expected_last_modified_time,
                                  &http_body))
           return false;
+        file_index++;
       } else {
         DCHECK(!item.data.empty());
         http_body.appendData(WebData(item.data));
@@ -190,8 +191,7 @@
   return true;
 }
 
-bool URLRequestRequiresUniversalAccess(
-    const ::ppapi::URLRequestInfoData& data) {
+bool URLRequestRequiresUniversalAccess(const URLRequestInfoData& data) {
   return
       data.has_custom_referrer_url ||
       data.has_custom_content_transfer_encoding ||
diff --git a/content/renderer/pepper/url_request_info_util.h b/content/renderer/pepper/url_request_info_util.h
index 4261535..2fb40e6 100644
--- a/content/renderer/pepper/url_request_info_util.h
+++ b/content/renderer/pepper/url_request_info_util.h
@@ -7,6 +7,7 @@
 
 #include "base/memory/ref_counted.h"
 #include "content/common/content_export.h"
+#include "ppapi/c/pp_instance.h"
 
 namespace ppapi {
 struct URLRequestInfoData;
@@ -23,13 +24,14 @@
 // on success, false if the request is invalid (in which case *dest may be
 // partially initialized). Any upload files with only resource IDs (no file ref
 // pointers) will be populated by this function on success.
-CONTENT_EXPORT bool CreateWebURLRequest(::ppapi::URLRequestInfoData* data,
+CONTENT_EXPORT bool CreateWebURLRequest(PP_Instance instance,
+                                        ppapi::URLRequestInfoData* data,
                                         WebKit::WebFrame* frame,
                                         WebKit::WebURLRequest* dest);
 
 // Returns true if universal access is required to use the given request.
 CONTENT_EXPORT bool URLRequestRequiresUniversalAccess(
-    const ::ppapi::URLRequestInfoData& data);
+    const ppapi::URLRequestInfoData& data);
 
 }  // namespace content
 
diff --git a/content/renderer/pepper/url_response_info_util.cc b/content/renderer/pepper/url_response_info_util.cc
index a9eccef..811ed35 100644
--- a/content/renderer/pepper/url_response_info_util.cc
+++ b/content/renderer/pepper/url_response_info_util.cc
@@ -7,7 +7,10 @@
 #include "base/bind.h"
 #include "base/files/file_path.h"
 #include "base/message_loop/message_loop.h"
-#include "content/renderer/pepper/ppb_file_ref_impl.h"
+#include "content/public/renderer/renderer_ppapi_host.h"
+#include "content/renderer/pepper/renderer_ppapi_host_impl.h"
+#include "ipc/ipc_message.h"
+#include "ppapi/proxy/ppapi_messages.h"
 #include "ppapi/shared_impl/url_response_info_data.h"
 #include "third_party/WebKit/public/platform/WebCString.h"
 #include "third_party/WebKit/public/platform/WebHTTPHeaderVisitor.h"
@@ -43,13 +46,23 @@
   return status >= 300 && status <= 399;
 }
 
+void DidCreateResourceHost(const ppapi::URLResponseInfoData& in_data,
+                           const base::FilePath& external_path,
+                           const DataFromWebURLResponseCallback& callback,
+                           int pending_resource_id) {
+  ppapi::URLResponseInfoData data = in_data;
+  data.body_as_file_ref = ppapi::MakeExternalFileRefCreateInfo(
+      external_path, std::string(), pending_resource_id);
+  callback.Run(data);
+}
+
 }  // namespace
 
-void DataFromWebURLResponse(PP_Instance pp_instance,
+void DataFromWebURLResponse(RendererPpapiHostImpl* host_impl,
+                            PP_Instance pp_instance,
                             const WebURLResponse& response,
                             const DataFromWebURLResponseCallback& callback) {
   ppapi::URLResponseInfoData data;
-
   data.url = response.url().spec();
   data.status_code = response.httpStatusCode();
   data.status_text = response.httpStatusText().utf8();
@@ -64,18 +77,16 @@
 
   WebString file_path = response.downloadFilePath();
   if (!file_path.isEmpty()) {
-    scoped_refptr<PPB_FileRef_Impl> file_ref(
-        PPB_FileRef_Impl::CreateExternal(
-            pp_instance,
-            base::FilePath::FromUTF16Unsafe(file_path),
-            std::string()));
-    data.body_as_file_ref = file_ref->GetCreateInfo();
-    file_ref->GetReference();  // The returned data has one ref for the plugin.
+    base::FilePath external_path = base::FilePath::FromUTF16Unsafe(file_path);
+    host_impl->CreateBrowserResourceHost(
+        pp_instance,
+        PpapiHostMsg_FileRef_CreateExternal(external_path),
+        base::Bind(&DidCreateResourceHost, data, external_path, callback));
+  } else {
+    base::MessageLoop::current()->PostTask(
+        FROM_HERE,
+        base::Bind(callback, data));
   }
-
-  // We post data to a callback instead of returning it here because the new
-  // implementation for FileRef is asynchronous when creating the resource.
-  base::MessageLoop::current()->PostTask(FROM_HERE, base::Bind(callback, data));
 }
 
 }  // namespace content
diff --git a/content/renderer/pepper/url_response_info_util.h b/content/renderer/pepper/url_response_info_util.h
index 21eba4c..ee0c238 100644
--- a/content/renderer/pepper/url_response_info_util.h
+++ b/content/renderer/pepper/url_response_info_util.h
@@ -14,6 +14,7 @@
 }
 
 namespace content {
+class RendererPpapiHostImpl;
 
 typedef base::Callback<void(const ppapi::URLResponseInfoData&)>
     DataFromWebURLResponseCallback;
@@ -21,7 +22,8 @@
 // The returned object will have one plugin reference to the "body_as_file_ref"
 // if it's non-null. It's expected that the result of this function will be
 // passed to the plugin.
-void DataFromWebURLResponse(PP_Instance pp_instance,
+void DataFromWebURLResponse(RendererPpapiHostImpl* host_impl,
+                            PP_Instance pp_instance,
                             const WebKit::WebURLResponse& response,
                             const DataFromWebURLResponseCallback& callback);
 
diff --git a/content/renderer/pepper/v8_var_converter.cc b/content/renderer/pepper/v8_var_converter.cc
index 25f9b66..8942c45 100644
--- a/content/renderer/pepper/v8_var_converter.cc
+++ b/content/renderer/pepper/v8_var_converter.cc
@@ -85,7 +85,7 @@
                         ParentVarSet* parent_ids) {
   *did_create = false;
 
-  if (::ppapi::VarTracker::IsVarTypeRefcounted(var.type)) {
+  if (ppapi::VarTracker::IsVarTypeRefcounted(var.type)) {
     if (parent_ids->count(var.value.as_id) != 0)
       return false;
     VarHandleMap::iterator it = visited_ids->find(var.value.as_id);
@@ -151,7 +151,7 @@
   }
 
   *did_create = true;
-  if (::ppapi::VarTracker::IsVarTypeRefcounted(var.type))
+  if (ppapi::VarTracker::IsVarTypeRefcounted(var.type))
     (*visited_ids)[var.value.as_id] = *result;
   return true;
 }
diff --git a/content/renderer/pepper/v8_var_converter_unittest.cc b/content/renderer/pepper/v8_var_converter_unittest.cc
index 3c3365d..c98766f 100644
--- a/content/renderer/pepper/v8_var_converter_unittest.cc
+++ b/content/renderer/pepper/v8_var_converter_unittest.cc
@@ -45,7 +45,7 @@
 bool Equals(const PP_Var& var,
             v8::Handle<v8::Value> val,
             VarHandleMap* visited_ids) {
-  if (::ppapi::VarTracker::IsVarTypeRefcounted(var.type)) {
+  if (ppapi::VarTracker::IsVarTypeRefcounted(var.type)) {
     VarHandleMap::iterator it = visited_ids->find(var.value.as_id);
     if (it != visited_ids->end())
       return it->second == val;
diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc
index fdc0df6..92bfb3d 100644
--- a/content/renderer/render_frame_impl.cc
+++ b/content/renderer/render_frame_impl.cc
@@ -6,7 +6,7 @@
 
 #include "base/strings/utf_string_conversions.h"
 #include "base/time/time.h"
-#include "content/child/appcache_dispatcher.h"
+#include "content/child/appcache/appcache_dispatcher.h"
 #include "content/child/fileapi/file_system_dispatcher.h"
 #include "content/child/fileapi/webfilesystem_callback_adapters.h"
 #include "content/child/quota_dispatcher.h"
@@ -65,11 +65,8 @@
 using WebKit::WebUserGestureIndicator;
 using WebKit::WebVector;
 using WebKit::WebView;
-
-using appcache::WebApplicationCacheHostImpl;
 using base::Time;
 using base::TimeDelta;
-
 using webkit_glue::WebURLResponseExtraDataImpl;
 
 namespace content {
@@ -78,9 +75,8 @@
     NULL;
 
 // static
-RenderFrameImpl* RenderFrameImpl::Create(
-    RenderViewImpl* render_view,
-    int32 routing_id) {
+RenderFrameImpl* RenderFrameImpl::Create(RenderViewImpl* render_view,
+                                         int32 routing_id) {
   DCHECK(routing_id != MSG_ROUTING_NONE);
 
   RenderFrameImpl* render_frame = NULL;
diff --git a/content/renderer/render_thread_impl.cc b/content/renderer/render_thread_impl.cc
index fd86944..b1e4a71 100644
--- a/content/renderer/render_thread_impl.cc
+++ b/content/renderer/render_thread_impl.cc
@@ -26,7 +26,8 @@
 #include "base/threading/thread_local.h"
 #include "base/threading/thread_restrictions.h"
 #include "base/values.h"
-#include "content/child/appcache_dispatcher.h"
+#include "content/child/appcache/appcache_dispatcher.h"
+#include "content/child/appcache/appcache_frontend_impl.h"
 #include "content/child/child_histogram_message_filter.h"
 #include "content/child/db_message_filter.h"
 #include "content/child/indexed_db/indexed_db_dispatcher.h"
@@ -108,7 +109,6 @@
 #include "v8/include/v8.h"
 #include "webkit/child/worker_task_runner.h"
 #include "webkit/glue/webkit_glue.h"
-#include "webkit/renderer/appcache/appcache_frontend_impl.h"
 #include "webkit/renderer/compositor_bindings/web_external_bitmap_impl.h"
 
 #if defined(OS_WIN)
@@ -351,7 +351,7 @@
   shutdown_event_ = NULL;
 
   appcache_dispatcher_.reset(
-      new AppCacheDispatcher(Get(), new appcache::AppCacheFrontendImpl()));
+      new AppCacheDispatcher(Get(), new AppCacheFrontendImpl()));
   dom_storage_dispatcher_.reset(new DomStorageDispatcher());
   main_thread_indexed_db_dispatcher_.reset(new IndexedDBDispatcher(
       thread_safe_sender()));
diff --git a/content/renderer/render_view_impl.cc b/content/renderer/render_view_impl.cc
index 5299bdd..c533788 100644
--- a/content/renderer/render_view_impl.cc
+++ b/content/renderer/render_view_impl.cc
@@ -29,7 +29,8 @@
 #include "base/strings/sys_string_conversions.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/time/time.h"
-#include "content/child/appcache_dispatcher.h"
+#include "content/child/appcache/appcache_dispatcher.h"
+#include "content/child/appcache/web_application_cache_host_impl.h"
 #include "content/child/child_thread.h"
 #include "content/child/fileapi/file_system_dispatcher.h"
 #include "content/child/fileapi/webfilesystem_callback_adapters.h"
@@ -205,7 +206,6 @@
 #include "ui/shell_dialogs/selected_file_info.h"
 #include "v8/include/v8.h"
 #include "webkit/child/weburlresponse_extradata_impl.h"
-#include "webkit/renderer/appcache/web_application_cache_host_impl.h"
 #include "webkit/renderer/webpreferences_renderer.h"
 
 #if defined(OS_ANDROID)
@@ -218,7 +218,8 @@
 #include "content/renderer/android/email_detector.h"
 #include "content/renderer/android/phone_number_detector.h"
 #include "content/renderer/media/android/renderer_media_player_manager.h"
-#include "content/renderer/media/android/stream_texture_factory_android.h"
+#include "content/renderer/media/android/stream_texture_factory_android_impl.h"
+#include "content/renderer/media/android/stream_texture_factory_android_synchronous_impl.h"
 #include "content/renderer/media/android/webmediaplayer_android.h"
 #include "content/renderer/media/android/webmediaplayer_proxy_android.h"
 #include "skia/ext/platform_canvas.h"
@@ -336,10 +337,8 @@
 using WebKit::WebView;
 using WebKit::WebWidget;
 using WebKit::WebWindowFeatures;
-using appcache::WebApplicationCacheHostImpl;
 using base::Time;
 using base::TimeDelta;
-
 using webkit_glue::WebURLResponseExtraDataImpl;
 
 #if defined(OS_ANDROID)
@@ -3022,6 +3021,15 @@
     media_player_proxy_ = new WebMediaPlayerProxyAndroid(
         this, media_player_manager_.get());
   }
+
+  scoped_ptr<StreamTextureFactory> stream_texture_factory;
+  if (UsingSynchronousRendererCompositor()) {
+    stream_texture_factory.reset(new StreamTextureFactorySynchronousImpl);
+  } else {
+    stream_texture_factory.reset(new StreamTextureFactoryImpl(
+        context_provider->Context3d(), gpu_channel_host, routing_id_));
+  }
+
   scoped_ptr<WebMediaPlayerAndroid> web_media_player_android(
       new WebMediaPlayerAndroid(
           frame,
@@ -3029,8 +3037,7 @@
           AsWeakPtr(),
           media_player_manager_.get(),
           media_player_proxy_,
-          new StreamTextureFactory(
-              context_provider->Context3d(), gpu_channel_host, routing_id_),
+          stream_texture_factory.release(),
           new RenderMediaLog()));
 #if defined(ENABLE_WEBRTC) && defined(GOOGLE_TV)
   if (media_stream_client_->IsMediaStream(url)) {
diff --git a/content/renderer/renderer_webapplicationcachehost_impl.h b/content/renderer/renderer_webapplicationcachehost_impl.h
index 334c136..0612039 100644
--- a/content/renderer/renderer_webapplicationcachehost_impl.h
+++ b/content/renderer/renderer_webapplicationcachehost_impl.h
@@ -5,20 +5,19 @@
 #ifndef CONTENT_RENDERER_RENDERER_WEBAPPLICATIONCACHEHOST_IMPL_H_
 #define CONTENT_RENDERER_RENDERER_WEBAPPLICATIONCACHEHOST_IMPL_H_
 
-#include "webkit/renderer/appcache/web_application_cache_host_impl.h"
+#include "content/child/appcache/web_application_cache_host_impl.h"
 
 namespace content {
 class RenderViewImpl;
 
-class RendererWebApplicationCacheHostImpl
-    : public appcache::WebApplicationCacheHostImpl {
+class RendererWebApplicationCacheHostImpl : public WebApplicationCacheHostImpl {
  public:
   RendererWebApplicationCacheHostImpl(
       RenderViewImpl* render_view,
       WebKit::WebApplicationCacheHostClient* client,
       appcache::AppCacheBackend* backend);
 
-  // appcache::WebApplicationCacheHostImpl methods.
+  // WebApplicationCacheHostImpl:
   virtual void OnLogMessage(appcache::LogLevel log_level,
                             const std::string& message) OVERRIDE;
   virtual void OnContentBlocked(const GURL& manifest_url) OVERRIDE;
diff --git a/webkit/plugins/sad_plugin.cc b/content/renderer/sad_plugin.cc
similarity index 93%
rename from webkit/plugins/sad_plugin.cc
rename to content/renderer/sad_plugin.cc
index ea355ee..a30788c 100644
--- a/webkit/plugins/sad_plugin.cc
+++ b/content/renderer/sad_plugin.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 "webkit/plugins/sad_plugin.h"
+#include "content/renderer/sad_plugin.h"
 
 #include <algorithm>
 
@@ -11,7 +11,7 @@
 #include "ui/gfx/blit.h"
 #include "ui/gfx/rect.h"
 
-namespace webkit {
+namespace content {
 
 void PaintSadPlugin(WebKit::WebCanvas* webcanvas,
                     const gfx::Rect& plugin_rect,
@@ -36,4 +36,4 @@
       SkIntToScalar(std::max(0, (height - sad_plugin_bitmap.height()) / 2)));
 }
 
-}  // namespace webkit
+}  // namespace content
diff --git a/content/renderer/sad_plugin.h b/content/renderer/sad_plugin.h
new file mode 100644
index 0000000..827d705
--- /dev/null
+++ b/content/renderer/sad_plugin.h
@@ -0,0 +1,26 @@
+// 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 CONTENT_RENDERER_SAD_PLUGIN_H_
+#define CONTENT_RENDERER_SAD_PLUGIN_H_
+
+#include "third_party/WebKit/public/platform/WebCanvas.h"
+
+class SkBitmap;
+
+namespace gfx {
+class Rect;
+}
+
+namespace content {
+
+// Paints the sad plugin to the given canvas for the given plugin bounds. This
+// is used by both the NPAPI and the PPAPI out-of-process plugin impls.
+void PaintSadPlugin(WebKit::WebCanvas* canvas,
+                    const gfx::Rect& plugin_rect,
+                    const SkBitmap& sad_plugin_bitmap);
+
+}  // namespace content
+
+#endif  // CONTENT_RENDERER_SAD_PLUGIN_H_
diff --git a/content/shell/renderer/shell_content_renderer_client.cc b/content/shell/renderer/shell_content_renderer_client.cc
index 4db6a52..433b368 100644
--- a/content/shell/renderer/shell_content_renderer_client.cc
+++ b/content/shell/renderer/shell_content_renderer_client.cc
@@ -188,7 +188,7 @@
 }
 
 bool ShellContentRendererClient::AllowBrowserPlugin(
-    WebKit::WebPluginContainer* container) const {
+    WebKit::WebPluginContainer* container) {
   if (CommandLine::ForCurrentProcess()->HasSwitch(
           switches::kEnableBrowserPluginForAllViewTypes)) {
     // Allow BrowserPlugin if forced by command line flag. This is generally
diff --git a/content/shell/renderer/shell_content_renderer_client.h b/content/shell/renderer/shell_content_renderer_client.h
index 10b2f43..fc35f03 100644
--- a/content/shell/renderer/shell_content_renderer_client.h
+++ b/content/shell/renderer/shell_content_renderer_client.h
@@ -54,7 +54,7 @@
   virtual WebKit::WebCrypto* OverrideWebCrypto() OVERRIDE;
   virtual WebKit::WebThemeEngine* OverrideThemeEngine() OVERRIDE;
   virtual bool AllowBrowserPlugin(
-      WebKit::WebPluginContainer* container) const OVERRIDE;
+      WebKit::WebPluginContainer* container) OVERRIDE;
 
  private:
    void WebTestProxyCreated(RenderView* render_view,
diff --git a/content/worker/DEPS b/content/worker/DEPS
index 34e8b17..24a1df5 100644
--- a/content/worker/DEPS
+++ b/content/worker/DEPS
@@ -1,7 +1,6 @@
 include_rules = [
   "+content/child",
   "+sandbox/win/src",
-  "+webkit/appcache",
   "+webkit/glue",
 ]
 
diff --git a/content/worker/worker_thread.cc b/content/worker/worker_thread.cc
index 5cf8dbb..4cabcb4 100644
--- a/content/worker/worker_thread.cc
+++ b/content/worker/worker_thread.cc
@@ -7,7 +7,8 @@
 #include "base/command_line.h"
 #include "base/lazy_instance.h"
 #include "base/threading/thread_local.h"
-#include "content/child/appcache_dispatcher.h"
+#include "content/child/appcache/appcache_dispatcher.h"
+#include "content/child/appcache/appcache_frontend_impl.h"
 #include "content/child/db_message_filter.h"
 #include "content/child/indexed_db/indexed_db_message_filter.h"
 #include "content/child/runtime_features.h"
@@ -22,7 +23,6 @@
 #include "third_party/WebKit/public/web/WebKit.h"
 #include "third_party/WebKit/public/web/WebRuntimeFeatures.h"
 #include "webkit/glue/webkit_glue.h"
-#include "webkit/renderer/appcache/appcache_frontend_impl.h"
 
 using WebKit::WebRuntimeFeatures;
 
@@ -40,7 +40,7 @@
   WebKit::initialize(webkit_platform_support_.get());
 
   appcache_dispatcher_.reset(
-      new AppCacheDispatcher(this, new appcache::AppCacheFrontendImpl()));
+      new AppCacheDispatcher(this, new AppCacheFrontendImpl()));
 
   web_database_observer_impl_.reset(
       new WebDatabaseObserverImpl(sync_message_filter()));
diff --git a/content/worker/worker_webapplicationcachehost_impl.cc b/content/worker/worker_webapplicationcachehost_impl.cc
index ef0c966..9283906 100644
--- a/content/worker/worker_webapplicationcachehost_impl.cc
+++ b/content/worker/worker_webapplicationcachehost_impl.cc
@@ -4,7 +4,7 @@
 
 #include "content/worker/worker_webapplicationcachehost_impl.h"
 
-#include "content/child/appcache_dispatcher.h"
+#include "content/child/appcache/appcache_dispatcher.h"
 #include "content/worker/worker_thread.h"
 
 namespace content {
diff --git a/content/worker/worker_webapplicationcachehost_impl.h b/content/worker/worker_webapplicationcachehost_impl.h
index 53482e1..2360cb3 100644
--- a/content/worker/worker_webapplicationcachehost_impl.h
+++ b/content/worker/worker_webapplicationcachehost_impl.h
@@ -5,7 +5,7 @@
 #ifndef CHROME_WORKER_WORKER_WEBAPPLICATIONCACHEHOST_IMPL_H_
 #define CHROME_WORKER_WORKER_WEBAPPLICATIONCACHEHOST_IMPL_H_
 
-#include "webkit/renderer/appcache/web_application_cache_host_impl.h"
+#include "content/child/appcache/web_application_cache_host_impl.h"
 
 namespace content {
 
@@ -26,8 +26,7 @@
   }
 };
 
-class WorkerWebApplicationCacheHostImpl
-    : public appcache::WebApplicationCacheHostImpl {
+class WorkerWebApplicationCacheHostImpl : public WebApplicationCacheHostImpl {
  public:
   WorkerWebApplicationCacheHostImpl(
       const WorkerAppCacheInitInfo& init_info,
diff --git a/chrome/browser/extensions/error_console/extension_error.cc b/extensions/browser/extension_error.cc
similarity index 89%
rename from chrome/browser/extensions/error_console/extension_error.cc
rename to extensions/browser/extension_error.cc
index 9d8944c..8b6196c 100644
--- a/chrome/browser/extensions/error_console/extension_error.cc
+++ b/extensions/browser/extension_error.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 "chrome/browser/extensions/error_console/extension_error.h"
+#include "extensions/browser/extension_error.h"
 
 #include "base/json/json_reader.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/values.h"
-#include "chrome/common/extensions/extension.h"
 #include "extensions/common/constants.h"
+#include "url/gurl.h"
 
 using base::string16;
 
@@ -28,7 +28,7 @@
 // populates |extension_id| with the ID. On failure, returns false and leaves
 // extension_id untouched.
 bool GetExtensionIDFromGURL(const GURL& url, std::string* extension_id) {
-  if (url.SchemeIs(extensions::kExtensionScheme)) {
+  if (url.SchemeIs(kExtensionScheme)) {
     *extension_id = url.host();
     return true;
   }
@@ -38,10 +38,12 @@
 }  // namespace
 
 ExtensionError::ExtensionError(Type type,
+                               const std::string& extension_id,
                                bool from_incognito,
                                const string16& source,
                                const string16& message)
     : type_(type),
+      extension_id_(extension_id),
       from_incognito_(from_incognito),
       source_(source),
       message_(message) {
@@ -58,15 +60,13 @@
          "\n  ID:      " + extension_id_;
 }
 
-ManifestParsingError::ManifestParsingError(bool from_incognito,
-                                           const string16& source,
-                                           const string16& message,
-                                           size_t line_number)
+ManifestParsingError::ManifestParsingError(const std::string& extension_id,
+                                           const string16& message)
     : ExtensionError(ExtensionError::MANIFEST_PARSING_ERROR,
-                     from_incognito,
-                     source,
-                     message),
-      line_number_(line_number) {
+                     extension_id,
+                     false,  // extensions can't be installed while incognito.
+                     base::FilePath(kManifestFilename).AsUTF16Unsafe(),
+                     message) {
 }
 
 ManifestParsingError::~ManifestParsingError() {
@@ -74,8 +74,7 @@
 
 std::string ManifestParsingError::PrintForTest() const {
   return ExtensionError::PrintForTest() +
-         "\n  Type:    ManifestParsingError" +
-         "\n  Line:    " + base::IntToString(line_number_);
+         "\n  Type:    ManifestParsingError";
 }
 
 JavascriptRuntimeError::StackFrame::StackFrame() : line_number(-1),
@@ -101,6 +100,7 @@
                                                logging::LogSeverity level,
                                                const string16& details)
     : ExtensionError(ExtensionError::JAVASCRIPT_RUNTIME_ERROR,
+                     std::string(),  // We don't know the id yet.
                      from_incognito,
                      source,
                      message),
diff --git a/chrome/browser/extensions/error_console/extension_error.h b/extensions/browser/extension_error.h
similarity index 84%
rename from chrome/browser/extensions/error_console/extension_error.h
rename to extensions/browser/extension_error.h
index e462d91..1cd4a7b 100644
--- a/chrome/browser/extensions/error_console/extension_error.h
+++ b/extensions/browser/extension_error.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROME_BROWSER_EXTENSIONS_ERROR_CONSOLE_EXTENSION_ERROR_H_
-#define CHROME_BROWSER_EXTENSIONS_ERROR_CONSOLE_EXTENSION_ERROR_H_
+#ifndef EXTENSIONS_BROWSER_EXTENSION_ERROR_H_
+#define EXTENSIONS_BROWSER_EXTENSION_ERROR_H_
 
 #include <string>
 #include <vector>
@@ -33,12 +33,15 @@
 
  protected:
   ExtensionError(Type type,
+                 const std::string& extension_id,
                  bool from_incognito,
                  const base::string16& source,
                  const base::string16& message);
 
   // Which type of error this is.
   Type type_;
+  // The ID of the extension which caused the error.
+  std::string extension_id_;
   // Whether or not the error was caused while incognito.
   bool from_incognito_;
   // The source for the error; this can be a script, web page, or manifest file.
@@ -47,27 +50,18 @@
   base::string16 source_;
   // The error message itself.
   base::string16 message_;
-  // The ID of the extension which caused the error. This may be absent, since
-  // we can't always know the id (such as when a manifest fails to parse).
-  std::string extension_id_;
 
   DISALLOW_COPY_AND_ASSIGN(ExtensionError);
 };
 
 class ManifestParsingError : public ExtensionError {
  public:
-  ManifestParsingError(bool from_incognito,
-                       const base::string16& source,
-                       const base::string16& message,
-                       size_t line_number);
+  ManifestParsingError(const std::string& extension_id,
+                       const base::string16& message);
   virtual ~ManifestParsingError();
 
   virtual std::string PrintForTest() const OVERRIDE;
-
-  size_t line_number() const { return line_number_; }
  private:
-  size_t line_number_;
-
   DISALLOW_COPY_AND_ASSIGN(ManifestParsingError);
 };
 
@@ -124,4 +118,4 @@
 
 }  // namespace extensions
 
-#endif  // CHROME_BROWSER_EXTENSIONS_ERROR_CONSOLE_EXTENSION_ERROR_H_
+#endif  // EXTENSIONS_BROWSER_EXTENSION_ERROR_H_
diff --git a/extensions/common/extensions_client.cc b/extensions/common/extensions_client.cc
new file mode 100644
index 0000000..e7f936d
--- /dev/null
+++ b/extensions/common/extensions_client.cc
@@ -0,0 +1,32 @@
+// 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/basictypes.h"
+#include "extensions/common/extensions_client.h"
+
+namespace extensions {
+
+namespace {
+
+ExtensionsClient* g_client = NULL;
+
+void Initialize(ExtensionsClient* client) {
+  client->RegisterManifestHandlers();
+}
+
+}  // namespace
+
+ExtensionsClient* ExtensionsClient::Get() {
+  return g_client;
+}
+
+void ExtensionsClient::Set(ExtensionsClient* client) {
+  // This can happen in unit tests, where the utility thread runs in-process.
+  if (g_client)
+    return;
+  g_client = client;
+  Initialize(g_client);
+}
+
+}  // namespace extensions
diff --git a/extensions/common/extensions_client.h b/extensions/common/extensions_client.h
new file mode 100644
index 0000000..83550a9
--- /dev/null
+++ b/extensions/common/extensions_client.h
@@ -0,0 +1,38 @@
+// 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 EXTENSIONS_COMMON_EXTENSIONS_CLIENT_H_
+#define EXTENSIONS_COMMON_EXTENSIONS_CLIENT_H_
+
+#include <string>
+
+namespace extensions {
+
+class FeatureProvider;
+class PermissionsProvider;
+
+// Sets up global state for the extensions system. Should be Set() once in each
+// process. This should be implemented by the client of the extensions system.
+class ExtensionsClient {
+ public:
+  // Returns a PermissionsProvider to initialize the permissions system.
+  virtual const PermissionsProvider& GetPermissionsProvider() const = 0;
+
+  // Gets a feature provider for a specific feature type.
+  virtual FeatureProvider* GetFeatureProviderByName(const std::string& name)
+      const = 0;
+
+  // Called at startup. Registers the handlers for parsing manifests.
+  virtual void RegisterManifestHandlers() const = 0;
+
+  // Return the extensions client.
+  static ExtensionsClient* Get();
+
+  // Initialize the extensions system with this extensions client.
+  static void Set(ExtensionsClient* client);
+};
+
+}  // namespace extensions
+
+#endif  // EXTENSIONS_COMMON_EXTENSIONS_CLIENT_H_
diff --git a/extensions/common/features/feature_provider.cc b/extensions/common/features/feature_provider.cc
new file mode 100644
index 0000000..8e15d4b
--- /dev/null
+++ b/extensions/common/features/feature_provider.cc
@@ -0,0 +1,16 @@
+// 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 "extensions/common/features/feature_provider.h"
+
+#include "base/basictypes.h"
+#include "extensions/common/extensions_client.h"
+
+namespace extensions {
+
+FeatureProvider* FeatureProvider::GetByName(const std::string& name) {
+  return ExtensionsClient::Get()->GetFeatureProviderByName(name);
+}
+
+}  // namespace extensions
diff --git a/chrome/common/extensions/features/feature_provider.h b/extensions/common/features/feature_provider.h
similarity index 64%
rename from chrome/common/extensions/features/feature_provider.h
rename to extensions/common/features/feature_provider.h
index 56942d5..c20e5d1 100644
--- a/chrome/common/extensions/features/feature_provider.h
+++ b/extensions/common/features/feature_provider.h
@@ -1,11 +1,12 @@
-// Copyright (c) 2012 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.
 
-#ifndef CHROME_COMMON_EXTENSIONS_FEATURES_FEATURE_PROVIDER_H_
-#define CHROME_COMMON_EXTENSIONS_FEATURES_FEATURE_PROVIDER_H_
+#ifndef EXTENSIONS_COMMON_FEATURES_FEATURE_PROVIDER_H_
+#define EXTENSIONS_COMMON_FEATURES_FEATURE_PROVIDER_H_
 
 #include <string>
+#include <vector>
 
 namespace extensions {
 
@@ -25,8 +26,11 @@
 
   // Returns all features described by this instance.
   virtual const std::vector<std::string>& GetAllFeatureNames() = 0;
+
+  // Gets a feature provider for a specific feature type, like "permission".
+  static FeatureProvider* GetByName(const std::string& name);
 };
 
 }  // namespace extensions
 
-#endif  // CHROME_COMMON_EXTENSIONS_FEATURES_FEATURE_PROVIDER_H_
+#endif  // EXTENSIONS_COMMON_FEATURES_FEATURE_PROVIDER_H_
diff --git a/extensions/common/permissions/permissions_provider.h b/extensions/common/permissions/permissions_provider.h
new file mode 100644
index 0000000..5a27a86
--- /dev/null
+++ b/extensions/common/permissions/permissions_provider.h
@@ -0,0 +1,37 @@
+// 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 EXTENSIONS_COMMON_PERMISSIONS_PERMISSIONS_PROVIDER_H_
+#define EXTENSIONS_COMMON_PERMISSIONS_PERMISSIONS_PROVIDER_H_
+
+#include <vector>
+
+namespace extensions {
+
+class APIPermissionInfo;
+
+// The PermissionsProvider creates the APIPermissions instances. It is only
+// needed at startup time.
+class PermissionsProvider {
+ public:
+  // An alias for a given permission |name|.
+  struct AliasInfo {
+    const char* name;
+    const char* alias;
+
+    AliasInfo(const char* name, const char* alias)
+        : name(name), alias(alias) {
+    }
+  };
+  // Returns all the known permissions. The caller, PermissionsInfo,
+  // takes ownership of the APIPermissionInfos.
+  virtual std::vector<APIPermissionInfo*> GetAllPermissions() const = 0;
+
+  // Returns all the known permission aliases.
+  virtual std::vector<AliasInfo> GetAllAliases() const = 0;
+};
+
+}  // namespace extensions
+
+#endif  // EXTENSIONS_COMMON_PERMISSIONS_PERMISSIONS_PROVIDER_H_
diff --git a/gpu/config/gpu_driver_bug_list_json.cc b/gpu/config/gpu_driver_bug_list_json.cc
index 93d940d..423a723 100644
--- a/gpu/config/gpu_driver_bug_list_json.cc
+++ b/gpu/config/gpu_driver_bug_list_json.cc
@@ -38,7 +38,7 @@
 // 13. "perf_graphics" is a FLOAT structure (defined below).
 // 14. "perf_gaming" is a FLOAT structure (defined below).
 // 15. "perf_overall" is a FLOAT structure (defined below).
-// 16. "machine_model" contais "name" and an optional "version".  "name" is a
+// 16. "machine_model" contains "name" and an optional "version".  "name" is a
 //     STRING structure and "version" is a VERSION structure (defined below).
 // 17. "gpu_count" is a INT structure (defined below).
 // 18  "cpu_info" is a STRING structure (defined below).
@@ -85,7 +85,7 @@
 {
   "name": "gpu driver bug list",
   // Please update the version number whenever you change this file.
-  "version": "2.4",
+  "version": "2.5",
   "entries": [
     {
       "id": 1,
@@ -411,6 +411,20 @@
       "features": [
         "disable_d3d11"
       ]
+    },
+    {
+      "id": 27,
+      "cr_bugs": [265115],
+      "description": "Async Readpixels with GL_BGRA format is broken on Haswell chipset on Mac.",
+      "os": {
+        "type": "macosx"
+      },
+      "vendor_id": "0x8086",
+      "device_id": ["0x0402", "0x0406", "0x040a", "0x0412", "0x0416", "0x041a",
+                    "0x0a04", "0x0a16", "0x0a22", "0x0a26", "0x0a2a"],
+      "features": [
+        "swizzle_rgba_for_async_readpixels"
+      ]
     }
   ]
 }
diff --git a/gpu/config/gpu_driver_bug_workaround_type.h b/gpu/config/gpu_driver_bug_workaround_type.h
index 8b733ea..20198da 100644
--- a/gpu/config/gpu_driver_bug_workaround_type.h
+++ b/gpu/config/gpu_driver_bug_workaround_type.h
@@ -60,6 +60,8 @@
          disable_async_readpixels)                           \
   GPU_OP(DISABLE_D3D11,                                      \
          disable_d3d11)                                      \
+  GPU_OP(SWIZZLE_RGBA_FOR_ASYNC_READPIXELS,                  \
+         swizzle_rgba_for_async_readpixels)                  \
 
 namespace gpu {
 
diff --git a/ios/public/DEPS b/ios/public/DEPS
index 3f0cd59..c04c1d5 100644
--- a/ios/public/DEPS
+++ b/ios/public/DEPS
@@ -4,7 +4,6 @@
   # be kept in sync with src/DEPS.
   "-base",
   "-build",
-  "-googleurl",
   "-library_loaders",
   "-testing",
   "-third_party/icu/source/common/unicode",
diff --git a/media/audio/OWNERS b/media/audio/OWNERS
index b0a7558..17c8ecc 100644
--- a/media/audio/OWNERS
+++ b/media/audio/OWNERS
@@ -3,9 +3,6 @@
 # Linux/Pulse
 xians@chromium.org
 
-# OSX
-crogers@google.com
-
 # Windows
 henrika@chromium.org
 
diff --git a/media/audio/audio_manager_base.cc b/media/audio/audio_manager_base.cc
index 7ffc7d3..db77f00 100644
--- a/media/audio/audio_manager_base.cc
+++ b/media/audio/audio_manager_base.cc
@@ -269,18 +269,15 @@
 
   const base::TimeDelta kCloseDelay =
       base::TimeDelta::FromSeconds(kStreamCloseDelaySeconds);
-
+  scoped_refptr<AudioOutputDispatcher> dispatcher;
   if (output_params.format() != AudioParameters::AUDIO_FAKE) {
-    scoped_refptr<AudioOutputDispatcher> dispatcher =
-        new AudioOutputResampler(this, params, output_params, input_device_id,
-                                 kCloseDelay);
-    dispatcher_params->dispatcher = dispatcher;
-    return new AudioOutputProxy(dispatcher.get());
+    dispatcher = new AudioOutputResampler(this, params, output_params,
+                                          input_device_id, kCloseDelay);
+  } else {
+    dispatcher = new AudioOutputDispatcherImpl(this, output_params,
+                                               input_device_id, kCloseDelay);
   }
 
-  scoped_refptr<AudioOutputDispatcher> dispatcher =
-      new AudioOutputDispatcherImpl(this, output_params, input_device_id,
-                                    kCloseDelay);
   dispatcher_params->dispatcher = dispatcher;
   output_dispatchers_.push_back(dispatcher_params);
   return new AudioOutputProxy(dispatcher.get());
diff --git a/media/audio/audio_power_monitor.cc b/media/audio/audio_power_monitor.cc
index 4dc1517..fa76828 100644
--- a/media/audio/audio_power_monitor.cc
+++ b/media/audio/audio_power_monitor.cc
@@ -84,7 +84,8 @@
         (average_power_ < kInsignificantPower) ? 0.0f : average_power_;
     if (power != last_reported_power_ ||
         clipped_since_last_notification_ != last_reported_clipped_) {
-      const float power_dbfs = 10.0f * log10f(power);
+      const float power_dbfs =
+          power > 0.0f ? 10.0f * log10f(power) : zero_power();
       // Try to post a task to run the callback with the dBFS result.  The
       // posting of the task is guaranteed to be non-blocking, and therefore
       // could fail.  However, in the common case, failures should be rare (and
diff --git a/media/base/android/java/src/org/chromium/media/WebAudioMediaCodecBridge.java b/media/base/android/java/src/org/chromium/media/WebAudioMediaCodecBridge.java
index ac752d4..1de7e42 100644
--- a/media/base/android/java/src/org/chromium/media/WebAudioMediaCodecBridge.java
+++ b/media/base/android/java/src/org/chromium/media/WebAudioMediaCodecBridge.java
@@ -61,7 +61,14 @@
 
         MediaFormat format = extractor.getTrackFormat(0);
 
-        int channelCount = format.getInteger(MediaFormat.KEY_CHANNEL_COUNT);
+        // Number of channels specified in the file
+        int inputChannelCount = format.getInteger(MediaFormat.KEY_CHANNEL_COUNT);
+
+        // Number of channels the decoder will provide. (Not
+        // necessarily the same as inputChannelCount.  See
+        // crbug.com/266006.)
+        int outputChannelCount = inputChannelCount;
+
         int sampleRate = format.getInteger(MediaFormat.KEY_SAMPLE_RATE);
         String mime = format.getString(MediaFormat.KEY_MIME);
 
@@ -77,13 +84,13 @@
         if (DEBUG) {
             Log.d(LOG_TAG, "Tracks: " + extractor.getTrackCount()
                   + " Rate: " + sampleRate
-                  + " Channels: " + channelCount
+                  + " Channels: " + inputChannelCount
                   + " Mime: " + mime
                   + " Duration: " + durationMicroseconds + " microsec");
         }
 
         nativeInitializeDestination(nativeMediaCodecBridge,
-                                    channelCount,
+                                    inputChannelCount,
                                     sampleRate,
                                     durationMicroseconds);
 
@@ -139,7 +146,8 @@
                 ByteBuffer buf = codecOutputBuffers[outputBufIndex];
 
                 if (info.size > 0) {
-                    nativeOnChunkDecoded(nativeMediaCodecBridge, buf, info.size);
+                    nativeOnChunkDecoded(nativeMediaCodecBridge, buf, info.size,
+                                         inputChannelCount, outputChannelCount);
                 }
 
                 buf.clear();
@@ -150,6 +158,10 @@
                 }
             } else if (outputBufIndex == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED) {
                 codecOutputBuffers = codec.getOutputBuffers();
+            } else if (outputBufIndex == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
+                MediaFormat newFormat = codec.getOutputFormat();
+                outputChannelCount = newFormat.getInteger(MediaFormat.KEY_CHANNEL_COUNT);
+                Log.d(LOG_TAG, "output format changed to " + newFormat);
             }
         }
 
@@ -163,11 +175,12 @@
     }
 
     private static native void nativeOnChunkDecoded(
-        int nativeWebAudioMediaCodecBridge, ByteBuffer buf, int size);
+        int nativeWebAudioMediaCodecBridge, ByteBuffer buf, int size,
+        int inputChannelCount, int outputChannelCount);
 
     private static native void nativeInitializeDestination(
         int nativeWebAudioMediaCodecBridge,
-        int channelCount,
+        int inputChannelCount,
         int sampleRate,
         long durationMicroseconds);
 }
diff --git a/media/base/android/media_player_bridge.cc b/media/base/android/media_player_bridge.cc
index e0d9868..342ceaa 100644
--- a/media/base/android/media_player_bridge.cc
+++ b/media/base/android/media_player_bridge.cc
@@ -390,6 +390,16 @@
 }
 
 void MediaPlayerBridge::SeekInternal(base::TimeDelta time) {
+  if (time > duration_)
+    time = duration_;
+
+  // Seeking to an invalid position may cause media player to stuck in an
+  // error state.
+  if (time < base::TimeDelta()) {
+    DCHECK_EQ(-1.0, time.InMillisecondsF());
+    return;
+  }
+
   JNIEnv* env = base::android::AttachCurrentThread();
   CHECK(env);
 
diff --git a/media/base/android/webaudio_media_codec_bridge.cc b/media/base/android/webaudio_media_codec_bridge.cc
index 6024a59..94f059a 100644
--- a/media/base/android/webaudio_media_codec_bridge.cc
+++ b/media/base/android/webaudio_media_codec_bridge.cc
@@ -17,6 +17,7 @@
 #include "base/basictypes.h"
 #include "base/logging.h"
 #include "base/posix/eintr_wrapper.h"
+#include "base/stl_util.h"
 #include "jni/WebAudioMediaCodecBridge_jni.h"
 #include "media/base/android/webaudio_media_codec_info.h"
 
@@ -148,15 +149,35 @@
     JNIEnv* env,
     jobject /*java object*/,
     jobject buf,
-    jint buf_size) {
+    jint buf_size,
+    jint input_channel_count,
+    jint output_channel_count) {
 
   if (buf_size <= 0 || !buf)
     return;
 
   int8_t* buffer =
       static_cast<int8_t*>(env->GetDirectBufferAddress(buf));
-
   size_t count = static_cast<size_t>(buf_size);
+  std::vector<int16_t> decoded_data;
+
+  if (input_channel_count == 1 && output_channel_count == 2) {
+    // See crbug.com/266006.  The file has one channel, but the
+    // decoder decided to return two channels.  To be consistent with
+    // the number of channels in the file, only send one channel (the
+    // first).
+    int16_t* data = static_cast<int16_t*>(env->GetDirectBufferAddress(buf));
+    int frame_count  = buf_size / sizeof(*data) / 2;
+
+    decoded_data.resize(frame_count);
+    for (int k = 0; k < frame_count; ++k) {
+      decoded_data[k] = *data;
+      data += 2;
+    }
+    buffer = reinterpret_cast<int8_t*>(vector_as_array(&decoded_data));
+    DCHECK(buffer);
+    count = frame_count * sizeof(*data);
+  }
 
   // Write out the data to the pipe in small chunks if necessary.
   while (count > 0) {
diff --git a/media/base/android/webaudio_media_codec_bridge.h b/media/base/android/webaudio_media_codec_bridge.h
index abf7f3f..fda6126 100644
--- a/media/base/android/webaudio_media_codec_bridge.h
+++ b/media/base/android/webaudio_media_codec_bridge.h
@@ -41,7 +41,9 @@
   void OnChunkDecoded(JNIEnv* env,
                       jobject /*java object*/,
                       jobject buf,
-                      jint buf_size);
+                      jint buf_size,
+                      jint input_channel_count,
+                      jint output_channel_count);
 
   void InitializeDestination(JNIEnv* env,
                              jobject /*java object*/,
diff --git a/media/base/media_file_checker.cc b/media/base/media_file_checker.cc
new file mode 100644
index 0000000..d4708e5
--- /dev/null
+++ b/media/base/media_file_checker.cc
@@ -0,0 +1,110 @@
+// 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/base/media_file_checker.h"
+
+#include <map>
+
+#include "base/bind.h"
+#include "base/time/time.h"
+#include "media/ffmpeg/ffmpeg_common.h"
+#include "media/filters/blocking_url_protocol.h"
+#include "media/filters/ffmpeg_glue.h"
+#include "media/filters/file_data_source.h"
+
+namespace media {
+
+static const int64 kMaxCheckTimeInSeconds = 5;
+
+static void OnError(bool* called) {
+  *called = false;
+}
+
+MediaFileChecker::MediaFileChecker(const base::PlatformFile& file)
+    : file_(file),
+      file_closer_(&file_) {
+}
+
+MediaFileChecker::~MediaFileChecker() {
+}
+
+bool MediaFileChecker::Start(base::TimeDelta check_time) {
+  media::FileDataSource source;
+  bool read_ok = true;
+  media::BlockingUrlProtocol protocol(&source, base::Bind(&OnError, &read_ok));
+  media::FFmpegGlue glue(&protocol);
+  source.InitializeFromPlatformFile(file_);
+  AVFormatContext* format_context = glue.format_context();
+
+  if (!glue.OpenContext())
+    return false;
+
+  if (avformat_find_stream_info(format_context, NULL) < 0)
+    return false;
+
+  // Remember the codec context for any decodable audio or video streams.
+  std::map<int, AVCodecContext*> stream_contexts;
+  for (size_t i = 0; i < format_context->nb_streams; ++i) {
+    AVCodecContext* c = format_context->streams[i]->codec;
+    if (c->codec_type == AVMEDIA_TYPE_AUDIO ||
+        c->codec_type == AVMEDIA_TYPE_VIDEO) {
+      AVCodec* codec = avcodec_find_decoder(c->codec_id);
+      if (codec && avcodec_open2(c, codec, NULL) >= 0)
+        stream_contexts[i] = c;
+    }
+  }
+
+  if (stream_contexts.size() == 0)
+    return false;
+
+  AVPacket packet;
+  scoped_ptr_malloc<AVFrame, media::ScopedPtrAVFree> frame(
+      avcodec_alloc_frame());
+  int result = 0;
+
+  base::Time deadline = base::Time::Now() +
+      std::min(check_time,
+               base::TimeDelta::FromSeconds(kMaxCheckTimeInSeconds));
+  do {
+    result = av_read_frame(glue.format_context(), &packet);
+    if (result < 0)
+      break;
+    result = av_dup_packet(&packet);
+    if (result < 0)
+      break;
+
+    std::map<int, AVCodecContext*>::const_iterator it =
+        stream_contexts.find(packet.stream_index);
+    if (it == stream_contexts.end()) {
+      av_free_packet(&packet);
+      continue;
+    }
+    AVCodecContext* av_context = it->second;
+
+    int frame_decoded = 0;
+    if (av_context->codec_type == AVMEDIA_TYPE_AUDIO) {
+      // A shallow copy of packet so we can slide packet.data as frames are
+      // decoded; otherwise av_free_packet() will corrupt memory.
+      AVPacket temp_packet = packet;
+      do {
+        avcodec_get_frame_defaults(frame.get());
+        result = avcodec_decode_audio4(av_context, frame.get(), &frame_decoded,
+                                       &temp_packet);
+        if (result < 0)
+          break;
+        temp_packet.size -= result;
+        temp_packet.data += result;
+      } while (temp_packet.size > 0);
+    } else if (av_context->codec_type == AVMEDIA_TYPE_VIDEO) {
+      avcodec_get_frame_defaults(frame.get());
+      result = avcodec_decode_video2(av_context, frame.get(), &frame_decoded,
+                                     &packet);
+    }
+    av_free_packet(&packet);
+  } while (base::Time::Now() < deadline && read_ok && result >= 0);
+
+  return read_ok && (result == AVERROR_EOF || result >= 0);
+}
+
+}  // namespace media
diff --git a/media/base/media_file_checker.h b/media/base/media_file_checker.h
new file mode 100644
index 0000000..6e8fc9f
--- /dev/null
+++ b/media/base/media_file_checker.h
@@ -0,0 +1,41 @@
+// 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_BASE_MEDIA_FILE_CHECKER_H_
+#define MEDIA_BASE_MEDIA_FILE_CHECKER_H_
+
+#include "base/basictypes.h"
+#include "base/files/scoped_platform_file_closer.h"
+#include "base/platform_file.h"
+#include "media/base/media_export.h"
+
+namespace base {
+class TimeDelta;
+}
+
+namespace media {
+
+// This class tries to determine if a file is a valid media file. The entire
+// file is not decoded so a positive result from this class does not make the
+// file safe to use in the browser process.
+class MEDIA_EXPORT MediaFileChecker {
+ public:
+  explicit MediaFileChecker(const base::PlatformFile& file);
+  ~MediaFileChecker();
+
+  // After opening |file|, up to |check_time| amount of wall-clock time is spent
+  // decoding the file. The amount of audio/video data decoded will depend on
+  // the bitrate of the file and the speed of the CPU.
+  bool Start(base::TimeDelta check_time);
+
+ private:
+  base::PlatformFile file_;
+  base::ScopedPlatformFileCloser file_closer_;
+
+  DISALLOW_COPY_AND_ASSIGN(MediaFileChecker);
+};
+
+}  // namespace media
+
+#endif  // MEDIA_BASE_MEDIA_FILE_CHECKER_H_
diff --git a/media/base/media_file_checker_unittest.cc b/media/base/media_file_checker_unittest.cc
new file mode 100644
index 0000000..f43c846
--- /dev/null
+++ b/media/base/media_file_checker_unittest.cc
@@ -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.
+
+#include "base/logging.h"
+#include "build/build_config.h"
+#include "media/base/media_file_checker.h"
+#include "media/base/test_data_util.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace media {
+
+static void RunMediaFileChecker(const std::string& filename, bool expectation) {
+  base::PlatformFileError error;
+  base::PlatformFile file = base::CreatePlatformFile(
+      GetTestDataFilePath(filename),
+      base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_READ,
+      NULL,
+      &error);
+  ASSERT_EQ(base::PLATFORM_FILE_OK, error);
+
+  MediaFileChecker checker(file);
+  const base::TimeDelta check_time = base::TimeDelta::FromMilliseconds(100);
+  bool result = checker.Start(check_time);
+  EXPECT_EQ(expectation, result);
+
+  base::ClosePlatformFile(file);
+}
+
+TEST(MediaFileCheckerTest, InvalidFile) {
+  RunMediaFileChecker("ten_byte_file", false);
+}
+
+TEST(MediaFileCheckerTest, Video) {
+  RunMediaFileChecker("bear.ogv", true);
+}
+
+TEST(MediaFileCheckerTest, Audio) {
+  RunMediaFileChecker("sfx.ogg", true);
+}
+
+#if defined(GOOGLE_CHROME_BUILD) || defined(USE_PROPRIETARY_CODECS)
+TEST(MediaFileCheckerTest, MP3) {
+  RunMediaFileChecker("sfx.mp3", true);
+}
+#endif
+
+}  // namespace media
diff --git a/media/base/media_switches.cc b/media/base/media_switches.cc
index 153c22a..3c1dc16 100644
--- a/media/base/media_switches.cc
+++ b/media/base/media_switches.cc
@@ -57,6 +57,12 @@
 // for details.
 const char kEnableExclusiveAudio[] = "enable-exclusive-audio";
 
+// Used to troubleshoot problems with different video capture implementations
+// on Windows.  By default we use the Media Foundation API on Windows 7 and up,
+// but specifying this switch will force use of DirectShow always.
+// See bug: http://crbug.com/268412
+const char kForceDirectShowVideoCapture[] = "force-directshow";
+
 // Use Windows WaveOut/In audio API even if Core Audio is supported.
 const char kForceWaveAudio[] = "force-wave-audio";
 
diff --git a/media/base/media_switches.h b/media/base/media_switches.h
index 0462ada..885839d 100644
--- a/media/base/media_switches.h
+++ b/media/base/media_switches.h
@@ -39,6 +39,7 @@
 
 #if defined(OS_WIN)
 MEDIA_EXPORT extern const char kEnableExclusiveAudio[];
+MEDIA_EXPORT extern const char kForceDirectShowVideoCapture[];
 MEDIA_EXPORT extern const char kForceWaveAudio[];
 MEDIA_EXPORT extern const char kWaveOutBuffers[];
 #endif
diff --git a/media/base/video_frame.cc b/media/base/video_frame.cc
index 10ad051..08e7e1a 100644
--- a/media/base/video_frame.cc
+++ b/media/base/video_frame.cc
@@ -34,6 +34,7 @@
     case VideoFrame::YV12:
     case VideoFrame::YV12A:
     case VideoFrame::YV16:
+    case VideoFrame::I420:
       frame->AllocateYUV();
       break;
     default:
@@ -117,20 +118,52 @@
 }
 
 // static
+scoped_refptr<VideoFrame> VideoFrame::WrapExternalSharedMemory(
+    Format format,
+    const gfx::Size& coded_size,
+    const gfx::Rect& visible_rect,
+    const gfx::Size& natural_size,
+    uint8* data,
+    base::SharedMemoryHandle handle,
+    base::TimeDelta timestamp,
+    const base::Closure& no_longer_needed_cb) {
+  switch (format) {
+    case I420: {
+      scoped_refptr<VideoFrame> frame(new VideoFrame(
+          format, coded_size, visible_rect, natural_size, timestamp));
+      frame->shared_memory_handle_ = handle;
+      frame->strides_[kYPlane] = coded_size.width();
+      frame->strides_[kUPlane] = coded_size.width() / 2;
+      frame->strides_[kVPlane] = coded_size.width() / 2;
+      frame->data_[kYPlane] = data;
+      frame->data_[kUPlane] = data + coded_size.GetArea();
+      frame->data_[kVPlane] = data + (coded_size.GetArea() * 5 / 4);
+      frame->no_longer_needed_cb_ = no_longer_needed_cb;
+      return frame;
+    }
+    default:
+      NOTIMPLEMENTED();
+      return NULL;
+  }
+}
+
+// static
 scoped_refptr<VideoFrame> VideoFrame::WrapExternalYuvData(
     Format format,
     const gfx::Size& coded_size,
     const gfx::Rect& visible_rect,
     const gfx::Size& natural_size,
-    int32 y_stride, int32 u_stride, int32 v_stride,
-    uint8* y_data, uint8* u_data, uint8* v_data,
+    int32 y_stride,
+    int32 u_stride,
+    int32 v_stride,
+    uint8* y_data,
+    uint8* u_data,
+    uint8* v_data,
     base::TimeDelta timestamp,
-    base::SharedMemoryHandle shm_handle,
     const base::Closure& no_longer_needed_cb) {
   DCHECK(format == YV12 || format == YV16 || format == I420) << format;
   scoped_refptr<VideoFrame> frame(new VideoFrame(
       format, coded_size, visible_rect, natural_size, timestamp));
-  frame->shared_memory_handle_ = shm_handle;
   frame->strides_[kYPlane] = y_stride;
   frame->strides_[kUPlane] = u_stride;
   frame->strides_[kVPlane] = v_stride;
@@ -198,11 +231,11 @@
       return 1;
     case VideoFrame::YV12:
     case VideoFrame::YV16:
+    case VideoFrame::I420:
       return 3;
     case VideoFrame::YV12A:
       return 4;
     case VideoFrame::EMPTY:
-    case VideoFrame::I420:
     case VideoFrame::INVALID:
       break;
   }
@@ -239,7 +272,7 @@
 
 void VideoFrame::AllocateYUV() {
   DCHECK(format_ == VideoFrame::YV12 || format_ == VideoFrame::YV16 ||
-         format_ == VideoFrame::YV12A);
+         format_ == VideoFrame::YV12A || format_ == VideoFrame::I420);
   // Align Y rows at least at 16 byte boundaries.  The stride for both
   // YV12 and YV16 is 1/2 of the stride of Y.  For YV12, every row of bytes for
   // U and V applies to two rows of Y (one byte of UV for 4 bytes of Y), so in
@@ -259,9 +292,11 @@
   // and then the size needs to be a multiple of two macroblocks (vertically).
   // See libavcodec/utils.c:avcodec_align_dimensions2().
   size_t y_height = RoundUp(coded_size_.height(), kFrameSizeAlignment * 2);
-  size_t uv_height = (format_ == VideoFrame::YV12 ||
-                      format_ == VideoFrame::YV12A) ?
-                              y_height / 2 : y_height;
+  size_t uv_height =
+      (format_ == VideoFrame::YV12 || format_ == VideoFrame::YV12A ||
+       format_ == VideoFrame::I420)
+          ? y_height / 2
+          : y_height;
   size_t y_bytes = y_height * y_stride;
   size_t uv_bytes = uv_height * uv_stride;
   size_t a_bytes = format_ == VideoFrame::YV12A ? y_bytes : 0;
@@ -327,10 +362,14 @@
       return width * 4;
 
     // Planar, 8bpp.
+    case YV12A:
+      if (plane == kAPlane)
+        return width;
+    // Fallthrough.
     case YV12:
     case YV16:
-    case YV12A:
-      if (plane == kYPlane || plane == kAPlane)
+    case I420:
+      if (plane == kYPlane)
         return width;
       return RoundUp(width, 2) / 2;
 
@@ -351,9 +390,13 @@
     case YV16:
       return height;
 
-    case YV12:
     case YV12A:
-      if (plane == kYPlane || plane == kAPlane)
+      if (plane == kAPlane)
+        return height;
+    // Fallthrough.
+    case YV12:
+    case I420:
+      if (plane == kYPlane)
         return height;
       return RoundUp(height, 2) / 2;
 
diff --git a/media/base/video_frame.h b/media/base/video_frame.h
index 8207d9b..82a08a9 100644
--- a/media/base/video_frame.h
+++ b/media/base/video_frame.h
@@ -137,9 +137,26 @@
   // least as large as 4*visible_rect().width()*visible_rect().height().
   void ReadPixelsFromNativeTexture(const SkBitmap& pixels);
 
+  // Wraps image data in a buffer backed by a base::SharedMemoryHandle with a
+  // VideoFrame.  The image data resides in |data| and is assumed to be packed
+  // tightly in a buffer of logical dimensions |coded_size| with the appropriate
+  // bit depth and plane count as given by |format|.  When the frame is
+  // destroyed |no_longer_needed_cb.Run()| will be called.
+  static scoped_refptr<VideoFrame> WrapExternalSharedMemory(
+      Format format,
+      const gfx::Size& coded_size,
+      const gfx::Rect& visible_rect,
+      const gfx::Size& natural_size,
+      uint8* data,
+      base::SharedMemoryHandle handle,
+      base::TimeDelta timestamp,
+      const base::Closure& no_longer_needed_cb);
+
   // Wraps external YUV data of the given parameters with a VideoFrame.
   // The returned VideoFrame does not own the data passed in. When the frame
   // is destroyed |no_longer_needed_cb.Run()| will be called.
+  // TODO(sheu): merge this into WrapExternalSharedMemory().
+  // http://crbug.com/270217
   static scoped_refptr<VideoFrame> WrapExternalYuvData(
       Format format,
       const gfx::Size& coded_size,
@@ -152,7 +169,6 @@
       uint8* u_data,
       uint8* v_data,
       base::TimeDelta timestamp,
-      base::SharedMemoryHandle shm_handle,  // may be NULLHandle()
       const base::Closure& no_longer_needed_cb);
 
   // Creates a frame with format equals to VideoFrame::EMPTY, width, height,
diff --git a/media/base/video_util.cc b/media/base/video_util.cc
index 9da651f..fda758e 100644
--- a/media/base/video_util.cc
+++ b/media/base/video_util.cc
@@ -143,7 +143,8 @@
   DCHECK(!(view_area.y() & 1));
   DCHECK(!(view_area.width() & 1));
   DCHECK(!(view_area.height() & 1));
-  DCHECK_EQ(frame->format(), VideoFrame::YV12);
+  DCHECK(frame->format() == VideoFrame::YV12 ||
+         frame->format() == VideoFrame::I420);
   LetterboxPlane(frame, VideoFrame::kYPlane, view_area, 0x00);
   gfx::Rect half_view_area(view_area.x() / 2,
                            view_area.y() / 2,
diff --git a/media/crypto/DEPS b/media/cdm/DEPS
similarity index 100%
rename from media/crypto/DEPS
rename to media/cdm/DEPS
diff --git a/media/crypto/aes_decryptor.cc b/media/cdm/aes_decryptor.cc
similarity index 98%
rename from media/crypto/aes_decryptor.cc
rename to media/cdm/aes_decryptor.cc
index fd7c628..da11442 100644
--- a/media/crypto/aes_decryptor.cc
+++ b/media/cdm/aes_decryptor.cc
@@ -1,8 +1,8 @@
-// Copyright (c) 2012 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.
 
-#include "media/crypto/aes_decryptor.h"
+#include "media/cdm/aes_decryptor.h"
 
 #include <vector>
 
diff --git a/media/crypto/aes_decryptor.h b/media/cdm/aes_decryptor.h
similarity index 98%
rename from media/crypto/aes_decryptor.h
rename to media/cdm/aes_decryptor.h
index aec55d7..fda5a0f 100644
--- a/media/crypto/aes_decryptor.h
+++ b/media/cdm/aes_decryptor.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2012 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.
 
diff --git a/media/crypto/aes_decryptor_unittest.cc b/media/cdm/aes_decryptor_unittest.cc
similarity index 99%
rename from media/crypto/aes_decryptor_unittest.cc
rename to media/cdm/aes_decryptor_unittest.cc
index 8feaec4..1edb8e8 100644
--- a/media/crypto/aes_decryptor_unittest.cc
+++ b/media/cdm/aes_decryptor_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2012 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.
 
@@ -10,7 +10,7 @@
 #include "media/base/decoder_buffer.h"
 #include "media/base/decrypt_config.h"
 #include "media/base/mock_filters.h"
-#include "media/crypto/aes_decryptor.h"
+#include "media/cdm/aes_decryptor.h"
 #include "media/webm/webm_constants.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
diff --git a/media/cdm/ppapi/DEPS b/media/cdm/ppapi/DEPS
new file mode 100644
index 0000000..473873d
--- /dev/null
+++ b/media/cdm/ppapi/DEPS
@@ -0,0 +1,7 @@
+# Since media/ does not depend on anything in media/cdm/ppapi/, these extra
+# dependencies are okay.
+include_rules = [
+  "+ppapi/c",
+  "+ppapi/cpp",
+  "+ppapi/utility",
+]
diff --git a/webkit/renderer/media/crypto/ppapi/cdm_video_decoder.cc b/media/cdm/ppapi/cdm_video_decoder.cc
similarity index 75%
rename from webkit/renderer/media/crypto/ppapi/cdm_video_decoder.cc
rename to media/cdm/ppapi/cdm_video_decoder.cc
index 5f2d71d..95523d4 100644
--- a/webkit/renderer/media/crypto/ppapi/cdm_video_decoder.cc
+++ b/media/cdm/ppapi/cdm_video_decoder.cc
@@ -4,22 +4,21 @@
 
 #include "base/basictypes.h"
 #include "base/memory/scoped_ptr.h"
-#include "webkit/renderer/media/crypto/ppapi/cdm/content_decryption_module.h"
-#include "webkit/renderer/media/crypto/ppapi/cdm_video_decoder.h"
+#include "media/cdm/ppapi/cdm_video_decoder.h"
 
 #if defined(CLEAR_KEY_CDM_USE_FAKE_VIDEO_DECODER)
-#include "webkit/renderer/media/crypto/ppapi/fake_cdm_video_decoder.h"
+#include "media/cdm/ppapi/fake_cdm_video_decoder.h"
 #endif
 
 #if defined(CLEAR_KEY_CDM_USE_FFMPEG_DECODER)
-#include "webkit/renderer/media/crypto/ppapi/ffmpeg_cdm_video_decoder.h"
+#include "media/cdm/ppapi/ffmpeg_cdm_video_decoder.h"
 #endif
 
 #if defined(CLEAR_KEY_CDM_USE_LIBVPX_DECODER)
-#include "webkit/renderer/media/crypto/ppapi/libvpx_cdm_video_decoder.h"
+#include "media/cdm/ppapi/libvpx_cdm_video_decoder.h"
 #endif
 
-namespace webkit_media {
+namespace media {
 
 scoped_ptr<CdmVideoDecoder> CreateVideoDecoder(
     cdm::Host* host, const cdm::VideoDecoderConfig& config) {
@@ -54,4 +53,4 @@
   return video_decoder.Pass();
 }
 
-}  // namespace webkit_media
+}  // namespace media
diff --git a/webkit/renderer/media/crypto/ppapi/cdm_video_decoder.h b/media/cdm/ppapi/cdm_video_decoder.h
similarity index 81%
rename from webkit/renderer/media/crypto/ppapi/cdm_video_decoder.h
rename to media/cdm/ppapi/cdm_video_decoder.h
index 86caff9..25d48f4 100644
--- a/webkit/renderer/media/crypto/ppapi/cdm_video_decoder.h
+++ b/media/cdm/ppapi/cdm_video_decoder.h
@@ -2,14 +2,14 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef WEBKIT_RENDERER_MEDIA_CRYPTO_PPAPI_CDM_VIDEO_DECODER_H_
-#define WEBKIT_RENDERER_MEDIA_CRYPTO_PPAPI_CDM_VIDEO_DECODER_H_
+#ifndef MEDIA_CDM_PPAPI_CDM_VIDEO_DECODER_H_
+#define MEDIA_CDM_PPAPI_CDM_VIDEO_DECODER_H_
 
 #include "base/basictypes.h"
 #include "base/memory/scoped_ptr.h"
-#include "webkit/renderer/media/crypto/ppapi/cdm/content_decryption_module.h"
+#include "media/cdm/ppapi/api/content_decryption_module.h"
 
-namespace webkit_media {
+namespace media {
 
 class CdmVideoDecoder {
  public:
@@ -38,6 +38,6 @@
 scoped_ptr<CdmVideoDecoder> CreateVideoDecoder(
     cdm::Host* host, const cdm::VideoDecoderConfig& config);
 
-}  // namespace webkit_media
+}  // namespace media
 
-#endif  // WEBKIT_RENDERER_MEDIA_CRYPTO_PPAPI_CDM_VIDEO_DECODER_H_
+#endif  // MEDIA_CDM_PPAPI_CDM_VIDEO_DECODER_H_
diff --git a/webkit/renderer/media/crypto/ppapi/cdm_wrapper.cc b/media/cdm/ppapi/cdm_wrapper.cc
similarity index 98%
rename from webkit/renderer/media/crypto/ppapi/cdm_wrapper.cc
rename to media/cdm/ppapi/cdm_wrapper.cc
index f175831..6348f19 100644
--- a/webkit/renderer/media/crypto/ppapi/cdm_wrapper.cc
+++ b/media/cdm/ppapi/cdm_wrapper.cc
@@ -10,6 +10,8 @@
 
 #include "base/basictypes.h"
 #include "base/compiler_specific.h"
+#include "media/cdm/ppapi/api/content_decryption_module.h"
+#include "media/cdm/ppapi/linked_ptr.h"
 #include "ppapi/c/pp_errors.h"
 #include "ppapi/c/pp_stdint.h"
 #include "ppapi/c/private/pp_content_decryptor.h"
@@ -25,8 +27,6 @@
 #include "ppapi/cpp/var.h"
 #include "ppapi/cpp/var_array_buffer.h"
 #include "ppapi/utility/completion_callback_factory.h"
-#include "webkit/renderer/media/crypto/ppapi/cdm/content_decryption_module.h"
-#include "webkit/renderer/media/crypto/ppapi/linked_ptr.h"
 
 #if defined(CHECK_DOCUMENT_URL)
 #include "ppapi/cpp/dev/url_util_dev.h"
@@ -204,7 +204,7 @@
 
 }  // namespace
 
-namespace webkit_media {
+namespace media {
 
 // cdm::Buffer implementation that provides access to memory owned by a
 // pp::Buffer_Dev.
@@ -1186,13 +1186,13 @@
   }
 };
 
-}  // namespace webkit_media
+}  // namespace media
 
 namespace pp {
 
 // Factory function for your specialization of the Module object.
 Module* CreateModule() {
-  return new webkit_media::CdmWrapperModule();
+  return new media::CdmWrapperModule();
 }
 
 }  // namespace pp
diff --git a/webkit/renderer/media/crypto/ppapi/clear_key_cdm.cc b/media/cdm/ppapi/clear_key_cdm.cc
similarity index 97%
rename from webkit/renderer/media/crypto/ppapi/clear_key_cdm.cc
rename to media/cdm/ppapi/clear_key_cdm.cc
index 7f35fd8..cd6a61f 100644
--- a/webkit/renderer/media/crypto/ppapi/clear_key_cdm.cc
+++ b/media/cdm/ppapi/clear_key_cdm.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 "webkit/renderer/media/crypto/ppapi/clear_key_cdm.h"
+#include "media/cdm/ppapi/clear_key_cdm.h"
 
 #include <algorithm>
 #include <sstream>
@@ -15,7 +15,7 @@
 #include "base/time/time.h"
 #include "media/base/decoder_buffer.h"
 #include "media/base/decrypt_config.h"
-#include "webkit/renderer/media/crypto/ppapi/cdm_video_decoder.h"
+#include "media/cdm/ppapi/cdm_video_decoder.h"
 
 #if defined(CLEAR_KEY_CDM_USE_FAKE_AUDIO_DECODER)
 #include "base/basictypes.h"
@@ -27,8 +27,8 @@
 #include "base/files/file_path.h"
 #include "base/path_service.h"
 #include "media/base/media.h"
-#include "webkit/renderer/media/crypto/ppapi/ffmpeg_cdm_audio_decoder.h"
-#include "webkit/renderer/media/crypto/ppapi/ffmpeg_cdm_video_decoder.h"
+#include "media/cdm/ppapi/ffmpeg_cdm_audio_decoder.h"
+#include "media/cdm/ppapi/ffmpeg_cdm_video_decoder.h"
 
 // Include FFmpeg avformat.h for av_register_all().
 extern "C" {
@@ -140,14 +140,14 @@
     return NULL;
 
   return static_cast<cdm::ContentDecryptionModule*>(
-      new webkit_media::ClearKeyCdm(host));
+      new media::ClearKeyCdm(host));
 }
 
 const char* GetCdmVersion() {
   return kClearKeyCdmVersion;
 }
 
-namespace webkit_media {
+namespace media {
 
 ClearKeyCdm::Client::Client() : status_(kKeyError) {}
 
@@ -315,7 +315,7 @@
     const cdm::AudioDecoderConfig& audio_decoder_config) {
 #if defined(CLEAR_KEY_CDM_USE_FFMPEG_DECODER)
   if (!audio_decoder_)
-    audio_decoder_.reset(new webkit_media::FFmpegCdmAudioDecoder(host_));
+    audio_decoder_.reset(new media::FFmpegCdmAudioDecoder(host_));
 
   if (!audio_decoder_->Initialize(audio_decoder_config))
     return cdm::kSessionError;
@@ -555,4 +555,4 @@
 }
 #endif  // CLEAR_KEY_CDM_USE_FAKE_AUDIO_DECODER
 
-}  // namespace webkit_media
+}  // namespace media
diff --git a/webkit/renderer/media/crypto/ppapi/clear_key_cdm.h b/media/cdm/ppapi/clear_key_cdm.h
similarity index 91%
rename from webkit/renderer/media/crypto/ppapi/clear_key_cdm.h
rename to media/cdm/ppapi/clear_key_cdm.h
index d82f90d..67637eb 100644
--- a/webkit/renderer/media/crypto/ppapi/clear_key_cdm.h
+++ b/media/cdm/ppapi/clear_key_cdm.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef WEBKIT_RENDERER_MEDIA_CRYPTO_PPAPI_CLEAR_KEY_CDM_H_
-#define WEBKIT_RENDERER_MEDIA_CRYPTO_PPAPI_CLEAR_KEY_CDM_H_
+#ifndef MEDIA_CDM_PPAPI_CLEAR_KEY_CDM_H_
+#define MEDIA_CDM_PPAPI_CLEAR_KEY_CDM_H_
 
 #include <string>
 #include <vector>
@@ -13,8 +13,8 @@
 #include "base/memory/ref_counted.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/synchronization/lock.h"
-#include "media/crypto/aes_decryptor.h"
-#include "webkit/renderer/media/crypto/ppapi/cdm/content_decryption_module.h"
+#include "media/cdm/aes_decryptor.h"
+#include "media/cdm/ppapi/api/content_decryption_module.h"
 
 // Enable this to use the fake decoder for testing.
 // TODO(tomfinegan): Move fake audio decoder into a separate class.
@@ -23,12 +23,8 @@
 #endif
 
 namespace media {
-class DecoderBuffer;
-}
-
-namespace webkit_media {
-
 class CdmVideoDecoder;
+class DecoderBuffer;
 class FFmpegCdmAudioDecoder;
 
 // Clear key implementation of the cdm::ContentDecryptionModule interface.
@@ -87,7 +83,7 @@
 
     void KeyAdded(const std::string& session_id);
     void KeyError(const std::string& session_id,
-                  media::MediaKeys::KeyError error_code,
+                  MediaKeys::KeyError error_code,
                   int system_code);
     void KeyMessage(const std::string& session_id,
                     const std::vector<uint8>& message,
@@ -113,7 +109,7 @@
   // |decrypted_buffer| should be ignored by the caller.
   cdm::Status DecryptToMediaDecoderBuffer(
       const cdm::InputBuffer& encrypted_buffer,
-      scoped_refptr<media::DecoderBuffer>* decrypted_buffer);
+      scoped_refptr<DecoderBuffer>* decrypted_buffer);
 
 #if defined(CLEAR_KEY_CDM_USE_FAKE_AUDIO_DECODER)
   int64 CurrentTimeStampInMicroseconds() const;
@@ -130,7 +126,7 @@
 #endif  // CLEAR_KEY_CDM_USE_FAKE_AUDIO_DECODER
 
   Client client_;
-  media::AesDecryptor decryptor_;
+  AesDecryptor decryptor_;
 
   // Protects the |client_| from being accessed by the |decryptor_|
   // simultaneously.
@@ -165,6 +161,6 @@
   DISALLOW_COPY_AND_ASSIGN(ClearKeyCdm);
 };
 
-}  // namespace webkit_media
+}  // namespace media
 
-#endif  // WEBKIT_RENDERER_MEDIA_CRYPTO_PPAPI_CLEAR_KEY_CDM_H_
+#endif  // MEDIA_CDM_PPAPI_CLEAR_KEY_CDM_H_
diff --git a/webkit/renderer/media/crypto/ppapi/fake_cdm_video_decoder.cc b/media/cdm/ppapi/fake_cdm_video_decoder.cc
similarity index 92%
rename from webkit/renderer/media/crypto/ppapi/fake_cdm_video_decoder.cc
rename to media/cdm/ppapi/fake_cdm_video_decoder.cc
index 1870621..b23e5a7 100644
--- a/webkit/renderer/media/crypto/ppapi/fake_cdm_video_decoder.cc
+++ b/media/cdm/ppapi/fake_cdm_video_decoder.cc
@@ -2,12 +2,11 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "webkit/renderer/media/crypto/ppapi/fake_cdm_video_decoder.h"
+#include "media/cdm/ppapi/fake_cdm_video_decoder.h"
 
 #include "base/logging.h"
-#include "webkit/renderer/media/crypto/ppapi/cdm/content_decryption_module.h"
 
-namespace webkit_media {
+namespace media {
 
 FakeCdmVideoDecoder::FakeCdmVideoDecoder(cdm::Host* host)
     : is_initialized_(false),
@@ -89,4 +88,4 @@
   return cdm::kSuccess;
 }
 
-}  // namespace webkit_media
+}  // namespace media
diff --git a/webkit/renderer/media/crypto/ppapi/fake_cdm_video_decoder.h b/media/cdm/ppapi/fake_cdm_video_decoder.h
similarity index 67%
rename from webkit/renderer/media/crypto/ppapi/fake_cdm_video_decoder.h
rename to media/cdm/ppapi/fake_cdm_video_decoder.h
index 7c110e2..05b16ad 100644
--- a/webkit/renderer/media/crypto/ppapi/fake_cdm_video_decoder.h
+++ b/media/cdm/ppapi/fake_cdm_video_decoder.h
@@ -2,19 +2,19 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef WEBKIT_RENDERER_MEDIA_CRYPTO_PPAPI_FAKE_CDM_VIDEO_DECODER_H_
-#define WEBKIT_RENDERER_MEDIA_CRYPTO_PPAPI_FAKE_CDM_VIDEO_DECODER_H_
+#ifndef MEDIA_CDM_PPAPI_FAKE_CDM_VIDEO_DECODER_H_
+#define MEDIA_CDM_PPAPI_FAKE_CDM_VIDEO_DECODER_H_
 
 #include "base/basictypes.h"
 #include "base/compiler_specific.h"
-#include "webkit/renderer/media/crypto/ppapi/cdm/content_decryption_module.h"
-#include "webkit/renderer/media/crypto/ppapi/cdm_video_decoder.h"
+#include "media/cdm/ppapi/api/content_decryption_module.h"
+#include "media/cdm/ppapi/cdm_video_decoder.h"
 
-namespace webkit_media {
+namespace media {
 
 class FakeCdmVideoDecoder : public CdmVideoDecoder {
  public:
-  explicit FakeCdmVideoDecoder(cdm::Allocator* allocator);
+  explicit FakeCdmVideoDecoder(cdm::Host* host);
   virtual ~FakeCdmVideoDecoder();
 
   // CdmVideoDecoder implementation.
@@ -36,6 +36,6 @@
   DISALLOW_COPY_AND_ASSIGN(FakeCdmVideoDecoder);
 };
 
-}  // namespace webkit_media
+}  // namespace media
 
-#endif  // WEBKIT_RENDERER_MEDIA_CRYPTO_PPAPI_FAKE_CDM_VIDEO_DECODER_H_
+#endif  // MEDIA_CDM_PPAPI_FAKE_CDM_VIDEO_DECODER_H_
diff --git a/webkit/renderer/media/crypto/ppapi/ffmpeg_cdm_audio_decoder.cc b/media/cdm/ppapi/ffmpeg_cdm_audio_decoder.cc
similarity index 92%
rename from webkit/renderer/media/crypto/ppapi/ffmpeg_cdm_audio_decoder.cc
rename to media/cdm/ppapi/ffmpeg_cdm_audio_decoder.cc
index 1391de8..ed619b2 100644
--- a/webkit/renderer/media/crypto/ppapi/ffmpeg_cdm_audio_decoder.cc
+++ b/media/cdm/ppapi/ffmpeg_cdm_audio_decoder.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 "webkit/renderer/media/crypto/ppapi/ffmpeg_cdm_audio_decoder.h"
+#include "media/cdm/ppapi/ffmpeg_cdm_audio_decoder.h"
 
 #include <algorithm>
 
@@ -12,7 +12,6 @@
 #include "media/base/buffers.h"
 #include "media/base/data_buffer.h"
 #include "media/base/limits.h"
-#include "webkit/renderer/media/crypto/ppapi/cdm/content_decryption_module.h"
 
 // Include FFmpeg header files.
 extern "C" {
@@ -22,7 +21,7 @@
 MSVC_POP_WARNING();
 }  // extern "C"
 
-namespace webkit_media {
+namespace media {
 
 // Maximum number of channels with defined layout in src/media.
 static const int kMaxChannels = 8;
@@ -90,7 +89,7 @@
       channels_(0),
       av_sample_format_(0),
       bytes_per_frame_(0),
-      last_input_timestamp_(media::kNoTimestamp()),
+      last_input_timestamp_(kNoTimestamp()),
       output_bytes_to_drop_(0) {
 }
 
@@ -143,7 +142,7 @@
     int channels = codec_context_->channels;
     if (codec_context_->sample_fmt == AV_SAMPLE_FMT_FLT)
       channels = 1;
-    converter_bus_ = media::AudioBus::CreateWrapper(channels);
+    converter_bus_ = AudioBus::CreateWrapper(channels);
   }
 
   // Success!
@@ -152,7 +151,7 @@
   samples_per_second_ = config.samples_per_second;
   bytes_per_frame_ = codec_context_->channels * bits_per_channel_ / 8;
   output_timestamp_helper_.reset(
-      new media::AudioTimestampHelper(config.samples_per_second));
+      new AudioTimestampHelper(config.samples_per_second));
   serialized_audio_frames_.reserve(bytes_per_frame_ * samples_per_second_);
   is_initialized_ = true;
 
@@ -183,9 +182,9 @@
          config.channel_count > 0 &&
          config.channel_count <= kMaxChannels &&
          config.bits_per_channel > 0 &&
-         config.bits_per_channel <= media::limits::kMaxBitsPerSample &&
+         config.bits_per_channel <= limits::kMaxBitsPerSample &&
          config.samples_per_second > 0 &&
-         config.samples_per_second <= media::limits::kMaxSampleRate;
+         config.samples_per_second <= limits::kMaxSampleRate;
 }
 
 cdm::Status FFmpegCdmAudioDecoder::DecodeBuffer(
@@ -200,7 +199,7 @@
 
   bool is_vorbis = codec_context_->codec_id == AV_CODEC_ID_VORBIS;
   if (!is_end_of_stream) {
-    if (last_input_timestamp_ == media::kNoTimestamp()) {
+    if (last_input_timestamp_ == kNoTimestamp()) {
       if (is_vorbis && 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
@@ -210,7 +209,7 @@
       } else {
         last_input_timestamp_ = timestamp;
       }
-    } else if (timestamp != media::kNoTimestamp()) {
+    } else if (timestamp != kNoTimestamp()) {
       if (timestamp < last_input_timestamp_) {
         base::TimeDelta diff = timestamp - last_input_timestamp_;
         DVLOG(1) << "Input timestamps are not monotonically increasing! "
@@ -260,9 +259,9 @@
     packet.size -= result;
     packet.data += result;
 
-    if (output_timestamp_helper_->base_timestamp() == media::kNoTimestamp() &&
+    if (output_timestamp_helper_->base_timestamp() == kNoTimestamp() &&
         !is_end_of_stream) {
-      DCHECK(timestamp != media::kNoTimestamp());
+      DCHECK(timestamp != kNoTimestamp());
       if (output_bytes_to_drop_ > 0) {
         // Currently Vorbis is the only codec that causes us to drop samples.
         // If we have to drop samples it always means the timeline starts at 0.
@@ -311,7 +310,7 @@
       output_bytes_to_drop_ -= dropped_size;
     }
 
-    scoped_refptr<media::DataBuffer> output;
+    scoped_refptr<DataBuffer> output;
     if (decoded_audio_size > 0) {
       DCHECK_EQ(decoded_audio_size % bytes_per_frame_, 0)
           << "Decoder didn't output full frames";
@@ -336,7 +335,7 @@
               av_frame_->extended_data[i]));
         }
 
-        output = new media::DataBuffer(decoded_audio_size);
+        output = new DataBuffer(decoded_audio_size);
         output->set_data_size(decoded_audio_size);
 
         DCHECK_EQ(frames_to_interleave, converter_bus_->frames() - skip_frames);
@@ -344,7 +343,7 @@
             skip_frames, frames_to_interleave, bits_per_channel_ / 8,
             output->writable_data());
       } else {
-        output = media::DataBuffer::CopyFrom(
+        output = DataBuffer::CopyFrom(
             av_frame_->extended_data[0] + start_sample * bytes_per_frame_,
             decoded_audio_size);
       }
@@ -384,8 +383,8 @@
 }
 
 void FFmpegCdmAudioDecoder::ResetTimestampState() {
-  output_timestamp_helper_->SetBaseTimestamp(media::kNoTimestamp());
-  last_input_timestamp_ = media::kNoTimestamp();
+  output_timestamp_helper_->SetBaseTimestamp(kNoTimestamp());
+  last_input_timestamp_ = kNoTimestamp();
   output_bytes_to_drop_ = 0;
 }
 
@@ -410,4 +409,4 @@
   memcpy(&serialized_audio_frames_[0] + previous_size, &value, sizeof(value));
 }
 
-}  // namespace webkit_media
+}  // namespace media
diff --git a/webkit/renderer/media/crypto/ppapi/ffmpeg_cdm_audio_decoder.h b/media/cdm/ppapi/ffmpeg_cdm_audio_decoder.h
similarity index 76%
rename from webkit/renderer/media/crypto/ppapi/ffmpeg_cdm_audio_decoder.h
rename to media/cdm/ppapi/ffmpeg_cdm_audio_decoder.h
index 2e93974..1b4fb8f 100644
--- a/webkit/renderer/media/crypto/ppapi/ffmpeg_cdm_audio_decoder.h
+++ b/media/cdm/ppapi/ffmpeg_cdm_audio_decoder.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef WEBKIT_RENDERER_MEDIA_CRYPTO_PPAPI_FFMPEG_CDM_AUDIO_DECODER_H_
-#define WEBKIT_RENDERER_MEDIA_CRYPTO_PPAPI_FFMPEG_CDM_AUDIO_DECODER_H_
+#ifndef MEDIA_CDM_PPAPI_FFMPEG_CDM_AUDIO_DECODER_H_
+#define MEDIA_CDM_PPAPI_FFMPEG_CDM_AUDIO_DECODER_H_
 
 #include <vector>
 
@@ -11,7 +11,7 @@
 #include "base/compiler_specific.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/time/time.h"
-#include "webkit/renderer/media/crypto/ppapi/cdm/content_decryption_module.h"
+#include "media/cdm/ppapi/api/content_decryption_module.h"
 
 struct AVCodecContext;
 struct AVFrame;
@@ -21,12 +21,12 @@
 class AudioTimestampHelper;
 }
 
-namespace webkit_media {
+namespace media {
 
-// TODO(xhwang): This class is partially cloned from media::FFmpegAudioDecoder.
-// When media::FFmpegAudioDecoder is updated, it's a pain to keep this class
-// in sync with media::FFmpegAudioDecoder. We need a long term sustainable
-// solution for this. See http://crbug.com/169203
+// TODO(xhwang): This class is partially cloned from FFmpegAudioDecoder. When
+// FFmpegAudioDecoder is updated, it's a pain to keep this class in sync with
+// FFmpegAudioDecoder. We need a long term sustainable solution for this. See
+// http://crbug.com/169203
 class FFmpegCdmAudioDecoder {
  public:
   explicit FFmpegCdmAudioDecoder(cdm::Host* host);
@@ -75,13 +75,13 @@
   int av_sample_format_;
 
   // Used for computing output timestamps.
-  scoped_ptr<media::AudioTimestampHelper> output_timestamp_helper_;
+  scoped_ptr<AudioTimestampHelper> output_timestamp_helper_;
   int bytes_per_frame_;
   base::TimeDelta last_input_timestamp_;
 
   // We may need to convert the audio data coming out of FFmpeg from planar
   // float to integer.
-  scoped_ptr<media::AudioBus> converter_bus_;
+  scoped_ptr<AudioBus> converter_bus_;
 
   // Number of output sample bytes to drop before generating output buffers.
   // This is required for handling negative timestamps when decoding Vorbis
@@ -94,6 +94,6 @@
   DISALLOW_COPY_AND_ASSIGN(FFmpegCdmAudioDecoder);
 };
 
-}  // namespace webkit_media
+}  // namespace media
 
-#endif  // WEBKIT_RENDERER_MEDIA_CRYPTO_PPAPI_FFMPEG_CDM_AUDIO_DECODER_H_
+#endif  // MEDIA_CDM_PPAPI_FFMPEG_CDM_AUDIO_DECODER_H_
diff --git a/webkit/renderer/media/crypto/ppapi/ffmpeg_cdm_video_decoder.cc b/media/cdm/ppapi/ffmpeg_cdm_video_decoder.cc
similarity index 96%
rename from webkit/renderer/media/crypto/ppapi/ffmpeg_cdm_video_decoder.cc
rename to media/cdm/ppapi/ffmpeg_cdm_video_decoder.cc
index faaa8f7..9a2439d 100644
--- a/webkit/renderer/media/crypto/ppapi/ffmpeg_cdm_video_decoder.cc
+++ b/media/cdm/ppapi/ffmpeg_cdm_video_decoder.cc
@@ -2,13 +2,12 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "webkit/renderer/media/crypto/ppapi/ffmpeg_cdm_video_decoder.h"
+#include "media/cdm/ppapi/ffmpeg_cdm_video_decoder.h"
 
 #include "base/logging.h"
 #include "base/memory/scoped_ptr.h"
 #include "media/base/buffers.h"
 #include "media/base/limits.h"
-#include "webkit/renderer/media/crypto/ppapi/cdm/content_decryption_module.h"
 
 // Include FFmpeg header files.
 extern "C" {
@@ -18,7 +17,7 @@
 MSVC_POP_WARNING();
 }  // extern "C"
 
-namespace webkit_media {
+namespace media {
 
 static const int kDecodeThreads = 1;
 
@@ -199,9 +198,9 @@
   return ((format == cdm::kYv12 || format == cdm::kI420) &&
           (data_size.width % 2) == 0 && (data_size.height % 2) == 0 &&
           data_size.width > 0 && data_size.height > 0 &&
-          data_size.width <= media::limits::kMaxDimension &&
-          data_size.height <= media::limits::kMaxDimension &&
-          data_size.width * data_size.height <= media::limits::kMaxCanvas);
+          data_size.width <= limits::kMaxDimension &&
+          data_size.height <= limits::kMaxDimension &&
+          data_size.width * data_size.height <= limits::kMaxCanvas);
 }
 
 cdm::Status FFmpegCdmVideoDecoder::DecodeFrame(
@@ -342,4 +341,4 @@
   }
 }
 
-}  // namespace webkit_media
+}  // namespace media
diff --git a/webkit/renderer/media/crypto/ppapi/ffmpeg_cdm_video_decoder.h b/media/cdm/ppapi/ffmpeg_cdm_video_decoder.h
similarity index 79%
rename from webkit/renderer/media/crypto/ppapi/ffmpeg_cdm_video_decoder.h
rename to media/cdm/ppapi/ffmpeg_cdm_video_decoder.h
index 5c4bb2b..17e2b57 100644
--- a/webkit/renderer/media/crypto/ppapi/ffmpeg_cdm_video_decoder.h
+++ b/media/cdm/ppapi/ffmpeg_cdm_video_decoder.h
@@ -2,18 +2,18 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef WEBKIT_RENDERER_MEDIA_CRYPTO_PPAPI_FFMPEG_CDM_VIDEO_DECODER_H_
-#define WEBKIT_RENDERER_MEDIA_CRYPTO_PPAPI_FFMPEG_CDM_VIDEO_DECODER_H_
+#ifndef MEDIA_CDM_PPAPI_FFMPEG_CDM_VIDEO_DECODER_H_
+#define MEDIA_CDM_PPAPI_FFMPEG_CDM_VIDEO_DECODER_H_
 
 #include "base/basictypes.h"
 #include "base/compiler_specific.h"
-#include "webkit/renderer/media/crypto/ppapi/cdm/content_decryption_module.h"
-#include "webkit/renderer/media/crypto/ppapi/cdm_video_decoder.h"
+#include "media/cdm/ppapi/api/content_decryption_module.h"
+#include "media/cdm/ppapi/cdm_video_decoder.h"
 
 struct AVCodecContext;
 struct AVFrame;
 
-namespace webkit_media {
+namespace media {
 
 class FFmpegCdmVideoDecoder : public CdmVideoDecoder {
  public:
@@ -53,6 +53,6 @@
   DISALLOW_COPY_AND_ASSIGN(FFmpegCdmVideoDecoder);
 };
 
-}  // namespace webkit_media
+}  // namespace media
 
-#endif  // WEBKIT_RENDERER_MEDIA_CRYPTO_PPAPI_FFMPEG_CDM_VIDEO_DECODER_H_
+#endif  // MEDIA_CDM_PPAPI_FFMPEG_CDM_VIDEO_DECODER_H_
diff --git a/webkit/renderer/media/crypto/ppapi/libvpx_cdm_video_decoder.cc b/media/cdm/ppapi/libvpx_cdm_video_decoder.cc
similarity index 92%
rename from webkit/renderer/media/crypto/ppapi/libvpx_cdm_video_decoder.cc
rename to media/cdm/ppapi/libvpx_cdm_video_decoder.cc
index beb365c..a81c485 100644
--- a/webkit/renderer/media/crypto/ppapi/libvpx_cdm_video_decoder.cc
+++ b/media/cdm/ppapi/libvpx_cdm_video_decoder.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 "webkit/renderer/media/crypto/ppapi/libvpx_cdm_video_decoder.h"
+#include "media/cdm/ppapi/libvpx_cdm_video_decoder.h"
 
 #include "base/logging.h"
 #include "base/memory/scoped_ptr.h"
@@ -14,17 +14,16 @@
 // backwards compatibility for legacy applications using the library.
 #define VPX_CODEC_DISABLE_COMPAT 1
 extern "C" {
+// Note: vpx_decoder.h must be first or compile will fail.
+#include "third_party/libvpx/source/libvpx/vpx/vpx_decoder.h"  // NOLINT
 #include "third_party/libvpx/source/libvpx/vpx/vp8dx.h"
-#include "third_party/libvpx/source/libvpx/vpx/vpx_decoder.h"
 }
 
-#include "webkit/renderer/media/crypto/ppapi/cdm/content_decryption_module.h"
-
 // Enable USE_COPYPLANE_WITH_LIBVPX to use |CopyPlane()| instead of memcpy to
 // copy video frame data.
 // #define USE_COPYPLANE_WITH_LIBVPX 1
 
-namespace webkit_media {
+namespace media {
 
 static const int kDecodeThreads = 2;
 
@@ -94,9 +93,9 @@
   return ((format == cdm::kYv12 || format == cdm::kI420) &&
           (data_size.width % 2) == 0 && (data_size.height % 2) == 0 &&
           data_size.width > 0 && data_size.height > 0 &&
-          data_size.width <= media::limits::kMaxDimension &&
-          data_size.height <= media::limits::kMaxDimension &&
-          data_size.width * data_size.height <= media::limits::kMaxCanvas);
+          data_size.width <= limits::kMaxDimension &&
+          data_size.height <= limits::kMaxDimension &&
+          data_size.width * data_size.height <= limits::kMaxCanvas);
 }
 
 cdm::Status LibvpxCdmVideoDecoder::DecodeFrame(
@@ -193,4 +192,4 @@
   return true;
 }
 
-}  // namespace webkit_media
+}  // namespace media
diff --git a/webkit/renderer/media/crypto/ppapi/libvpx_cdm_video_decoder.h b/media/cdm/ppapi/libvpx_cdm_video_decoder.h
similarity index 78%
rename from webkit/renderer/media/crypto/ppapi/libvpx_cdm_video_decoder.h
rename to media/cdm/ppapi/libvpx_cdm_video_decoder.h
index 59674b6..3edaa07 100644
--- a/webkit/renderer/media/crypto/ppapi/libvpx_cdm_video_decoder.h
+++ b/media/cdm/ppapi/libvpx_cdm_video_decoder.h
@@ -2,18 +2,18 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef WEBKIT_RENDERER_MEDIA_CRYPTO_PPAPI_LIBVPX_CDM_VIDEO_DECODER_H_
-#define WEBKIT_RENDERER_MEDIA_CRYPTO_PPAPI_LIBVPX_CDM_VIDEO_DECODER_H_
+#ifndef MEDIA_CDM_PPAPI_LIBVPX_CDM_VIDEO_DECODER_H_
+#define MEDIA_CDM_PPAPI_LIBVPX_CDM_VIDEO_DECODER_H_
 
 #include "base/basictypes.h"
 #include "base/compiler_specific.h"
-#include "webkit/renderer/media/crypto/ppapi/cdm/content_decryption_module.h"
-#include "webkit/renderer/media/crypto/ppapi/cdm_video_decoder.h"
+#include "media/cdm/ppapi/api/content_decryption_module.h"
+#include "media/cdm/ppapi/cdm_video_decoder.h"
 
 struct vpx_codec_ctx;
 struct vpx_image;
 
-namespace webkit_media {
+namespace media {
 
 class LibvpxCdmVideoDecoder : public CdmVideoDecoder {
  public:
@@ -50,6 +50,6 @@
   DISALLOW_COPY_AND_ASSIGN(LibvpxCdmVideoDecoder);
 };
 
-}  // namespace webkit_media
+}  // namespace media
 
-#endif  // WEBKIT_RENDERER_MEDIA_CRYPTO_PPAPI_LIBVPX_CDM_VIDEO_DECODER_H_
+#endif  // MEDIA_CDM_PPAPI_LIBVPX_CDM_VIDEO_DECODER_H_
diff --git a/webkit/renderer/media/crypto/ppapi/linked_ptr.h b/media/cdm/ppapi/linked_ptr.h
similarity index 96%
rename from webkit/renderer/media/crypto/ppapi/linked_ptr.h
rename to media/cdm/ppapi/linked_ptr.h
index 5dd61fe..f3eccbb 100644
--- a/webkit/renderer/media/crypto/ppapi/linked_ptr.h
+++ b/media/cdm/ppapi/linked_ptr.h
@@ -37,8 +37,8 @@
 //  - is thread safe for copying and deletion
 //  - supports weak_ptrs
 
-#ifndef WEBKIT_RENDERER_MEDIA_CRYPTO_PPAPI_LINKED_PTR_H_
-#define WEBKIT_RENDERER_MEDIA_CRYPTO_PPAPI_LINKED_PTR_H_
+#ifndef MEDIA_CDM_PPAPI_LINKED_PTR_H_
+#define MEDIA_CDM_PPAPI_LINKED_PTR_H_
 
 #include "ppapi/cpp/logging.h"
 
@@ -182,4 +182,4 @@
   return linked_ptr<T>(ptr);
 }
 
-#endif  // WEBKIT_RENDERER_MEDIA_CRYPTO_PPAPI_LINKED_PTR_H_
+#endif  // MEDIA_CDM_PPAPI_LINKED_PTR_H_
diff --git a/media/filters/file_data_source.cc b/media/filters/file_data_source.cc
index 2f34718..341347e 100644
--- a/media/filters/file_data_source.cc
+++ b/media/filters/file_data_source.cc
@@ -25,6 +25,17 @@
   return true;
 }
 
+bool FileDataSource::InitializeFromPlatformFile(
+    const base::PlatformFile& file) {
+  DCHECK(!file_.IsValid());
+
+  if (!file_.Initialize(file))
+    return false;
+
+  UpdateHostBytes();
+  return true;
+}
+
 void FileDataSource::set_host(DataSourceHost* host) {
   DataSource::set_host(host);
   UpdateHostBytes();
diff --git a/media/filters/file_data_source.h b/media/filters/file_data_source.h
index e55ecdf..c0164dac 100644
--- a/media/filters/file_data_source.h
+++ b/media/filters/file_data_source.h
@@ -9,6 +9,7 @@
 
 #include "base/files/file_path.h"
 #include "base/files/memory_mapped_file.h"
+#include "base/platform_file.h"
 #include "media/base/data_source.h"
 
 namespace media {
@@ -21,6 +22,7 @@
   virtual ~FileDataSource();
 
   bool Initialize(const base::FilePath& file_path);
+  bool InitializeFromPlatformFile(const base::PlatformFile& file);
 
   // Implementation of DataSource.
   virtual void set_host(DataSourceHost* host) OVERRIDE;
diff --git a/media/filters/gpu_video_decoder.cc b/media/filters/gpu_video_decoder.cc
index a106ab5..30c6dfa 100644
--- a/media/filters/gpu_video_decoder.cc
+++ b/media/filters/gpu_video_decoder.cc
@@ -137,7 +137,7 @@
       BindToCurrentLoop(orig_status_cb));
 
   bool previously_initialized = config_.IsValidConfig();
-#if !defined(OS_CHROMEOS) || !defined(ARCH_CPU_X86_FAMILY)
+#if !defined(OS_CHROMEOS)
   if (previously_initialized) {
     // TODO(xhwang): Make GpuVideoDecoder reinitializable.
     // See http://crbug.com/233608
diff --git a/media/filters/pipeline_integration_test.cc b/media/filters/pipeline_integration_test.cc
index f260708..26f65b9 100644
--- a/media/filters/pipeline_integration_test.cc
+++ b/media/filters/pipeline_integration_test.cc
@@ -11,7 +11,7 @@
 #include "media/base/decoder_buffer.h"
 #include "media/base/media_keys.h"
 #include "media/base/test_data_util.h"
-#include "media/crypto/aes_decryptor.h"
+#include "media/cdm/aes_decryptor.h"
 #include "media/filters/chunk_demuxer.h"
 
 using testing::AnyNumber;
diff --git a/media/media.gyp b/media/media.gyp
index b2bde3d..c685090 100644
--- a/media/media.gyp
+++ b/media/media.gyp
@@ -261,6 +261,8 @@
         'base/filter_collection.h',
         'base/media.cc',
         'base/media.h',
+        'base/media_file_checker.cc',
+        'base/media_file_checker.h',
         'base/media_keys.cc',
         'base/media_keys.h',
         'base/media_log.cc',
@@ -312,8 +314,8 @@
         'base/video_util.h',
         'base/yuv_convert.cc',
         'base/yuv_convert.h',
-        'crypto/aes_decryptor.cc',
-        'crypto/aes_decryptor.h',
+        'cdm/aes_decryptor.cc',
+        'cdm/aes_decryptor.h',
         'ffmpeg/ffmpeg_common.cc',
         'ffmpeg/ffmpeg_common.h',
         'filters/audio_decoder_selector.cc',
@@ -466,6 +468,8 @@
           'sources!': [
             'base/container_names.cc',
             'base/container_names.h',
+            'base/media_file_checker.cc',
+            'base/media_file_checker.h',
             'base/media_posix.cc',
             'ffmpeg/ffmpeg_common.cc',
             'ffmpeg/ffmpeg_common.h',
@@ -926,6 +930,7 @@
         'base/decoder_buffer_unittest.cc',
         'base/djb2_unittest.cc',
         'base/gmock_callback_support_unittest.cc',
+        'base/media_file_checker_unittest.cc',
         'base/multi_channel_resampler_unittest.cc',
         'base/pipeline_unittest.cc',
         'base/ranges_unittest.cc',
@@ -940,7 +945,7 @@
         'base/video_frame_unittest.cc',
         'base/video_util_unittest.cc',
         'base/yuv_convert_unittest.cc',
-        'crypto/aes_decryptor_unittest.cc',
+        'cdm/aes_decryptor_unittest.cc',
         'ffmpeg/ffmpeg_common_unittest.cc',
         'filters/audio_decoder_selector_unittest.cc',
         'filters/audio_file_reader_unittest.cc',
@@ -998,6 +1003,10 @@
           'dependencies': [
             '../third_party/ffmpeg/ffmpeg.gyp:ffmpeg',
           ],
+        }, {  # media_use_ffmpeg== 0
+          'sources!': [
+            'base/media_file_checker_unittest.cc',
+          ],
         }],
         ['os_posix==1 and OS!="mac" and OS!="ios"', {
           'conditions': [
@@ -1285,6 +1294,9 @@
       ], # targets
     }],
     ['OS!="ios"', {
+      'includes': [
+        'media_cdm.gypi',
+      ],
       'targets': [
         {
           # Minimal target for NaCl and other renderer side media clients which
diff --git a/media/media.target.darwin-arm.mk b/media/media.target.darwin-arm.mk
index 9a453af..4c15e9f 100644
--- a/media/media.target.darwin-arm.mk
+++ b/media/media.target.darwin-arm.mk
@@ -114,7 +114,7 @@
 	media/base/video_renderer.cc \
 	media/base/video_util.cc \
 	media/base/yuv_convert.cc \
-	media/crypto/aes_decryptor.cc \
+	media/cdm/aes_decryptor.cc \
 	media/filters/audio_decoder_selector.cc \
 	media/filters/audio_renderer_algorithm.cc \
 	media/filters/audio_renderer_impl.cc \
@@ -220,6 +220,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DPOSIX_AVOID_MMAP' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-D__STDC_CONSTANT_MACROS' \
@@ -331,6 +332,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DPOSIX_AVOID_MMAP' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-D__STDC_CONSTANT_MACROS' \
diff --git a/media/media.target.darwin-mips.mk b/media/media.target.darwin-mips.mk
index 0df3761..e18928c 100644
--- a/media/media.target.darwin-mips.mk
+++ b/media/media.target.darwin-mips.mk
@@ -114,7 +114,7 @@
 	media/base/video_renderer.cc \
 	media/base/video_util.cc \
 	media/base/yuv_convert.cc \
-	media/crypto/aes_decryptor.cc \
+	media/cdm/aes_decryptor.cc \
 	media/filters/audio_decoder_selector.cc \
 	media/filters/audio_renderer_algorithm.cc \
 	media/filters/audio_renderer_impl.cc \
@@ -219,6 +219,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DPOSIX_AVOID_MMAP' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-D__STDC_CONSTANT_MACROS' \
@@ -329,6 +330,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DPOSIX_AVOID_MMAP' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-D__STDC_CONSTANT_MACROS' \
diff --git a/media/media.target.darwin-x86.mk b/media/media.target.darwin-x86.mk
index 665877b..d4ee0ac 100644
--- a/media/media.target.darwin-x86.mk
+++ b/media/media.target.darwin-x86.mk
@@ -114,7 +114,7 @@
 	media/base/video_renderer.cc \
 	media/base/video_util.cc \
 	media/base/yuv_convert.cc \
-	media/crypto/aes_decryptor.cc \
+	media/cdm/aes_decryptor.cc \
 	media/filters/audio_decoder_selector.cc \
 	media/filters/audio_renderer_algorithm.cc \
 	media/filters/audio_renderer_impl.cc \
@@ -223,6 +223,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
@@ -336,6 +337,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
diff --git a/media/media.target.linux-arm.mk b/media/media.target.linux-arm.mk
index 9a453af..4c15e9f 100644
--- a/media/media.target.linux-arm.mk
+++ b/media/media.target.linux-arm.mk
@@ -114,7 +114,7 @@
 	media/base/video_renderer.cc \
 	media/base/video_util.cc \
 	media/base/yuv_convert.cc \
-	media/crypto/aes_decryptor.cc \
+	media/cdm/aes_decryptor.cc \
 	media/filters/audio_decoder_selector.cc \
 	media/filters/audio_renderer_algorithm.cc \
 	media/filters/audio_renderer_impl.cc \
@@ -220,6 +220,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DPOSIX_AVOID_MMAP' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-D__STDC_CONSTANT_MACROS' \
@@ -331,6 +332,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DPOSIX_AVOID_MMAP' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-D__STDC_CONSTANT_MACROS' \
diff --git a/media/media.target.linux-mips.mk b/media/media.target.linux-mips.mk
index 0df3761..e18928c 100644
--- a/media/media.target.linux-mips.mk
+++ b/media/media.target.linux-mips.mk
@@ -114,7 +114,7 @@
 	media/base/video_renderer.cc \
 	media/base/video_util.cc \
 	media/base/yuv_convert.cc \
-	media/crypto/aes_decryptor.cc \
+	media/cdm/aes_decryptor.cc \
 	media/filters/audio_decoder_selector.cc \
 	media/filters/audio_renderer_algorithm.cc \
 	media/filters/audio_renderer_impl.cc \
@@ -219,6 +219,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DPOSIX_AVOID_MMAP' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-D__STDC_CONSTANT_MACROS' \
@@ -329,6 +330,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DPOSIX_AVOID_MMAP' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-D__STDC_CONSTANT_MACROS' \
diff --git a/media/media.target.linux-x86.mk b/media/media.target.linux-x86.mk
index 665877b..d4ee0ac 100644
--- a/media/media.target.linux-x86.mk
+++ b/media/media.target.linux-x86.mk
@@ -114,7 +114,7 @@
 	media/base/video_renderer.cc \
 	media/base/video_util.cc \
 	media/base/yuv_convert.cc \
-	media/crypto/aes_decryptor.cc \
+	media/cdm/aes_decryptor.cc \
 	media/filters/audio_decoder_selector.cc \
 	media/filters/audio_renderer_algorithm.cc \
 	media/filters/audio_renderer_impl.cc \
@@ -223,6 +223,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
@@ -336,6 +337,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
diff --git a/webkit/renderer/media/webkit_media.gypi b/media/media_cdm.gypi
similarity index 81%
rename from webkit/renderer/media/webkit_media.gypi
rename to media/media_cdm.gypi
index 198ebfe..a4a94f7 100644
--- a/webkit/renderer/media/webkit_media.gypi
+++ b/media/media_cdm.gypi
@@ -29,8 +29,8 @@
         ['use_fake_video_decoder == 1' , {
           'defines': ['CLEAR_KEY_CDM_USE_FAKE_VIDEO_DECODER'],
           'sources': [
-            'crypto/ppapi/fake_cdm_video_decoder.cc',
-            'crypto/ppapi/fake_cdm_video_decoder.h',
+            'cdm/ppapi/fake_cdm_video_decoder.cc',
+            'cdm/ppapi/fake_cdm_video_decoder.h',
           ],
         }],
         ['use_ffmpeg == 1'  , {
@@ -39,14 +39,14 @@
             '<(DEPTH)/third_party/ffmpeg/ffmpeg.gyp:ffmpeg',
           ],
           'sources': [
-            'crypto/ppapi/ffmpeg_cdm_audio_decoder.cc',
-            'crypto/ppapi/ffmpeg_cdm_audio_decoder.h',
+            'cdm/ppapi/ffmpeg_cdm_audio_decoder.cc',
+            'cdm/ppapi/ffmpeg_cdm_audio_decoder.h',
           ],
         }],
         ['use_ffmpeg == 1 and use_fake_video_decoder == 0'  , {
           'sources': [
-            'crypto/ppapi/ffmpeg_cdm_video_decoder.cc',
-            'crypto/ppapi/ffmpeg_cdm_video_decoder.h',
+            'cdm/ppapi/ffmpeg_cdm_video_decoder.cc',
+            'cdm/ppapi/ffmpeg_cdm_video_decoder.h',
           ],
         }],
         ['use_libvpx == 1 and use_fake_video_decoder == 0' , {
@@ -55,8 +55,8 @@
             '<(DEPTH)/third_party/libvpx/libvpx.gyp:libvpx',
           ],
           'sources': [
-            'crypto/ppapi/libvpx_cdm_video_decoder.cc',
-            'crypto/ppapi/libvpx_cdm_video_decoder.h',
+            'cdm/ppapi/libvpx_cdm_video_decoder.cc',
+            'cdm/ppapi/libvpx_cdm_video_decoder.h',
           ],
         }],
         ['os_posix == 1 and OS != "mac" and enable_pepper_cdms==1', {
@@ -73,16 +73,16 @@
       ],
       'defines': ['CDM_IMPLEMENTATION'],
       'dependencies': [
-        '<(DEPTH)/base/base.gyp:base',
-        '<(DEPTH)/media/media.gyp:media',
+        'media',
         # Include the following for media::AudioBus.
-        '<(DEPTH)/media/media.gyp:shared_memory_support',
+        'shared_memory_support',
+        '<(DEPTH)/base/base.gyp:base',
       ],
       'sources': [
-        'crypto/ppapi/cdm_video_decoder.cc',
-        'crypto/ppapi/cdm_video_decoder.h',
-        'crypto/ppapi/clear_key_cdm.cc',
-        'crypto/ppapi/clear_key_cdm.h',
+        'cdm/ppapi/cdm_video_decoder.cc',
+        'cdm/ppapi/cdm_video_decoder.h',
+        'cdm/ppapi/clear_key_cdm.cc',
+        'cdm/ppapi/clear_key_cdm.h',
       ],
       # TODO(jschuh): crbug.com/167187 fix size_t to int truncations.
       'msvs_disabled_warnings': [ 4267, ],
@@ -97,9 +97,9 @@
         'clearkeycdm',
       ],
       'sources': [
-        'crypto/ppapi/cdm_wrapper.cc',
-        'crypto/ppapi/cdm/content_decryption_module.h',
-        'crypto/ppapi/linked_ptr.h',
+        'cdm/ppapi/api/content_decryption_module.h',
+        'cdm/ppapi/cdm_wrapper.cc',
+        'cdm/ppapi/linked_ptr.h',
       ],
       'conditions': [
         ['os_posix == 1 and OS != "mac" and enable_pepper_cdms==1', {
diff --git a/media/video/capture/win/video_capture_device_win.cc b/media/video/capture/win/video_capture_device_win.cc
index 81f057a..1a7c3b7 100644
--- a/media/video/capture/win/video_capture_device_win.cc
+++ b/media/video/capture/win/video_capture_device_win.cc
@@ -7,9 +7,11 @@
 #include <algorithm>
 #include <list>
 
+#include "base/command_line.h"
 #include "base/strings/string_util.h"
 #include "base/strings/sys_string_conversions.h"
 #include "base/win/scoped_variant.h"
+#include "media/base/media_switches.h"
 #include "media/video/capture/win/video_capture_device_mf_win.h"
 
 using base::win::ScopedComPtr;
@@ -150,7 +152,9 @@
 void VideoCaptureDevice::GetDeviceNames(Names* device_names) {
   Names::iterator it;
 
-  if (VideoCaptureDeviceMFWin::PlatformSupported()) {
+  const CommandLine* cmd_line = CommandLine::ForCurrentProcess();
+  if (VideoCaptureDeviceMFWin::PlatformSupported() &&
+      !cmd_line->HasSwitch(switches::kForceDirectShowVideoCapture)) {
     VideoCaptureDeviceMFWin::GetDeviceNames(device_names);
   }
   // Retrieve the devices with DirectShow (DS) interface. They might (partially)
diff --git a/native_client_sdk/src/build_tools/build_sdk.py b/native_client_sdk/src/build_tools/build_sdk.py
index 190e5c3..37626fa 100755
--- a/native_client_sdk/src/build_tools/build_sdk.py
+++ b/native_client_sdk/src/build_tools/build_sdk.py
@@ -54,7 +54,7 @@
 CYGTAR = os.path.join(NACL_DIR, 'build', 'cygtar.py')
 
 NACLPORTS_URL = 'https://naclports.googlecode.com/svn/trunk/src'
-NACLPORTS_REV = 774
+NACLPORTS_REV = 850
 
 GYPBUILD_DIR = 'gypbuild'
 
@@ -186,6 +186,18 @@
   open(os.path.join(pepperdir, 'README'), 'w').write(readme_text)
 
 
+def PrunePNaClToolchain(root):
+  dirs_to_prune = [
+    'newlib/lib-bc-x86-64',
+    'newlib/usr-bc-x86-64'
+    # TODO(sbc): remove this once its really not needed.
+    # Currently we seem to rely on it at least for <bits/stat.h>
+    #'newlib/sysroot',
+  ]
+  for dirname in dirs_to_prune:
+    buildbot_common.RemoveDir(os.path.join(root, dirname))
+
+
 def BuildStepUntarToolchains(pepperdir, arch, toolchains):
   buildbot_common.BuildStep('Untar Toolchains')
   platform = getos.GetPlatform()
@@ -236,6 +248,7 @@
     # Then rename/move it to the pepper toolchain directory
     pnacldir = os.path.join(pepperdir, 'toolchain', tcname + '_pnacl')
     buildbot_common.Move(tmpdir, pnacldir)
+    PrunePNaClToolchain(pnacldir)
 
   buildbot_common.RemoveDir(tmpdir)
 
diff --git a/native_client_sdk/src/build_tools/sdk_files.list b/native_client_sdk/src/build_tools/sdk_files.list
index f4e890a..a210f4a 100644
--- a/native_client_sdk/src/build_tools/sdk_files.list
+++ b/native_client_sdk/src/build_tools/sdk_files.list
@@ -314,7 +314,6 @@
 include/nacl_io/error.h
 include/nacl_io/event_emitter.h
 include/nacl_io/event_listener.h
-include/nacl_io/error.h
 include/nacl_io/host_resolver.h
 include/nacl_io/inode_pool.h
 include/nacl_io/ioctl.h
@@ -331,10 +330,12 @@
 include/nacl_io/mount_http.h
 include/nacl_io/mount_mem.h
 include/nacl_io/mount_node.h
+include/nacl_io/mount_node_char.h
 include/nacl_io/mount_node_dir.h
 include/nacl_io/mount_node_html5fs.h
 include/nacl_io/mount_node_http.h
 include/nacl_io/mount_node_mem.h
+include/nacl_io/mount_node_tty.h
 include/nacl_io/mount_passthrough.h
 include/nacl_io/nacl_io.h
 include/nacl_io/osdirent.h
@@ -357,8 +358,10 @@
 include/newlib/arpa/inet.h
 include/newlib/netdb.h
 include/newlib/netinet/in.h
+include/newlib/netinet/tcp.h
 include/newlib/netinet6/in6.h
 include/newlib/poll.h
+include/newlib/sys/mount.h
 include/newlib/sys/select.h
 include/newlib/sys/socket.h
 include/newlib/sys/termios.h
@@ -366,8 +369,10 @@
 include/pnacl/arpa/inet.h
 include/pnacl/netdb.h
 include/pnacl/netinet/in.h
+include/pnacl/netinet/tcp.h
 include/pnacl/netinet6/in6.h
 include/pnacl/poll.h
+include/pnacl/sys/mount.h
 include/pnacl/sys/select.h
 include/pnacl/sys/socket.h
 include/pnacl/sys/termios.h
@@ -612,7 +617,6 @@
 [win]include/win/pthread.h
 [win]include/win/sched.h
 [win]include/win/semaphore.h
-
 [linux]lib/${PLATFORM}_host/Debug/libgmock.a
 [linux]lib/${PLATFORM}_host/Debug/libgtest.a
 [linux]lib/${PLATFORM}_host/Debug/libjsoncpp.a
@@ -858,33 +862,58 @@
 src/nacl_io/mount_node_html5fs.cc
 src/nacl_io/mount_node_http.cc
 src/nacl_io/mount_node_mem.cc
+src/nacl_io/mount_node_tty.cc
 src/nacl_io/mount_passthrough.cc
 src/nacl_io/nacl_io.cc
 src/nacl_io/path.cc
 src/nacl_io/pepper_interface.cc
 src/nacl_io/real_pepper_interface.cc
+src/nacl_io/syscalls/accept.c
 src/nacl_io/syscalls/access.c
+src/nacl_io/syscalls/bind.c
 src/nacl_io/syscalls/chdir.c
 src/nacl_io/syscalls/chmod.c
 src/nacl_io/syscalls/chown.c
+src/nacl_io/syscalls/connect.c
 src/nacl_io/syscalls/fchown.c
 src/nacl_io/syscalls/fsync.c
 src/nacl_io/syscalls/ftruncate.c
 src/nacl_io/syscalls/getcwd.c
 src/nacl_io/syscalls/getdents.c
+src/nacl_io/syscalls/gethostbyname.c
+src/nacl_io/syscalls/getpeername.c
+src/nacl_io/syscalls/getsockname.c
+src/nacl_io/syscalls/getsockopt.c
 src/nacl_io/syscalls/getwd.c
+src/nacl_io/syscalls/herror.c
+src/nacl_io/syscalls/hstrerror.cc
+src/nacl_io/syscalls/htonl.c
+src/nacl_io/syscalls/htons.c
 src/nacl_io/syscalls/inet_ntoa.cc
 src/nacl_io/syscalls/inet_ntop.cc
 src/nacl_io/syscalls/ioctl.c
 src/nacl_io/syscalls/isatty.c
 src/nacl_io/syscalls/lchown.c
 src/nacl_io/syscalls/link.c
+src/nacl_io/syscalls/listen.c
 src/nacl_io/syscalls/mkdir.c
 src/nacl_io/syscalls/mount.c
+src/nacl_io/syscalls/ntohl.c
+src/nacl_io/syscalls/ntohs.c
 src/nacl_io/syscalls/poll.c
+src/nacl_io/syscalls/recv.c
+src/nacl_io/syscalls/recvfrom.c
+src/nacl_io/syscalls/recvmsg.c
 src/nacl_io/syscalls/remove.c
 src/nacl_io/syscalls/rmdir.c
 src/nacl_io/syscalls/select.c
+src/nacl_io/syscalls/send.c
+src/nacl_io/syscalls/sendmsg.c
+src/nacl_io/syscalls/sendto.c
+src/nacl_io/syscalls/setsockopt.c
+src/nacl_io/syscalls/shutdown.c
+src/nacl_io/syscalls/socket.c
+src/nacl_io/syscalls/socketpair.c
 src/nacl_io/syscalls/tcflush.c
 src/nacl_io/syscalls/tcgetattr.c
 src/nacl_io/syscalls/tcsetattr.c
diff --git a/native_client_sdk/src/examples/common.js b/native_client_sdk/src/examples/common.js
index efa140c..51adb54 100644
--- a/native_client_sdk/src/examples/common.js
+++ b/native_client_sdk/src/examples/common.js
@@ -6,6 +6,10 @@
 // string.
 var isTest = false;
 
+// Set to true when loading a "Release" NaCl module, false when loading a
+// "Debug" NaCl module.
+var isRelease = false;
+
 // Javascript module pattern:
 //   see http://en.wikipedia.org/wiki/Unobtrusive_JavaScript#Namespaces
 // In essence, we define an anonymous function which is immediately called and
@@ -22,11 +26,10 @@
    * Return the mime type for NaCl plugin.
    *
    * @param {string} tool The name of the toolchain, e.g. "glibc", "newlib" etc.
-   * @param {bool} isRelease True if this is a release build.
    * @return {string} The mime-type for the kind of NaCl plugin matching
    * the given toolchain.
    */
-  function mimeTypeForTool(tool, isRelease) {
+  function mimeTypeForTool(tool) {
     // For NaCl modules use application/x-nacl.
     var mimetype = 'application/x-nacl';
     if (isHostToolchain(tool)) {
@@ -36,7 +39,7 @@
         mimetype = 'application/x-ppapi-release';
       else
         mimetype = 'application/x-ppapi-debug';
-    } else if (tool == 'pnacl') {
+    } else if (tool == 'pnacl' && isRelease) {
       mimetype = 'application/x-pnacl';
     }
     return mimetype;
@@ -293,8 +296,7 @@
     // status message indicating that the module is still loading.  Otherwise,
     // do not change the status message.
     updateStatus('Page loaded.');
-    var isRelease = path.toLowerCase().indexOf('release') != -1;
-    if (!browserSupportsNaCl(tool, isRelease)) {
+    if (!browserSupportsNaCl(tool)) {
       updateStatus(
           'Browser does not support NaCl (' + tool + '), or NaCl is disabled');
     } else if (common.naclModule == null) {
@@ -399,6 +401,7 @@
       var path = pathFormat.replace('{tc}', tc).replace('{config}', config);
 
       isTest = searchVars.test === 'true';
+      isRelease = path.toLowerCase().indexOf('release') != -1;
 
       loadFunction(body.dataset.name, tc, path, body.dataset.width,
                    body.dataset.height, attrs);
diff --git a/native_client_sdk/src/examples/demo/earth/earth.cc b/native_client_sdk/src/examples/demo/earth/earth.cc
index d0c6de7..2a1c958 100644
--- a/native_client_sdk/src/examples/demo/earth/earth.cc
+++ b/native_client_sdk/src/examples/demo/earth/earth.cc
@@ -383,9 +383,14 @@
   if (!base_tex_ || !night_tex_)
     return;
   const int kColorBlack = MakeRGBA(0, 0, 0, 0xFF);
+  float width = ps_context_->width;
+  float height = ps_context_->height;
+  float min_dim = width < height ? width : height;
+  float offset_x = width < height ? 0 : (width - min_dim) * 0.5f;
+  float offset_y = width < height ? (height - min_dim) * 0.5f : 0;
   float y0 = eye_y_;
   float z0 = eye_z_;
-  float y1 = (static_cast<float>(y) / ps_context_->height) * 2.0f - 1.0f;
+  float y1 = (static_cast<float>(y - offset_y) / min_dim) * 2.0f - 1.0f;
   float z1 = 0.0f;
   float dy = (y1 - y0);
   float dz = (z1 - z0);
@@ -394,11 +399,11 @@
                                   2.0f * dz * (z0 - planet_z_);
   float planet_xyz_eye_xyz = planet_xyz_ + eye_xyz_;
   float y_y0_z_z0 = planet_y_ * y0 + planet_z_ * z0;
-  float oowidth = 1.0f / ps_context_->width;
+  float oowidth = 1.0f / min_dim;
   uint32_t* pixels = this->wGetAddr(x0, y);
   for (int x = x0; x <= x1; ++x) {
     // scan normalized screen -1..1
-    float x1 = (static_cast<float>(x) * oowidth) * 2.0f - 1.0f;
+    float x1 = (static_cast<float>(x - offset_x) * oowidth) * 2.0f - 1.0f;
     // eye
     float x0 = eye_x_;
     // delta from screen to eye
diff --git a/native_client_sdk/src/examples/demo/flock/flock.cc b/native_client_sdk/src/examples/demo/flock/flock.cc
index de23691..94707a0 100644
--- a/native_client_sdk/src/examples/demo/flock/flock.cc
+++ b/native_client_sdk/src/examples/demo/flock/flock.cc
@@ -5,14 +5,13 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <sys/mount.h>
 
 #include <algorithm>
 #include <sstream>
 #include <string>
 #include <vector>
 
-#include "nacl_io/nacl_io.h"
-
 #include "ppapi/c/pp_rect.h"
 #include "ppapi/c/pp_size.h"
 
diff --git a/native_client_sdk/src/examples/demo/nacl_io/nacl_io_demo.c b/native_client_sdk/src/examples/demo/nacl_io/nacl_io_demo.c
index 9a1babd..c38fefc 100644
--- a/native_client_sdk/src/examples/demo/nacl_io/nacl_io_demo.c
+++ b/native_client_sdk/src/examples/demo/nacl_io/nacl_io_demo.c
@@ -9,6 +9,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <sys/mount.h>
 #include <pthread.h>
 
 #include "ppapi/c/pp_errors.h"
diff --git a/native_client_sdk/src/examples/tutorial/dlopen/dlopen.cc b/native_client_sdk/src/examples/tutorial/dlopen/dlopen.cc
index 9291464..8b5df97 100644
--- a/native_client_sdk/src/examples/tutorial/dlopen/dlopen.cc
+++ b/native_client_sdk/src/examples/tutorial/dlopen/dlopen.cc
@@ -7,6 +7,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <sys/mount.h>
 
 #include <ppapi/cpp/completion_callback.h>
 #include <ppapi/cpp/instance.h>
diff --git a/native_client_sdk/src/libraries/nacl_io/host_resolver.cc b/native_client_sdk/src/libraries/nacl_io/host_resolver.cc
index f059f9a..beae726 100644
--- a/native_client_sdk/src/libraries/nacl_io/host_resolver.cc
+++ b/native_client_sdk/src/libraries/nacl_io/host_resolver.cc
@@ -4,13 +4,9 @@
 
 #include "nacl_io/host_resolver.h"
 
-#include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 
-#include <sstream>
-#include <string>
-
 #include "nacl_io/kernel_proxy.h"
 #include "nacl_io/ossocket.h"
 #include "nacl_io/pepper_interface.h"
@@ -176,51 +172,6 @@
   hostent_.h_addr_list = NULL;
 }
 
-void HostResolver::herror(const char* s) {
-  if (s) {
-    fprintf(stderr, "%s: ", s);
-  }
-
-  fprintf(stderr, "%s\n", hstrerror(h_errno));
-}
-
-const char* HostResolver::hstrerror(int err) {
-  // These error message texts are taken straight from the man page
-  const char* host_not_found_msg =
-    "The specified host is unknown.";
-  const char* no_address_msg =
-    "The requested name is valid but does not have an IP address.";
-  const char* no_recovery_msg =
-    "A nonrecoverable name server error occurred.";
-  const char* try_again_msg =
-    "A temporary error occurred on an authoritative name server. "
-    "Try again later.";
-  const char* internal_msg =
-    "Internal error in gethostbyname.";
-  const char* unknown_msg_base =
-    "Unknown error in gethostbyname: ";
-
-  switch (err) {
-    case HOST_NOT_FOUND:
-      return host_not_found_msg;
-    case NO_ADDRESS:
-      return no_address_msg;
-    case NO_RECOVERY:
-      return no_recovery_msg;
-    case TRY_AGAIN:
-      return try_again_msg;
-    case NETDB_INTERNAL:
-      return internal_msg;
-    default:
-      std::stringstream msg;
-      msg << unknown_msg_base << err << ".";
-
-      static std::string unknown_msg;
-      unknown_msg.assign(msg.str());
-      return unknown_msg.c_str();
-  }
-}
-
 }  // namespace nacl_io
 
 #endif  // PROVIDES_SOCKET_API
diff --git a/native_client_sdk/src/libraries/nacl_io/host_resolver.h b/native_client_sdk/src/libraries/nacl_io/host_resolver.h
index 0a942bd..59f3f7f 100644
--- a/native_client_sdk/src/libraries/nacl_io/host_resolver.h
+++ b/native_client_sdk/src/libraries/nacl_io/host_resolver.h
@@ -20,8 +20,6 @@
   void Init(PepperInterface* ppapi);
 
   struct hostent* gethostbyname(const char* name);
-  static void herror(const char* s);
-  static const char* hstrerror(int err);
 
  private:
   void hostent_initialize();
diff --git a/native_client_sdk/src/libraries/nacl_io/include/sys/mount.h b/native_client_sdk/src/libraries/nacl_io/include/sys/mount.h
new file mode 100644
index 0000000..dde0ab3
--- /dev/null
+++ b/native_client_sdk/src/libraries/nacl_io/include/sys/mount.h
@@ -0,0 +1,19 @@
+/* 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 LIBRARIES_NACL_IO_INCLUDE_SYS_MOUNT_H
+#define LIBRARIES_NACL_IO_INCLUDE_SYS_MOUNT_H
+
+#include <sys/cdefs.h>
+
+__BEGIN_DECLS
+
+int mount(const char* source, const char* target, const char* filesystemtype,
+          unsigned long mountflags, const void *data);
+
+int umount(const char *target);
+
+__END_DECLS
+
+#endif  /* LIBRARIES_NACL_IO_INCLUDE_SYS_MOUNT_H */
diff --git a/native_client_sdk/src/libraries/nacl_io/include/sys/termios.h b/native_client_sdk/src/libraries/nacl_io/include/sys/termios.h
index 8eabbd9..a817565 100644
--- a/native_client_sdk/src/libraries/nacl_io/include/sys/termios.h
+++ b/native_client_sdk/src/libraries/nacl_io/include/sys/termios.h
@@ -2,8 +2,8 @@
  * Use of this source code is governed by a BSD-style license that can be
  * found in the LICENSE file. */
 
-#ifndef SYS_TERMIOS_H_
-#define SYS_TERMIOS_H_
+#ifndef LIBRARIES_NACL_IO_INCLUDE_SYS_TERMIOS_H_
+#define LIBRARIES_NACL_IO_INCLUDE_SYS_TERMIOS_H_
 
 #define IGNBRK  0000001
 #define BRKINT  0000002
@@ -126,4 +126,4 @@
 
 __END_DECLS
 
-#endif  /* SYS_TERMIOS_H_ */
+#endif  /* LIBRARIES_NACL_IO_INCLUDE_SYS_TERMIOS_H_ */
diff --git a/native_client_sdk/src/libraries/nacl_io/include/sys/utsname.h b/native_client_sdk/src/libraries/nacl_io/include/sys/utsname.h
index 2e3cd3d..2292915 100644
--- a/native_client_sdk/src/libraries/nacl_io/include/sys/utsname.h
+++ b/native_client_sdk/src/libraries/nacl_io/include/sys/utsname.h
@@ -2,8 +2,8 @@
  * Use of this source code is governed by a BSD-style license that can be
  * found in the LICENSE file. */
 
-#ifndef LIBRARIES_NACL_SYS_UTSNAME_H_
-#define LIBRARIES_NACL_SYS_UTSNAME_H_
+#ifndef LIBRARIES_NACL_IO_INCLUDE_SYS_UTSNAME_H_
+#define LIBRARIES_NACL_IO_INCLUDE_SYS_UTSNAME_H_
 
 #define _UTSNAME_LENGTH 65
 
@@ -15,6 +15,12 @@
   char machine[_UTSNAME_LENGTH];
 };
 
+#include <sys/cdefs.h>
+
+__BEGIN_DECLS
+
 int uname(struct utsname *buf);
 
-#endif
+__END_DECLS
+
+#endif  /* LIBRARIES_NACL_IO_INCLUDE_SYS_UTSNAME_H_ */
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 912fd18..d1bad01 100644
--- a/native_client_sdk/src/libraries/nacl_io/kernel_intercept.cc
+++ b/native_client_sdk/src/libraries/nacl_io/kernel_intercept.cc
@@ -287,14 +287,6 @@
   return s_kp->getsockopt(fd, lvl, optname, optval, len);
 }
 
-void ki_herror(const char *s) {
-  return s_kp->herror(s);
-}
-
-const char *ki_hstrerror(int err) {
-  return s_kp->hstrerror(err);
-}
-
 int ki_listen(int fd, int backlog) {
   return s_kp->listen(fd, backlog);
 }
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 b570c8f..6ef44b3 100644
--- a/native_client_sdk/src/libraries/nacl_io/kernel_intercept.h
+++ b/native_client_sdk/src/libraries/nacl_io/kernel_intercept.h
@@ -85,8 +85,6 @@
 int ki_getpeername(int fd, struct sockaddr* addr, socklen_t* len);
 int ki_getsockname(int fd, struct sockaddr* addr, socklen_t* len);
 int ki_getsockopt(int fd, int lvl, int optname, void* optval, socklen_t* len);
-void ki_herror(const char *s);
-const char *ki_hstrerror(int err);
 int ki_listen(int fd, int backlog);
 ssize_t ki_recv(int fd, void* buf, size_t len, int flags);
 ssize_t ki_recvfrom(int fd, void* buf, size_t len, int flags,
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 a64a800..292f91e 100644
--- a/native_client_sdk/src/libraries/nacl_io/kernel_proxy.cc
+++ b/native_client_sdk/src/libraries/nacl_io/kernel_proxy.cc
@@ -975,14 +975,6 @@
   return -1;
 }
 
-void KernelProxy::herror(const char* s) {
-  return host_resolver_.herror(s);
-}
-
-const char* KernelProxy::hstrerror(int err) {
-  return host_resolver_.hstrerror(err);
-}
-
 int KernelProxy::listen(int fd, int backlog) {
   ScopedKernelHandle handle;
   if (AcquireSocketHandle(fd, &handle) == -1)
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 47b6f77..fc0191f 100644
--- a/native_client_sdk/src/libraries/nacl_io/kernel_proxy.h
+++ b/native_client_sdk/src/libraries/nacl_io/kernel_proxy.h
@@ -142,8 +142,6 @@
                          int optname,
                          void* optval,
                          socklen_t* len);
-  virtual void herror(const char* s);
-  virtual const char* hstrerror(int err);
   virtual int listen(int fd, int backlog);
   virtual ssize_t recv(int fd,
                        void* buf,
diff --git a/native_client_sdk/src/libraries/nacl_io/kernel_wrap.h b/native_client_sdk/src/libraries/nacl_io/kernel_wrap.h
index 6b79d4f..33a4c2d 100644
--- a/native_client_sdk/src/libraries/nacl_io/kernel_wrap.h
+++ b/native_client_sdk/src/libraries/nacl_io/kernel_wrap.h
@@ -106,8 +106,6 @@
 int getpeername(int fd, struct sockaddr* addr, socklen_t* len);
 int getsockname(int fd, struct sockaddr* addr, socklen_t* len);
 int getsockopt(int fd, int lvl, int optname, void* optval, socklen_t* len);
-void herror(const char *s);
-const char *hstrerror(int err);
 int listen(int fd, int backlog);
 ssize_t recv(int fd, void* buf, size_t len, int flags);
 ssize_t recvfrom(int fd, void* buf, size_t len, int flags,
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 7c52f4d..c2a9e1f 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
@@ -11,6 +11,7 @@
 #include "nacl_io/kernel_wrap.h"
 
 #include <alloca.h>
+#include <assert.h>
 #include <dirent.h>
 #include <errno.h>
 #include <irt.h>
@@ -103,9 +104,14 @@
 // Macro to get the WRAP function
 #define WRAP(name) __nacl_irt_##name##_wrap
 
-// Declare REAL function pointer and assign it the REAL function.
+// Declare REAL function pointer.
 #define DECLARE_REAL_PTR(name) \
-  typeof(__nacl_irt_##name) REAL(name) = __nacl_irt_##name;
+  typeof(__nacl_irt_##name) REAL(name);
+
+// Assign the REAL function pointer.
+#define ASSIGN_REAL_PTR(name) \
+  assert(__nacl_irt_##name != NULL); \
+  REAL(name) = __nacl_irt_##name;
 
 // Switch IRT's pointer to the REAL pointer
 #define USE_REAL(name) \
@@ -279,90 +285,6 @@
   return (signed_nwrote < 0) ? errno : 0;
 }
 
-// Socket functions
-int accept(int fd, struct sockaddr* addr, socklen_t* len) {
-  return ki_accept(fd, addr, len);
-}
-
-int bind(int fd, const struct sockaddr* addr, socklen_t len) {
-  return ki_bind(fd, addr, len);
-}
-
-int connect(int fd, const struct sockaddr* addr, socklen_t len) {
-  return ki_connect(fd, addr, len);
-}
-
-struct hostent* gethostbyname(const char* name) {
-  return ki_gethostbyname(name);
-}
-
-int getpeername(int fd, struct sockaddr* addr, socklen_t* len) {
-  return ki_getpeername(fd, addr, len);
-}
-
-int getsockname(int fd, struct sockaddr* addr, socklen_t* len) {
-  return ki_getsockname(fd, addr, len);
-}
-
-int getsockopt(int fd, int lvl, int optname, void* optval, socklen_t* len) {
-  return ki_getsockopt(fd, lvl, optname, optval, len);
-}
-
-void herror(const char *s) {
-  return ki_herror(s);
-}
-
-const char *hstrerror(int err) {
-  return ki_hstrerror(err);
-}
-
-int listen(int fd, int backlog) {
-  return ki_listen(fd, backlog);
-}
-
-ssize_t recv(int fd, void* buf, size_t len, int flags) {
-  return ki_recv(fd, buf, len, flags);
-}
-
-ssize_t recvfrom(int fd, void* buf, size_t len, int flags,
-                 struct sockaddr* addr, socklen_t* addrlen) {
-  return ki_recvfrom(fd, buf, len, flags, addr, addrlen);
-}
-
-ssize_t recvmsg(int fd, struct msghdr* msg, int flags) {
-  return ki_recvmsg(fd, msg, flags);
-}
-
-ssize_t send(int fd, const void* buf, size_t len, int flags) {
-  return ki_send(fd, buf, len, flags);
-}
-
-ssize_t sendto(int fd, const void* buf, size_t len, int flags,
-               const struct sockaddr* addr, socklen_t addrlen) {
-  return ki_sendto(fd, buf, len, flags, addr, addrlen);
-}
-
-ssize_t sendmsg(int fd, const struct msghdr* msg, int flags) {
-  return ki_sendmsg(fd, msg, flags);
-}
-
-int setsockopt(int fd, int lvl, int optname, const void* optval,
-                  socklen_t len) {
-  return ki_setsockopt(fd, lvl, optname, optval, len);
-}
-
-int shutdown(int fd, int how) {
-  return ki_shutdown(fd, how);
-}
-
-int socket(int domain, int type, int protocol) {
-  return ki_socket(domain, type, protocol);
-}
-
-int socketpair(int domain, int type, int protocol, int* sv) {
-  return ki_socketpair(domain, type, protocol, sv);
-}
-
 // "real" functions, i.e. the unwrapped original functions.
 
 int _real_close(int fd) {
@@ -454,8 +376,13 @@
 }
 
 static bool s_wrapped = false;
+static bool s_assigned = false;
 void kernel_wrap_init() {
   if (!s_wrapped) {
+    if (!s_assigned) {
+      EXPAND_SYMBOL_LIST_OPERATION(ASSIGN_REAL_PTR)
+      s_assigned = true;
+    }
     EXPAND_SYMBOL_LIST_OPERATION(USE_WRAP)
     s_wrapped = true;
   }
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 e218301..34ab407 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
@@ -9,6 +9,7 @@
 #if defined(__native_client__) && !defined(__GLIBC__)
 
 #include "nacl_io/kernel_wrap.h"
+#include <assert.h>
 #include <dirent.h>
 #include <errno.h>
 #include <irt.h>
@@ -25,9 +26,14 @@
 // Macro to get the WRAP function
 #define WRAP(name) __nacl_irt_##name##_wrap
 
-// Declare REAL function pointer and assign it the REAL function.
+// Declare REAL function pointer.
 #define DECLARE_REAL_PTR(group, name) \
-  typeof(__libnacl_irt_##group.name) REAL(name) = __libnacl_irt_##group.name;
+  typeof(__libnacl_irt_##group.name) REAL(name);
+
+// Assign the REAL function pointer.
+#define ASSIGN_REAL_PTR(group, name) \
+  assert(__libnacl_irt_##group.name != NULL); \
+  REAL(name) = __libnacl_irt_##group.name;
 
 // Switch IRT's pointer to the REAL pointer
 #define USE_REAL(group, name) \
@@ -37,10 +43,10 @@
 #define USE_WRAP(group, name) \
   __libnacl_irt_##group.name = (typeof(REAL(name))) WRAP(name); \
 
-
+extern void __libnacl_irt_filename_init(void);
 
 extern struct nacl_irt_fdio __libnacl_irt_fdio;
-extern struct nacl_irt_filename __libnacl_irt_filename;
+extern struct nacl_irt_dev_filename __libnacl_irt_dev_filename;
 extern struct nacl_irt_memory __libnacl_irt_memory;
 
 // Create function pointers to the REAL implementation
@@ -53,8 +59,8 @@
   OP(fdio, read); \
   OP(fdio, seek); \
   OP(fdio, write); \
-  OP(filename, open); \
-  OP(filename, stat); \
+  OP(dev_filename, open); \
+  OP(dev_filename, stat); \
   OP(memory, mmap); \
   OP(memory, munmap);
 
@@ -131,90 +137,6 @@
   return (signed_nwrote < 0) ? errno : 0;
 }
 
-// Socket functions
-int accept(int fd, struct sockaddr* addr, socklen_t* len) {
-  return ki_accept(fd, addr, len);
-}
-
-int bind(int fd, const struct sockaddr* addr, socklen_t len) {
-  return ki_bind(fd, addr, len);
-}
-
-int connect(int fd, const struct sockaddr* addr, socklen_t len) {
-  return ki_connect(fd, addr, len);
-}
-
-struct hostent* gethostbyname(const char* name) {
-  return ki_gethostbyname(name);
-}
-
-int getpeername(int fd, struct sockaddr* addr, socklen_t* len) {
-  return ki_getpeername(fd, addr, len);
-}
-
-int getsockname(int fd, struct sockaddr* addr, socklen_t* len) {
-  return ki_getsockname(fd, addr, len);
-}
-
-int getsockopt(int fd, int lvl, int optname, void* optval, socklen_t* len) {
-  return ki_getsockopt(fd, lvl, optname, optval, len);
-}
-
-void herror(const char* s) {
-  return ki_herror(s);
-}
-
-const char* hstrerror(int err) {
-  return ki_hstrerror(err);
-}
-
-int listen(int fd, int backlog) {
-  return ki_listen(fd, backlog);
-}
-
-ssize_t recv(int fd, void* buf, size_t len, int flags) {
-  return ki_recv(fd, buf, len, flags);
-}
-
-ssize_t recvfrom(int fd, void* buf, size_t len, int flags,
-                 struct sockaddr* addr, socklen_t* addrlen) {
-  return ki_recvfrom(fd, buf, len, flags, addr, addrlen);
-}
-
-ssize_t recvmsg(int fd, struct msghdr* msg, int flags) {
-  return ki_recvmsg(fd, msg, flags);
-}
-
-ssize_t send(int fd, const void* buf, size_t len, int flags) {
-  return ki_send(fd, buf, len, flags);
-}
-
-ssize_t sendto(int fd, const void* buf, size_t len, int flags,
-               const struct sockaddr* addr, socklen_t addrlen) {
-  return ki_sendto(fd, buf, len, flags, addr, addrlen);
-}
-
-ssize_t sendmsg(int fd, const struct msghdr* msg, int flags) {
-  return ki_sendmsg(fd, msg, flags);
-}
-
-int setsockopt(int fd, int lvl, int optname, const void* optval,
-               socklen_t len) {
-  return ki_setsockopt(fd, lvl, optname, optval, len);
-}
-
-int shutdown(int fd, int how) {
-  return ki_shutdown(fd, how);
-}
-
-int socket(int domain, int type, int protocol) {
-  return ki_socket(domain, type, protocol);
-}
-
-int socketpair(int domain, int type, int protocol, int* sv) {
-  return ki_socketpair(domain, type, protocol, sv);
-}
-
 // "real" functions, i.e. the unwrapped original functions.
 
 int _real_close(int fd) {
@@ -273,16 +195,22 @@
 }
 
 static bool s_wrapped = false;
+static bool s_assigned = false;
 void kernel_wrap_init() {
   if (!s_wrapped) {
-    EXPAND_SYMBOL_LIST_OPERATION(USE_WRAP);
+    if (!s_assigned) {
+      __libnacl_irt_filename_init();
+      EXPAND_SYMBOL_LIST_OPERATION(ASSIGN_REAL_PTR)
+      s_assigned = true;
+    }
+    EXPAND_SYMBOL_LIST_OPERATION(USE_WRAP)
     s_wrapped = true;
   }
 }
 
 void kernel_wrap_uninit() {
   if (s_wrapped) {
-    EXPAND_SYMBOL_LIST_OPERATION(USE_REAL);
+    EXPAND_SYMBOL_LIST_OPERATION(USE_REAL)
     s_wrapped = false;
   }
 }
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 b13d7f8..9a9bce6 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
@@ -5,6 +5,7 @@
 #ifndef LIBRARIES_NACL_IO_KERNEL_WRAP_REAL_H_
 #define LIBRARIES_NACL_IO_KERNEL_WRAP_REAL_H_
 
+#include "nacl_io/osstat.h"
 #include "nacl_io/ostypes.h"
 #include "sdk_util/macros.h"
 
diff --git a/native_client_sdk/src/libraries/nacl_io/library.dsc b/native_client_sdk/src/libraries/nacl_io/library.dsc
index 011a9c6..4d75b2c 100644
--- a/native_client_sdk/src/libraries/nacl_io/library.dsc
+++ b/native_client_sdk/src/libraries/nacl_io/library.dsc
@@ -32,36 +32,61 @@
         "mount_node_html5fs.cc",
         "mount_node_http.cc",
         "mount_node_mem.cc",
+        "mount_node_tty.cc",
         "mount_passthrough.cc",
         "nacl_io.cc",
         "path.cc",
         "pepper_interface.cc",
         "real_pepper_interface.cc",
+        "syscalls/accept.c",
         "syscalls/access.c",
+        "syscalls/bind.c",
         "syscalls/chdir.c",
         "syscalls/chmod.c",
         "syscalls/chown.c",
+        "syscalls/connect.c",
         "syscalls/fchown.c",
         "syscalls/fsync.c",
         "syscalls/ftruncate.c",
-        "syscalls/getdents.c",
-        "syscalls/getwd.c",
         "syscalls/getcwd.c",
+        "syscalls/getdents.c",
+        "syscalls/gethostbyname.c",
+        "syscalls/getpeername.c",
+        "syscalls/getsockname.c",
+        "syscalls/getsockopt.c",
+        "syscalls/getwd.c",
+        "syscalls/herror.c",
+        "syscalls/hstrerror.cc",
+        "syscalls/htonl.c",
+        "syscalls/htons.c",
         "syscalls/inet_ntoa.cc",
         "syscalls/inet_ntop.cc",
         "syscalls/ioctl.c",
         "syscalls/isatty.c",
-        "syscalls/link.c",
         "syscalls/lchown.c",
+        "syscalls/link.c",
+        "syscalls/listen.c",
         "syscalls/mkdir.c",
         "syscalls/mount.c",
+        "syscalls/ntohl.c",
+        "syscalls/ntohs.c",
         "syscalls/poll.c",
-        "syscalls/remove.c",
         "syscalls/rmdir.c",
-        "syscalls/select.c",
+        "syscalls/recv.c",
+        "syscalls/recvfrom.c",
+        "syscalls/recvmsg.c",
+        "syscalls/remove.c",
         "syscalls/tcflush.c",
         "syscalls/tcgetattr.c",
         "syscalls/tcsetattr.c",
+        "syscalls/select.c",
+        "syscalls/send.c",
+        "syscalls/sendmsg.c",
+        "syscalls/sendto.c",
+        "syscalls/setsockopt.c",
+        "syscalls/shutdown.c",
+        "syscalls/socket.c",
+        "syscalls/socketpair.c",
         "syscalls/unlink.c",
         "syscalls/umount.c",
         "syscalls/uname.c",
@@ -90,11 +115,13 @@
         "mount_html5fs.h",
         "mount_http.h",
         "mount_mem.h",
-        "mount_node_dir.h",
         "mount_node.h",
+        "mount_node_char.h",
+        "mount_node_dir.h",
         "mount_node_html5fs.h",
         "mount_node_http.h",
         "mount_node_mem.h",
+        "mount_node_tty.h",
         "mount_passthrough.h",
         "nacl_io.h",
         "osdirent.h",
@@ -119,8 +146,10 @@
         "arpa/inet.h",
         "netdb.h",
         "netinet/in.h",
+        "netinet/tcp.h",
         "netinet6/in6.h",
         "poll.h",
+        "sys/mount.h",
         "sys/select.h",
         "sys/socket.h",
         "sys/termios.h",
@@ -133,8 +162,10 @@
         "arpa/inet.h",
         "netdb.h",
         "netinet/in.h",
+        "netinet/tcp.h",
         "netinet6/in6.h",
         "poll.h",
+        "sys/mount.h",
         "sys/select.h",
         "sys/socket.h",
         "sys/termios.h",
diff --git a/native_client_sdk/src/libraries/nacl_io/mount_dev.cc b/native_client_sdk/src/libraries/nacl_io/mount_dev.cc
index f409b19..3c7ffe0 100644
--- a/native_client_sdk/src/libraries/nacl_io/mount_dev.cc
+++ b/native_client_sdk/src/libraries/nacl_io/mount_dev.cc
@@ -11,13 +11,11 @@
 #include <pthread.h>
 #include <string.h>
 
-#include <deque>
-
-#include "nacl_io/ioctl.h"
 #include "nacl_io/kernel_wrap_real.h"
 #include "nacl_io/mount_dev.h"
 #include "nacl_io/mount_node.h"
 #include "nacl_io/mount_node_dir.h"
+#include "nacl_io/mount_node_tty.h"
 #include "nacl_io/osunistd.h"
 #include "nacl_io/pepper_interface.h"
 #include "sdk_util/auto_lock.h"
@@ -47,9 +45,9 @@
   int fd_;
 };
 
-class NullNode : public MountNode {
+class NullNode : public MountNodeCharDevice {
  public:
-  explicit NullNode(Mount* mount);
+  explicit NullNode(Mount* mount) : MountNodeCharDevice(mount) {}
 
   virtual Error Read(size_t offs, void* buf, size_t count, int* out_bytes);
   virtual Error Write(size_t offs,
@@ -58,7 +56,7 @@
                       int* out_bytes);
 };
 
-class ConsoleNode : public NullNode {
+class ConsoleNode : public MountNodeCharDevice {
  public:
   ConsoleNode(Mount* mount, PP_LogLevel level);
 
@@ -71,30 +69,6 @@
   PP_LogLevel level_;
 };
 
-class TtyNode : public NullNode {
- public:
-  explicit TtyNode(Mount* mount);
-  ~TtyNode();
-
-  virtual Error Ioctl(int request,
-                      char* arg);
-
-  virtual Error Read(size_t offs,
-                     void* buf,
-                     size_t count,
-                     int* out_bytes);
-
-  virtual Error Write(size_t offs,
-                      const void* buf,
-                      size_t count,
-                      int* out_bytes);
-
- private:
-  std::deque<char> input_buffer_;
-  pthread_cond_t is_readable_;
-  std::string prefix_;
-};
-
 class ZeroNode : public MountNode {
  public:
   explicit ZeroNode(Mount* mount);
@@ -156,8 +130,6 @@
 
 Error RealNode::GetStat(struct stat* stat) { return _real_fstat(fd_, stat); }
 
-NullNode::NullNode(Mount* mount) : MountNode(mount) { stat_.st_mode = S_IFCHR; }
-
 Error NullNode::Read(size_t offs, void* buf, size_t count, int* out_bytes) {
   *out_bytes = 0;
   return 0;
@@ -172,8 +144,7 @@
 }
 
 ConsoleNode::ConsoleNode(Mount* mount, PP_LogLevel level)
-    : NullNode(mount), level_(level) {
-  stat_.st_mode = S_IFCHR;
+    : MountNodeCharDevice(mount), level_(level) {
 }
 
 Error ConsoleNode::Write(size_t offs,
@@ -197,88 +168,6 @@
   return 0;
 }
 
-TtyNode::TtyNode(Mount* mount) : NullNode(mount) {
-  pthread_cond_init(&is_readable_, NULL);
-}
-
-TtyNode::~TtyNode() {
-  pthread_cond_destroy(&is_readable_);
-}
-
-Error TtyNode::Write(size_t offs,
-                     const void* buf,
-                     size_t count,
-                     int* out_bytes) {
-  *out_bytes = 0;
-
-  MessagingInterface* msg_intr = mount_->ppapi()->GetMessagingInterface();
-  VarInterface* var_intr = mount_->ppapi()->GetVarInterface();
-
-  if (!(var_intr && msg_intr))
-    return ENOSYS;
-
-  // We append the prefix_ to the data in buf, then package it up
-  // and post it as a message.
-  const char* data = static_cast<const char*>(buf);
-  std::string message;
-  {
-    AUTO_LOCK(node_lock_);
-    message = prefix_;
-  }
-  message.append(data, count);
-  uint32_t len = static_cast<uint32_t>(message.size());
-  struct PP_Var val = var_intr->VarFromUtf8(message.data(), len);
-  msg_intr->PostMessage(mount_->ppapi()->GetInstance(), val);
-  *out_bytes = count;
-  return 0;
-}
-
-Error TtyNode::Read(size_t offs, void* buf, size_t count, int* out_bytes) {
-  AUTO_LOCK(node_lock_);
-  while (input_buffer_.size() <= 0) {
-    pthread_cond_wait(&is_readable_, node_lock_.mutex());
-  }
-
-  // Copies data from the input buffer into buf.
-  size_t bytes_to_copy = std::min(count, input_buffer_.size());
-  std::copy(input_buffer_.begin(), input_buffer_.begin() + bytes_to_copy,
-            static_cast<char*>(buf));
-  *out_bytes = bytes_to_copy;
-  input_buffer_.erase(input_buffer_.begin(),
-                      input_buffer_.begin() + bytes_to_copy);
-  return 0;
-}
-
-Error TtyNode::Ioctl(int request, char* arg) {
-  if (request == TIOCNACLPREFIX) {
-    // This ioctl is used to change the prefix for this tty node.
-    // The prefix is used to distinguish messages intended for this
-    // tty node from all the other messages cluttering up the
-    // javascript postMessage() channel.
-    AUTO_LOCK(node_lock_);
-    prefix_ = arg;
-    return 0;
-  } else if (request == TIOCNACLINPUT) {
-    // This ioctl is used to deliver data from the user to this tty node's
-    // input buffer. We check if the prefix in the input data matches the
-    // prefix for this node, and only deliver the data if so.
-    struct tioc_nacl_input_string* message =
-      reinterpret_cast<struct tioc_nacl_input_string*>(arg);
-    AUTO_LOCK(node_lock_);
-    if (message->length >= prefix_.size() &&
-        strncmp(message->buffer, prefix_.data(), prefix_.size()) == 0) {
-      input_buffer_.insert(input_buffer_.end(),
-                           message->buffer + prefix_.size(),
-                           message->buffer + message->length);
-      pthread_cond_broadcast(&is_readable_);
-      return 0;
-    }
-    return ENOTTY;
-  } else {
-    return EINVAL;
-  }
-}
-
 ZeroNode::ZeroNode(Mount* mount) : MountNode(mount) { stat_.st_mode = S_IFCHR; }
 
 Error ZeroNode::Read(size_t offs, void* buf, size_t count, int* out_bytes) {
@@ -407,7 +296,7 @@
   INITIALIZE_DEV_NODE_1("/console1", ConsoleNode, PP_LOGLEVEL_LOG);
   INITIALIZE_DEV_NODE_1("/console2", ConsoleNode, PP_LOGLEVEL_WARNING);
   INITIALIZE_DEV_NODE_1("/console3", ConsoleNode, PP_LOGLEVEL_ERROR);
-  INITIALIZE_DEV_NODE("/tty", TtyNode);
+  INITIALIZE_DEV_NODE("/tty", MountNodeTty);
   INITIALIZE_DEV_NODE_1("/stdin", RealNode, 0);
   INITIALIZE_DEV_NODE_1("/stdout", RealNode, 1);
   INITIALIZE_DEV_NODE_1("/stderr", RealNode, 2);
diff --git a/native_client_sdk/src/libraries/nacl_io/mount_node_char.h b/native_client_sdk/src/libraries/nacl_io/mount_node_char.h
new file mode 100644
index 0000000..48ad86f
--- /dev/null
+++ b/native_client_sdk/src/libraries/nacl_io/mount_node_char.h
@@ -0,0 +1,21 @@
+// 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 LIBRARIES_NACL_IO_MOUNT_NODE_CHAR_H
+#define LIBRARIES_NACL_IO_MOUNT_NODE_CHAR_H
+
+#include "nacl_io/mount_node.h"
+
+namespace nacl_io {
+
+class MountNodeCharDevice : public MountNode {
+ public:
+  explicit MountNodeCharDevice(Mount* mount) : MountNode(mount) {
+    stat_.st_mode = S_IFCHR;
+  }
+};
+
+}
+
+#endif  // LIBRARIES_NACL_IO_MOUNT_NODE_CHAR_H
diff --git a/native_client_sdk/src/libraries/nacl_io/mount_node_tty.cc b/native_client_sdk/src/libraries/nacl_io/mount_node_tty.cc
new file mode 100644
index 0000000..7b9fb79
--- /dev/null
+++ b/native_client_sdk/src/libraries/nacl_io/mount_node_tty.cc
@@ -0,0 +1,271 @@
+// 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 "nacl_io/mount_node_tty.h"
+
+#include <assert.h>
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <algorithm>
+
+#include "nacl_io/ioctl.h"
+#include "nacl_io/mount.h"
+#include "nacl_io/pepper_interface.h"
+#include "sdk_util/auto_lock.h"
+
+#define CHECK_LFLAG(TERMIOS, FLAG) (TERMIOS .c_lflag & FLAG)
+
+#define IS_ECHO CHECK_LFLAG(termios_, ECHO)
+#define IS_ECHOE CHECK_LFLAG(termios_, ECHOE)
+#define IS_ECHONL CHECK_LFLAG(termios_, ECHONL)
+#define IS_ECHOCTL CHECK_LFLAG(termios_, ECHOCTL)
+#define IS_ICANON CHECK_LFLAG(termios_, ICANON)
+
+namespace nacl_io {
+
+MountNodeTty::MountNodeTty(Mount* mount) : MountNodeCharDevice(mount),
+                                           is_readable_(false) {
+  pthread_cond_init(&is_readable_cond_, NULL);
+  InitTermios();
+}
+
+void MountNodeTty::InitTermios() {
+  // Some sane values that produce good result.
+  termios_.c_iflag = ICRNL | IXON | IXOFF | IUTF8;
+  termios_.c_oflag = OPOST | ONLCR;
+  termios_.c_cflag = CREAD | 077;
+  termios_.c_lflag =
+      ISIG | ICANON | ECHO | ECHOE | ECHOK | ECHOCTL | ECHOKE | IEXTEN;
+  termios_.c_ispeed = B38400;
+  termios_.c_ospeed = B38400;
+  termios_.c_cc[VINTR] = 3;
+  termios_.c_cc[VQUIT] = 28;
+  termios_.c_cc[VERASE] = 127;
+  termios_.c_cc[VKILL] = 21;
+  termios_.c_cc[VEOF] = 4;
+  termios_.c_cc[VTIME] = 0;
+  termios_.c_cc[VMIN] = 1;
+  termios_.c_cc[VSWTC] = 0;
+  termios_.c_cc[VSTART] = 17;
+  termios_.c_cc[VSTOP] = 19;
+  termios_.c_cc[VSUSP] = 26;
+  termios_.c_cc[VEOL] = 0;
+  termios_.c_cc[VREPRINT] = 18;
+  termios_.c_cc[VDISCARD] = 15;
+  termios_.c_cc[VWERASE] = 23;
+  termios_.c_cc[VLNEXT] = 22;
+  termios_.c_cc[VEOL2] = 0;
+}
+
+MountNodeTty::~MountNodeTty() {
+  pthread_cond_destroy(&is_readable_cond_);
+}
+
+Error MountNodeTty::Write(size_t offs,
+                     const void* buf,
+                     size_t count,
+                     int* out_bytes) {
+  return Write(offs, buf, count, out_bytes, false);
+}
+
+Error MountNodeTty::Write(size_t offs,
+                     const void* buf,
+                     size_t count,
+                     int* out_bytes,
+                     bool locked) {
+  *out_bytes = 0;
+
+  if (!mount_->ppapi())
+    return ENOSYS;
+
+  MessagingInterface* msg_intr = mount_->ppapi()->GetMessagingInterface();
+  VarInterface* var_intr = mount_->ppapi()->GetVarInterface();
+
+  if (!(var_intr && msg_intr))
+    return ENOSYS;
+
+  // We append the prefix_ to the data in buf, then package it up
+  // and post it as a message.
+  const char* data = static_cast<const char*>(buf);
+  std::string message;
+  if (locked) {
+    message = prefix_;
+  } else {
+    AUTO_LOCK(node_lock_);
+    message = prefix_;
+  }
+
+  message.append(data, count);
+  uint32_t len = static_cast<uint32_t>(message.size());
+  struct PP_Var val = var_intr->VarFromUtf8(message.data(), len);
+  msg_intr->PostMessage(mount_->ppapi()->GetInstance(), val);
+  var_intr->Release(val);
+  *out_bytes = count;
+  return 0;
+}
+
+Error MountNodeTty::Read(size_t offs, void* buf, size_t count, int* out_bytes) {
+  AUTO_LOCK(node_lock_);
+  while (!is_readable_) {
+    pthread_cond_wait(&is_readable_cond_, node_lock_.mutex());
+  }
+
+  size_t bytes_to_copy = std::min(count, input_buffer_.size());
+
+  if (IS_ICANON) {
+    // Only read up to (and including) the first newline
+    std::deque<char>::iterator nl = std::find(input_buffer_.begin(),
+                                              input_buffer_.end(),
+                                              '\n');
+
+    if (nl != input_buffer_.end()) {
+      // We found a newline in the buffer, adjust bytes_to_copy accordingly
+      size_t line_len = static_cast<size_t>(nl - input_buffer_.begin()) + 1;
+      bytes_to_copy = std::min(bytes_to_copy, line_len);
+    }
+  }
+
+
+  // Copies data from the input buffer into buf.
+  std::copy(input_buffer_.begin(), input_buffer_.begin() + bytes_to_copy,
+            static_cast<char*>(buf));
+  *out_bytes = bytes_to_copy;
+  input_buffer_.erase(input_buffer_.begin(),
+                      input_buffer_.begin() + bytes_to_copy);
+
+  // mark input as no longer readable if we consumed
+  // the entire buffer or, in the case of buffered input,
+  // we consumed the final \n char.
+  if (IS_ICANON)
+    is_readable_ =
+        std::find(input_buffer_.begin(),
+                  input_buffer_.end(), '\n') != input_buffer_.end();
+  else
+    is_readable_ = input_buffer_.size() > 0;
+
+  return 0;
+}
+
+Error MountNodeTty::Echo(const char* string, int count) {
+  int wrote;
+  Error error = Write(0, string, count, &wrote, true);
+  if (error != 0 || wrote != count) {
+    // TOOD(sbc): Do something more useful in response to a
+    // failure to echo.
+    return error;
+  }
+
+  return 0;
+}
+
+Error MountNodeTty::ProcessInput(struct tioc_nacl_input_string* message) {
+  AUTO_LOCK(node_lock_);
+  if (message->length < prefix_.size() ||
+      strncmp(message->buffer, prefix_.data(), prefix_.size()) != 0) {
+    return ENOTTY;
+  }
+
+  const char* buffer = message->buffer + prefix_.size();
+  int num_bytes = message->length - prefix_.size();
+
+  for (int i = 0; i < num_bytes; i++) {
+    char c = buffer[i];
+    // Transform characters according to input flags.
+    if (c == '\r') {
+      if (termios_.c_iflag & IGNCR)
+        continue;
+      if (termios_.c_iflag & ICRNL)
+        c = '\n';
+    } else if (c == '\n') {
+      if (termios_.c_iflag & INLCR)
+        c = '\r';
+    }
+
+    bool skip = false;
+
+    // ICANON mode means we wait for a newline before making the
+    // file readable.
+    if (IS_ICANON) {
+      if (IS_ECHOE && c == termios_.c_cc[VERASE]) {
+        // Remove previous character in the line if any.
+        if (!input_buffer_.empty()) {
+          char char_to_delete = input_buffer_.back();
+          if (char_to_delete != '\n') {
+            input_buffer_.pop_back();
+            if (IS_ECHO)
+              Echo("\b \b", 3);
+
+            // When ECHOCTL is set the echo buffer contains an extra
+            // char for each control char.
+            if (IS_ECHOCTL && iscntrl(char_to_delete))
+              Echo("\b \b", 3);
+          }
+        }
+        continue;
+      } else if (IS_ECHO || (IS_ECHONL && c == '\n')) {
+        if (c == termios_.c_cc[VEOF]) {
+          // VEOF sequence is not echoed, nor is it sent as
+          // input.
+          skip = true;
+        } else if (c != '\n' && iscntrl(c) && IS_ECHOCTL) {
+          // In ECHOCTL mode a control char C is echoed  as '^'
+          // followed by the ascii char which at C + 0x40.
+          char visible_char = c + 0x40;
+          Echo("^", 1);
+          Echo(&visible_char, 1);
+        } else {
+          Echo(&c, 1);
+        }
+      }
+    }
+
+    if (!skip)
+      input_buffer_.push_back(c);
+
+    if (c == '\n' || c == termios_.c_cc[VEOF] || !IS_ICANON)
+      is_readable_ = true;
+  }
+
+  if (is_readable_)
+    pthread_cond_broadcast(&is_readable_cond_);
+  return 0;
+}
+
+Error MountNodeTty::Ioctl(int request, char* arg) {
+  if (request == TIOCNACLPREFIX) {
+    // This ioctl is used to change the prefix for this tty node.
+    // The prefix is used to distinguish messages intended for this
+    // tty node from all the other messages cluttering up the
+    // javascript postMessage() channel.
+    AUTO_LOCK(node_lock_);
+    prefix_ = arg;
+    return 0;
+  } else if (request == TIOCNACLINPUT) {
+    // This ioctl is used to deliver data from the user to this tty node's
+    // input buffer. We check if the prefix in the input data matches the
+    // prefix for this node, and only deliver the data if so.
+    struct tioc_nacl_input_string* message =
+      reinterpret_cast<struct tioc_nacl_input_string*>(arg);
+    return ProcessInput(message);
+  } else {
+    return EINVAL;
+  }
+}
+
+Error MountNodeTty::Tcgetattr(struct termios* termios_p) {
+  AUTO_LOCK(node_lock_);
+  *termios_p = termios_;
+  return 0;
+}
+
+Error MountNodeTty::Tcsetattr(int optional_actions,
+                         const struct termios *termios_p) {
+  AUTO_LOCK(node_lock_);
+  termios_ = *termios_p;
+  return 0;
+}
+
+}
diff --git a/native_client_sdk/src/libraries/nacl_io/mount_node_tty.h b/native_client_sdk/src/libraries/nacl_io/mount_node_tty.h
new file mode 100644
index 0000000..0707420
--- /dev/null
+++ b/native_client_sdk/src/libraries/nacl_io/mount_node_tty.h
@@ -0,0 +1,60 @@
+// 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 LIBRARIES_NACL_IO_MOUNT_NODE_TTY_H_
+#define LIBRARIES_NACL_IO_MOUNT_NODE_TTY_H_
+
+#include <pthread.h>
+
+#include <deque>
+
+#include "nacl_io/ioctl.h"
+#include "nacl_io/mount_node_char.h"
+#include "nacl_io/ostermios.h"
+
+
+namespace nacl_io {
+
+class MountNodeTty : public MountNodeCharDevice {
+ public:
+  explicit MountNodeTty(Mount* mount);
+  ~MountNodeTty();
+
+  virtual Error Ioctl(int request,
+                      char* arg);
+
+  virtual Error Read(size_t offs,
+                     void* buf,
+                     size_t count,
+                     int* out_bytes);
+
+  virtual Error Write(size_t offs,
+                      const void* buf,
+                      size_t count,
+                      int* out_bytes);
+
+  virtual Error Tcgetattr(struct termios* termios_p);
+  virtual Error Tcsetattr(int optional_actions,
+                          const struct termios *termios_p);
+
+ private:
+  virtual Error Write(size_t offs,
+                      const void* buf,
+                      size_t count,
+                      int* out_bytes,
+                      bool locked);
+  Error ProcessInput(struct tioc_nacl_input_string* message);
+  Error Echo(const char* string, int count);
+  void InitTermios();
+
+  std::deque<char> input_buffer_;
+  bool is_readable_;
+  pthread_cond_t is_readable_cond_;
+  std::string prefix_;
+  struct termios termios_;
+};
+
+}
+
+#endif
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 e72b5a5..058ba68 100644
--- a/native_client_sdk/src/libraries/nacl_io/nacl_io.h
+++ b/native_client_sdk/src/libraries/nacl_io/nacl_io.h
@@ -8,20 +8,20 @@
 #include <ppapi/c/pp_instance.h>
 #include <ppapi/c/ppb.h>
 
-#include "nacl_io/kernel_wrap.h"
 #include "sdk_util/macros.h"
 
 EXTERN_C_BEGIN
 
-
-/** Initialize nacl_io.
+/**
+ * Initialize nacl_io.
  *
  * NOTE: If you initialize nacl_io with this constructor, you cannot
  * use any mounts that require PPAPI; e.g. persistent storage, etc.
  */
 void nacl_io_init();
 
-/** Initialize nacl_io with PPAPI support.
+/**
+ * Initialize nacl_io with PPAPI support.
  *
  * Usage:
  *   PP_Instance instance;
@@ -42,7 +42,11 @@
                         PPB_GetInterface get_interface);
 
 
-/** Mount a new filesystem type.
+/**
+ * Mount a new filesystem type.
+ *
+ * This function is declared in <sys/mount.h>, but we document it here
+ * because nacl_io is controlled primarily through mount(2)/umount(2).
  *
  * Some parameters are dependent on the filesystem type being mounted.
  *
@@ -108,9 +112,10 @@
  * @param[in] mountflags Unused.
  * @param[in] data Depends on the filesystem type. See above.
  * @return 0 on success, -1 on failure (with errno set).
+ *
+ * int mount(const char* source, const char* target, const char* filesystemtype,
+ *         unsigned long mountflags, const void *data) NOTHROW;
  */
-int mount(const char* source, const char* target, const char* filesystemtype,
-          unsigned long mountflags, const void *data) NOTHROW;
 
 EXTERN_C_END
 
diff --git a/native_client_sdk/src/libraries/nacl_io/pepper/all_interfaces.h b/native_client_sdk/src/libraries/nacl_io/pepper/all_interfaces.h
index cb75d73..1f2e1bf 100644
--- a/native_client_sdk/src/libraries/nacl_io/pepper/all_interfaces.h
+++ b/native_client_sdk/src/libraries/nacl_io/pepper/all_interfaces.h
@@ -64,6 +64,7 @@
 END_INTERFACE(MessagingInterface, PPB_Messaging)
 
 BEGIN_INTERFACE(VarInterface, PPB_Var, PPB_VAR_INTERFACE_1_1)
+  METHOD1(VarInterface, void, Release, struct PP_Var)
   METHOD2(VarInterface, struct PP_Var, VarFromUtf8, const char *, uint32_t)
   METHOD2(VarInterface, const char*, VarToUtf8, PP_Var, uint32_t*)
 END_INTERFACE(VarInterface, PPB_Var)
diff --git a/native_client_sdk/src/libraries/nacl_io/syscalls/accept.c b/native_client_sdk/src/libraries/nacl_io/syscalls/accept.c
new file mode 100644
index 0000000..ff4f7df
--- /dev/null
+++ b/native_client_sdk/src/libraries/nacl_io/syscalls/accept.c
@@ -0,0 +1,14 @@
+/* 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 "nacl_io/kernel_intercept.h"
+#include "nacl_io/kernel_wrap.h"
+
+#ifdef PROVIDES_SOCKET_API
+
+int accept(int fd, struct sockaddr* addr, socklen_t* len) {
+  return ki_accept(fd, addr, len);
+}
+
+#endif
diff --git a/native_client_sdk/src/libraries/nacl_io/syscalls/bind.c b/native_client_sdk/src/libraries/nacl_io/syscalls/bind.c
new file mode 100644
index 0000000..2dbfb3b
--- /dev/null
+++ b/native_client_sdk/src/libraries/nacl_io/syscalls/bind.c
@@ -0,0 +1,14 @@
+/* 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 "nacl_io/kernel_intercept.h"
+#include "nacl_io/kernel_wrap.h"
+
+#ifdef PROVIDES_SOCKET_API
+
+int bind(int fd, const struct sockaddr* addr, socklen_t len) {
+  return ki_bind(fd, addr, len);
+}
+
+#endif
diff --git a/native_client_sdk/src/libraries/nacl_io/syscalls/connect.c b/native_client_sdk/src/libraries/nacl_io/syscalls/connect.c
new file mode 100644
index 0000000..8d2a10f
--- /dev/null
+++ b/native_client_sdk/src/libraries/nacl_io/syscalls/connect.c
@@ -0,0 +1,14 @@
+/* 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 "nacl_io/kernel_intercept.h"
+#include "nacl_io/kernel_wrap.h"
+
+#ifdef PROVIDES_SOCKET_API
+
+int connect(int fd, const struct sockaddr* addr, socklen_t len) {
+  return ki_connect(fd, addr, len);
+}
+
+#endif
diff --git a/native_client_sdk/src/libraries/nacl_io/syscalls/gethostbyname.c b/native_client_sdk/src/libraries/nacl_io/syscalls/gethostbyname.c
new file mode 100644
index 0000000..d370075
--- /dev/null
+++ b/native_client_sdk/src/libraries/nacl_io/syscalls/gethostbyname.c
@@ -0,0 +1,16 @@
+/* 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 "nacl_io/ossocket.h"
+
+#ifdef PROVIDES_SOCKET_API
+
+#include "nacl_io/kernel_intercept.h"
+#include "nacl_io/kernel_wrap.h"
+
+struct hostent* gethostbyname(const char* name) {
+  return ki_gethostbyname(name);
+}
+
+#endif /* PROVIDES_SOCKET_API */
diff --git a/native_client_sdk/src/libraries/nacl_io/syscalls/getpeername.c b/native_client_sdk/src/libraries/nacl_io/syscalls/getpeername.c
new file mode 100644
index 0000000..20d241c
--- /dev/null
+++ b/native_client_sdk/src/libraries/nacl_io/syscalls/getpeername.c
@@ -0,0 +1,14 @@
+/* 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 "nacl_io/kernel_intercept.h"
+#include "nacl_io/kernel_wrap.h"
+
+#ifdef PROVIDES_SOCKET_API
+
+int getpeername(int fd, struct sockaddr* addr, socklen_t* len) {
+  return ki_getpeername(fd, addr, len);
+}
+
+#endif
diff --git a/native_client_sdk/src/libraries/nacl_io/syscalls/getsockname.c b/native_client_sdk/src/libraries/nacl_io/syscalls/getsockname.c
new file mode 100644
index 0000000..79639de
--- /dev/null
+++ b/native_client_sdk/src/libraries/nacl_io/syscalls/getsockname.c
@@ -0,0 +1,14 @@
+/* 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 "nacl_io/kernel_intercept.h"
+#include "nacl_io/kernel_wrap.h"
+
+#ifdef PROVIDES_SOCKET_API
+
+int getsockname(int fd, struct sockaddr* addr, socklen_t* len) {
+  return ki_getsockname(fd, addr, len);
+}
+
+#endif
diff --git a/native_client_sdk/src/libraries/nacl_io/syscalls/getsockopt.c b/native_client_sdk/src/libraries/nacl_io/syscalls/getsockopt.c
new file mode 100644
index 0000000..aa55f22
--- /dev/null
+++ b/native_client_sdk/src/libraries/nacl_io/syscalls/getsockopt.c
@@ -0,0 +1,15 @@
+/* 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 "nacl_io/kernel_intercept.h"
+#include "nacl_io/kernel_wrap.h"
+
+#ifdef PROVIDES_SOCKET_API
+
+int getsockopt(int fd, int lvl, int optname, void* optval, socklen_t* len) {
+  return ki_getsockopt(fd, lvl, optname, optval, len);
+}
+
+#endif
+
diff --git a/native_client_sdk/src/libraries/nacl_io/syscalls/herror.c b/native_client_sdk/src/libraries/nacl_io/syscalls/herror.c
new file mode 100644
index 0000000..01bcd91
--- /dev/null
+++ b/native_client_sdk/src/libraries/nacl_io/syscalls/herror.c
@@ -0,0 +1,19 @@
+/* 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 "nacl_io/ossocket.h"
+
+#ifdef PROVIDES_SOCKET_API
+
+#include <stdio.h>
+
+void herror(const char* s) {
+  if (s) {
+    fprintf(stderr, "%s: ", s);
+  }
+
+  fprintf(stderr, "%s\n", hstrerror(h_errno));
+}
+
+#endif /* PROVIDES_SOCKET_API */
diff --git a/native_client_sdk/src/libraries/nacl_io/syscalls/hstrerror.cc b/native_client_sdk/src/libraries/nacl_io/syscalls/hstrerror.cc
new file mode 100644
index 0000000..f1354d9
--- /dev/null
+++ b/native_client_sdk/src/libraries/nacl_io/syscalls/hstrerror.cc
@@ -0,0 +1,54 @@
+// 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 "nacl_io/ossocket.h"
+
+#ifdef PROVIDES_SOCKET_API
+
+#include <sstream>
+#include <string>
+#include "sdk_util/macros.h"
+
+EXTERN_C_BEGIN
+
+const char* hstrerror(int err) {
+  // These error message texts are taken straight from the man page
+  const char* host_not_found_msg =
+    "The specified host is unknown.";
+  const char* no_address_msg =
+    "The requested name is valid but does not have an IP address.";
+  const char* no_recovery_msg =
+    "A nonrecoverable name server error occurred.";
+  const char* try_again_msg =
+    "A temporary error occurred on an authoritative name server. "
+    "Try again later.";
+  const char* internal_msg =
+    "Internal error in gethostbyname.";
+  const char* unknown_msg_base =
+    "Unknown error in gethostbyname: ";
+
+  switch (err) {
+    case HOST_NOT_FOUND:
+      return host_not_found_msg;
+    case NO_ADDRESS:
+      return no_address_msg;
+    case NO_RECOVERY:
+      return no_recovery_msg;
+    case TRY_AGAIN:
+      return try_again_msg;
+    case NETDB_INTERNAL:
+      return internal_msg;
+    default:
+      std::stringstream msg;
+      msg << unknown_msg_base << err << ".";
+
+      static std::string unknown_msg;
+      unknown_msg.assign(msg.str());
+      return unknown_msg.c_str();
+  }
+}
+
+EXTERN_C_END
+
+#endif // PROVIDES_SOCKET_API
diff --git a/native_client_sdk/src/libraries/nacl_io/syscalls/htonl.c b/native_client_sdk/src/libraries/nacl_io/syscalls/htonl.c
new file mode 100644
index 0000000..c29386f
--- /dev/null
+++ b/native_client_sdk/src/libraries/nacl_io/syscalls/htonl.c
@@ -0,0 +1,23 @@
+/* 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 "nacl_io/ossocket.h"
+
+#if defined(PROVIDES_SOCKET_API) && !defined(__GLIBC__)
+
+#include <string.h>
+
+inline uint32_t htonl(uint32_t hostlong) {
+  uint8_t result_bytes[4];
+  result_bytes[0] = (uint8_t) ((hostlong >> 24) & 0xFF);
+  result_bytes[1] = (uint8_t) ((hostlong >> 16) & 0xFF);
+  result_bytes[2] = (uint8_t) ((hostlong >> 8) & 0xFF);
+  result_bytes[3] = (uint8_t) (hostlong & 0xFF);
+
+  uint32_t result;
+  memcpy(&result, result_bytes, 4);
+  return result;
+}
+
+#endif  /* defined(PROVIDES_SOCKET_API) && !defined(__GLIBC__) */
diff --git a/native_client_sdk/src/libraries/nacl_io/syscalls/htons.c b/native_client_sdk/src/libraries/nacl_io/syscalls/htons.c
new file mode 100644
index 0000000..0bdab70
--- /dev/null
+++ b/native_client_sdk/src/libraries/nacl_io/syscalls/htons.c
@@ -0,0 +1,21 @@
+/* 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 "nacl_io/ossocket.h"
+
+#if defined(PROVIDES_SOCKET_API) && !defined(__GLIBC__)
+
+#include <string.h>
+
+inline uint16_t htons(uint16_t hostshort) {
+  uint8_t result_bytes[2];
+  result_bytes[0] = (uint8_t) ((hostshort >> 8) & 0xFF);
+  result_bytes[1] = (uint8_t) (hostshort & 0xFF);
+
+  uint16_t result;
+  memcpy(&result, result_bytes, 2);
+  return result;
+}
+
+#endif  /* defined(PROVIDES_SOCKET_API) && !defined(__GLIBC__) */
diff --git a/native_client_sdk/src/libraries/nacl_io/syscalls/inet_ntoa.cc b/native_client_sdk/src/libraries/nacl_io/syscalls/inet_ntoa.cc
index 93825e7..c6cf610 100644
--- a/native_client_sdk/src/libraries/nacl_io/syscalls/inet_ntoa.cc
+++ b/native_client_sdk/src/libraries/nacl_io/syscalls/inet_ntoa.cc
@@ -1,6 +1,6 @@
-/* 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 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 "nacl_io/ossocket.h"
 #if defined(PROVIDES_SOCKET_API) && !defined(__GLIBC__)
diff --git a/native_client_sdk/src/libraries/nacl_io/syscalls/inet_ntop.cc b/native_client_sdk/src/libraries/nacl_io/syscalls/inet_ntop.cc
index 807bdfe..ceabae5 100644
--- a/native_client_sdk/src/libraries/nacl_io/syscalls/inet_ntop.cc
+++ b/native_client_sdk/src/libraries/nacl_io/syscalls/inet_ntop.cc
@@ -1,6 +1,6 @@
-/* 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 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 "nacl_io/ossocket.h"
 #if defined(PROVIDES_SOCKET_API) && !defined(__GLIBC__)
diff --git a/native_client_sdk/src/libraries/nacl_io/syscalls/listen.c b/native_client_sdk/src/libraries/nacl_io/syscalls/listen.c
new file mode 100644
index 0000000..18c7c4f
--- /dev/null
+++ b/native_client_sdk/src/libraries/nacl_io/syscalls/listen.c
@@ -0,0 +1,14 @@
+/* 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 "nacl_io/kernel_intercept.h"
+#include "nacl_io/kernel_wrap.h"
+
+#ifdef PROVIDES_SOCKET_API
+
+int listen(int fd, int backlog) {
+  return ki_listen(fd, backlog);
+}
+
+#endif
diff --git a/native_client_sdk/src/libraries/nacl_io/syscalls/ntohl.c b/native_client_sdk/src/libraries/nacl_io/syscalls/ntohl.c
new file mode 100644
index 0000000..8338a6a
--- /dev/null
+++ b/native_client_sdk/src/libraries/nacl_io/syscalls/ntohl.c
@@ -0,0 +1,21 @@
+/* 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 "nacl_io/ossocket.h"
+
+#if defined(PROVIDES_SOCKET_API) && !defined(__GLIBC__)
+
+#include <string.h>
+
+inline uint32_t ntohl(uint32_t networklong) {
+  uint8_t input[4];
+  memcpy(input, &networklong, 4);
+
+  return ((((uint32_t) input[0]) << 24) |
+          (((uint32_t) input[1]) << 16) |
+          (((uint32_t) input[2]) << 8) |
+          ((uint32_t) input[3]));
+}
+
+#endif  /* defined(PROVIDES_SOCKET_API) && !defined(__GLIBC__) */
diff --git a/native_client_sdk/src/libraries/nacl_io/syscalls/ntohs.c b/native_client_sdk/src/libraries/nacl_io/syscalls/ntohs.c
new file mode 100644
index 0000000..19b6afe
--- /dev/null
+++ b/native_client_sdk/src/libraries/nacl_io/syscalls/ntohs.c
@@ -0,0 +1,19 @@
+/* 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 "nacl_io/ossocket.h"
+
+#if defined(PROVIDES_SOCKET_API) && !defined(__GLIBC__)
+
+#include <string.h>
+
+inline uint16_t ntohs(uint16_t networkshort) {
+  uint8_t input[2];
+  memcpy(input, &networkshort, 2);
+
+  return ((((uint32_t) input[0]) << 8) |
+          ((uint32_t) input[1]));
+}
+
+#endif  /* defined(PROVIDES_SOCKET_API) && !defined(__GLIBC__) */
diff --git a/native_client_sdk/src/libraries/nacl_io/syscalls/recv.c b/native_client_sdk/src/libraries/nacl_io/syscalls/recv.c
new file mode 100644
index 0000000..566798c
--- /dev/null
+++ b/native_client_sdk/src/libraries/nacl_io/syscalls/recv.c
@@ -0,0 +1,14 @@
+/* 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 "nacl_io/kernel_intercept.h"
+#include "nacl_io/kernel_wrap.h"
+
+#ifdef PROVIDES_SOCKET_API
+
+ssize_t recv(int fd, void* buf, size_t len, int flags) {
+  return ki_recv(fd, buf, len, flags);
+}
+
+#endif
diff --git a/native_client_sdk/src/libraries/nacl_io/syscalls/recvfrom.c b/native_client_sdk/src/libraries/nacl_io/syscalls/recvfrom.c
new file mode 100644
index 0000000..4032ced
--- /dev/null
+++ b/native_client_sdk/src/libraries/nacl_io/syscalls/recvfrom.c
@@ -0,0 +1,15 @@
+/* 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 "nacl_io/kernel_intercept.h"
+#include "nacl_io/kernel_wrap.h"
+
+#ifdef PROVIDES_SOCKET_API
+
+ssize_t recvfrom(int fd, void* buf, size_t len, int flags,
+                 struct sockaddr* addr, socklen_t* addrlen) {
+  return ki_recvfrom(fd, buf, len, flags, addr, addrlen);
+}
+
+#endif
diff --git a/native_client_sdk/src/libraries/nacl_io/syscalls/recvmsg.c b/native_client_sdk/src/libraries/nacl_io/syscalls/recvmsg.c
new file mode 100644
index 0000000..99cdd3a
--- /dev/null
+++ b/native_client_sdk/src/libraries/nacl_io/syscalls/recvmsg.c
@@ -0,0 +1,10 @@
+/* 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 "nacl_io/kernel_intercept.h"
+#include "nacl_io/kernel_wrap.h"
+
+ssize_t recvmsg(int fd, struct msghdr* msg, int flags) {
+  return ki_recvmsg(fd, msg, flags);
+}
diff --git a/native_client_sdk/src/libraries/nacl_io/syscalls/send.c b/native_client_sdk/src/libraries/nacl_io/syscalls/send.c
new file mode 100644
index 0000000..eb1d53c
--- /dev/null
+++ b/native_client_sdk/src/libraries/nacl_io/syscalls/send.c
@@ -0,0 +1,14 @@
+/* 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 "nacl_io/kernel_intercept.h"
+#include "nacl_io/kernel_wrap.h"
+
+#ifdef PROVIDES_SOCKET_API
+
+ssize_t send(int fd, const void* buf, size_t len, int flags) {
+  return ki_send(fd, buf, len, flags);
+}
+
+#endif
diff --git a/native_client_sdk/src/libraries/nacl_io/syscalls/sendmsg.c b/native_client_sdk/src/libraries/nacl_io/syscalls/sendmsg.c
new file mode 100644
index 0000000..64d020c
--- /dev/null
+++ b/native_client_sdk/src/libraries/nacl_io/syscalls/sendmsg.c
@@ -0,0 +1,14 @@
+/* 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 "nacl_io/kernel_intercept.h"
+#include "nacl_io/kernel_wrap.h"
+
+#ifdef PROVIDES_SOCKET_API
+
+ssize_t sendmsg(int fd, const struct msghdr* msg, int flags) {
+  return ki_sendmsg(fd, msg, flags);
+}
+
+#endif
diff --git a/native_client_sdk/src/libraries/nacl_io/syscalls/sendto.c b/native_client_sdk/src/libraries/nacl_io/syscalls/sendto.c
new file mode 100644
index 0000000..f0ab62f
--- /dev/null
+++ b/native_client_sdk/src/libraries/nacl_io/syscalls/sendto.c
@@ -0,0 +1,15 @@
+/* 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 "nacl_io/kernel_intercept.h"
+#include "nacl_io/kernel_wrap.h"
+
+#ifdef PROVIDES_SOCKET_API
+
+ssize_t sendto(int fd, const void* buf, size_t len, int flags,
+               const struct sockaddr* addr, socklen_t addrlen) {
+  return ki_sendto(fd, buf, len, flags, addr, addrlen);
+}
+
+#endif
diff --git a/native_client_sdk/src/libraries/nacl_io/syscalls/setsockopt.c b/native_client_sdk/src/libraries/nacl_io/syscalls/setsockopt.c
new file mode 100644
index 0000000..bde469e
--- /dev/null
+++ b/native_client_sdk/src/libraries/nacl_io/syscalls/setsockopt.c
@@ -0,0 +1,15 @@
+/* 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 "nacl_io/kernel_intercept.h"
+#include "nacl_io/kernel_wrap.h"
+
+#ifdef PROVIDES_SOCKET_API
+
+int setsockopt(int fd, int lvl, int optname, const void* optval,
+               socklen_t len) {
+  return ki_setsockopt(fd, lvl, optname, optval, len);
+}
+
+#endif
diff --git a/native_client_sdk/src/libraries/nacl_io/syscalls/shutdown.c b/native_client_sdk/src/libraries/nacl_io/syscalls/shutdown.c
new file mode 100644
index 0000000..985d95f
--- /dev/null
+++ b/native_client_sdk/src/libraries/nacl_io/syscalls/shutdown.c
@@ -0,0 +1,14 @@
+/* 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 "nacl_io/kernel_intercept.h"
+#include "nacl_io/kernel_wrap.h"
+
+#ifdef PROVIDES_SOCKET_API
+
+int shutdown(int fd, int how) {
+  return ki_shutdown(fd, how);
+}
+
+#endif
diff --git a/native_client_sdk/src/libraries/nacl_io/syscalls/socket.c b/native_client_sdk/src/libraries/nacl_io/syscalls/socket.c
new file mode 100644
index 0000000..d4b4b9b
--- /dev/null
+++ b/native_client_sdk/src/libraries/nacl_io/syscalls/socket.c
@@ -0,0 +1,14 @@
+/* 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 "nacl_io/kernel_intercept.h"
+#include "nacl_io/kernel_wrap.h"
+
+#ifdef PROVIDES_SOCKET_API
+
+int socket(int domain, int type, int protocol) {
+  return ki_socket(domain, type, protocol);
+}
+
+#endif
diff --git a/native_client_sdk/src/libraries/nacl_io/syscalls/socketpair.c b/native_client_sdk/src/libraries/nacl_io/syscalls/socketpair.c
new file mode 100644
index 0000000..422b4d1
--- /dev/null
+++ b/native_client_sdk/src/libraries/nacl_io/syscalls/socketpair.c
@@ -0,0 +1,14 @@
+/* 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 "nacl_io/kernel_intercept.h"
+#include "nacl_io/kernel_wrap.h"
+
+#ifdef PROVIDES_SOCKET_API
+
+int socketpair(int domain, int type, int protocol, int* sv) {
+  return ki_socketpair(domain, type, protocol, sv);
+}
+
+#endif
diff --git a/native_client_sdk/src/libraries/nacl_io_test/kernel_proxy_mock.h b/native_client_sdk/src/libraries/nacl_io_test/kernel_proxy_mock.h
index c082856..159e3cb 100644
--- a/native_client_sdk/src/libraries/nacl_io_test/kernel_proxy_mock.h
+++ b/native_client_sdk/src/libraries/nacl_io_test/kernel_proxy_mock.h
@@ -67,8 +67,6 @@
   MOCK_METHOD3(getpeername, int(int, struct sockaddr*, socklen_t*));
   MOCK_METHOD3(getsockname, int(int, struct sockaddr*, socklen_t*));
   MOCK_METHOD5(getsockopt, int(int, int, int, void*, socklen_t*));
-  MOCK_METHOD1(herror, void(const char*));
-  MOCK_METHOD1(hstrerror, const char*(int));
   MOCK_METHOD2(listen, int(int, int));
   MOCK_METHOD4(recv, ssize_t(int, void*, size_t, int));
   MOCK_METHOD6(recvfrom, ssize_t(int, void*, size_t, int,
diff --git a/native_client_sdk/src/libraries/nacl_io_test/kernel_wrap_test.cc b/native_client_sdk/src/libraries/nacl_io_test/kernel_wrap_test.cc
index 6b48c88..34db64a 100644
--- a/native_client_sdk/src/libraries/nacl_io_test/kernel_wrap_test.cc
+++ b/native_client_sdk/src/libraries/nacl_io_test/kernel_wrap_test.cc
@@ -347,16 +347,6 @@
   getsockopt(DUMMY_FD, 456, 789, NULL, NULL);
 }
 
-TEST_F(KernelWrapTest, herror) {
-  EXPECT_CALL(mock, herror(NULL)).Times(1);
-  herror(NULL);
-}
-
-TEST_F(KernelWrapTest, hstrerror) {
-  EXPECT_CALL(mock, hstrerror(123)).Times(1);
-  hstrerror(123);
-}
-
 TEST_F(KernelWrapTest, listen) {
   EXPECT_CALL(mock, listen(DUMMY_FD, 456)).Times(1);
   listen(DUMMY_FD, 456);
diff --git a/native_client_sdk/src/libraries/nacl_io_test/mount_test.cc b/native_client_sdk/src/libraries/nacl_io_test/mount_test.cc
index cc1c437..4829ccf 100644
--- a/native_client_sdk/src/libraries/nacl_io_test/mount_test.cc
+++ b/native_client_sdk/src/libraries/nacl_io_test/mount_test.cc
@@ -322,7 +322,7 @@
 
   // Now let's try sending some data over.
   // First we create the message.
-  std::string content("hello, how are you?");
+  std::string content("hello, how are you?\n");
   std::string message = prefix.append(content);
   struct tioc_nacl_input_string packaged_message;
   packaged_message.length = message.size();
diff --git a/native_client_sdk/src/libraries/nacl_io_test/socket_test.cc b/native_client_sdk/src/libraries/nacl_io_test/socket_test.cc
index ec45185..e98aa7a 100644
--- a/native_client_sdk/src/libraries/nacl_io_test/socket_test.cc
+++ b/native_client_sdk/src/libraries/nacl_io_test/socket_test.cc
@@ -128,11 +128,6 @@
   EXPECT_EQ(errno, ENOTSOCK);
 }
 
-TEST_F(SocketTest, Hstrerror) {
-  EXPECT_STREQ(ki_hstrerror(2718),
-               "Unknown error in gethostbyname: 2718.");
-}
-
 TEST_F(SocketTest, Listen) {
   EXPECT_LT(ki_listen(-1, 123), 0);
   EXPECT_EQ(errno, EBADF);
@@ -268,6 +263,31 @@
 // implementations of these functions).
 #if !defined(__GLIBC__)
 
+TEST(SocketUtilityFunctions, Hstrerror) {
+  EXPECT_STREQ(hstrerror(2718),
+               "Unknown error in gethostbyname: 2718.");
+}
+
+TEST(SocketUtilityFunctions, Htonl) {
+  uint32_t host_long = 0x44332211;
+  uint32_t network_long = htonl(host_long);
+  uint8_t network_bytes[4];
+  memcpy(network_bytes, &network_long, 4);
+  EXPECT_EQ(network_bytes[0], 0x44);
+  EXPECT_EQ(network_bytes[1], 0x33);
+  EXPECT_EQ(network_bytes[2], 0x22);
+  EXPECT_EQ(network_bytes[3], 0x11);
+}
+
+TEST(SocketUtilityFunctions, Htons) {
+  uint16_t host_short = 0x2211;
+  uint16_t network_short = htons(host_short);
+  uint8_t network_bytes[2];
+  memcpy(network_bytes, &network_short, 2);
+  EXPECT_EQ(network_bytes[0], 0x22);
+  EXPECT_EQ(network_bytes[1], 0x11);
+}
+
 static struct in_addr generate_ipv4_addr(int tuple1, int tuple2,
                                          int tuple3, int tuple4) {
   unsigned char addr[4];
@@ -275,8 +295,9 @@
   addr[1] = static_cast<unsigned char>(tuple2);
   addr[2] = static_cast<unsigned char>(tuple3);
   addr[3] = static_cast<unsigned char>(tuple4);
-  struct in_addr* real_addr = reinterpret_cast<struct in_addr*>(addr);
-  return *real_addr;
+  struct in_addr real_addr;
+  memcpy(&real_addr, addr, 4);
+  return real_addr;
 }
 
 static struct in6_addr generate_ipv6_addr(int* tuples) {
@@ -285,8 +306,9 @@
     addr[2*i] = (tuples[i] >> 8) & 0xFF;
     addr[2*i+1] = tuples[i] & 0xFF;
   }
-  struct in6_addr* real_addr = reinterpret_cast<struct in6_addr*>(addr);
-  return *real_addr;
+  struct in6_addr real_addr;
+  memcpy(&real_addr, addr, 16);
+  return real_addr;
 }
 
 TEST(SocketUtilityFunctions, Inet_ntoa) {
@@ -372,5 +394,21 @@
   EXPECT_EQ(errno, ENOSPC);
 }
 
+TEST(SocketUtilityFunctions, Ntohs) {
+  uint8_t network_bytes[2] = { 0x22, 0x11 };
+  uint16_t network_short;
+  memcpy(&network_short, network_bytes, 2);
+  uint16_t host_short = ntohs(network_short);
+  EXPECT_EQ(host_short, 0x2211);
+}
+
+TEST(SocketUtilityFunctions, Ntohl) {
+  uint8_t network_bytes[4] = { 0x44, 0x33, 0x22, 0x11 };
+  uint32_t network_long;
+  memcpy(&network_long, network_bytes, 4);
+  uint32_t host_long = ntohl(network_long);
+  EXPECT_EQ(host_long, 0x44332211);
+}
+
 #endif  // !defined(__GLIBC__)
 #endif  // PROVIDES_SOCKETPAIR_API
diff --git a/native_client_sdk/src/libraries/third_party/newlib-extras/README.chromium b/native_client_sdk/src/libraries/third_party/newlib-extras/README.chromium
index 4d577fd..3b46d4c 100644
--- a/native_client_sdk/src/libraries/third_party/newlib-extras/README.chromium
+++ b/native_client_sdk/src/libraries/third_party/newlib-extras/README.chromium
@@ -21,3 +21,6 @@
 * Removed the revoked third clause from the licenses in the header files.
 * Correctly wrapped netdb.h to allow it to be included in both C and C++ files.
 * Removed faulty _BSD_SIZE_T_ typedef in arpa/inet.h
+* Removed macros in arpa/inet.h which added underbars to various functions of
+  the form inet_*, to avoid problems with forward declarations in user code.
+* Added prototypes for htonl, htons, ntohl, and ntohs to netinet/in.h
diff --git a/native_client_sdk/src/libraries/third_party/newlib-extras/arpa/inet.h b/native_client_sdk/src/libraries/third_party/newlib-extras/arpa/inet.h
index 8578137..1d496a9 100644
--- a/native_client_sdk/src/libraries/third_party/newlib-extras/arpa/inet.h
+++ b/native_client_sdk/src/libraries/third_party/newlib-extras/arpa/inet.h
@@ -107,21 +107,6 @@
 #define	_STRUCT_IN_ADDR_DECLARED
 #endif
 
-#define	inet_addr	__inet_addr
-#define	inet_aton	__inet_aton
-#define	inet_lnaof	__inet_lnaof
-#define	inet_makeaddr	__inet_makeaddr
-#define	inet_neta	__inet_neta
-#define	inet_netof	__inet_netof
-#define	inet_network	__inet_network
-#define	inet_net_ntop	__inet_net_ntop
-#define	inet_net_pton	__inet_net_pton
-#define	inet_ntoa	__inet_ntoa
-#define	inet_pton	__inet_pton
-#define	inet_ntop	__inet_ntop
-#define	inet_nsap_addr	__inet_nsap_addr
-#define	inet_nsap_ntoa	__inet_nsap_ntoa
-
 __BEGIN_DECLS
 in_addr_t	 inet_addr(const char *);
 char		*inet_ntoa(struct in_addr);
diff --git a/native_client_sdk/src/libraries/third_party/newlib-extras/netinet/in.h b/native_client_sdk/src/libraries/third_party/newlib-extras/netinet/in.h
index c66ad51..a0cd05c 100644
--- a/native_client_sdk/src/libraries/third_party/newlib-extras/netinet/in.h
+++ b/native_client_sdk/src/libraries/third_party/newlib-extras/netinet/in.h
@@ -562,4 +562,11 @@
 #include <netinet6/in6.h>
 #undef __KAME_NETINET_IN_H_INCLUDED_
 
+__BEGIN_DECLS
+uint32_t         htonl(uint32_t hostlong);
+uint16_t         htons(uint16_t hostshort);
+uint32_t         ntohl(uint32_t networklong);
+uint16_t         ntohs(uint16_t networkshort);
+__END_DECLS
+
 #endif /* !_NETINET_IN_H_*/
diff --git a/native_client_sdk/src/libraries/third_party/newlib-extras/netinet/tcp.h b/native_client_sdk/src/libraries/third_party/newlib-extras/netinet/tcp.h
new file mode 100644
index 0000000..04d2284
--- /dev/null
+++ b/native_client_sdk/src/libraries/third_party/newlib-extras/netinet/tcp.h
@@ -0,0 +1,167 @@
+/*
+ * Copyright (c) 1982, 1986, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University 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 REGENTS 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 REGENTS 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.
+ *
+ *	@(#)tcp.h	8.1 (Berkeley) 6/10/93
+ * $FreeBSD: src/sys/netinet/tcp.h,v 1.16 2001/01/09 18:26:17 rwatson Exp $
+ */
+
+#ifndef _NETINET_TCP_H_
+#define _NETINET_TCP_H_
+
+#include <sys/types.h>
+
+#if defined(__native_client__)
+/*
+ *  The following section is NaCl specific and is needed to more
+ *  closely match the types defined in the BSD sys/types.h.
+ *  This is needed to let the RTEMS/BSD TCP/IP stack compile.
+ */
+
+/* deprecated */
+#if ___int8_t_defined
+typedef __uint8_t	u_int8_t;
+#endif
+#if ___int16_t_defined
+typedef __uint16_t	u_int16_t;
+#endif 
+#if ___int32_t_defined
+typedef __uint32_t	u_int32_t;
+#endif
+
+#if ___int64_t_defined
+typedef __uint64_t	u_int64_t;
+
+/* deprecated */
+typedef	__uint64_t	u_quad_t;
+typedef	__int64_t	quad_t;
+typedef	quad_t *	qaddr_t;
+#endif
+#endif
+
+typedef	u_int32_t tcp_seq;
+typedef u_int32_t tcp_cc;		/* connection count per rfc1644 */
+
+#define tcp6_seq	tcp_seq	/* for KAME src sync over BSD*'s */
+#define tcp6hdr		tcphdr	/* for KAME src sync over BSD*'s */
+
+/*
+ * TCP header.
+ * Per RFC 793, September, 1981.
+ */
+struct tcphdr {
+	u_short	th_sport;		/* source port */
+	u_short	th_dport;		/* destination port */
+	tcp_seq	th_seq;			/* sequence number */
+	tcp_seq	th_ack;			/* acknowledgement number */
+#if BYTE_ORDER == LITTLE_ENDIAN
+	u_int	th_x2:4,		/* (unused) */
+		th_off:4;		/* data offset */
+#endif
+#if BYTE_ORDER == BIG_ENDIAN
+	u_int	th_off:4,		/* data offset */
+		th_x2:4;		/* (unused) */
+#endif
+	u_char	th_flags;
+#define	TH_FIN	0x01
+#define	TH_SYN	0x02
+#define	TH_RST	0x04
+#define	TH_PUSH	0x08
+#define	TH_ACK	0x10
+#define	TH_URG	0x20
+#define	TH_ECE	0x40
+#define	TH_CWR	0x80
+#define	TH_FLAGS	(TH_FIN|TH_SYN|TH_RST|TH_ACK|TH_URG|TH_ECE|TH_CWR)
+
+	u_short	th_win;			/* window */
+	u_short	th_sum;			/* checksum */
+	u_short	th_urp;			/* urgent pointer */
+};
+
+#define	TCPOPT_EOL		0
+#define	TCPOPT_NOP		1
+#define	TCPOPT_MAXSEG		2
+#define    TCPOLEN_MAXSEG		4
+#define TCPOPT_WINDOW		3
+#define    TCPOLEN_WINDOW		3
+#define TCPOPT_SACK_PERMITTED	4		/* Experimental */
+#define    TCPOLEN_SACK_PERMITTED	2
+#define TCPOPT_SACK		5		/* Experimental */
+#define TCPOPT_TIMESTAMP	8
+#define    TCPOLEN_TIMESTAMP		10
+#define    TCPOLEN_TSTAMP_APPA		(TCPOLEN_TIMESTAMP+2) /* appendix A */
+#define    TCPOPT_TSTAMP_HDR		\
+    (TCPOPT_NOP<<24|TCPOPT_NOP<<16|TCPOPT_TIMESTAMP<<8|TCPOLEN_TIMESTAMP)
+
+#define	TCPOPT_CC		11		/* CC options: RFC-1644 */
+#define TCPOPT_CCNEW		12
+#define TCPOPT_CCECHO		13
+#define	   TCPOLEN_CC			6
+#define	   TCPOLEN_CC_APPA		(TCPOLEN_CC+2)
+#define	   TCPOPT_CC_HDR(ccopt)		\
+    (TCPOPT_NOP<<24|TCPOPT_NOP<<16|(ccopt)<<8|TCPOLEN_CC)
+
+/*
+ * Default maximum segment size for TCP.
+ * With an IP MSS of 576, this is 536,
+ * but 512 is probably more convenient.
+ * This should be defined as MIN(512, IP_MSS - sizeof (struct tcpiphdr)).
+ */
+#define	TCP_MSS	512
+
+/*
+ * Default maximum segment size for TCP6.
+ * With an IP6 MSS of 1280, this is 1220,
+ * but 1024 is probably more convenient. (xxx kazu in doubt)
+ * This should be defined as MIN(1024, IP6_MSS - sizeof (struct tcpip6hdr))
+ */
+#define	TCP6_MSS	1024
+
+#define	TCP_MAXWIN	65535	/* largest value for (unscaled) window */
+#define	TTCP_CLIENT_SND_WND	4096	/* dflt send window for T/TCP client */
+
+#define TCP_MAX_WINSHIFT	14	/* maximum window shift */
+
+#define TCP_MAXBURST		4 	/* maximum segments in a burst */
+
+#define TCP_MAXHLEN	(0xf<<2)	/* max length of header in bytes */
+#define TCP_MAXOLEN	(TCP_MAXHLEN - sizeof(struct tcphdr))
+					/* max space left for options */
+
+/*
+ * User-settable options (used with setsockopt).
+ */
+#define	TCP_NODELAY	0x01	/* don't delay send to coalesce packets */
+#define	TCP_MAXSEG	0x02	/* set maximum segment size */
+#define TCP_NOPUSH	0x04	/* don't push last block of write */
+#define TCP_NOOPT	0x08	/* don't use TCP options */
+
+#endif
diff --git a/native_client_sdk/src/tools/common.mk b/native_client_sdk/src/tools/common.mk
index 11feea8..3082072 100644
--- a/native_client_sdk/src/tools/common.mk
+++ b/native_client_sdk/src/tools/common.mk
@@ -476,9 +476,9 @@
 run_package: check_for_chrome all
 	$(CHROME_PATH) --load-and-launch-app=$(CURDIR) $(CHROME_ARGS)
 
-
-GDB_ARGS += -D $(TC_PATH)/$(OSNAME)_x86_$(TOOLCHAIN)/bin/$(SYSARCH)-nacl-gdb
-GDB_ARGS += -D $(abspath $(OUTDIR))/$(TARGET)_$(SYSARCH).nexe
+GDB_ARGS += -D $(TC_PATH)/$(OSNAME)_x86_newlib/bin/$(SYSARCH)-nacl-gdb
+GDB_ARGS += -D --eval-command="nacl-manifest $(abspath $(OUTDIR))/$(TARGET).nmf"
+GDB_ARGS += -D $(GDB_DEBUG_TARGET)
 
 .PHONY: debug
 debug: check_for_chrome all $(PAGE)
diff --git a/native_client_sdk/src/tools/nacl_gcc.mk b/native_client_sdk/src/tools/nacl_gcc.mk
index d046714..c176d9b 100644
--- a/native_client_sdk/src/tools/nacl_gcc.mk
+++ b/native_client_sdk/src/tools/nacl_gcc.mk
@@ -429,3 +429,22 @@
 $(OUTDIR)/$(1).html: $(EXECUTABLES)
 	$(call LOG,CREATE_HTML,$$@,$(CREATE_HTML) $(HTML_FLAGS) -o $$@ $$^)
 endef
+
+
+#
+# Determine which executable to pass into the debugger.  For newlib
+# this is the NEXE which will actually be used.  For glibc, runnable-ld.so
+# is the "app", and the "app" is actual an .so we load.
+#
+ifeq (x86_32,$(SYSARCH))
+LIB_NAME = lib32
+else
+LIB_NAME = lib64
+endif
+
+
+ifeq (newlib,$(TOOLCHAIN))
+GDB_DEBUG_TARGET = $(abspath $(OUTDIR))/$(TARGET)_$(SYSARCH).nexe
+else
+GDB_DEBUG_TARGET = $(abspath $(OUTDIR))/$(LIB_NAME)/runnable-ld.so
+endif
diff --git a/native_client_sdk/src/tools/nacl_llvm.mk b/native_client_sdk/src/tools/nacl_llvm.mk
index 3299e4c..a8a310b 100644
--- a/native_client_sdk/src/tools/nacl_llvm.mk
+++ b/native_client_sdk/src/tools/nacl_llvm.mk
@@ -1,4 +1,4 @@
-# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# 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.
 
@@ -17,6 +17,7 @@
 PNACL_LIB ?= $(PNACL_BIN)/pnacl-ar
 PNACL_STRIP ?= $(PNACL_BIN)/pnacl-strip
 PNACL_FINALIZE ?= $(PNACL_BIN)/pnacl-finalize
+PNACL_TRANSLATE ?= $(PNACL_BIN)/pnacl-translate
 
 #
 # Compile Macro
@@ -93,11 +94,24 @@
 # $5 = List of lib dirs
 # $6 = Other Linker Args
 #
+# For debugging, we translate the pre-finalized .bc file.
+#
 define LINKER_RULE
-all: $(1).pexe
-$(1).pexe: $(2) $(foreach dep,$(4),$(STAMPDIR)/$(dep).stamp)
-	$(call LOG,LINK,$(1).bc,$(PNACL_LINK) -o $(1).bc $(2) $(foreach path,$(5),-L$(path)/pnacl/$(CONFIG)) $(foreach lib,$(3),-l$(lib)) $(6))
-	$(call LOG,FINALIZE,$(1).pexe,$(PNACL_FINALIZE) -o $(1).pexe $(1).bc)
+all: $(1).pexe 
+$(1)_x86_32.nexe : $(1).bc
+	$(call LOG,TRANSLATE,$$@,$(PNACL_TRANSLATE) --allow-llvm-bitcode-input -arch x86-32 $$^ -o $$@)
+
+$(1)_x86_64.nexe : $(1).bc
+	$(call LOG,TRANSLATE,$$@,$(PNACL_TRANSLATE) --allow-llvm-bitcode-input -arch x86-64 $$^ -o $$@)
+
+$(1)_arm.nexe : $(1).bc
+	$(call LOG,TRANSLATE,$$@,$(PNACL_TRANSLATE) --allow-llvm-bitcode-input -arch arm $$^ -o $$@)
+
+$(1).pexe: $(1).bc
+	$(call LOG,FINALIZE,$$@,$(PNACL_FINALIZE) -o $$@ $$^)
+
+$(1).bc: $(2) $(foreach dep,$(4),$(STAMPDIR)/$(dep).stamp)
+	$(call LOG,LINK,$$@,$(PNACL_LINK) -o $$@ $(2) $(foreach path,$(5),-L$(path)/pnacl/$(CONFIG)) $(foreach lib,$(3),-l$(lib)) $(6))
 endef
 
 
@@ -111,7 +125,15 @@
 # $5 = POSIX Linker Switches
 # $6 = VC Linker Switches
 #
+# NOTE:  For Debug builds we translate the .bc file to a .nexe instead of
+# using the finalizing to a .pexe.  This enables debugging.
+#
 define LINK_RULE
+ifeq ($(CONFIG),Debug)
+EXECUTABLES=$(OUTDIR)/$(1)_x86_32.nexe $(OUTDIR)/$(1)_x86_64.nexe $(OUTDIR)/$(1)_arm.nexe
+else
+EXECUTABLES=$(OUTDIR)/$(1).pexe
+endif
 $(call LINKER_RULE,$(OUTDIR)/$(1),$(foreach src,$(2),$(call SRC_TO_OBJ,$(src),_pnacl)),$(filter-out pthread,$(3)),$(4),$(LIB_PATHS),$(5))
 endef
 
@@ -149,7 +171,7 @@
 
 define NMF_RULE
 all: $(OUTDIR)/$(1).nmf
-$(OUTDIR)/$(1).nmf: $(OUTDIR)/$(1).pexe
+$(OUTDIR)/$(1).nmf: $(EXECUTABLES)
 	$(call LOG,CREATE_NMF,$$@,$(NMF) -o $$@ $$^ -s $(OUTDIR) $(2))
 endef
 
@@ -160,6 +182,13 @@
 
 define HTML_RULE
 all: $(OUTDIR)/$(1).html
-$(OUTDIR)/$(1).html: $(OUTDIR)/$(1).pexe
+$(OUTDIR)/$(1).html: $(EXECUTABLES)
 	$(call LOG,CREATE_HTML,$$@,$(CREATE_HTML) -o $$@ $$^)
 endef
+
+
+#
+# Determine which executable to pass into the debugger.  For pnacl, this is
+# the .bc -> .nexe translated app.
+#
+GDB_DEBUG_TARGET = $(abspath $(OUTDIR))/$(TARGET)_$(SYSARCH).nexe
diff --git a/net/base/mime_sniffer.cc b/net/base/mime_sniffer.cc
index c582cff..cc83c7c 100644
--- a/net/base/mime_sniffer.cc
+++ b/net/base/mime_sniffer.cc
@@ -807,6 +807,9 @@
                           url.SchemeIs("http") ||
                           url.SchemeIs("https") ||
                           url.SchemeIs("ftp") ||
+#if defined(OS_ANDROID)
+                          url.SchemeIs("content") ||
+#endif
                           url.SchemeIsFile() ||
                           url.SchemeIsFileSystem();
   if (!sniffable_scheme) {
diff --git a/net/cert/cert_verify_proc.cc b/net/cert/cert_verify_proc.cc
index b9bbbe0..ec1ef68 100644
--- a/net/cert/cert_verify_proc.cc
+++ b/net/cert/cert_verify_proc.cc
@@ -64,12 +64,12 @@
 }
 
 void RecordPublicKeyHistogram(const char* chain_position,
-                              bool after_baseline_date,
+                              bool baseline_keysize_applies,
                               size_t size_bits,
                               X509Certificate::PublicKeyType cert_type) {
   std::string histogram_name =
-      base::StringPrintf("CertificateType.%s.%s.%s",
-                         after_baseline_date ? "BR" : "NonBR",
+      base::StringPrintf("CertificateType2.%s.%s.%s",
+                         baseline_keysize_applies ? "BR" : "NonBR",
                          chain_position,
                          CertTypeToString(cert_type));
   // Do not use UMA_HISTOGRAM_... macros here, as it caches the Histogram
@@ -118,18 +118,26 @@
 bool ExaminePublicKeys(const scoped_refptr<X509Certificate>& cert,
                        bool should_histogram) {
   // The effective date of the CA/Browser Forum's Baseline Requirements -
-  // 2014-01-01 00:00:00 UTC.
+  // 2012-07-01 00:00:00 UTC.
   const base::Time kBaselineEffectiveDate =
+      base::Time::FromInternalValue(GG_INT64_C(12985574400000000));
+  // The effective date of the key size requirements from Appendix A, v1.1.5
+  // 2014-01-01 00:00:00 UTC.
+  const base::Time kBaselineKeysizeEffectiveDate =
       base::Time::FromInternalValue(GG_INT64_C(13033008000000000));
 
   size_t size_bits = 0;
   X509Certificate::PublicKeyType type = X509Certificate::kPublicKeyTypeUnknown;
   bool weak_key = false;
-  bool after_baseline_date = cert->valid_expiry() >= kBaselineEffectiveDate;
+  bool baseline_keysize_applies =
+      cert->valid_start() >= kBaselineEffectiveDate &&
+      cert->valid_expiry() >= kBaselineKeysizeEffectiveDate;
 
   X509Certificate::GetPublicKeyInfo(cert->os_cert_handle(), &size_bits, &type);
-  if (should_histogram)
-    RecordPublicKeyHistogram(kLeafCert, after_baseline_date, size_bits, type);
+  if (should_histogram) {
+    RecordPublicKeyHistogram(kLeafCert, baseline_keysize_applies, size_bits,
+                             type);
+  }
   if (IsWeakKey(type, size_bits))
     weak_key = true;
 
@@ -140,7 +148,7 @@
     if (should_histogram) {
       RecordPublicKeyHistogram(
           (i < intermediates.size() - 1) ? kIntermediateCert : kRootCert,
-          after_baseline_date,
+          baseline_keysize_applies,
           size_bits,
           type);
     }
diff --git a/net/cert/jwk_serializer_nss.cc b/net/cert/jwk_serializer_nss.cc
index 0259c5c..d844580 100644
--- a/net/cert/jwk_serializer_nss.cc
+++ b/net/cert/jwk_serializer_nss.cc
@@ -22,12 +22,12 @@
 bool ConvertEcPrime256v1PublicKeyInfoToJwk(
     CERTSubjectPublicKeyInfo* spki,
     base::DictionaryValue* public_key_jwk) {
-  static const int kPrime256v1EncodingType = 4;
+  static const int kUncompressedEncodingType = 4;
   static const int kPrime256v1PublicKeyLength = 64;
   // The public key value is encoded as 0x04 + 64 bytes of public key.
   // NSS gives the length as the bit length.
   if (spki->subjectPublicKey.len != (kPrime256v1PublicKeyLength + 1) * 8 ||
-      spki->subjectPublicKey.data[0] != kPrime256v1EncodingType)
+      spki->subjectPublicKey.data[0] != kUncompressedEncodingType)
     return false;
 
   public_key_jwk->SetString("alg", "EC");
diff --git a/net/cert/jwk_serializer_openssl.cc b/net/cert/jwk_serializer_openssl.cc
index ef15b4b..b11e969 100644
--- a/net/cert/jwk_serializer_openssl.cc
+++ b/net/cert/jwk_serializer_openssl.cc
@@ -2,9 +2,10 @@
 // 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 "net/cert/jwk_serializer.h"
 
+#include "base/logging.h"
+
 namespace net {
 
 namespace JwkSerializer {
diff --git a/net/cert/jwk_serializer_unittest.cc b/net/cert/jwk_serializer_unittest.cc
index 37b8002..8059e73 100644
--- a/net/cert/jwk_serializer_unittest.cc
+++ b/net/cert/jwk_serializer_unittest.cc
@@ -26,7 +26,7 @@
     0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03,
     0x42, 0x00, 0x04
 };
-static const unsigned int kEcPointSize = 32U;
+static const unsigned int kEcCoordinateSize = 32U;
 
 // This is a valid P-256 public key.
 static const unsigned char kSpkiEc[] = {
@@ -82,19 +82,19 @@
   EXPECT_TRUE(public_key_jwk.GetString("x", &string_value));
   std::string decoded_coordinate;
   EXPECT_TRUE(base::Base64Decode(string_value, &decoded_coordinate));
-  EXPECT_EQ(kEcPointSize, decoded_coordinate.size());
+  EXPECT_EQ(kEcCoordinateSize, decoded_coordinate.size());
   EXPECT_EQ(0,
             memcmp(decoded_coordinate.data(),
                    kSpkiEc + sizeof(kP256SpkiPrefix),
-                   kEcPointSize));
+                   kEcCoordinateSize));
 
   EXPECT_TRUE(public_key_jwk.GetString("y", &string_value));
   EXPECT_TRUE(base::Base64Decode(string_value, &decoded_coordinate));
-  EXPECT_EQ(kEcPointSize, decoded_coordinate.size());
+  EXPECT_EQ(kEcCoordinateSize, decoded_coordinate.size());
   EXPECT_EQ(0,
             memcmp(decoded_coordinate.data(),
-                  kSpkiEc + sizeof(kP256SpkiPrefix) + kEcPointSize,
-                  kEcPointSize));
+                  kSpkiEc + sizeof(kP256SpkiPrefix) + kEcCoordinateSize,
+                  kEcCoordinateSize));
 
   // Test the result of a corner case: leading 0s in the x, y coordinates are
   // not trimmed, but the point is fixed-length encoded.
@@ -109,19 +109,19 @@
 
   EXPECT_TRUE(public_key_jwk.GetString("x", &string_value));
   EXPECT_TRUE(base::Base64Decode(string_value, &decoded_coordinate));
-  EXPECT_EQ(kEcPointSize, decoded_coordinate.size());
+  EXPECT_EQ(kEcCoordinateSize, decoded_coordinate.size());
   EXPECT_EQ(0,
             memcmp(decoded_coordinate.data(),
                    kSpkiEcWithZeroXY + sizeof(kP256SpkiPrefix),
-                   kEcPointSize));
+                   kEcCoordinateSize));
 
   EXPECT_TRUE(public_key_jwk.GetString("y", &string_value));
   EXPECT_TRUE(base::Base64Decode(string_value, &decoded_coordinate));
-  EXPECT_EQ(kEcPointSize, decoded_coordinate.size());
+  EXPECT_EQ(kEcCoordinateSize, decoded_coordinate.size());
   EXPECT_EQ(0,
-            memcmp(decoded_coordinate.data(),
-                   kSpkiEcWithZeroXY + sizeof(kP256SpkiPrefix) + kEcPointSize,
-                   kEcPointSize));
+      memcmp(decoded_coordinate.data(),
+             kSpkiEcWithZeroXY + sizeof(kP256SpkiPrefix) + kEcCoordinateSize,
+             kEcCoordinateSize));
 }
 
 #else
diff --git a/net/disk_cache/simple/simple_index.cc b/net/disk_cache/simple/simple_index.cc
index caec19f..78ce87e 100644
--- a/net/disk_cache/simple/simple_index.cc
+++ b/net/disk_cache/simple/simple_index.cc
@@ -359,18 +359,24 @@
     index_file_entries->erase(*it);
   }
 
-  // Recalculate the cache size while merging the two sets.
-  for (EntrySet::const_iterator it = index_file_entries->begin();
-       it != index_file_entries->end(); ++it) {
-    // If there is already an entry in the current entries_set_, we need to
-    // merge the new data there with the data loaded in the initialization.
-    EntrySet::iterator current_entry = entries_set_.find(it->first);
-    // When Merging, existing data in the |current_entry| will prevail.
-    if (current_entry == entries_set_.end()) {
-      InsertInEntrySet(it->first, it->second, &entries_set_);
-      cache_size_ += it->second.GetEntrySize();
-    }
+  for (EntrySet::const_iterator it = entries_set_.begin();
+       it != entries_set_.end(); ++it) {
+    const uint64 entry_hash = it->first;
+    std::pair<EntrySet::iterator, bool> insert_result =
+        index_file_entries->insert(EntrySet::value_type(entry_hash,
+                                                        EntryMetadata()));
+    EntrySet::iterator& possibly_inserted_entry = insert_result.first;
+    possibly_inserted_entry->second = it->second;
   }
+
+  uint64 merged_cache_size = 0;
+  for (EntrySet::iterator it = index_file_entries->begin();
+       it != index_file_entries->end(); ++it) {
+    merged_cache_size += it->second.GetEntrySize();
+  }
+
+  entries_set_.swap(*index_file_entries);
+  cache_size_ = merged_cache_size;
   initialized_ = true;
   removed_entries_.clear();
 
diff --git a/net/disk_cache/simple/simple_index_file.cc b/net/disk_cache/simple/simple_index_file.cc
index 596b816..7bcea7c 100644
--- a/net/disk_cache/simple/simple_index_file.cc
+++ b/net/disk_cache/simple/simple_index_file.cc
@@ -8,6 +8,7 @@
 
 #include "base/file_util.h"
 #include "base/files/file_enumerator.h"
+#include "base/files/memory_mapped_file.h"
 #include "base/hash.h"
 #include "base/logging.h"
 #include "base/metrics/histogram.h"
@@ -254,14 +255,16 @@
                                        SimpleIndexLoadResult* out_result) {
   out_result->Reset();
 
-  std::string contents;
-  if (!file_util::ReadFileToString(index_filename, &contents)) {
-    LOG(WARNING) << "Could not read Simple Index file.";
+  base::MemoryMappedFile index_file_map;
+  if (!index_file_map.Initialize(index_filename)) {
+    LOG(WARNING) << "Could not map Simple Index file.";
     base::DeleteFile(index_filename, false);
     return;
   }
 
-  SimpleIndexFile::Deserialize(contents.data(), contents.size(), out_result);
+  SimpleIndexFile::Deserialize(
+      reinterpret_cast<const char*>(index_file_map.data()),
+      index_file_map.length(), out_result);
 
   if (!out_result->did_load)
     base::DeleteFile(index_filename, false);
@@ -322,6 +325,10 @@
     return;
   }
 
+#if !defined(OS_WIN)
+  // TODO(gavinp): Consider using std::unordered_map.
+  entries->resize(index_metadata.GetNumberOfEntries() + kExtraSizeForMerge);
+#endif
   while (entries->size() < index_metadata.GetNumberOfEntries()) {
     uint64 hash_key;
     EntryMetadata entry_metadata;
diff --git a/net/disk_cache/simple/simple_index_file.h b/net/disk_cache/simple/simple_index_file.h
index 8a96a72..b536df9 100644
--- a/net/disk_cache/simple/simple_index_file.h
+++ b/net/disk_cache/simple/simple_index_file.h
@@ -97,6 +97,10 @@
  private:
   friend class WrappedSimpleIndexFile;
 
+  // When loading the entries from disk, add this many extra hash buckets to
+  // prevent reallocation on the IO thread when merging in new live entries.
+  static const int kExtraSizeForMerge = 512;
+
   // Synchronous (IO performing) implementation of LoadIndexEntries.
   static void SyncLoadIndexEntries(base::Time cache_last_modified,
                                    const base::FilePath& cache_directory,
diff --git a/net/disk_cache/simple/simple_index_unittest.cc b/net/disk_cache/simple/simple_index_unittest.cc
index cfc83b3..0c845b2 100644
--- a/net/disk_cache/simple/simple_index_unittest.cc
+++ b/net/disk_cache/simple/simple_index_unittest.cc
@@ -197,12 +197,15 @@
   {
     scoped_ptr<SimpleIndexLoadResult> result(new SimpleIndexLoadResult());
     result->did_load = true;
-    const uint64 hash_key = simple_util::GetEntryHashKey("eleven");
+    const uint64 new_hash_key = simple_util::GetEntryHashKey("eleven");
     result->entries.insert(
-        std::make_pair(hash_key, EntryMetadata(base::Time::Now(), 11)));
+        std::make_pair(new_hash_key, EntryMetadata(base::Time::Now(), 11)));
+    const uint64 redundant_hash_key = simple_util::GetEntryHashKey("seven");
+    result->entries.insert(std::make_pair(redundant_hash_key,
+                                          EntryMetadata(base::Time::Now(), 7)));
     index()->MergeInitializingSet(result.Pass());
   }
-  EXPECT_EQ(25U, index()->cache_size_);
+  EXPECT_EQ(2U + 5U + 7U + 11U, index()->cache_size_);
 }
 
 // State of index changes as expected with an insert and a remove.
diff --git a/net/disk_cache/simple/simple_util.cc b/net/disk_cache/simple/simple_util.cc
index 40d3894..72a4612 100644
--- a/net/disk_cache/simple/simple_util.cc
+++ b/net/disk_cache/simple/simple_util.cc
@@ -21,25 +21,6 @@
 // Size of the uint64 hash_key number in Hex format in a string.
 const size_t kEntryHashKeyAsHexStringSize = 2 * sizeof(uint64);
 
-// TODO(clamy, gavinp): this should go in base
-bool GetNanoSecsFromStat(const struct stat& st,
-                         time_t* out_sec,
-                         long* out_nsec) {
-#if defined(OS_ANDROID)
-  *out_sec = st.st_mtime;
-  *out_nsec = st.st_mtime_nsec;
-#elif defined(OS_LINUX)
-  *out_sec = st.st_mtim.tv_sec;
-  *out_nsec = st.st_mtim.tv_nsec;
-#elif defined(OS_MACOSX) || defined(OS_IOS) || defined(OS_BSD)
-  *out_sec = st.st_mtimespec.tv_sec;
-  *out_nsec = st.st_mtimespec.tv_nsec;
-#else
-  return false;
-#endif
-  return true;
-}
-
 }  // namespace
 
 namespace disk_cache {
@@ -107,20 +88,6 @@
 // TODO(clamy, gavinp): this should go in base
 bool GetMTime(const base::FilePath& path, base::Time* out_mtime) {
   DCHECK(out_mtime);
-#if defined(OS_POSIX)
-  base::ThreadRestrictions::AssertIOAllowed();
-  struct stat file_stat;
-  if (stat(path.value().c_str(), &file_stat) != 0)
-    return false;
-  time_t sec;
-  long nsec;
-  if (GetNanoSecsFromStat(file_stat, &sec, &nsec)) {
-    int64 usec = (nsec / base::Time::kNanosecondsPerMicrosecond);
-    *out_mtime = base::Time::FromTimeT(sec)
-        + base::TimeDelta::FromMicroseconds(usec);
-    return true;
-  }
-#endif
   base::PlatformFileInfo file_info;
   if (!file_util::GetFileInfo(path, &file_info))
     return false;
diff --git a/net/disk_cache/simple/simple_util.h b/net/disk_cache/simple/simple_util.h
index 505501e..2e92b4a 100644
--- a/net/disk_cache/simple/simple_util.h
+++ b/net/disk_cache/simple/simple_util.h
@@ -62,8 +62,8 @@
     const std::string& key,
     int data_offset);
 
-// Fills |out_time| with the time the file last modified time. Unlike the
-// functions in platform_file.h, the time resolution is milliseconds.
+// Fills |out_time| with the time the file last modified time.
+// TODO(gavinp): Remove this function.
 NET_EXPORT_PRIVATE bool GetMTime(const base::FilePath& path,
                                  base::Time* out_mtime);
 }  // namespace simple_backend
diff --git a/net/http/http_network_transaction.cc b/net/http/http_network_transaction.cc
index c26564c..70292be 100644
--- a/net/http/http_network_transaction.cc
+++ b/net/http/http_network_transaction.cc
@@ -1219,6 +1219,7 @@
         GetHostAndPort(request_->url));
   }
 
+  bool should_fallback = false;
   uint16 version_max = server_ssl_config_.version_max;
 
   switch (error) {
@@ -1250,18 +1251,33 @@
             (server_ssl_config_.unrestricted_ssl3_fallback_enabled ||
              !TransportSecurityState::IsGooglePinnedProperty(
                  request_->url.host(), true /* include SNI */))) {
-          net_log_.AddEvent(
-              NetLog::TYPE_SSL_VERSION_FALLBACK,
-              base::Bind(&NetLogSSLVersionFallbackCallback,
-                         &request_->url, error, server_ssl_config_.version_max,
-                         version_max));
-          server_ssl_config_.version_max = version_max;
-          server_ssl_config_.version_fallback = true;
-          ResetConnectionAndRequestForResend();
-          error = OK;
+          should_fallback = true;
         }
       }
       break;
+    case ERR_SSL_BAD_RECORD_MAC_ALERT:
+      if (version_max >= SSL_PROTOCOL_VERSION_TLS1_1 &&
+          version_max > server_ssl_config_.version_min) {
+        // Some broken SSL devices negotiate TLS 1.0 when sent a TLS 1.1 or
+        // 1.2 ClientHello, but then return a bad_record_mac alert. See
+        // crbug.com/260358. In order to make the fallback as minimal as
+        // possible, this fallback is only triggered for >= TLS 1.1.
+        version_max--;
+        should_fallback = true;
+      }
+      break;
+  }
+
+  if (should_fallback) {
+    net_log_.AddEvent(
+        NetLog::TYPE_SSL_VERSION_FALLBACK,
+        base::Bind(&NetLogSSLVersionFallbackCallback,
+                   &request_->url, error, server_ssl_config_.version_max,
+                   version_max));
+    server_ssl_config_.version_max = version_max;
+    server_ssl_config_.version_fallback = true;
+    ResetConnectionAndRequestForResend();
+    error = OK;
   }
 
   return error;
diff --git a/net/net.gyp b/net/net.gyp
index 0165031..cedc05b 100644
--- a/net/net.gyp
+++ b/net/net.gyp
@@ -782,6 +782,8 @@
         'quic/crypto/strike_register.h',
         'quic/crypto/source_address_token.cc',
         'quic/crypto/source_address_token.h',
+        'quic/quic_alarm.cc',
+        'quic/quic_alarm.h',
         'quic/quic_bandwidth.cc',
         'quic/quic_bandwidth.h',
         'quic/quic_blocked_writer_interface.h',
@@ -1734,6 +1736,7 @@
         'quic/test_tools/simple_quic_framer.h',
         'quic/test_tools/test_task_runner.cc',
         'quic/test_tools/test_task_runner.h',
+        'quic/quic_alarm_test.cc',
         'quic/quic_bandwidth_test.cc',
         'quic/quic_client_session_test.cc',
         'quic/quic_clock_test.cc',
@@ -1867,6 +1870,9 @@
             'flip_balsa_and_epoll_library',
           ],
           'sources': [
+            'tools/flip_server/balsa_frame_test.cc',
+            'tools/flip_server/balsa_headers_test.cc',
+            'tools/flip_server/mem_cache_test.cc',
             'tools/flip_server/simple_buffer.cc',
             'tools/flip_server/simple_buffer.h',
             'tools/quic/end_to_end_test.cc',
diff --git a/net/net.target.darwin-arm.mk b/net/net.target.darwin-arm.mk
index 88d78fc..36ad05d 100644
--- a/net/net.target.darwin-arm.mk
+++ b/net/net.target.darwin-arm.mk
@@ -308,6 +308,7 @@
 	net/quic/crypto/scoped_evp_cipher_ctx.cc \
 	net/quic/crypto/strike_register.cc \
 	net/quic/crypto/source_address_token.cc \
+	net/quic/quic_alarm.cc \
 	net/quic/quic_bandwidth.cc \
 	net/quic/quic_client_session.cc \
 	net/quic/quic_config.cc \
diff --git a/net/net.target.darwin-mips.mk b/net/net.target.darwin-mips.mk
index 6fedabc..203e38d 100644
--- a/net/net.target.darwin-mips.mk
+++ b/net/net.target.darwin-mips.mk
@@ -308,6 +308,7 @@
 	net/quic/crypto/scoped_evp_cipher_ctx.cc \
 	net/quic/crypto/strike_register.cc \
 	net/quic/crypto/source_address_token.cc \
+	net/quic/quic_alarm.cc \
 	net/quic/quic_bandwidth.cc \
 	net/quic/quic_client_session.cc \
 	net/quic/quic_config.cc \
diff --git a/net/net.target.darwin-x86.mk b/net/net.target.darwin-x86.mk
index 4479a95..e8410cd 100644
--- a/net/net.target.darwin-x86.mk
+++ b/net/net.target.darwin-x86.mk
@@ -308,6 +308,7 @@
 	net/quic/crypto/scoped_evp_cipher_ctx.cc \
 	net/quic/crypto/strike_register.cc \
 	net/quic/crypto/source_address_token.cc \
+	net/quic/quic_alarm.cc \
 	net/quic/quic_bandwidth.cc \
 	net/quic/quic_client_session.cc \
 	net/quic/quic_config.cc \
diff --git a/net/net.target.linux-arm.mk b/net/net.target.linux-arm.mk
index 88d78fc..36ad05d 100644
--- a/net/net.target.linux-arm.mk
+++ b/net/net.target.linux-arm.mk
@@ -308,6 +308,7 @@
 	net/quic/crypto/scoped_evp_cipher_ctx.cc \
 	net/quic/crypto/strike_register.cc \
 	net/quic/crypto/source_address_token.cc \
+	net/quic/quic_alarm.cc \
 	net/quic/quic_bandwidth.cc \
 	net/quic/quic_client_session.cc \
 	net/quic/quic_config.cc \
diff --git a/net/net.target.linux-mips.mk b/net/net.target.linux-mips.mk
index 6fedabc..203e38d 100644
--- a/net/net.target.linux-mips.mk
+++ b/net/net.target.linux-mips.mk
@@ -308,6 +308,7 @@
 	net/quic/crypto/scoped_evp_cipher_ctx.cc \
 	net/quic/crypto/strike_register.cc \
 	net/quic/crypto/source_address_token.cc \
+	net/quic/quic_alarm.cc \
 	net/quic/quic_bandwidth.cc \
 	net/quic/quic_client_session.cc \
 	net/quic/quic_config.cc \
diff --git a/net/net.target.linux-x86.mk b/net/net.target.linux-x86.mk
index 4479a95..e8410cd 100644
--- a/net/net.target.linux-x86.mk
+++ b/net/net.target.linux-x86.mk
@@ -308,6 +308,7 @@
 	net/quic/crypto/scoped_evp_cipher_ctx.cc \
 	net/quic/crypto/strike_register.cc \
 	net/quic/crypto/source_address_token.cc \
+	net/quic/quic_alarm.cc \
 	net/quic/quic_bandwidth.cc \
 	net/quic/quic_client_session.cc \
 	net/quic/quic_config.cc \
diff --git a/net/quic/congestion_control/quic_congestion_manager.cc b/net/quic/congestion_control/quic_congestion_manager.cc
index 838195f..ba6bab8 100644
--- a/net/quic/congestion_control/quic_congestion_manager.cc
+++ b/net/quic/congestion_control/quic_congestion_manager.cc
@@ -20,7 +20,7 @@
 // define the minimum RTO to 200ms, we will use the same until we have data to
 // support a higher or lower value.
 static const int kMinRetransmissionTimeMs = 200;
-static const int kMaxRetransmissionTimeMs = 10000;
+static const int kMaxRetransmissionTimeMs = 60000;
 static const size_t kMaxRetransmissions = 10;
 static const size_t kTailDropWindowSize = 5;
 static const size_t kTailDropMaxRetransmissions = 4;
@@ -176,6 +176,7 @@
       retransmission_delay.ToMilliseconds() * static_cast<size_t>(
           (1 << min<size_t>(number_retransmissions, kMaxRetransmissions))));
 
+  // TODO(rch): This code should move to |send_algorithm_|.
   if (retransmission_delay.ToMilliseconds() < kMinRetransmissionTimeMs) {
     return QuicTime::Delta::FromMilliseconds(kMinRetransmissionTimeMs);
   }
diff --git a/net/quic/congestion_control/send_algorithm_interface.cc b/net/quic/congestion_control/send_algorithm_interface.cc
index 9b794b0..ce24a00 100644
--- a/net/quic/congestion_control/send_algorithm_interface.cc
+++ b/net/quic/congestion_control/send_algorithm_interface.cc
@@ -4,12 +4,17 @@
 
 #include "net/quic/congestion_control/send_algorithm_interface.h"
 
+#include "net/quic/congestion_control/cubic.h"
 #include "net/quic/congestion_control/fix_rate_sender.h"
 #include "net/quic/congestion_control/tcp_cubic_sender.h"
 
 namespace net {
 
 const bool kUseReno = false;
+// TODO(ianswett): Increase the max congestion window once the RTO logic is
+// improved, particularly in cases when RTT is larger than the RTO. b/10075719
+// Maximum number of outstanding packets for tcp.
+const QuicTcpCongestionWindow kMaxTcpCongestionWindow = 50;
 
 // Factory for send side congestion control algorithm.
 SendAlgorithmInterface* SendAlgorithmInterface::Create(
@@ -17,7 +22,7 @@
     CongestionFeedbackType type) {
   switch (type) {
     case kTCP:
-      return new TcpCubicSender(clock, kUseReno);
+      return new TcpCubicSender(clock, kUseReno, kMaxTcpCongestionWindow);
     case kInterArrival:
       break;  // TODO(pwestin) Implement.
     case kFixRate:
diff --git a/net/quic/congestion_control/tcp_cubic_sender.cc b/net/quic/congestion_control/tcp_cubic_sender.cc
index 56cc624..1e98c12 100644
--- a/net/quic/congestion_control/tcp_cubic_sender.cc
+++ b/net/quic/congestion_control/tcp_cubic_sender.cc
@@ -12,7 +12,6 @@
 const QuicByteCount kMaxSegmentSize = kMaxPacketSize;
 const QuicByteCount kDefaultReceiveWindow = 64000;
 const int64 kInitialCongestionWindow = 10;
-const int64 kMaxCongestionWindow = 10000;
 const int kMaxBurstLength = 3;
 const int kInitialRttMs = 60;  // At a typical RTT 60 ms.
 const float kAlpha = 0.125f;
@@ -21,7 +20,10 @@
 const float kOneMinusBeta = (1 - kBeta);
 };  // namespace
 
-TcpCubicSender::TcpCubicSender(const QuicClock* clock, bool reno)
+TcpCubicSender::TcpCubicSender(
+    const QuicClock* clock,
+    bool reno,
+    QuicTcpCongestionWindow max_tcp_congestion_window)
     : hybrid_slow_start_(clock),
       cubic_(clock),
       reno_(reno),
@@ -32,7 +34,8 @@
       update_end_sequence_number_(true),
       end_sequence_number_(0),
       congestion_window_(kInitialCongestionWindow),
-      slowstart_threshold_(kMaxCongestionWindow),
+      slowstart_threshold_(max_tcp_congestion_window),
+      max_tcp_congestion_window_(max_tcp_congestion_window),
       delay_min_(QuicTime::Delta::Zero()),
       smoothed_rtt_(QuicTime::Delta::Zero()),
       mean_deviation_(QuicTime::Delta::Zero()) {
@@ -191,13 +194,13 @@
       hybrid_slow_start_.Reset(end_sequence_number_);
     }
     // congestion_window_cnt is the number of acks since last change of snd_cwnd
-    if (congestion_window_ < kMaxCongestionWindow) {
+    if (congestion_window_ < max_tcp_congestion_window_) {
       // TCP slow start, exponentail growth, increase by one for each ACK.
       congestion_window_++;
     }
     DLOG(INFO) << "Slow start; congestion window:" << congestion_window_;
   } else {
-    if (congestion_window_ < kMaxCongestionWindow) {
+    if (congestion_window_ < max_tcp_congestion_window_) {
       if (reno_) {
         // Classic Reno congestion avoidance provided for testing.
         if (congestion_window_count_ >= congestion_window_) {
diff --git a/net/quic/congestion_control/tcp_cubic_sender.h b/net/quic/congestion_control/tcp_cubic_sender.h
index de8f9c3..c22813a 100644
--- a/net/quic/congestion_control/tcp_cubic_sender.h
+++ b/net/quic/congestion_control/tcp_cubic_sender.h
@@ -26,8 +26,10 @@
 
 class NET_EXPORT_PRIVATE TcpCubicSender : public SendAlgorithmInterface {
  public:
-  // Reno option provided for testing.
-  TcpCubicSender(const QuicClock* clock, bool reno);
+  // Reno option and max_tcp_congestion_window are provided for testing.
+  TcpCubicSender(const QuicClock* clock,
+                 bool reno,
+                 QuicTcpCongestionWindow max_tcp_congestion_window);
   virtual ~TcpCubicSender();
 
   // Start implementation of SendAlgorithmInterface.
@@ -94,6 +96,9 @@
   // Slow start congestion window in packets.
   QuicTcpCongestionWindow slowstart_threshold_;
 
+  // Maximum number of outstanding packets for tcp.
+  QuicTcpCongestionWindow max_tcp_congestion_window_;
+
   // Min RTT during this session.
   QuicTime::Delta delay_min_;
 
diff --git a/net/quic/congestion_control/tcp_cubic_sender_test.cc b/net/quic/congestion_control/tcp_cubic_sender_test.cc
index ecc8f21..e9f8893 100644
--- a/net/quic/congestion_control/tcp_cubic_sender_test.cc
+++ b/net/quic/congestion_control/tcp_cubic_sender_test.cc
@@ -17,8 +17,9 @@
 
 class TcpCubicSenderPeer : public TcpCubicSender {
  public:
+  // TODO(ianswett): Remove 10000 once b/10075719 is fixed.
   TcpCubicSenderPeer(const QuicClock* clock, bool reno)
-      : TcpCubicSender(clock, reno) {
+      : TcpCubicSender(clock, reno, 10000) {
   }
   using TcpCubicSender::AvailableCongestionWindow;
   using TcpCubicSender::CongestionWindow;
@@ -35,6 +36,7 @@
        sequence_number_(1),
        acked_sequence_number_(0) {
   }
+
   void SendAvailableCongestionWindow() {
     QuicByteCount bytes_to_send = sender_->AvailableCongestionWindow();
     while (bytes_to_send > 0) {
@@ -138,8 +140,8 @@
     SendAvailableCongestionWindow();
     AckNPackets(2);
   }
-  QuicByteCount expected_congestion_window = kDefaultWindowTCP +
-      (kMaxPacketSize * 2 * kNumberOfAck);
+  QuicByteCount expected_congestion_window =
+      kDefaultWindowTCP + (kMaxPacketSize * 2 * kNumberOfAck);
   EXPECT_EQ(expected_congestion_window, sender_->CongestionWindow());
   // We should now have fallen out of slow start.
   SendAvailableCongestionWindow();
diff --git a/net/quic/crypto/crypto_protocol.h b/net/quic/crypto/crypto_protocol.h
index 082976a..586569a 100644
--- a/net/quic/crypto/crypto_protocol.h
+++ b/net/quic/crypto/crypto_protocol.h
@@ -48,8 +48,12 @@
 const QuicTag kINAR = TAG('I', 'N', 'A', 'R');  // Inter arrival
 
 // Proof types (i.e. certificate types)
-const QuicTag kX509 = TAG('X', '5', '0', '9');  // X.509 certificate
-const QuicTag kX59R = TAG('X', '5', '9', 'R');  // X.509  - RSA only
+// NOTE: although it would be silly to do so, specifying both kX509 and kX59R
+// is allowed and is equivalent to specifying only kX509.
+const QuicTag kX509 = TAG('X', '5', '0', '9');  // X.509 certificate, all key
+                                                // types
+const QuicTag kX59R = TAG('X', '5', '9', 'R');  // X.509 certificate, RSA keys
+                                                // only
 const QuicTag kCHID = TAG('C', 'H', 'I', 'D');  // Channel ID.
 
 // Client hello tags
diff --git a/net/quic/crypto/crypto_server_config.cc b/net/quic/crypto/crypto_server_config.cc
index 62a4381..f270dde 100644
--- a/net/quic/crypto/crypto_server_config.cc
+++ b/net/quic/crypto/crypto_server_config.cc
@@ -304,6 +304,7 @@
 
 QuicErrorCode QuicCryptoServerConfig::ProcessClientHello(
     const CryptoHandshakeMessage& client_hello,
+    QuicVersion version,
     QuicGuid guid,
     const IPEndPoint& client_ip,
     const QuicClock* clock,
@@ -358,7 +359,8 @@
       !info.client_nonce_well_formed ||
       !info.unique ||
       !requested_config.get()) {
-    BuildRejection(primary_config, client_hello, info, rand, out);
+    BuildRejection(version, primary_config.get(), client_hello, info, rand,
+                   out);
     return QUIC_NO_ERROR;
   }
 
@@ -662,6 +664,7 @@
 }
 
 void QuicCryptoServerConfig::BuildRejection(
+    QuicVersion version,
     const scoped_refptr<Config>& config,
     const CryptoHandshakeMessage& client_hello,
     const ClientHelloInfo& info,
@@ -705,8 +708,9 @@
 
   const vector<string>* certs;
   string signature;
-  if (!proof_source_->GetProof(info.sni.as_string(), config->serialized,
-                               x509_ecdsa_supported, &certs, &signature)) {
+  if (!proof_source_->GetProof(version, info.sni.as_string(),
+                               config->serialized, x509_ecdsa_supported,
+                               &certs, &signature)) {
     return;
   }
 
diff --git a/net/quic/crypto/crypto_server_config.h b/net/quic/crypto/crypto_server_config.h
index 1a99136..364c200 100644
--- a/net/quic/crypto/crypto_server_config.h
+++ b/net/quic/crypto/crypto_server_config.h
@@ -116,6 +116,8 @@
   // an error code is returned.
   //
   // client_hello: the incoming client hello message.
+  // version: the QUIC version for the connection. TODO(wtc): Remove once
+  //     QUIC_VERSION_7 and before are removed.
   // guid: the GUID for the connection, which is used in key derivation.
   // client_ip: the IP address of the client, which is used to generate and
   //     validate source-address tokens.
@@ -127,6 +129,7 @@
   // out: the resulting handshake message (either REJ or SHLO)
   // error_details: used to store a string describing any error.
   QuicErrorCode ProcessClientHello(const CryptoHandshakeMessage& client_hello,
+                                   QuicVersion version,
                                    QuicGuid guid,
                                    const IPEndPoint& client_ip,
                                    const QuicClock* clock,
@@ -259,6 +262,7 @@
 
   // BuildRejection sets |out| to be a REJ message in reply to |client_hello|.
   void BuildRejection(
+      QuicVersion version,
       const scoped_refptr<Config>& config,
       const CryptoHandshakeMessage& client_hello,
       const ClientHelloInfo& info,
diff --git a/net/quic/crypto/crypto_server_test.cc b/net/quic/crypto/crypto_server_test.cc
index b2cdf82..6744d12 100644
--- a/net/quic/crypto/crypto_server_test.cc
+++ b/net/quic/crypto/crypto_server_test.cc
@@ -72,8 +72,8 @@
   void ShouldSucceed(const CryptoHandshakeMessage& message) {
     string error_details;
     QuicErrorCode error = config_.ProcessClientHello(
-        message, 1 /* GUID */, addr_, &clock_,
-        rand_, &params_, &out_, &error_details);
+        message, QuicVersionMax(), 1 /* GUID */, addr_,
+        &clock_, rand_, &params_, &out_, &error_details);
 
     ASSERT_EQ(error, QUIC_NO_ERROR)
         << "Message failed with error " << error_details << ": "
@@ -84,8 +84,8 @@
                             const CryptoHandshakeMessage& message) {
     string error_details;
     QuicErrorCode error = config_.ProcessClientHello(
-        message, 1 /* GUID */, addr_, &clock_,
-        rand_, &params_, &out_, &error_details);
+        message, QuicVersionMax(), 1 /* GUID */, addr_,
+        &clock_, rand_, &params_, &out_, &error_details);
 
     ASSERT_NE(error, QUIC_NO_ERROR)
         << "Message didn't fail: " << message.DebugString();
diff --git a/net/quic/crypto/proof_source.h b/net/quic/crypto/proof_source.h
index 277549f..42d8d50 100644
--- a/net/quic/crypto/proof_source.h
+++ b/net/quic/crypto/proof_source.h
@@ -9,6 +9,7 @@
 #include <vector>
 
 #include "net/base/net_export.h"
+#include "net/quic/quic_protocol.h"
 
 namespace net {
 
@@ -27,6 +28,12 @@
   //
   // The signature uses SHA-256 as the hash function when the key is ECDSA.
   //
+  // If |ecdsa_ok| is true, the signature may use an ECDSA key. Otherwise, the
+  // signature must use an RSA key.
+  //
+  // |version| is the QUIC version for the connection. TODO(wtc): Remove once
+  // QUIC_VERSION_7 and before are removed.
+  //
   // |out_certs| is a pointer to a pointer, not a pointer to an array.
   //
   // The number of certificate chains is expected to be small and fixed thus
@@ -42,7 +49,8 @@
   // used.
   //
   // This function may be called concurrently.
-  virtual bool GetProof(const std::string& hostname,
+  virtual bool GetProof(QuicVersion version,
+                        const std::string& hostname,
                         const std::string& server_config,
                         bool ecdsa_ok,
                         const std::vector<std::string>** out_certs,
diff --git a/net/quic/crypto/proof_source_chromium.cc b/net/quic/crypto/proof_source_chromium.cc
index 7522631..4c1fe26 100644
--- a/net/quic/crypto/proof_source_chromium.cc
+++ b/net/quic/crypto/proof_source_chromium.cc
@@ -12,7 +12,8 @@
 ProofSourceChromium::ProofSourceChromium() {
 }
 
-bool ProofSourceChromium::GetProof(const string& hostname,
+bool ProofSourceChromium::GetProof(QuicVersion version,
+                                   const string& hostname,
                                    const string& server_config,
                                    bool ecdsa_ok,
                                    const vector<string>** out_certs,
diff --git a/net/quic/crypto/proof_source_chromium.h b/net/quic/crypto/proof_source_chromium.h
index 70ab92d..2b93e2d 100644
--- a/net/quic/crypto/proof_source_chromium.h
+++ b/net/quic/crypto/proof_source_chromium.h
@@ -23,7 +23,8 @@
   virtual ~ProofSourceChromium() {}
 
   // ProofSource interface
-  virtual bool GetProof(const std::string& hostname,
+  virtual bool GetProof(QuicVersion version,
+                        const std::string& hostname,
                         const std::string& server_config,
                         bool ecdsa_ok,
                         const std::vector<std::string>** out_certs,
diff --git a/net/quic/crypto/proof_test.cc b/net/quic/crypto/proof_test.cc
index f973bde..97b0dcb 100644
--- a/net/quic/crypto/proof_test.cc
+++ b/net/quic/crypto/proof_test.cc
@@ -25,7 +25,21 @@
 namespace net {
 namespace test {
 
-TEST(Proof, Verify) {
+class ProofTest : public ::testing::TestWithParam<QuicVersion> {
+ protected:
+  ProofTest() {
+    version_ = GetParam();
+  }
+
+  QuicVersion version_;
+};
+
+// Run all ProofTests with QUIC versions 7 and 8.
+INSTANTIATE_TEST_CASE_P(ProofTests,
+                        ProofTest,
+                        ::testing::Values(QUIC_VERSION_7, QUIC_VERSION_8));
+
+TEST_P(ProofTest, Verify) {
   // TODO(rtenneti): Enable testing of ProofVerifier.
 #if 0
   scoped_ptr<ProofSource> source(CryptoTestUtils::ProofSourceForTesting());
@@ -39,10 +53,11 @@
   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));
+  ASSERT_TRUE(source->GetProof(version_, hostname, server_config,
+                               false /* no ECDSA */, &first_certs,
+                               &first_signature));
+  ASSERT_TRUE(source->GetProof(version_, hostname, server_config,
+                               false /* no ECDSA */, &certs, &signature));
 
   // Check that the proof source is caching correctly:
   ASSERT_EQ(first_certs, certs);
@@ -50,22 +65,23 @@
 
   int rv;
   TestCompletionCallback callback;
-  rv = verifier->VerifyProof(hostname, server_config, *certs, signature,
-                             &error_details, &cert_verify_result,
+  rv = verifier->VerifyProof(version_, 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,
+  rv = verifier->VerifyProof(version_, "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),
+  rv = verifier->VerifyProof(version_, hostname,
+                             server_config.substr(1, string::npos),
                              *certs, signature, &error_details,
                              &cert_verify_result, callback.callback());
   rv = callback.GetResult(rv);
@@ -73,9 +89,9 @@
   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 = verifier->VerifyProof(version_, 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);
@@ -84,8 +100,8 @@
   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,
+  rv = verifier->VerifyProof(version_, "foo.com", server_config, wrong_certs,
+                             signature, &error_details, &cert_verify_result,
                              callback.callback());
   rv = callback.GetResult(rv);
   ASSERT_EQ(ERR_FAILED, rv);
@@ -122,7 +138,8 @@
 
 // RunVerification runs |verifier->VerifyProof| and asserts that the result
 // matches |expected_ok|.
-static void RunVerification(ProofVerifier* verifier,
+static void RunVerification(QuicVersion version,
+                            ProofVerifier* verifier,
                             const std::string& hostname,
                             const std::string& server_config,
                             const vector<std::string>& certs,
@@ -136,7 +153,7 @@
       new TestProofVerifierCallback(&comp_callback, &ok, &error_details);
 
   ProofVerifier::Status status = verifier->VerifyProof(
-      hostname, server_config, certs, proof, &error_details, &details,
+      version, hostname, server_config, certs, proof, &error_details, &details,
       callback);
 
   switch (status) {
@@ -168,59 +185,9 @@
 
 // A known answer test that allows us to test ProofVerifier without a working
 // ProofSource.
-TEST(Proof, VerifyRSAKnownAnswerTest) {
+TEST_P(ProofTest, VerifyRSAKnownAnswerTest) {
   // These sample signatures were generated by running the Proof.Verify test
   // and dumping the bytes of the |signature| output of ProofSource::GetProof().
-#if 0
-  // In the future, we will change the |sLen| parameter of RSA-PSS to be the
-  // same as |hLen|, and these are the sample signatures with the parameter
-  // |sLen| equal to |hLen|.
-  static const unsigned char signature_data_0[] = {
-    0x9e, 0xe6, 0x74, 0x3b, 0x8f, 0xb8, 0x66, 0x77, 0x57, 0x09,
-    0x8a, 0x04, 0xe9, 0xf0, 0x7c, 0x91, 0xa9, 0x5c, 0xe9, 0xdf,
-    0x12, 0x4d, 0x23, 0x82, 0x8c, 0x29, 0x72, 0x7f, 0xc2, 0x20,
-    0xa7, 0xb3, 0xe5, 0xbc, 0xcf, 0x3c, 0x0d, 0x8f, 0xae, 0x46,
-    0x6a, 0xb9, 0xee, 0x0c, 0xe1, 0x13, 0x21, 0xc0, 0x7e, 0x45,
-    0x24, 0x24, 0x4b, 0x72, 0x43, 0x5e, 0xc4, 0x0d, 0xdf, 0x6c,
-    0xd8, 0xaa, 0x35, 0x97, 0x05, 0x40, 0x76, 0xd3, 0x2c, 0xee,
-    0x82, 0x16, 0x6a, 0x43, 0xf9, 0xa2, 0xd0, 0x41, 0x3c, 0xed,
-    0x3f, 0x40, 0x10, 0x95, 0xc7, 0xa9, 0x1f, 0x04, 0xdb, 0xd5,
-    0x98, 0x9f, 0xe2, 0xbf, 0x77, 0x3d, 0xc9, 0x9a, 0xaf, 0xf7,
-    0xef, 0x63, 0x0b, 0x7d, 0xc8, 0x37, 0xda, 0x37, 0x23, 0x88,
-    0x78, 0xc8, 0x8b, 0xf5, 0xb9, 0x36, 0x5d, 0x72, 0x1f, 0xfc,
-    0x14, 0xff, 0xa7, 0x81, 0x27, 0x49, 0xae, 0xe1,
-  };
-  static const unsigned char signature_data_1[] = {
-    0x5e, 0xc2, 0xab, 0x6b, 0x16, 0xe6, 0x55, 0xf3, 0x16, 0x46,
-    0x35, 0xdc, 0xcc, 0xde, 0xd0, 0xbd, 0x6c, 0x66, 0xb2, 0x3d,
-    0xd3, 0x14, 0x78, 0xed, 0x47, 0x55, 0xfb, 0xdb, 0xe1, 0x7d,
-    0xbf, 0x31, 0xf6, 0xf4, 0x10, 0x4c, 0x8d, 0x22, 0x17, 0xaa,
-    0xe1, 0x85, 0xc7, 0x96, 0x4c, 0x42, 0xfb, 0xf4, 0x63, 0x53,
-    0x8a, 0x79, 0x01, 0x63, 0x48, 0xa8, 0x3a, 0xbc, 0xc9, 0xd2,
-    0xf5, 0xec, 0xe9, 0x09, 0x71, 0xaf, 0xce, 0x34, 0x56, 0xe5,
-    0x00, 0xbe, 0xee, 0x3c, 0x1c, 0xc4, 0xa0, 0x07, 0xd5, 0x77,
-    0xb8, 0x83, 0x57, 0x7d, 0x1a, 0xc9, 0xd0, 0xc0, 0x59, 0x9a,
-    0x88, 0x19, 0x3f, 0xb9, 0xf0, 0x45, 0x37, 0xc3, 0x00, 0x8b,
-    0xb3, 0x89, 0xf4, 0x89, 0x07, 0xa9, 0xc3, 0x26, 0xbf, 0x81,
-    0xaf, 0x6b, 0x47, 0xbc, 0x16, 0x55, 0x37, 0x0a, 0xbe, 0x0e,
-    0xc5, 0x75, 0x3f, 0x3d, 0x8e, 0xe8, 0x44, 0xe3,
-  };
-  static const unsigned char signature_data_2[] = {
-    0x8e, 0x5c, 0x78, 0x63, 0x74, 0x99, 0x2e, 0x96, 0xc0, 0x14,
-    0x8d, 0xb5, 0x13, 0x74, 0xa3, 0xa4, 0xe0, 0x43, 0x3e, 0x85,
-    0xba, 0x8f, 0x3c, 0x5e, 0x14, 0x64, 0x0e, 0x5e, 0xff, 0x89,
-    0x88, 0x8a, 0x65, 0xe2, 0xa2, 0x79, 0xe4, 0xe9, 0x3a, 0x7f,
-    0xf6, 0x9d, 0x3d, 0xe2, 0xb0, 0x8a, 0x35, 0x55, 0xed, 0x21,
-    0xee, 0x20, 0xd8, 0x8a, 0x60, 0x47, 0xca, 0x52, 0x54, 0x91,
-    0x99, 0x69, 0x8d, 0x16, 0x34, 0x69, 0xe1, 0x46, 0x56, 0x67,
-    0x5f, 0x50, 0xf0, 0x94, 0xe7, 0x8b, 0xf2, 0x6a, 0x73, 0x0f,
-    0x30, 0x30, 0xde, 0x59, 0xdc, 0xc7, 0xfe, 0xb6, 0x83, 0xe1,
-    0x86, 0x1d, 0x88, 0xd3, 0x2f, 0x2f, 0x74, 0x68, 0xbd, 0x6c,
-    0xd1, 0x46, 0x76, 0x06, 0xa9, 0xd4, 0x03, 0x3f, 0xda, 0x7d,
-    0xa7, 0xff, 0x48, 0xe4, 0xb4, 0x42, 0x06, 0xac, 0x19, 0x12,
-    0xe6, 0x05, 0xae, 0xbe, 0x29, 0x94, 0x8f, 0x99,
-  };
-#else
   // sLen = special value -2 used by OpenSSL.
   static const unsigned char signature_data_0[] = {
     0x4c, 0x68, 0x3c, 0xc2, 0x1f, 0x31, 0x73, 0xa5, 0x29, 0xd3,
@@ -267,7 +234,51 @@
     0xd2, 0x50, 0x81, 0x78, 0x41, 0x13, 0x2c, 0x65, 0x9c, 0x9e,
     0xf4, 0xd2, 0xd5, 0x58, 0x5b, 0x8b, 0x87, 0xcf,
   };
-#endif
+  static const unsigned char signature_data_4[] = {
+    0x9e, 0xe6, 0x74, 0x3b, 0x8f, 0xb8, 0x66, 0x77, 0x57, 0x09,
+    0x8a, 0x04, 0xe9, 0xf0, 0x7c, 0x91, 0xa9, 0x5c, 0xe9, 0xdf,
+    0x12, 0x4d, 0x23, 0x82, 0x8c, 0x29, 0x72, 0x7f, 0xc2, 0x20,
+    0xa7, 0xb3, 0xe5, 0xbc, 0xcf, 0x3c, 0x0d, 0x8f, 0xae, 0x46,
+    0x6a, 0xb9, 0xee, 0x0c, 0xe1, 0x13, 0x21, 0xc0, 0x7e, 0x45,
+    0x24, 0x24, 0x4b, 0x72, 0x43, 0x5e, 0xc4, 0x0d, 0xdf, 0x6c,
+    0xd8, 0xaa, 0x35, 0x97, 0x05, 0x40, 0x76, 0xd3, 0x2c, 0xee,
+    0x82, 0x16, 0x6a, 0x43, 0xf9, 0xa2, 0xd0, 0x41, 0x3c, 0xed,
+    0x3f, 0x40, 0x10, 0x95, 0xc7, 0xa9, 0x1f, 0x04, 0xdb, 0xd5,
+    0x98, 0x9f, 0xe2, 0xbf, 0x77, 0x3d, 0xc9, 0x9a, 0xaf, 0xf7,
+    0xef, 0x63, 0x0b, 0x7d, 0xc8, 0x37, 0xda, 0x37, 0x23, 0x88,
+    0x78, 0xc8, 0x8b, 0xf5, 0xb9, 0x36, 0x5d, 0x72, 0x1f, 0xfc,
+    0x14, 0xff, 0xa7, 0x81, 0x27, 0x49, 0xae, 0xe1,
+  };
+  static const unsigned char signature_data_5[] = {
+    0x5e, 0xc2, 0xab, 0x6b, 0x16, 0xe6, 0x55, 0xf3, 0x16, 0x46,
+    0x35, 0xdc, 0xcc, 0xde, 0xd0, 0xbd, 0x6c, 0x66, 0xb2, 0x3d,
+    0xd3, 0x14, 0x78, 0xed, 0x47, 0x55, 0xfb, 0xdb, 0xe1, 0x7d,
+    0xbf, 0x31, 0xf6, 0xf4, 0x10, 0x4c, 0x8d, 0x22, 0x17, 0xaa,
+    0xe1, 0x85, 0xc7, 0x96, 0x4c, 0x42, 0xfb, 0xf4, 0x63, 0x53,
+    0x8a, 0x79, 0x01, 0x63, 0x48, 0xa8, 0x3a, 0xbc, 0xc9, 0xd2,
+    0xf5, 0xec, 0xe9, 0x09, 0x71, 0xaf, 0xce, 0x34, 0x56, 0xe5,
+    0x00, 0xbe, 0xee, 0x3c, 0x1c, 0xc4, 0xa0, 0x07, 0xd5, 0x77,
+    0xb8, 0x83, 0x57, 0x7d, 0x1a, 0xc9, 0xd0, 0xc0, 0x59, 0x9a,
+    0x88, 0x19, 0x3f, 0xb9, 0xf0, 0x45, 0x37, 0xc3, 0x00, 0x8b,
+    0xb3, 0x89, 0xf4, 0x89, 0x07, 0xa9, 0xc3, 0x26, 0xbf, 0x81,
+    0xaf, 0x6b, 0x47, 0xbc, 0x16, 0x55, 0x37, 0x0a, 0xbe, 0x0e,
+    0xc5, 0x75, 0x3f, 0x3d, 0x8e, 0xe8, 0x44, 0xe3,
+  };
+  static const unsigned char signature_data_6[] = {
+    0x8e, 0x5c, 0x78, 0x63, 0x74, 0x99, 0x2e, 0x96, 0xc0, 0x14,
+    0x8d, 0xb5, 0x13, 0x74, 0xa3, 0xa4, 0xe0, 0x43, 0x3e, 0x85,
+    0xba, 0x8f, 0x3c, 0x5e, 0x14, 0x64, 0x0e, 0x5e, 0xff, 0x89,
+    0x88, 0x8a, 0x65, 0xe2, 0xa2, 0x79, 0xe4, 0xe9, 0x3a, 0x7f,
+    0xf6, 0x9d, 0x3d, 0xe2, 0xb0, 0x8a, 0x35, 0x55, 0xed, 0x21,
+    0xee, 0x20, 0xd8, 0x8a, 0x60, 0x47, 0xca, 0x52, 0x54, 0x91,
+    0x99, 0x69, 0x8d, 0x16, 0x34, 0x69, 0xe1, 0x46, 0x56, 0x67,
+    0x5f, 0x50, 0xf0, 0x94, 0xe7, 0x8b, 0xf2, 0x6a, 0x73, 0x0f,
+    0x30, 0x30, 0xde, 0x59, 0xdc, 0xc7, 0xfe, 0xb6, 0x83, 0xe1,
+    0x86, 0x1d, 0x88, 0xd3, 0x2f, 0x2f, 0x74, 0x68, 0xbd, 0x6c,
+    0xd1, 0x46, 0x76, 0x06, 0xa9, 0xd4, 0x03, 0x3f, 0xda, 0x7d,
+    0xa7, 0xff, 0x48, 0xe4, 0xb4, 0x42, 0x06, 0xac, 0x19, 0x12,
+    0xe6, 0x05, 0xae, 0xbe, 0x29, 0x94, 0x8f, 0x99,
+  };
 
   scoped_ptr<ProofVerifier> verifier(
       CryptoTestUtils::ProofVerifierForTesting());
@@ -284,41 +295,52 @@
   // Signatures are nondeterministic, so we test multiple signatures on the
   // same server_config.
   vector<string> signatures(3);
-  signatures[0].assign(reinterpret_cast<const char*>(signature_data_0),
-                       sizeof(signature_data_0));
-  signatures[1].assign(reinterpret_cast<const char*>(signature_data_1),
-                       sizeof(signature_data_1));
-  signatures[2].assign(reinterpret_cast<const char*>(signature_data_2),
-                       sizeof(signature_data_2));
+  if (version_ < QUIC_VERSION_8) {
+    signatures[0].assign(reinterpret_cast<const char*>(signature_data_0),
+                         sizeof(signature_data_0));
+    signatures[1].assign(reinterpret_cast<const char*>(signature_data_1),
+                         sizeof(signature_data_1));
+    signatures[2].assign(reinterpret_cast<const char*>(signature_data_2),
+                         sizeof(signature_data_2));
+  } else {
+    signatures[0].assign(reinterpret_cast<const char*>(signature_data_4),
+                         sizeof(signature_data_4));
+    signatures[1].assign(reinterpret_cast<const char*>(signature_data_5),
+                         sizeof(signature_data_5));
+    signatures[2].assign(reinterpret_cast<const char*>(signature_data_6),
+                         sizeof(signature_data_6));
+  }
 
   for (size_t i = 0; i < signatures.size(); i++) {
     const string& signature = signatures[i];
 
     RunVerification(
-        verifier.get(), hostname, server_config, certs, signature, true);
+        version_, verifier.get(), hostname, server_config, certs, signature,
+        true);
     RunVerification(
-        verifier.get(), "foo.com", server_config, certs, signature, false);
+        version_, verifier.get(), "foo.com", server_config, certs, signature,
+        false);
     RunVerification(
-        verifier.get(), hostname, server_config.substr(1, string::npos),
-        certs, signature, false);
+        version_, verifier.get(), hostname,
+        server_config.substr(1, string::npos), certs, signature, false);
 
     const string corrupt_signature = "1" + signature;
     RunVerification(
-        verifier.get(), hostname, server_config, certs, corrupt_signature,
-        false);
+        version_, 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(), hostname, server_config, wrong_certs,
-                    signature, false);
+    RunVerification(version_, verifier.get(), hostname, server_config,
+                    wrong_certs, signature, false);
   }
 }
 
 // A known answer test that allows us to test ProofVerifier without a working
 // ProofSource.
-TEST(Proof, VerifyECDSAKnownAnswerTest) {
+TEST_P(ProofTest, VerifyECDSAKnownAnswerTest) {
   // Disable this test on platforms that do not support ECDSA certificates.
 #if defined(OS_WIN)
   if (base::win::GetVersion() < base::win::VERSION_VISTA)
@@ -384,33 +406,36 @@
     const string& signature = signatures[i];
 
     RunVerification(
-        verifier.get(), hostname, server_config, certs, signature, true);
+        version_, verifier.get(), hostname, server_config, certs, signature,
+        true);
     RunVerification(
-        verifier.get(), "foo.com", server_config, certs, signature, false);
+        version_, verifier.get(), "foo.com", server_config, certs, signature,
+        false);
     RunVerification(
-        verifier.get(), hostname, server_config.substr(1, string::npos),
-        certs, signature, false);
+        version_, verifier.get(), hostname,
+        server_config.substr(1, string::npos), certs, signature, false);
 
     // An ECDSA signature is DER-encoded. Corrupt the last byte so that the
     // signature can still be DER-decoded correctly.
     string corrupt_signature = signature;
     corrupt_signature[corrupt_signature.size() - 1] += 1;
     RunVerification(
-        verifier.get(), hostname, server_config, certs, corrupt_signature,
-        false);
+        version_, verifier.get(), hostname, server_config, certs,
+        corrupt_signature, false);
 
     // Prepending a "1" makes the DER invalid.
     const string bad_der_signature1 = "1" + signature;
     RunVerification(
-        verifier.get(), hostname, server_config, certs, bad_der_signature1,
-        false);
+        version_, verifier.get(), hostname, server_config, certs,
+        bad_der_signature1, false);
 
     vector<string> wrong_certs;
     for (size_t i = 1; i < certs.size(); i++) {
       wrong_certs.push_back(certs[i]);
     }
     RunVerification(
-        verifier.get(), hostname, server_config, wrong_certs, signature, false);
+        version_, verifier.get(), hostname, server_config, wrong_certs,
+        signature, false);
   }
 }
 
diff --git a/net/quic/crypto/proof_verifier.h b/net/quic/crypto/proof_verifier.h
index f469c55..ecab113 100644
--- a/net/quic/crypto/proof_verifier.h
+++ b/net/quic/crypto/proof_verifier.h
@@ -10,6 +10,7 @@
 
 #include "net/base/completion_callback.h"
 #include "net/base/net_export.h"
+#include "net/quic/quic_protocol.h"
 
 namespace net {
 
@@ -70,7 +71,11 @@
   //
   // The signature uses SHA-256 as the hash function and PSS padding in the
   // case of RSA.
-  virtual Status VerifyProof(const std::string& hostname,
+  //
+  // |version| is the QUIC version for the connection. TODO(wtc): Remove once
+  // QUIC_VERSION_7 and before are removed.
+  virtual Status VerifyProof(QuicVersion version,
+                             const std::string& hostname,
                              const std::string& server_config,
                              const std::vector<std::string>& certs,
                              const std::string& signature,
diff --git a/net/quic/crypto/proof_verifier_chromium.cc b/net/quic/crypto/proof_verifier_chromium.cc
index c8b197b..8865305 100644
--- a/net/quic/crypto/proof_verifier_chromium.cc
+++ b/net/quic/crypto/proof_verifier_chromium.cc
@@ -42,6 +42,7 @@
 }
 
 ProofVerifierChromium::Status ProofVerifierChromium::VerifyProof(
+    QuicVersion version,
     const string& hostname,
     const string& server_config,
     const vector<string>& certs,
@@ -89,7 +90,7 @@
 
   // We call VerifySignature first to avoid copying of server_config and
   // signature.
-  if (!VerifySignature(server_config, signature, certs[0])) {
+  if (!VerifySignature(version, server_config, signature, certs[0])) {
     *error_details = "Failed to verify signature of server config";
     DLOG(WARNING) << *error_details;
     verify_details_->cert_verify_result.cert_status = CERT_STATUS_INVALID;
@@ -176,7 +177,8 @@
   return result;
 }
 
-bool ProofVerifierChromium::VerifySignature(const string& signed_data,
+bool ProofVerifierChromium::VerifySignature(QuicVersion version,
+                                            const string& signed_data,
                                             const string& signature,
                                             const string& cert) {
   StringPiece spki;
@@ -196,8 +198,8 @@
         crypto::SignatureVerifier::SHA256;
     crypto::SignatureVerifier::HashAlgorithm mask_hash_alg = hash_alg;
     unsigned int hash_len = 32;  // 32 is the length of a SHA-256 hash.
-    // TODO(wtc): change this to hash_len when we can change the wire format.
-    unsigned int salt_len = signature.size() - hash_len - 2;
+    unsigned int salt_len =
+        version >= QUIC_VERSION_8 ? hash_len : signature.size() - hash_len - 2;
 
     bool ok = verifier.VerifyInitRSAPSS(
         hash_alg, mask_hash_alg, salt_len,
diff --git a/net/quic/crypto/proof_verifier_chromium.h b/net/quic/crypto/proof_verifier_chromium.h
index 4969cc8..8786e52 100644
--- a/net/quic/crypto/proof_verifier_chromium.h
+++ b/net/quic/crypto/proof_verifier_chromium.h
@@ -39,7 +39,8 @@
   virtual ~ProofVerifierChromium();
 
   // ProofVerifier interface
-  virtual Status VerifyProof(const std::string& hostname,
+  virtual Status VerifyProof(QuicVersion version,
+                             const std::string& hostname,
                              const std::string& server_config,
                              const std::vector<std::string>& certs,
                              const std::string& signature,
@@ -59,7 +60,8 @@
   int DoVerifyCert(int result);
   int DoVerifyCertComplete(int result);
 
-  bool VerifySignature(const std::string& signed_data,
+  bool VerifySignature(QuicVersion version,
+                       const std::string& signed_data,
                        const std::string& signature,
                        const std::string& cert);
 
diff --git a/net/quic/quic_alarm.cc b/net/quic/quic_alarm.cc
new file mode 100644
index 0000000..e1d4a16
--- /dev/null
+++ b/net/quic/quic_alarm.cc
@@ -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.
+
+#include "net/quic/quic_alarm.h"
+
+#include "base/logging.h"
+
+namespace net {
+
+QuicAlarm::QuicAlarm(Delegate* delegate)
+    : delegate_(delegate),
+      deadline_(QuicTime::Zero()) {
+}
+
+QuicAlarm::~QuicAlarm() {}
+
+void QuicAlarm::Set(QuicTime deadline) {
+  DCHECK(!IsSet());
+  DCHECK(deadline.IsInitialized());
+  deadline_ = deadline;
+  SetImpl();
+}
+
+void QuicAlarm::Cancel() {
+  deadline_ = QuicTime::Zero();
+  CancelImpl();
+}
+
+bool QuicAlarm::IsSet() const {
+  return deadline_.IsInitialized();
+}
+
+void QuicAlarm::Fire() {
+  if (!deadline_.IsInitialized()) {
+    return;
+  }
+
+  deadline_ = QuicTime::Zero();
+  QuicTime deadline = delegate_->OnAlarm();
+  // delegate_->OnAlarm() might call Set(), in which case  deadline_ will
+  // already contain the new value, so don't overwrite it.
+  if (!deadline_.IsInitialized() && deadline.IsInitialized()) {
+    Set(deadline);
+  }
+}
+
+}  // namespace net
diff --git a/net/quic/quic_alarm.h b/net/quic/quic_alarm.h
new file mode 100644
index 0000000..bee5157
--- /dev/null
+++ b/net/quic/quic_alarm.h
@@ -0,0 +1,77 @@
+// 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 NET_QUIC_QUIC_ALARM_H_
+#define NET_QUIC_QUIC_ALARM_H_
+
+#include "base/memory/scoped_ptr.h"
+#include "net/base/net_export.h"
+#include "net/quic/quic_time.h"
+
+namespace net {
+
+// Abstract class which represents an alarm which will go off at a
+// scheduled time, and execute the |OnAlarm| method of the delegate.
+// An alarm may be cancelled, in which case it may or may not be
+// removed from the underlying scheduling system, but in either case
+// the task will not be executed.
+class NET_EXPORT_PRIVATE QuicAlarm {
+ public:
+  class NET_EXPORT_PRIVATE Delegate {
+   public:
+    virtual ~Delegate() {}
+
+    // Invoked when the alarm fires.  If the return value is not
+    // infinite, then the alarm will be rescheduled at the
+    // specified time.
+    virtual QuicTime OnAlarm() = 0;
+  };
+
+  explicit QuicAlarm(Delegate* delegate);
+  virtual ~QuicAlarm();
+
+  // Sets the alarm to fire at |deadline|.  Must not be called while
+  // the alarm is set.  To reschedule an alarm, call Cancel() first,
+  // then Set().
+  void Set(QuicTime deadline);
+
+  // Cancels the alarm.  May be called repeatedly.  Does not
+  // guarantee that the underlying scheduling system will remove
+  // the alarm's associated task, but guarantees that the
+  // delegates OnAlarm method will not be called.
+  void Cancel();
+
+  bool IsSet() const;
+
+  QuicTime deadline() const { return deadline_; }
+
+ protected:
+  // Subclasses implement this method to perform the platform-specific
+  // scheduling of the alarm.  Is called from Set() or Fire(), after the
+  // deadline has been updated.
+  virtual void SetImpl() = 0;
+
+  // Subclasses implement this method to perform the platform-specific
+  // cancelation of the alarm.
+  virtual void CancelImpl() = 0;
+
+  // Called by subclasses when the alarm fires.  Invokes the
+  // delegates |OnAlarm| if a delegate is set, and if the deadline
+  // has been exceeded.  Implementations which do not remove the
+  // alarm from the underlying scheduler on Cancel() may need to handle
+  // the situation where the task executes before the deadline has been
+  // reached, in which case they need to reschedule the task and must not
+  // call invoke this method.
+  void Fire();
+
+ private:
+  scoped_ptr<Delegate> delegate_;
+  QuicTime deadline_;
+
+  DISALLOW_COPY_AND_ASSIGN(QuicAlarm);
+};
+
+}  // namespace net
+
+#endif  // NET_QUIC_QUIC_ALARM_H_
diff --git a/net/quic/quic_alarm_test.cc b/net/quic/quic_alarm_test.cc
new file mode 100644
index 0000000..cd7d8a5
--- /dev/null
+++ b/net/quic/quic_alarm_test.cc
@@ -0,0 +1,126 @@
+// 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/quic_alarm.h"
+
+#include "base/logging.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using testing::Return;
+using testing::Invoke;
+
+namespace net {
+namespace test {
+namespace {
+
+class MockDelegate : public QuicAlarm::Delegate {
+ public:
+  MOCK_METHOD0(OnAlarm, QuicTime());
+};
+
+class TestAlarm : public QuicAlarm {
+ public:
+  TestAlarm(QuicAlarm::Delegate* delegate)
+      : QuicAlarm(delegate) {
+  }
+
+  bool scheduled() const { return scheduled_; }
+
+  void FireAlarm() {
+    scheduled_ = false;
+    Fire();
+  }
+
+ protected:
+  virtual void SetImpl() OVERRIDE {
+    DCHECK(deadline().IsInitialized());
+    scheduled_ = true;
+  }
+
+  virtual void CancelImpl() OVERRIDE {
+    DCHECK(!deadline().IsInitialized());
+    scheduled_ = false;
+  }
+
+ private:
+  bool scheduled_;
+};
+
+class QuicAlarmTest : public ::testing::Test {
+ public:
+  QuicAlarmTest()
+      : delegate_(new MockDelegate()),
+        alarm_(delegate_),
+        deadline_(QuicTime::Zero().Add(QuicTime::Delta::FromSeconds(7))),
+        deadline2_(QuicTime::Zero().Add(QuicTime::Delta::FromSeconds(14))),
+        new_deadline_(QuicTime::Zero()) {
+  }
+
+  void ResetAlarm() {
+    alarm_.Set(new_deadline_);
+  }
+
+  MockDelegate* delegate_;  // not owned
+  TestAlarm alarm_;
+  QuicTime deadline_;
+  QuicTime deadline2_;
+  QuicTime new_deadline_;
+};
+
+TEST_F(QuicAlarmTest, IsSet) {
+  EXPECT_FALSE(alarm_.IsSet());
+}
+
+TEST_F(QuicAlarmTest, Set) {
+  QuicTime deadline = QuicTime::Zero().Add(QuicTime::Delta::FromSeconds(7));
+  alarm_.Set(deadline);
+  EXPECT_TRUE(alarm_.IsSet());
+  EXPECT_TRUE(alarm_.scheduled());
+  EXPECT_EQ(deadline, alarm_.deadline());
+}
+
+TEST_F(QuicAlarmTest, Cancel) {
+  QuicTime deadline = QuicTime::Zero().Add(QuicTime::Delta::FromSeconds(7));
+  alarm_.Set(deadline);
+  alarm_.Cancel();
+  EXPECT_FALSE(alarm_.IsSet());
+  EXPECT_FALSE(alarm_.scheduled());
+  EXPECT_EQ(QuicTime::Zero(), alarm_.deadline());
+}
+
+TEST_F(QuicAlarmTest, Fire) {
+  QuicTime deadline = QuicTime::Zero().Add(QuicTime::Delta::FromSeconds(7));
+  alarm_.Set(deadline);
+  EXPECT_CALL(*delegate_, OnAlarm()).WillOnce(Return(QuicTime::Zero()));
+  alarm_.FireAlarm();
+  EXPECT_FALSE(alarm_.IsSet());
+  EXPECT_FALSE(alarm_.scheduled());
+  EXPECT_EQ(QuicTime::Zero(), alarm_.deadline());
+}
+
+TEST_F(QuicAlarmTest, FireAndResetViaReturn) {
+  alarm_.Set(deadline_);
+  EXPECT_CALL(*delegate_, OnAlarm()).WillOnce(Return(deadline2_));
+  alarm_.FireAlarm();
+  EXPECT_TRUE(alarm_.IsSet());
+  EXPECT_TRUE(alarm_.scheduled());
+  EXPECT_EQ(deadline2_, alarm_.deadline());
+}
+
+TEST_F(QuicAlarmTest, FireAndResetViaSet) {
+  alarm_.Set(deadline_);
+  new_deadline_ = deadline2_;
+  EXPECT_CALL(*delegate_, OnAlarm()).WillOnce(DoAll(
+      Invoke(this, &QuicAlarmTest::ResetAlarm),
+      Return(QuicTime::Zero())));
+  alarm_.FireAlarm();
+  EXPECT_TRUE(alarm_.IsSet());
+  EXPECT_TRUE(alarm_.scheduled());
+  EXPECT_EQ(deadline2_, alarm_.deadline());
+}
+
+}  // namespace
+}  // namespace test
+}  // namespace net
diff --git a/net/quic/quic_client_session.cc b/net/quic/quic_client_session.cc
index 69e9775..d7fb0d2 100644
--- a/net/quic/quic_client_session.cc
+++ b/net/quic/quic_client_session.cc
@@ -263,6 +263,8 @@
 void QuicClientSession::ConnectionClose(QuicErrorCode error, bool from_peer) {
   UMA_HISTOGRAM_SPARSE_SLOWLY("Net.QuicSession.ConnectionCloseErrorCode",
                               error);
+  UMA_HISTOGRAM_SPARSE_SLOWLY("Net.QuicSession.QuicVersion",
+                              connection()->version());
   if (!callback_.is_null()) {
     base::ResetAndReturn(&callback_).Run(ERR_QUIC_PROTOCOL_ERROR);
   }
@@ -319,6 +321,7 @@
 base::Value* QuicClientSession::GetInfoAsValue(const HostPortPair& pair) const {
   base::DictionaryValue* dict = new base::DictionaryValue();
   dict->SetString("host_port_pair", pair.ToString());
+  dict->SetString("version", QuicVersionToString(connection()->version()));
   dict->SetInteger("open_streams", GetNumOpenStreams());
   dict->SetInteger("total_streams", num_total_streams_);
   dict->SetString("peer_address", peer_address().ToString());
diff --git a/net/quic/quic_connection.cc b/net/quic/quic_connection.cc
index 30f822c..fefeba9 100644
--- a/net/quic/quic_connection.cc
+++ b/net/quic/quic_connection.cc
@@ -62,6 +62,74 @@
   return delta <= kMaxPacketGap;
 }
 
+
+// An alarm that is scheduled to send an ack if a timeout occurs.
+class AckAlarm : public QuicAlarm::Delegate {
+ public:
+  explicit AckAlarm(QuicConnection* connection)
+      : connection_(connection) {
+  }
+
+  virtual QuicTime OnAlarm() OVERRIDE {
+    connection_->SendAck();
+    return QuicTime::Zero();
+  }
+
+ private:
+  QuicConnection* connection_;
+};
+
+// This alarm will be scheduled any time a data-bearing packet is sent out.
+// When the alarm goes off, the connection checks to see if the oldest packets
+// have been acked, and retransmit them if they have not.
+class RetransmissionAlarm : public QuicAlarm::Delegate {
+ public:
+  explicit RetransmissionAlarm(QuicConnection* connection)
+      : connection_(connection) {
+  }
+
+  virtual QuicTime OnAlarm() OVERRIDE {
+    return connection_->OnRetransmissionTimeout();
+  }
+
+ private:
+  QuicConnection* connection_;
+};
+
+// An alarm that is scheduled when the sent scheduler requires a
+// a delay before sending packets and fires when the packet may be sent.
+class SendAlarm : public QuicAlarm::Delegate {
+ public:
+  explicit SendAlarm(QuicConnection* connection)
+      : connection_(connection) {
+  }
+
+  virtual QuicTime OnAlarm() OVERRIDE {
+    connection_->OnCanWrite();
+    // Never reschedule the alarm, since OnCanWrite does that.
+    return QuicTime::Zero();
+  }
+
+ private:
+  QuicConnection* connection_;
+};
+
+class TimeoutAlarm : public QuicAlarm::Delegate {
+ public:
+  explicit TimeoutAlarm(QuicConnection* connection)
+      : connection_(connection) {
+  }
+
+  virtual QuicTime OnAlarm() OVERRIDE {
+    connection_->CheckForTimeout();
+    // Never reschedule the alarm, since CheckForTimeout does that.
+    return QuicTime::Zero();
+  }
+
+ private:
+  QuicConnection* connection_;
+};
+
 }  // namespace
 
 #define ENDPOINT (is_server_ ? "Server: " : " Client: ")
@@ -83,6 +151,10 @@
       largest_seen_packet_with_ack_(0),
       handling_retransmission_timeout_(false),
       write_blocked_(false),
+      ack_alarm_(helper->CreateAlarm(new AckAlarm(this))),
+      retransmission_alarm_(helper->CreateAlarm(new RetransmissionAlarm(this))),
+      send_alarm_(helper->CreateAlarm(new SendAlarm(this))),
+      timeout_alarm_(helper->CreateAlarm(new TimeoutAlarm(this))),
       debug_visitor_(NULL),
       packet_creator_(guid_, &framer_, random_generator_, is_server),
       packet_generator_(this, NULL, &packet_creator_),
@@ -101,7 +173,7 @@
       send_ack_in_response_to_packet_(false),
       address_migrating_(false) {
   helper_->SetConnection(this);
-  helper_->SetTimeoutAlarm(idle_network_timeout_);
+  timeout_alarm_->Set(clock_->ApproximateNow().Add(idle_network_timeout_));
   framer_.set_visitor(this);
   framer_.set_received_entropy_calculator(&received_packet_manager_);
 
@@ -151,6 +223,11 @@
 }
 
 void QuicConnection::OnPacket() {
+  DCHECK(last_stream_frames_.empty() &&
+         last_goaway_frames_.empty() &&
+         last_rst_frames_.empty() &&
+         last_ack_frames_.empty() &&
+         last_congestion_frames_.empty());
 }
 
 void QuicConnection::OnPublicResetPacket(
@@ -179,12 +256,12 @@
     case START_NEGOTIATION:
       if (!framer_.IsSupportedVersion(received_version)) {
         SendVersionNegotiationPacket();
-        version_negotiation_state_ = SENT_NEGOTIATION_PACKET;
+        version_negotiation_state_ = NEGOTIATION_IN_PROGRESS;
         return false;
       }
       break;
 
-    case SENT_NEGOTIATION_PACKET:
+    case NEGOTIATION_IN_PROGRESS:
       if (!framer_.IsSupportedVersion(received_version)) {
         // Drop packets which can't be parsed due to version mismatch.
         return false;
@@ -224,7 +301,7 @@
     debug_visitor_->OnVersionNegotiationPacket(packet);
   }
 
-  if (version_negotiation_state_ == NEGOTIATED_VERSION) {
+  if (version_negotiation_state_ != START_NEGOTIATION) {
     // Possibly a duplicate version negotiation packet.
     return;
   }
@@ -245,7 +322,7 @@
     return;
   }
 
-  version_negotiation_state_ = NEGOTIATED_VERSION;
+  version_negotiation_state_ = NEGOTIATION_IN_PROGRESS;
   RetransmitUnackedPackets(ALL_PACKETS);
 }
 
@@ -314,6 +391,7 @@
   --stats_.packets_dropped;
   DVLOG(1) << ENDPOINT << "Received packet header: " << header;
   last_header_ = header;
+  DCHECK(connected_);
   return true;
 }
 
@@ -346,12 +424,17 @@
     DLOG(INFO) << ENDPOINT << "Received an old ack frame: ignoring";
     return true;
   }
-  largest_seen_packet_with_ack_ = last_header_.packet_sequence_number;
 
   if (!ValidateAckFrame(incoming_ack)) {
     SendConnectionClose(QUIC_INVALID_ACK_DATA);
     return false;
   }
+  last_ack_frames_.push_back(incoming_ack);
+  return connected_;
+}
+
+void QuicConnection::ProcessAckFrame(const QuicAckFrame& incoming_ack) {
+  largest_seen_packet_with_ack_ = last_header_.packet_sequence_number;
 
   received_truncated_ack_ =
       incoming_ack.received_info.missing_packets.size() >=
@@ -373,19 +456,6 @@
   }
   congestion_manager_.OnIncomingAckFrame(incoming_ack,
                                          time_of_last_received_packet_);
-
-  // Now the we have received an ack, we might be able to send packets which are
-  // queued locally, or drain streams which are blocked.
-  QuicTime::Delta delay = congestion_manager_.TimeUntilSend(
-      time_of_last_received_packet_, NOT_RETRANSMISSION,
-      HAS_RETRANSMITTABLE_DATA, NOT_HANDSHAKE);
-  if (delay.IsZero()) {
-    helper_->UnregisterSendAlarmIfRegistered();
-    WriteIfNotBlocked();
-  } else if (!delay.IsInfinite()) {
-    helper_->SetSendAlarm(time_of_last_received_packet_.Add(delay));
-  }
-  return connected_;
 }
 
 bool QuicConnection::OnCongestionFeedbackFrame(
@@ -394,8 +464,7 @@
   if (debug_visitor_) {
     debug_visitor_->OnCongestionFeedbackFrame(feedback);
   }
-  congestion_manager_.OnIncomingQuicCongestionFeedbackFrame(
-      feedback, time_of_last_received_packet_);
+  last_congestion_frames_.push_back(feedback);
   return connected_;
 }
 
@@ -557,7 +626,7 @@
   }
   DLOG(INFO) << ENDPOINT << "Stream reset with error "
              << QuicUtils::StreamErrorToString(frame.error_code);
-  visitor_->OnRstStream(frame);
+  last_rst_frames_.push_back(frame);
   return connected_;
 }
 
@@ -571,6 +640,7 @@
              << QuicUtils::ErrorToString(frame.error_code)
              << " " << frame.error_details;
   CloseConnection(frame.error_code, true);
+  DCHECK(!connected_);
   return false;
 }
 
@@ -579,30 +649,35 @@
   DLOG(INFO) << ENDPOINT << "Go away received with error "
              << QuicUtils::ErrorToString(frame.error_code)
              << " and reason:" << frame.reason_phrase;
-  visitor_->OnGoAway(frame);
+  last_goaway_frames_.push_back(frame);
   return connected_;
 }
 
 void QuicConnection::OnPacketComplete() {
   // Don't do anything if this packet closed the connection.
   if (!connected_) {
-    last_stream_frames_.clear();
+    ClearLastFrames();
     return;
   }
 
+  DLOG(INFO) << ENDPOINT << (last_packet_revived_ ? "Revived" : "Got")
+             << " packet " << last_header_.packet_sequence_number
+             << " with " << last_ack_frames_.size() << " acks, "
+             << last_congestion_frames_.size() << " congestions, "
+             << last_goaway_frames_.size() << " goaways, "
+             << last_rst_frames_.size() << " rsts, "
+             << last_stream_frames_.size()
+             << " stream frames for " << last_header_.public_header.guid;
   if (!last_packet_revived_) {
-    DLOG(INFO) << ENDPOINT << "Got packet "
-               << last_header_.packet_sequence_number
-               << " with " << last_stream_frames_.size()
-               << " stream frames for " << last_header_.public_header.guid;
     congestion_manager_.RecordIncomingPacket(
         last_size_, last_header_.packet_sequence_number,
         time_of_last_received_packet_, last_packet_revived_);
-  } else {
-    DLOG(INFO) << ENDPOINT << "Got revived packet with "
-               << last_stream_frames_.size() << " frames.";
   }
 
+  // Must called before ack processing, because processing acks removes entries
+  // from unacket_packets_, increasing the least_unacked.
+  const bool last_packet_should_instigate_ack = ShouldLastPacketInstigateAck();
+
   if ((last_stream_frames_.empty() ||
        visitor_->OnPacket(self_address_, peer_address_,
                           last_header_, last_stream_frames_))) {
@@ -610,8 +685,32 @@
         last_header_, time_of_last_received_packet_);
   }
 
-  MaybeSendAckInResponseToPacket();
+  // Process stream resets, then acks, then congestion feedback.
+  for (size_t i = 0; i < last_goaway_frames_.size(); ++i) {
+    visitor_->OnGoAway(last_goaway_frames_[i]);
+  }
+  for (size_t i = 0; i < last_rst_frames_.size(); ++i) {
+    visitor_->OnRstStream(last_rst_frames_[i]);
+  }
+  for (size_t i = 0; i < last_ack_frames_.size(); ++i) {
+    ProcessAckFrame(last_ack_frames_[i]);
+  }
+  for (size_t i = 0; i < last_congestion_frames_.size(); ++i) {
+    congestion_manager_.OnIncomingQuicCongestionFeedbackFrame(
+        last_congestion_frames_[i], time_of_last_received_packet_);
+  }
+
+  MaybeSendInResponseToPacket(last_packet_should_instigate_ack);
+
+  ClearLastFrames();
+}
+
+void QuicConnection::ClearLastFrames() {
   last_stream_frames_.clear();
+  last_goaway_frames_.clear();
+  last_rst_frames_.clear();
+  last_ack_frames_.clear();
+  last_congestion_frames_.clear();
 }
 
 QuicAckFrame* QuicConnection::CreateAckFrame() {
@@ -627,13 +726,60 @@
   return new QuicCongestionFeedbackFrame(outgoing_congestion_feedback_);
 }
 
-void QuicConnection::MaybeSendAckInResponseToPacket() {
+bool QuicConnection::ShouldLastPacketInstigateAck() {
+  if (!last_stream_frames_.empty() ||
+      !last_goaway_frames_.empty() ||
+      !last_rst_frames_.empty()) {
+    return true;
+  }
+
+  // If the peer is still waiting for a packet that we are no
+  // longer planning to send, we should send an ack to raise
+  // the high water mark.
+  if (!last_ack_frames_.empty() &&
+      !last_ack_frames_.back().received_info.missing_packets.empty() &&
+      !unacked_packets_.empty()) {
+    if (unacked_packets_.begin()->first >
+        *last_ack_frames_.back().received_info.missing_packets.begin()) {
+      return true;
+    }
+  }
+
+  return false;
+}
+
+void QuicConnection::MaybeSendInResponseToPacket(
+    bool last_packet_should_instigate_ack) {
+  // TODO(ianswett): Better merge these two blocks to queue up an ack if
+  // necessary, then either only send the ack or bundle it with other data.
+  if (!last_ack_frames_.empty()) {
+    // Now the we have received an ack, we might be able to send packets which
+    // are queued locally, or drain streams which are blocked.
+    QuicTime::Delta delay = congestion_manager_.TimeUntilSend(
+        time_of_last_received_packet_, NOT_RETRANSMISSION,
+        HAS_RETRANSMITTABLE_DATA, NOT_HANDSHAKE);
+    if (delay.IsZero()) {
+      send_alarm_->Cancel();
+      WriteIfNotBlocked();
+    } else if (!delay.IsInfinite()) {
+      send_alarm_->Cancel();
+      send_alarm_->Set(time_of_last_received_packet_.Add(delay));
+    }
+  }
+
+  if (!last_packet_should_instigate_ack) {
+    return;
+  }
+
   if (send_ack_in_response_to_packet_) {
     SendAck();
   } else if (!last_stream_frames_.empty()) {
     // TODO(alyssar) this case should really be "if the packet contained any
     // non-ack frame", rather than "if the packet contained a stream frame"
-    helper_->SetAckAlarm(congestion_manager_.DefaultRetransmissionTime());
+    if (!ack_alarm_->IsSet()) {
+      ack_alarm_->Set(clock_->ApproximateNow().Add(
+          congestion_manager_.DefaultRetransmissionTime()));
+    }
   }
   send_ack_in_response_to_packet_ = !send_ack_in_response_to_packet_;
 }
@@ -750,7 +896,8 @@
       // We're not write blocked, but some stream didn't write out all of its
       // bytes.  Register for 'immediate' resumption so we'll keep writing after
       // other quic connections have had a chance to use the socket.
-      helper_->SetSendAlarm(clock_->ApproximateNow());
+      send_alarm_->Cancel();
+      send_alarm_->Set(clock_->ApproximateNow());
     }
   }
 
@@ -900,7 +1047,7 @@
                               IsHandshake handshake) {
   // TODO(ianswett): If the packet is a retransmit, the current send alarm may
   // be too long.
-  if (write_blocked_ || helper_->IsSendAlarmSet()) {
+  if (write_blocked_ || send_alarm_->IsSet()) {
     return false;
   }
 
@@ -913,7 +1060,8 @@
 
   // If the scheduler requires a delay, then we can not send this packet now.
   if (!delay.IsZero()) {
-    helper_->SetSendAlarm(now.Add(delay));
+    send_alarm_->Cancel();
+    send_alarm_->Set(now.Add(delay));
     return false;
   }
   return true;
@@ -953,8 +1101,9 @@
   // Do not set the retransmisson alarm if we're already handling the
   // retransmission alarm because the retransmission alarm will be reset when
   // OnRetransmissionTimeout completes.
-  if (!handling_retransmission_timeout_) {
-    helper_->SetRetransmissionAlarm(retransmission_delay);
+  if (!handling_retransmission_timeout_ && !retransmission_alarm_->IsSet()) {
+    retransmission_alarm_->Set(
+        clock_->ApproximateNow().Add(retransmission_delay));
   }
   // TODO(satyamshekhar): restore packet reordering with Ian's TODO in
   // SendStreamData().
@@ -1169,7 +1318,7 @@
 }
 
 void QuicConnection::SendAck() {
-  helper_->ClearAckAlarm();
+  ack_alarm_->Cancel();
 
   // TODO(rch): delay this until the CreateFeedbackFrame
   // method is invoked.  This requires changes SetShouldSendAck
@@ -1286,7 +1435,7 @@
     return;
   }
 
-  while (!undecryptable_packets_.empty()) {
+  while (connected_ && !undecryptable_packets_.empty()) {
     DVLOG(1) << ENDPOINT << "Attempting to process undecryptable packet";
     QuicEncryptedPacket* packet = undecryptable_packets_.front();
     if (!framer_.ProcessPacket(*packet) &&
@@ -1309,7 +1458,7 @@
 
 void QuicConnection::MaybeProcessRevivedPacket() {
   QuicFecGroup* group = GetFecGroup();
-  if (group == NULL || !group->CanRevive()) {
+  if (!connected_ || group == NULL || !group->CanRevive()) {
     return;
   }
   QuicPacketHeader revived_header;
@@ -1384,7 +1533,7 @@
                    serialized_packet.sequence_number,
                    serialized_packet.packet,
                    serialized_packet.retransmittable_frames != NULL ?
-                      HAS_RETRANSMITTABLE_DATA : NO_RETRANSMITTABLE_DATA,
+                       HAS_RETRANSMITTABLE_DATA : NO_RETRANSMITTABLE_DATA,
                    FORCE)) {
     delete serialized_packet.packet;
   }
@@ -1399,6 +1548,7 @@
 }
 
 void QuicConnection::CloseConnection(QuicErrorCode error, bool from_peer) {
+  DCHECK(connected_);
   connected_ = false;
   visitor_->ConnectionClose(error, from_peer);
 }
@@ -1499,7 +1649,8 @@
     }
   }
 
-  helper_->SetTimeoutAlarm(timeout);
+  timeout_alarm_->Cancel();
+  timeout_alarm_->Set(clock_->ApproximateNow().Add(timeout));
   return false;
 }
 
diff --git a/net/quic/quic_connection.h b/net/quic/quic_connection.h
index 4ac4fa4..41172f7 100644
--- a/net/quic/quic_connection.h
+++ b/net/quic/quic_connection.h
@@ -27,6 +27,7 @@
 #include "net/base/ip_endpoint.h"
 #include "net/base/linked_hash_map.h"
 #include "net/quic/congestion_control/quic_congestion_manager.h"
+#include "net/quic/quic_alarm.h"
 #include "net/quic/quic_blocked_writer_interface.h"
 #include "net/quic/quic_framer.h"
 #include "net/quic/quic_packet_creator.h"
@@ -167,38 +168,10 @@
   // as EAGAIN or ERR_IO_PENDING.
   virtual bool IsWriteBlocked(int error) = 0;
 
-  // Sets up an alarm to retransmit a packet if we haven't received an ack
-  // in the expected time frame.  Implementations must invoke
-  // OnRetransmissionAlarm when the alarm fires.  Implementations must also
-  // handle the case where |this| is deleted before the alarm fires.  If the
-  // alarm is already set, this call is a no-op.
-  virtual void SetRetransmissionAlarm(QuicTime::Delta delay) = 0;
-
-  // Sets an alarm to send packets at |alarm_time|.  Implementations must
-  // invoke OnCanWrite when the alarm fires.  Implementations must also
-  // handle the case where |this| is deleted before the alarm fires.
-  virtual void SetSendAlarm(QuicTime alarm_time) = 0;
-
-  // Sets an alarm which fires when the connection may have timed out.
-  // Implementations must call CheckForTimeout() and then reregister the alarm
-  // if the connection has not yet timed out.
-  virtual void SetTimeoutAlarm(QuicTime::Delta delay) = 0;
-
-  // Returns true if a send alarm is currently set.
-  virtual bool IsSendAlarmSet() = 0;
-
-  // If a send alarm is currently set, this method unregisters it.  If
-  // no send alarm is set, it does nothing.
-  virtual void UnregisterSendAlarmIfRegistered() = 0;
-
-  // Sets an alarm which fires when an Ack may need to be sent.
-  // Implementations must call SendAck() when the alarm fires.
-  // If the alarm is already registered for a shorter timeout, this call is a
-  // no-op.
-  virtual void SetAckAlarm(QuicTime::Delta delay) = 0;
-
-  // Clears the ack alarm if it was set.  If it was not set, this is a no-op.
-  virtual void ClearAckAlarm() = 0;
+  // Creates a new platform-specific alarm which will be configured to
+  // notify |delegate| when the alarm fires.  Caller takes ownership
+  // of the new alarm, which will not yet be "set" to fire.
+  virtual QuicAlarm* CreateAlarm(QuicAlarm::Delegate* delegate) = 0;
 };
 
 class NET_EXPORT_PRIVATE QuicConnection
@@ -530,6 +503,9 @@
 
   void SetupAbandonFecTimer(QuicPacketSequenceNumber sequence_number);
 
+  // Clears any accumulated frames from the last received packet.
+  void ClearLastFrames();
+
   // Called from OnCanWrite and WriteIfNotBlocked to write queued packets.
   // Returns false if the socket has become blocked.
   bool DoWrite();
@@ -555,6 +531,8 @@
   // revive and process the packet.
   void MaybeProcessRevivedPacket();
 
+  void ProcessAckFrame(const QuicAckFrame& incoming_ack);
+
   void HandleAckForSentPackets(const QuicAckFrame& incoming_ack,
                                SequenceNumberSet* acked_packets);
   void HandleAckForSentFecPackets(const QuicAckFrame& incoming_ack,
@@ -563,7 +541,12 @@
   // Update the |sent_info| for an outgoing ack.
   void UpdateSentPacketInfo(SentPacketInfo* sent_info);
 
-  void MaybeSendAckInResponseToPacket();
+  // Checks if the last packet should instigate an ack.
+  bool ShouldLastPacketInstigateAck();
+
+  // Sends any packets which are a response to the last packet, including both
+  // acks and pending writes if an ack opened the congestion window.
+  void MaybeSendInResponseToPacket(bool last_packet_should_instigate_ack);
 
   void MaybeAbandonFecPacket(QuicPacketSequenceNumber sequence_number);
 
@@ -589,6 +572,10 @@
   size_t last_size_;  // Size of the last received packet.
   QuicPacketHeader last_header_;
   std::vector<QuicStreamFrame> last_stream_frames_;
+  std::vector<QuicAckFrame> last_ack_frames_;
+  std::vector<QuicCongestionFeedbackFrame> last_congestion_frames_;
+  std::vector<QuicRstStreamFrame> last_rst_frames_;
+  std::vector<QuicGoAwayFrame> last_goaway_frames_;
 
   QuicCongestionFeedbackFrame outgoing_congestion_feedback_;
 
@@ -640,6 +627,16 @@
   QuicReceivedPacketManager received_packet_manager_;
   QuicSentEntropyManager sent_entropy_manager_;
 
+  // An alarm that fires when an ACK should be sent to the peer.
+  scoped_ptr<QuicAlarm> ack_alarm_;
+  // An alarm that fires when a packet needs to be retransmitted.
+  scoped_ptr<QuicAlarm> retransmission_alarm_;
+  // An alarm that is scheduled when the sent scheduler requires a
+  // a delay before sending packets and fires when the packet may be sent.
+  scoped_ptr<QuicAlarm> send_alarm_;
+  // An alarm that fires when the connection may have timed out.
+  scoped_ptr<QuicAlarm> timeout_alarm_;
+
   QuicConnectionVisitorInterface* visitor_;
   QuicConnectionDebugVisitorInterface* debug_visitor_;
   QuicPacketCreator packet_creator_;
diff --git a/net/quic/quic_connection_helper.cc b/net/quic/quic_connection_helper.cc
index c58bbad..c3e796f 100644
--- a/net/quic/quic_connection_helper.cc
+++ b/net/quic/quic_connection_helper.cc
@@ -14,6 +14,72 @@
 
 namespace net {
 
+namespace {
+
+class QuicChromeAlarm : public QuicAlarm {
+ public:
+  QuicChromeAlarm(const QuicClock* clock,
+                  base::TaskRunner* task_runner,
+                  QuicAlarm::Delegate* delegate)
+      : QuicAlarm(delegate),
+        clock_(clock),
+        task_runner_(task_runner),
+        task_posted_(false),
+        weak_factory_(this) {}
+
+ protected:
+  virtual void SetImpl() OVERRIDE {
+    DCHECK(deadline().IsInitialized());
+    if (task_posted_) {
+      // Since tasks can not be un-posted, OnAlarm will be invoked which
+      // will notice that deadline has not yet been reached, and will set
+      // the alarm for the new deadline.
+      return;
+    }
+
+    int64 delay_us = deadline().Subtract(clock_->Now()).ToMicroseconds();
+    if (delay_us < 0) {
+      delay_us = 0;
+    }
+    task_runner_->PostDelayedTask(
+        FROM_HERE,
+        base::Bind(&QuicChromeAlarm::OnAlarm, weak_factory_.GetWeakPtr()),
+        base::TimeDelta::FromMicroseconds(delay_us));
+    task_posted_ = true;
+  }
+
+  virtual void CancelImpl() OVERRIDE {
+    DCHECK(!deadline().IsInitialized());
+    // Since tasks can not be un-posted, OnAlarm will be invoked which
+    // will notice that deadline is not Initialized and will do nothing.
+  }
+
+ private:
+  void OnAlarm() {
+    DCHECK(task_posted_);
+    task_posted_ = false;
+    // The alarm may have been cancelled.
+    if (!deadline().IsInitialized()) {
+      return;
+    }
+
+    // The alarm may have been re-set to a later time.
+    if (clock_->Now() < deadline()) {
+      SetImpl();
+      return;
+    }
+
+    Fire();
+  }
+
+  const QuicClock* clock_;
+  base::TaskRunner* task_runner_;
+  bool task_posted_;
+  base::WeakPtrFactory<QuicChromeAlarm> weak_factory_;
+};
+
+}  // namespace
+
 QuicConnectionHelper::QuicConnectionHelper(base::TaskRunner* task_runner,
                                            const QuicClock* clock,
                                            QuicRandom* random_generator,
@@ -22,13 +88,7 @@
       task_runner_(task_runner),
       socket_(socket),
       clock_(clock),
-      random_generator_(random_generator),
-      send_alarm_registered_(false),
-      timeout_alarm_registered_(false),
-      retransmission_alarm_registered_(false),
-      retransmission_alarm_running_(false),
-      ack_alarm_registered_(false),
-      ack_alarm_time_(QuicTime::Zero()) {
+      random_generator_(random_generator) {
 }
 
 QuicConnectionHelper::~QuicConnectionHelper() {
@@ -81,107 +141,8 @@
   return error == ERR_IO_PENDING;
 }
 
-void QuicConnectionHelper::SetRetransmissionAlarm(QuicTime::Delta delay) {
-  if (!retransmission_alarm_registered_) {
-    task_runner_->PostDelayedTask(
-        FROM_HERE,
-        base::Bind(&QuicConnectionHelper::OnRetransmissionAlarm,
-                   weak_factory_.GetWeakPtr()),
-        base::TimeDelta::FromMicroseconds(delay.ToMicroseconds()));
-  }
-}
-
-void QuicConnectionHelper::SetAckAlarm(QuicTime::Delta delay) {
-  ack_alarm_time_ = clock_->Now().Add(delay);
-  if (!ack_alarm_registered_) {
-    task_runner_->PostDelayedTask(
-        FROM_HERE,
-        base::Bind(&QuicConnectionHelper::OnAckAlarm,
-                   weak_factory_.GetWeakPtr()),
-        base::TimeDelta::FromMicroseconds(delay.ToMicroseconds()));
-  }
-  ack_alarm_registered_ = true;
-}
-
-void QuicConnectionHelper::ClearAckAlarm() {
-  ack_alarm_time_ = QuicTime::Zero();
-}
-
-void QuicConnectionHelper::SetSendAlarm(QuicTime alarm_time) {
-  send_alarm_registered_ = true;
-  int64 delay_us = alarm_time.Subtract(clock_->Now()).ToMicroseconds();
-  if (delay_us < 0) {
-    delay_us = 0;
-  }
-  task_runner_->PostDelayedTask(
-      FROM_HERE,
-      base::Bind(&QuicConnectionHelper::OnSendAlarm,
-                 weak_factory_.GetWeakPtr()),
-      base::TimeDelta::FromMicroseconds(delay_us));
-}
-
-void QuicConnectionHelper::SetTimeoutAlarm(QuicTime::Delta delay) {
-  // CheckForTimeout will call SetTimeoutAlarm for the remaining time if alarm
-  // goes off before the delay.
-  if (timeout_alarm_registered_)
-    return;
-  timeout_alarm_registered_ = true;
-  task_runner_->PostDelayedTask(
-      FROM_HERE,
-      base::Bind(&QuicConnectionHelper::OnTimeoutAlarm,
-                 weak_factory_.GetWeakPtr()),
-      base::TimeDelta::FromMicroseconds(delay.ToMicroseconds()));
-}
-
-bool QuicConnectionHelper::IsSendAlarmSet() {
-  return send_alarm_registered_;
-}
-
-void QuicConnectionHelper::UnregisterSendAlarmIfRegistered() {
-  send_alarm_registered_ = false;
-}
-
-void QuicConnectionHelper::OnRetransmissionAlarm() {
-  QuicTime when = connection_->OnRetransmissionTimeout();
-  if (!when.IsInitialized()) {
-    return;
-  }
-  QuicTime now = clock_->Now();
-  QuicTime::Delta delta(when.Subtract(now));
-  if (delta < QuicTime::Delta::FromSeconds(0)) {
-    delta = QuicTime::Delta::FromSeconds(0);
-  }
-  SetRetransmissionAlarm(delta);
-}
-
-void QuicConnectionHelper::OnSendAlarm() {
-  if (send_alarm_registered_) {
-    send_alarm_registered_ = false;
-    connection_->OnCanWrite();
-  }
-}
-
-void QuicConnectionHelper::OnTimeoutAlarm() {
-  timeout_alarm_registered_ = false;
-  connection_->CheckForTimeout();
-}
-
-void QuicConnectionHelper::OnAckAlarm() {
-  ack_alarm_registered_ = false;
-  // Alarm may have been cleared.
-  if (!ack_alarm_time_.IsInitialized()) {
-    return;
-  }
-
-  // Alarm may have been reset to a later time.
-  QuicTime now = clock_->Now();
-  if (now < ack_alarm_time_) {
-    SetAckAlarm(ack_alarm_time_.Subtract(now));
-    return;
-  }
-
-  ack_alarm_time_ = QuicTime::Zero();
-  connection_->SendAck();
+QuicAlarm* QuicConnectionHelper::CreateAlarm(QuicAlarm::Delegate* delegate) {
+  return new QuicChromeAlarm(clock_, task_runner_, delegate);
 }
 
 void QuicConnectionHelper::OnWriteComplete(int result) {
diff --git a/net/quic/quic_connection_helper.h b/net/quic/quic_connection_helper.h
index 12f80bb..6667b95 100644
--- a/net/quic/quic_connection_helper.h
+++ b/net/quic/quic_connection_helper.h
@@ -49,30 +49,13 @@
                                 int* error) OVERRIDE;
   virtual bool IsWriteBlockedDataBuffered() OVERRIDE;
   virtual bool IsWriteBlocked(int error) OVERRIDE;
-  virtual void SetRetransmissionAlarm(QuicTime::Delta delay) OVERRIDE;
-  virtual void SetSendAlarm(QuicTime alarm_time) OVERRIDE;
-  virtual void SetTimeoutAlarm(QuicTime::Delta delay) OVERRIDE;
-  virtual bool IsSendAlarmSet() OVERRIDE;
-  virtual void UnregisterSendAlarmIfRegistered() OVERRIDE;
-  virtual void SetAckAlarm(QuicTime::Delta delay) OVERRIDE;
-  virtual void ClearAckAlarm() OVERRIDE;
+  virtual QuicAlarm* CreateAlarm(QuicAlarm::Delegate* delegate) OVERRIDE;
 
  private:
   friend class test::QuicConnectionHelperPeer;
 
-  // An alarm is scheduled for each data-bearing packet as it is sent out.
-  // When the alarm goes off, the connection checks to see if the packet has
-  // been acked, and retransmits if it has not.
-  void OnRetransmissionAlarm();
-  // An alarm that is scheduled when the sent scheduler requires a
-  // a delay before sending packets and fires when the packet may be sent.
-  void OnSendAlarm();
-  // An alarm which fires when the connection may have timed out.
-  void OnTimeoutAlarm();
   // A completion callback invoked when a write completes.
   void OnWriteComplete(int result);
-  // An alarm which fires if we've hit a timeout on sending an ack.
-  void OnAckAlarm();
 
   base::WeakPtrFactory<QuicConnectionHelper> weak_factory_;
   base::TaskRunner* task_runner_;
@@ -80,14 +63,6 @@
   QuicConnection* connection_;
   const QuicClock* clock_;
   QuicRandom* random_generator_;
-  bool send_alarm_registered_;
-  bool timeout_alarm_registered_;
-  bool retransmission_alarm_registered_;
-  bool retransmission_alarm_running_;
-  bool ack_alarm_registered_;
-  QuicTime ack_alarm_time_;
-  // Times that packets should be retransmitted.
-  std::map<QuicPacketSequenceNumber, QuicTime> retransmission_times_;
 
   DISALLOW_COPY_AND_ASSIGN(QuicConnectionHelper);
 };
diff --git a/net/quic/quic_connection_helper_test.cc b/net/quic/quic_connection_helper_test.cc
index 6e84c0f..4822ea6 100644
--- a/net/quic/quic_connection_helper_test.cc
+++ b/net/quic/quic_connection_helper_test.cc
@@ -25,6 +25,21 @@
 const char kData[] = "foo";
 const bool kFromPeer = true;
 
+class TestDelegate : public QuicAlarm::Delegate {
+ public:
+  TestDelegate() : fired_(false) {}
+
+  virtual QuicTime OnAlarm() OVERRIDE {
+    fired_ = true;
+    return QuicTime::Zero();
+  }
+
+  bool fired() const { return fired_; }
+
+ private:
+  bool fired_;
+};
+
 class TestConnection : public QuicConnection {
  public:
   TestConnection(QuicGuid guid,
@@ -218,85 +233,69 @@
   EXPECT_EQ(&random_generator_, helper_->GetRandomGenerator());
 }
 
-TEST_F(QuicConnectionHelperTest, IsSendAlarmSet) {
-  EXPECT_FALSE(helper_->IsSendAlarmSet());
-}
-
-TEST_F(QuicConnectionHelperTest, SetSendAlarm) {
-  helper_->SetSendAlarm(
-      clock_.ApproximateNow().Add(QuicTime::Delta::FromSeconds(1)));
-  EXPECT_TRUE(helper_->IsSendAlarmSet());
-}
-
-TEST_F(QuicConnectionHelperTest, UnregisterSendAlarmIfRegistered) {
-  helper_->SetSendAlarm(
-      clock_.ApproximateNow().Add(QuicTime::Delta::FromSeconds(1)));
-  helper_->UnregisterSendAlarmIfRegistered() ;
-  EXPECT_FALSE(helper_->IsSendAlarmSet());
-}
-
-TEST_F(QuicConnectionHelperTest, SetAckAlarm) {
-  AddWrite(SYNCHRONOUS, ConstructAckPacket(1));
-  Initialize();
+TEST_F(QuicConnectionHelperTest, CreateAlarm) {
+  TestDelegate* delegate = new TestDelegate();
+  scoped_ptr<QuicAlarm> alarm(helper_->CreateAlarm(delegate));
 
   // The timeout alarm task is always posted.
   ASSERT_EQ(1u, runner_->GetPostedTasks().size());
 
-  QuicTime::Delta delta(QuicTime::Delta::FromMilliseconds(10));
-  helper_->SetAckAlarm(delta);
+  QuicTime::Delta delta = QuicTime::Delta::FromMicroseconds(1);
+  alarm->Set(clock_.Now().Add(delta));
 
-  // Verify that the ack alarm task has been posted.
+  // Verify that the alarm task has been posted.
   ASSERT_EQ(2u, runner_->GetPostedTasks().size());
   EXPECT_EQ(base::TimeDelta::FromMicroseconds(delta.ToMicroseconds()),
             runner_->GetPostedTasks()[1].delay);
 
-  EXPECT_CALL(*send_algorithm_, SentPacket(_, 1, _, NOT_RETRANSMISSION));
   runner_->RunNextTask();
-  EXPECT_EQ(QuicTime::Zero().Add(delta), clock_.ApproximateNow());
+  EXPECT_EQ(QuicTime::Zero().Add(delta), clock_.Now());
+  EXPECT_TRUE(delegate->fired());
 }
 
-TEST_F(QuicConnectionHelperTest, ClearAckAlarm) {
-  Initialize();
+TEST_F(QuicConnectionHelperTest, CreateAlarmAndCancel) {
+  TestDelegate* delegate = new TestDelegate();
+  scoped_ptr<QuicAlarm> alarm(helper_->CreateAlarm(delegate));
 
-  // Verify that the timeout alarm task has been posted.
-  ASSERT_EQ(1u, runner_->GetPostedTasks().size());
+  QuicTime::Delta delta = QuicTime::Delta::FromMicroseconds(1);
+  alarm->Set(clock_.Now().Add(delta));
+  alarm->Cancel();
 
-  QuicTime::Delta delta(QuicTime::Delta::FromMilliseconds(10));
-  helper_->SetAckAlarm(delta);
+  // The alarm task should still be posted.
+  ASSERT_EQ(2u, runner_->GetPostedTasks().size());
+  EXPECT_EQ(base::TimeDelta::FromMicroseconds(delta.ToMicroseconds()),
+            runner_->GetPostedTasks()[1].delay);
 
-  helper_->ClearAckAlarm();
-
-  // When the AckAlarm actually fires, no ack will be sent.
   runner_->RunNextTask();
-  EXPECT_EQ(QuicTime::Zero().Add(delta), clock_.ApproximateNow());
+  EXPECT_EQ(QuicTime::Zero().Add(delta), clock_.Now());
+  EXPECT_FALSE(delegate->fired());
 }
 
-TEST_F(QuicConnectionHelperTest, ResetAckAlarm) {
-  AddWrite(SYNCHRONOUS, ConstructAckPacket(1));
-  Initialize();
+TEST_F(QuicConnectionHelperTest, CreateAlarmAndReset) {
+  TestDelegate* delegate = new TestDelegate();
+  scoped_ptr<QuicAlarm> alarm(helper_->CreateAlarm(delegate));
 
-  // Verify that the timeout alarm task has been posted.
-  ASSERT_EQ(1u, runner_->GetPostedTasks().size());
+  QuicTime::Delta delta = QuicTime::Delta::FromMicroseconds(1);
+  alarm->Set(clock_.Now().Add(delta));
+  alarm->Cancel();
+  QuicTime::Delta new_delta = QuicTime::Delta::FromMicroseconds(3);
+  alarm->Set(clock_.Now().Add(new_delta));
 
-  QuicTime::Delta delta1(QuicTime::Delta::FromMilliseconds(10));
-  QuicTime::Delta delta2(QuicTime::Delta::FromMilliseconds(20));
-  helper_->SetAckAlarm(delta1);
-  helper_->ClearAckAlarm();
-  helper_->SetAckAlarm(delta2);
-  // We should only have 1 ack alarm task posted.
+  // The alarm task should still be posted.
+  ASSERT_EQ(2u, runner_->GetPostedTasks().size());
+  EXPECT_EQ(base::TimeDelta::FromMicroseconds(delta.ToMicroseconds()),
+            runner_->GetPostedTasks()[1].delay);
+
+  runner_->RunNextTask();
+  EXPECT_EQ(QuicTime::Zero().Add(delta), clock_.Now());
+  EXPECT_FALSE(delegate->fired());
+
+  // The alarm task should be posted again.
   ASSERT_EQ(2u, runner_->GetPostedTasks().size());
 
-  // The task will execute at delta1, but will not send and ack,
-  // but it will reschedule itself for delta2
   runner_->RunNextTask();
-  EXPECT_EQ(QuicTime::Zero().Add(delta1), clock_.ApproximateNow());
-
-  // Verify that the ack alarm task has been re-posted.
-  ASSERT_EQ(2u, runner_->GetPostedTasks().size());
-
-  EXPECT_CALL(*send_algorithm_, SentPacket(_, 1, _, NOT_RETRANSMISSION));
-  runner_->RunNextTask();
-  EXPECT_EQ(QuicTime::Zero().Add(delta2), clock_.ApproximateNow());
+  EXPECT_EQ(QuicTime::Zero().Add(new_delta), clock_.Now());
+  EXPECT_TRUE(delegate->fired());
 }
 
 TEST_F(QuicConnectionHelperTest, TestRetransmission) {
diff --git a/net/quic/quic_connection_test.cc b/net/quic/quic_connection_test.cc
index 80854aa..8732713 100644
--- a/net/quic/quic_connection_test.cc
+++ b/net/quic/quic_connection_test.cc
@@ -221,17 +221,24 @@
 
 class TestConnectionHelper : public QuicConnectionHelperInterface {
  public:
+  class TestAlarm : public QuicAlarm {
+   public:
+    explicit TestAlarm(QuicAlarm::Delegate* delegate)
+        : QuicAlarm(delegate) {
+    }
+
+    virtual void SetImpl() OVERRIDE {}
+    virtual void CancelImpl() OVERRIDE {}
+  };
+
   TestConnectionHelper(MockClock* clock, MockRandom* random_generator)
       : clock_(clock),
         random_generator_(random_generator),
-        retransmission_alarm_(QuicTime::Zero()),
-        send_alarm_(QuicTime::Zero().Subtract(
-            QuicTime::Delta::FromMilliseconds(1))),
-        timeout_alarm_(QuicTime::Zero()),
         blocked_(false),
         is_server_(true),
         use_tagging_decrypter_(false),
         packets_write_attempts_(0) {
+    clock_->AdvanceTime(QuicTime::Delta::FromSeconds(1));
   }
 
   // QuicConnectionHelperInterface
@@ -293,36 +300,10 @@
     return error == ERR_IO_PENDING;
   }
 
-  virtual void SetRetransmissionAlarm(QuicTime::Delta delay) OVERRIDE {
-    retransmission_alarm_ = clock_->ApproximateNow().Add(delay);
+  virtual QuicAlarm* CreateAlarm(QuicAlarm::Delegate* delegate) OVERRIDE {
+    return new TestAlarm(delegate);
   }
 
-  virtual void SetSendAlarm(QuicTime alarm_time) OVERRIDE {
-    send_alarm_ = alarm_time;
-  }
-
-  virtual void SetTimeoutAlarm(QuicTime::Delta delay) OVERRIDE {
-    timeout_alarm_ = clock_->ApproximateNow().Add(delay);
-  }
-
-  virtual bool IsSendAlarmSet() OVERRIDE {
-    return send_alarm_ >= clock_->ApproximateNow();
-  }
-
-  virtual void UnregisterSendAlarmIfRegistered() OVERRIDE {
-    send_alarm_ =
-        QuicTime::Zero().Subtract(QuicTime::Delta::FromMilliseconds(1));
-  }
-
-  virtual void SetAckAlarm(QuicTime::Delta delay) OVERRIDE {}
-  virtual void ClearAckAlarm() OVERRIDE {}
-
-  QuicTime retransmission_alarm() const {
-    return retransmission_alarm_;
-  }
-
-  QuicTime timeout_alarm() const { return timeout_alarm_; }
-
   QuicPacketHeader* header() { return &header_; }
 
   size_t frame_count() const { return frame_count_; }
@@ -362,9 +343,6 @@
  private:
   MockClock* clock_;
   MockRandom* random_generator_;
-  QuicTime retransmission_alarm_;
-  QuicTime send_alarm_;
-  QuicTime timeout_alarm_;
   QuicPacketHeader header_;
   size_t frame_count_;
   scoped_ptr<QuicAckFrame> ack_;
@@ -427,6 +405,22 @@
     QuicConnectionPeer::SetIsServer(this, is_server);
   }
 
+  QuicAlarm* GetAckAlarm() {
+    return QuicConnectionPeer::GetAckAlarm(this);
+  }
+
+  QuicAlarm* GetRetransmissionAlarm() {
+    return QuicConnectionPeer::GetRetransmissionAlarm(this);
+  }
+
+  QuicAlarm* GetSendAlarm() {
+    return QuicConnectionPeer::GetSendAlarm(this);
+  }
+
+  QuicAlarm* GetTimeoutAlarm() {
+    return QuicConnectionPeer::GetTimeoutAlarm(this);
+  }
+
   using QuicConnection::SendOrQueuePacket;
   using QuicConnection::SelectMutualVersion;
 
@@ -544,7 +538,6 @@
 
   void ProcessClosePacket(QuicPacketSequenceNumber number,
                           QuicFecGroupNumber fec_group) {
-    EXPECT_CALL(visitor_, OnCanWrite()).Times(1).WillOnce(Return(true));
     scoped_ptr<QuicPacket> packet(ConstructClosePacket(number, fec_group));
     scoped_ptr<QuicEncryptedPacket> encrypted(framer_.EncryptPacket(
         ENCRYPTION_NONE, number, *packet));
@@ -839,7 +832,7 @@
   EXPECT_FALSE(QuicConnectionPeer::GetReceivedTruncatedAck(&connection_));
 }
 
-TEST_F(QuicConnectionTest, DISABLED_AckReceiptCausesAckSend) {
+TEST_F(QuicConnectionTest, AckReceiptCausesAckSendBadEntropy) {
   ProcessPacket(1);
   // Delay sending, then queue up an ack.
   EXPECT_CALL(*send_algorithm_,
@@ -858,6 +851,37 @@
   ProcessAckPacket(&frame, true);
 }
 
+TEST_F(QuicConnectionTest, AckReceiptCausesAckSend) {
+  EXPECT_CALL(*send_algorithm_, OnIncomingLoss(_)).Times(1);
+  QuicPacketSequenceNumber largest_observed;
+  QuicByteCount packet_size;
+  EXPECT_CALL(*send_algorithm_, SentPacket(_, _, _, NOT_RETRANSMISSION))
+      .WillOnce(DoAll(SaveArg<1>(&largest_observed), SaveArg<2>(&packet_size)));
+  EXPECT_CALL(*send_algorithm_, AbandoningPacket(1, _)).Times(1);
+  connection_.SendStreamData(1, "foo", 0, !kFin);
+  QuicAckFrame frame(1, QuicTime::Zero(), largest_observed);
+  frame.received_info.missing_packets.insert(largest_observed);
+  frame.received_info.entropy_hash = QuicConnectionPeer::GetSentEntropyHash(
+      &connection_, largest_observed - 1);
+  ProcessAckPacket(&frame, true);
+  ProcessAckPacket(&frame, true);
+  // Third nack should retransmit the largest observed packet.
+  EXPECT_CALL(*send_algorithm_, SentPacket(_, _, packet_size - kQuicVersionSize,
+                                           IS_RETRANSMISSION));
+  ProcessAckPacket(&frame, true);
+
+  // Now if the peer sends an ack which still reports the retransmitted packet
+  // as missing, then that will count as a packet which instigates an ack.
+  ProcessAckPacket(&frame, true);
+  EXPECT_CALL(*send_algorithm_, SentPacket(_, _, _, NOT_RETRANSMISSION));
+  ProcessAckPacket(&frame, true);
+
+  // But an ack with no new missing packest will not send an ack.
+  frame.received_info.missing_packets.clear();
+  ProcessAckPacket(&frame, true);
+  ProcessAckPacket(&frame, true);
+}
+
 TEST_F(QuicConnectionTest, LeastUnackedLower) {
   SendStreamDataToPeer(1, "foo", 0, !kFin, NULL);
   SendStreamDataToPeer(1, "bar", 3, !kFin, NULL);
@@ -960,7 +984,7 @@
   SequenceNumberSet expected_acks;
   expected_acks.insert(1);
 
-  // Client acks up to packet 3
+  // Peer acks up to packet 3.
   EXPECT_CALL(visitor_, OnAck(ContainerEq(expected_acks)));
   QuicAckFrame frame(3, QuicTime::Zero(), 0);
   frame.received_info.entropy_hash =
@@ -975,25 +999,28 @@
   expected_acks.clear();
   expected_acks.insert(4);
 
-  // Client acks up to packet 4, the last packet
+  // Peer acks up to packet 4, the last packet.
   EXPECT_CALL(visitor_, OnAck(ContainerEq(expected_acks)));
   QuicAckFrame frame2(6, QuicTime::Zero(), 0);
   frame2.received_info.entropy_hash =
       QuicConnectionPeer::GetSentEntropyHash(&connection_, 6);
-  ProcessAckPacket(&frame2, true);  // Even parity triggers ack packet 7
+  ProcessAckPacket(&frame2, true);  // Acks don't instigate acks.
 
-  // The least packet awaiting ack should now be 7
-  EXPECT_EQ(7u, last_ack()->sent_info.least_unacked);
+  // Verify that we did not send an ack.
+  EXPECT_EQ(6u, last_header()->packet_sequence_number);
+
+  // So the last ack has not changed.
+  EXPECT_EQ(4u, last_ack()->sent_info.least_unacked);
 
   // If we force an ack, we shouldn't change our retransmit state.
-  SendAckPacketToPeer();  // Packet 8
-  EXPECT_EQ(8u, last_ack()->sent_info.least_unacked);
+  SendAckPacketToPeer();  // Packet 7
+  EXPECT_EQ(7u, last_ack()->sent_info.least_unacked);
 
   // But if we send more data it should.
-  SendStreamDataToPeer(1, "eep", 6, !kFin, &last_packet);  // Packet 9
-  EXPECT_EQ(9u, last_packet);
-  SendAckPacketToPeer();  // Packet10
-  EXPECT_EQ(9u, last_ack()->sent_info.least_unacked);
+  SendStreamDataToPeer(1, "eep", 6, !kFin, &last_packet);  // Packet 8
+  EXPECT_EQ(8u, last_packet);
+  SendAckPacketToPeer();  // Packet 9
+  EXPECT_EQ(8u, last_ack()->sent_info.least_unacked);
 }
 
 TEST_F(QuicConnectionTest, FECSending) {
@@ -1086,7 +1113,7 @@
 
 TEST_F(QuicConnectionTest, FramePacking) {
   // Block the connection.
-  helper_->SetSendAlarm(
+  connection_.GetSendAlarm()->Set(
       clock_.ApproximateNow().Add(QuicTime::Delta::FromSeconds(1)));
 
   // Send an ack and two stream frames in 1 packet by queueing them.
@@ -1099,7 +1126,7 @@
       Return(true)));
 
   // Unblock the connection.
-  helper_->UnregisterSendAlarmIfRegistered();
+  connection_.GetSendAlarm()->Cancel();
   EXPECT_CALL(*send_algorithm_,
               SentPacket(_, _, _, NOT_RETRANSMISSION))
       .Times(1);
@@ -1120,7 +1147,7 @@
   // Enable fec.
   connection_.options()->max_packets_per_fec_group = 6;
   // Block the connection.
-  helper_->SetSendAlarm(
+  connection_.GetSendAlarm()->Set(
       clock_.ApproximateNow().Add(QuicTime::Delta::FromSeconds(1)));
 
   // Send an ack and two stream frames in 1 packet by queueing them.
@@ -1133,7 +1160,7 @@
       Return(true)));
 
   // Unblock the connection.
-  helper_->UnregisterSendAlarmIfRegistered();
+  connection_.GetSendAlarm()->Cancel();
   EXPECT_CALL(*send_algorithm_,
               SentPacket(_, _, _, NOT_RETRANSMISSION)).Times(2);
   connection_.OnCanWrite();
@@ -1183,7 +1210,7 @@
   expected_acks.insert(1);
   EXPECT_CALL(visitor_, OnAck(ContainerEq(expected_acks)));
 
-  // Client acks one but not two or three.  Right now we only retransmit on
+  // Peer acks one but not two or three.  Right now we only retransmit on
   // explicit nack, so it should not trigger a retransimission.
   QuicAckFrame ack_one(1, QuicTime::Zero(), 0);
   ack_one.received_info.entropy_hash =
@@ -1196,7 +1223,7 @@
   expected_acks.insert(3);
   EXPECT_CALL(visitor_, OnAck(ContainerEq(expected_acks)));
 
-  // Client acks up to 3 with two explicitly missing.  Two nacks should cause no
+  // Peer acks up to 3 with two explicitly missing.  Two nacks should cause no
   // change.
   QuicAckFrame nack_two(3, QuicTime::Zero(), 0);
   nack_two.received_info.missing_packets.insert(2);
@@ -1227,9 +1254,6 @@
   frame.received_info.entropy_hash = QuicConnectionPeer::GetSentEntropyHash(
       &connection_, largest_observed - 1);
   ProcessAckPacket(&frame, true);
-  // Second udp packet will force an ack frame.
-  EXPECT_CALL(*send_algorithm_,
-              SentPacket(_, _, _, NOT_RETRANSMISSION));
   ProcessAckPacket(&frame, true);
   // Third nack should retransmit the largest observed packet.
   EXPECT_CALL(*send_algorithm_, SentPacket(_, _, packet_size - kQuicVersionSize,
@@ -1302,15 +1326,13 @@
 
   // Nack three times.
   ProcessAckPacket(&nack, true);
-  // The second call will trigger an ack.
-  EXPECT_CALL(*send_algorithm_, SentPacket(_, _, _, _)).Times(1);
   ProcessAckPacket(&nack, true);
   // The third call should trigger retransmitting 10 packets.
   EXPECT_CALL(*send_algorithm_, SentPacket(_, _, _, _)).Times(10);
   ProcessAckPacket(&nack, true);
 
-  // The fourth call should trigger retransmitting the 11th packet and an ack.
-  EXPECT_CALL(*send_algorithm_, SentPacket(_, _, _, _)).Times(2);
+  // The fourth call should trigger retransmitting the 11th packet.
+  EXPECT_CALL(*send_algorithm_, SentPacket(_, _, _, _)).Times(1);
   ProcessAckPacket(&nack, true);
 }
 
@@ -1371,7 +1393,7 @@
   // an ack for Packet 2 (ack packet).
   SequenceNumberSet expected_acks;
   expected_acks.insert(1);
-  // Client acks packet 1
+  // Peer acks packet 1.
   EXPECT_CALL(visitor_, OnAck(ContainerEq(expected_acks)));
   QuicAckFrame frame(1, QuicTime::Zero(), 0);
   frame.received_info.entropy_hash = QuicConnectionPeer::GetSentEntropyHash(
@@ -1445,7 +1467,8 @@
   EXPECT_EQ(1u, outgoing_ack()->sent_info.least_unacked);
 
   EXPECT_EQ(1u, last_header()->packet_sequence_number);
-  EXPECT_EQ(default_retransmission_time, helper_->retransmission_alarm());
+  EXPECT_EQ(default_retransmission_time,
+            connection_.GetRetransmissionAlarm()->deadline());
   // Simulate the retransimission alarm firing
   clock_.AdvanceTime(kDefaultRetransmissionTime);
   EXPECT_CALL(*send_algorithm_, SentPacket(_, _, _, _));
@@ -1474,7 +1497,8 @@
   SendStreamDataToPeer(1, "foo", 0, !kFin, NULL);
   EXPECT_EQ(0x02020202u, final_bytes_of_last_packet());
 
-  EXPECT_EQ(default_retransmission_time, helper_->retransmission_alarm());
+  EXPECT_EQ(default_retransmission_time,
+            connection_.GetRetransmissionAlarm()->deadline());
   // Simulate the retransimission alarm firing
   clock_.AdvanceTime(kDefaultRetransmissionTime);
   EXPECT_CALL(*send_algorithm_, AbandoningPacket(_, _)).Times(2);
@@ -1509,7 +1533,8 @@
   QuicTime default_retransmission_time = clock_.ApproximateNow().Add(
       kDefaultRetransmissionTime);
 
-  EXPECT_EQ(default_retransmission_time, helper_->retransmission_alarm());
+  EXPECT_EQ(default_retransmission_time,
+            connection_.GetRetransmissionAlarm()->deadline());
   // Simulate the retransimission alarm firing
   clock_.AdvanceTime(kDefaultRetransmissionTime);
   connection_.OnRetransmissionTimeout();
@@ -1714,7 +1739,7 @@
 
   QuicTime default_timeout = clock_.ApproximateNow().Add(
       QuicTime::Delta::FromSeconds(kDefaultInitialTimeoutSecs));
-  EXPECT_EQ(default_timeout, helper_->timeout_alarm());
+  EXPECT_EQ(default_timeout, connection_.GetTimeoutAlarm()->deadline());
 
   // Simulate the timeout alarm firing
   clock_.AdvanceTime(
@@ -1735,7 +1760,7 @@
 
   // Send an ack so we don't set the retransimission alarm.
   SendAckPacketToPeer();
-  EXPECT_EQ(default_timeout, helper_->timeout_alarm());
+  EXPECT_EQ(default_timeout, connection_.GetTimeoutAlarm()->deadline());
 
   // The original alarm will fire.  We should not time out because we had a
   // network event at t=5000.  The alarm will reregister.
@@ -1745,7 +1770,7 @@
   EXPECT_FALSE(connection_.CheckForTimeout());
   EXPECT_TRUE(connection_.connected());
   EXPECT_EQ(default_timeout.Add(QuicTime::Delta::FromMilliseconds(5)),
-            helper_->timeout_alarm());
+            connection_.GetTimeoutAlarm()->deadline());
 
   // This time, we should time out.
   EXPECT_CALL(visitor_, ConnectionClose(QUIC_CONNECTION_TIMED_OUT, false));
@@ -1822,7 +1847,7 @@
               TimeUntilSend(_, NOT_RETRANSMISSION, _, _)).WillRepeatedly(
                   testing::Return(QuicTime::Delta::Zero()));
   clock_.AdvanceTime(QuicTime::Delta::FromMicroseconds(1));
-  helper_->UnregisterSendAlarmIfRegistered();
+  connection_.GetSendAlarm()->Cancel();
   EXPECT_CALL(*send_algorithm_, SentPacket(_, _, _, _));
   EXPECT_CALL(visitor_, OnCanWrite());
   connection_.OnCanWrite();
@@ -1856,7 +1881,7 @@
   EXPECT_CALL(*send_algorithm_,
               SentPacket(_, _, _, IS_RETRANSMISSION));
   clock_.AdvanceTime(QuicTime::Delta::FromMicroseconds(1));
-  helper_->UnregisterSendAlarmIfRegistered();
+  connection_.GetSendAlarm()->Cancel();
   EXPECT_CALL(visitor_, OnCanWrite());
   connection_.OnCanWrite();
   EXPECT_EQ(0u, connection_.NumQueuedPackets());
@@ -1899,7 +1924,7 @@
 
   EXPECT_EQ(0u, connection_.NumQueuedPackets());
   // Ensure alarm is not set
-  EXPECT_FALSE(helper_->IsSendAlarmSet());
+  EXPECT_FALSE(connection_.GetSendAlarm()->IsSet());
 }
 
 TEST_F(QuicConnectionTest, SendSchedulerDelayThenAckAndHold) {
@@ -2119,10 +2144,7 @@
       << "";
 }
 
-// TODO(satyamsehkhar): Add more test when we start supporting more versions.
-TEST_F(QuicConnectionTest, SendVersionNegotiationPacket) {
-  // TODO(rjshade): Update this to use a real version once we have multiple
-  //                versions in the codebase.
+TEST_F(QuicConnectionTest, ServerSendsVersionNegotiationPacket) {
   framer_.set_version_for_tests(QUIC_VERSION_UNSUPPORTED);
 
   QuicPacketHeader header;
@@ -2159,6 +2181,72 @@
   }
 }
 
+TEST_F(QuicConnectionTest, ClientHandlesVersionNegotiation) {
+  // Start out with some unsupported version.
+  QuicConnectionPeer::GetFramer(&connection_)->set_version_for_tests(
+      QUIC_VERSION_UNSUPPORTED);
+
+  QuicPacketHeader header;
+  header.public_header.guid = guid_;
+  header.public_header.reset_flag = false;
+  header.public_header.version_flag = true;
+  header.entropy_flag = false;
+  header.fec_flag = false;
+  header.packet_sequence_number = 12;
+  header.fec_group = 0;
+
+  QuicVersionVector supported_versions;
+  for (size_t i = 0; i < arraysize(kSupportedQuicVersions); ++i) {
+    supported_versions.push_back(kSupportedQuicVersions[i]);
+  }
+
+  // Send a version negotiation packet.
+  scoped_ptr<QuicEncryptedPacket> encrypted(
+      framer_.BuildVersionNegotiationPacket(
+          header.public_header, supported_versions));
+  connection_.ProcessUdpPacket(IPEndPoint(), IPEndPoint(), *encrypted);
+
+  // Now force another packet.  The connection should transition into
+  // NEGOTIATED_VERSION state and tell the packet creator to StopSendingVersion.
+  header.public_header.version_flag = false;
+  QuicFrames frames;
+  QuicFrame frame(&frame1_);
+  frames.push_back(frame);
+  scoped_ptr<QuicPacket> packet(
+      framer_.BuildUnsizedDataPacket(header, frames).packet);
+  encrypted.reset(framer_.EncryptPacket(ENCRYPTION_NONE, 12, *packet));
+  EXPECT_CALL(visitor_, OnPacket(_, _, _, _)).Times(1);
+  connection_.ProcessUdpPacket(IPEndPoint(), IPEndPoint(), *encrypted);
+
+  ASSERT_FALSE(QuicPacketCreatorPeer::SendVersionInPacket(
+      QuicConnectionPeer::GetPacketCreator(&connection_)));
+}
+
+TEST_F(QuicConnectionTest, BadVersionNegotiation) {
+  QuicPacketHeader header;
+  header.public_header.guid = guid_;
+  header.public_header.reset_flag = false;
+  header.public_header.version_flag = true;
+  header.entropy_flag = false;
+  header.fec_flag = false;
+  header.packet_sequence_number = 12;
+  header.fec_group = 0;
+
+  QuicVersionVector supported_versions;
+  for (size_t i = 0; i < arraysize(kSupportedQuicVersions); ++i) {
+    supported_versions.push_back(kSupportedQuicVersions[i]);
+  }
+
+  // Send a version negotiation packet with the version the client started with.
+  // It should be rejected.
+  EXPECT_CALL(visitor_, ConnectionClose(QUIC_INVALID_VERSION_NEGOTIATION_PACKET,
+                                        false));
+  scoped_ptr<QuicEncryptedPacket> encrypted(
+      framer_.BuildVersionNegotiationPacket(
+          header.public_header, supported_versions));
+  connection_.ProcessUdpPacket(IPEndPoint(), IPEndPoint(), *encrypted);
+}
+
 TEST_F(QuicConnectionTest, CheckSendStats) {
   EXPECT_CALL(*send_algorithm_, AbandoningPacket(_, _)).Times(3);
   EXPECT_CALL(*send_algorithm_,
@@ -2167,7 +2255,7 @@
   size_t first_packet_size = last_sent_packet_size();
 
   EXPECT_CALL(*send_algorithm_,
-              SentPacket(_, _, _, NOT_RETRANSMISSION)).Times(2);
+              SentPacket(_, _, _, NOT_RETRANSMISSION));
   connection_.SendStreamData(1u, "second", 0, !kFin);
   size_t second_packet_size = last_sent_packet_size();
 
@@ -2194,7 +2282,6 @@
 
   ProcessFramePacket(frame);
   ProcessFramePacket(frame);
-  size_t ack_packet_size = last_sent_packet_size();
   ProcessFramePacket(frame);
 
   EXPECT_CALL(*send_algorithm_, SmoothedRtt()).WillOnce(
@@ -2203,9 +2290,9 @@
       Return(QuicBandwidth::Zero()));
 
   const QuicConnectionStats& stats = connection_.GetStats();
-  EXPECT_EQ(3 * first_packet_size + 2 * second_packet_size + ack_packet_size -
-            kQuicVersionSize, stats.bytes_sent);
-  EXPECT_EQ(6u, stats.packets_sent);
+  EXPECT_EQ(3 * first_packet_size + 2 * second_packet_size - kQuicVersionSize,
+            stats.bytes_sent);
+  EXPECT_EQ(5u, stats.packets_sent);
   EXPECT_EQ(2 * first_packet_size + second_packet_size - kQuicVersionSize,
             stats.bytes_retransmitted);
   EXPECT_EQ(3u, stats.packets_retransmitted);
@@ -2280,7 +2367,6 @@
   scoped_ptr<QuicEncryptedPacket> encrypted(framer_.EncryptPacket(
       ENCRYPTION_NONE, 1, *packet));
 
-  EXPECT_CALL(visitor_, OnCanWrite()).Times(1).WillOnce(Return(true));
   EXPECT_CALL(visitor_, ConnectionClose(QUIC_PEER_GOING_AWAY, true));
   EXPECT_CALL(visitor_, OnPacket(_, _, _, _)).Times(0);
 
@@ -2318,7 +2404,7 @@
   helper_->set_blocked(false);  // Already default.
 
   // Send a packet (but write will not block).
-  ProcessFecPacket(2, 1, true, !kEntropyFlag);
+  connection_.SendStreamData(1, "foo", 0, !kFin);
   EXPECT_EQ(0u, connection_.NumQueuedPackets());
   EXPECT_EQ(1u, helper_->packets_write_attempts());
 
@@ -2329,10 +2415,11 @@
 }
 
 TEST_F(QuicConnectionTest, ConnectionCloseWhenWriteBlocked) {
+  EXPECT_EQ(0u, connection_.NumQueuedPackets());
   helper_->set_blocked(true);
 
   // Send a packet to so that write will really block.
-  ProcessFecPacket(2, 1, true, !kEntropyFlag);
+  connection_.SendStreamData(1, "foo", 0, !kFin);
   EXPECT_EQ(1u, connection_.NumQueuedPackets());
   EXPECT_EQ(1u, helper_->packets_write_attempts());
 
diff --git a/net/quic/quic_crypto_client_stream.cc b/net/quic/quic_crypto_client_stream.cc
index edeef11..ab1d974 100644
--- a/net/quic/quic_crypto_client_stream.cc
+++ b/net/quic/quic_crypto_client_stream.cc
@@ -262,6 +262,7 @@
         verify_ok_ = false;
 
         ProofVerifier::Status status = verifier->VerifyProof(
+            session()->connection()->version(),
             server_hostname_,
             cached->server_config(),
             cached->certs(),
diff --git a/net/quic/quic_crypto_server_stream.cc b/net/quic/quic_crypto_server_stream.cc
index 6f49864..f7b67b7 100644
--- a/net/quic/quic_crypto_server_stream.cc
+++ b/net/quic/quic_crypto_server_stream.cc
@@ -129,6 +129,7 @@
     string* error_details) {
   return crypto_config_.ProcessClientHello(
       message,
+      session()->connection()->version(),
       session()->connection()->guid(),
       session()->connection()->peer_address(),
       session()->connection()->clock(),
diff --git a/net/quic/quic_http_stream_test.cc b/net/quic/quic_http_stream_test.cc
index 997dc95..b378416 100644
--- a/net/quic/quic_http_stream_test.cc
+++ b/net/quic/quic_http_stream_test.cc
@@ -324,7 +324,6 @@
   SetRequestString("GET", "/");
   AddWrite(SYNCHRONOUS, ConstructDataPacket(1, true, kFin, 0,
                                             request_data_));
-  AddWrite(SYNCHRONOUS, ConstructAckPacket(2, 2, 1));
   Initialize();
 
   request_.method = "GET";
@@ -366,7 +365,6 @@
 TEST_F(QuicHttpStreamTest, GetRequestFullResponseInSinglePacket) {
   SetRequestString("GET", "/");
   AddWrite(SYNCHRONOUS, ConstructDataPacket(1, true, kFin, 0, request_data_));
-  AddWrite(SYNCHRONOUS, ConstructAckPacket(2, 2, 1));
   Initialize();
 
   request_.method = "GET";
@@ -412,7 +410,7 @@
   AddWrite(SYNCHRONOUS, ConstructDataPacket(2, true, kFin,
                                             request_data_.length(),
                                             kUploadData));
-  AddWrite(SYNCHRONOUS, ConstructAckPacket(3, 2, 1));
+  AddWrite(SYNCHRONOUS, ConstructAckPacket(3, 3, 1));
 
   Initialize();
 
@@ -473,7 +471,7 @@
   AddWrite(SYNCHRONOUS, ConstructDataPacket(3, true, kFin,
                                             request_data_.length() + chunk_size,
                                             kUploadData));
-  AddWrite(SYNCHRONOUS, ConstructAckPacket(4, 2, 1));
+  AddWrite(SYNCHRONOUS, ConstructAckPacket(4, 3, 1));
 
   Initialize();
 
@@ -528,7 +526,6 @@
 TEST_F(QuicHttpStreamTest, DestroyedEarly) {
   SetRequestString("GET", "/");
   AddWrite(SYNCHRONOUS, ConstructDataPacket(1, true, kFin, 0, request_data_));
-  AddWrite(SYNCHRONOUS, ConstructAckPacket(2, 2, 1));
   use_closing_stream_ = true;
   Initialize();
 
diff --git a/net/quic/quic_protocol.cc b/net/quic/quic_protocol.cc
index 6d21710..0b83b14 100644
--- a/net/quic/quic_protocol.cc
+++ b/net/quic/quic_protocol.cc
@@ -129,6 +129,8 @@
       return MakeQuicTag('Q', '0', '0', '6');
     case QUIC_VERSION_7:
       return MakeQuicTag('Q', '0', '0', '7');
+    case QUIC_VERSION_8:
+      return MakeQuicTag('Q', '0', '0', '8');
     default:
       // This shold be an ERROR because we should never attempt to convert an
       // invalid QuicVersion to be written to the wire.
@@ -140,11 +142,14 @@
 QuicVersion QuicTagToQuicVersion(const QuicTag version_tag) {
   const QuicTag quic_tag_v6 = MakeQuicTag('Q', '0', '0', '6');
   const QuicTag quic_tag_v7 = MakeQuicTag('Q', '0', '0', '7');
+  const QuicTag quic_tag_v8 = MakeQuicTag('Q', '0', '0', '8');
 
   if (version_tag == quic_tag_v6) {
     return QUIC_VERSION_6;
   } else if (version_tag == quic_tag_v7) {
     return QUIC_VERSION_7;
+  } else if (version_tag == quic_tag_v8) {
+    return QUIC_VERSION_8;
   } else {
     // Reading from the client so this should not be considered an ERROR.
     DLOG(INFO) << "Unsupported QuicTag version: "
@@ -153,14 +158,15 @@
   }
 }
 
+#define RETURN_STRING_LITERAL(x) \
+case x: \
+return #x
+
 string QuicVersionToString(const QuicVersion version) {
-  // TODO(rjshade): Possibly start using RETURN_STRING_LITERAL here when we
-  //                start supporting a lot of versions.
   switch (version) {
-    case QUIC_VERSION_6:
-      return "QUIC_VERSION_6";
-    case QUIC_VERSION_7:
-      return "QUIC_VERSION_7";
+    RETURN_STRING_LITERAL(QUIC_VERSION_6);
+    RETURN_STRING_LITERAL(QUIC_VERSION_7);
+    RETURN_STRING_LITERAL(QUIC_VERSION_8);
     default:
       return "QUIC_VERSION_UNSUPPORTED";
   }
diff --git a/net/quic/quic_protocol.h b/net/quic/quic_protocol.h
index fe4da4c..f332f9f 100644
--- a/net/quic/quic_protocol.h
+++ b/net/quic/quic_protocol.h
@@ -180,14 +180,16 @@
 // The available versions of QUIC. Guaranteed that the integer value of the enum
 // will match the version number.
 // When adding a new version to this enum you should add it to
-// kSupportedVersions (if appropriate), and also add a new case to the helper
-// methods QuicVersionToQuicTag, and QuicTagToQuicVersion.
+// kSupportedQuicVersions (if appropriate), and also add a new case to the
+// helper methods QuicVersionToQuicTag, QuicTagToQuicVersion, and
+// QuicVersionToString.
 enum QuicVersion {
   // Special case to indicate unknown/unsupported QUIC version.
   QUIC_VERSION_UNSUPPORTED = 0,
 
   QUIC_VERSION_6 = 6,
-  QUIC_VERSION_7 = 7,  // Current version.
+  QUIC_VERSION_7 = 7,
+  QUIC_VERSION_8 = 8,  // Current version.
 };
 
 // This vector contains QUIC versions which we currently support.
@@ -195,7 +197,7 @@
 // element, with subsequent elements in descending order (versions can be
 // skipped as necessary).
 static const QuicVersion kSupportedQuicVersions[] =
-    {QUIC_VERSION_7, QUIC_VERSION_6};
+    {QUIC_VERSION_8, QUIC_VERSION_7, QUIC_VERSION_6};
 
 typedef std::vector<QuicVersion> QuicVersionVector;
 
@@ -424,7 +426,15 @@
 
 enum QuicVersionNegotiationState {
   START_NEGOTIATION = 0,
-  SENT_NEGOTIATION_PACKET,
+  // Server-side this implies we've sent a version negotiation packet and are
+  // waiting on the client to select a compatible version.  Client-side this
+  // implies we've gotten a version negotiation packet, are retransmitting the
+  // initial packets with a supported version and are waiting for our first
+  // packet from the server.
+  NEGOTIATION_IN_PROGRESS,
+  // This indicates this endpoint has received a packet from the peer with a
+  // version this endpoint supports.  Version negotiation is complete, and the
+  // version number will no longer be sent with future packets.
   NEGOTIATED_VERSION
 };
 
diff --git a/net/quic/quic_protocol_test.cc b/net/quic/quic_protocol_test.cc
index 877f03d..b073d85 100644
--- a/net/quic/quic_protocol_test.cc
+++ b/net/quic/quic_protocol_test.cc
@@ -56,8 +56,8 @@
 #endif
 
   // Explicitly test a specific version.
-  EXPECT_EQ(MakeQuicTag('Q', '0', '0', '6'),
-            QuicVersionToQuicTag(QUIC_VERSION_6));
+  EXPECT_EQ(MakeQuicTag('Q', '0', '0', '7'),
+            QuicVersionToQuicTag(QUIC_VERSION_7));
 
   // Loop over all supported versions and make sure that we never hit the
   // default case (i.e. all supported versions should be successfully converted
@@ -95,8 +95,8 @@
 #endif
 
   // Explicitly test specific versions.
-  EXPECT_EQ(QUIC_VERSION_6,
-            QuicTagToQuicVersion(MakeQuicTag('Q', '0', '0', '6')));
+  EXPECT_EQ(QUIC_VERSION_7,
+            QuicTagToQuicVersion(MakeQuicTag('Q', '0', '0', '7')));
 
   for (size_t i = 0; i < arraysize(kSupportedQuicVersions); ++i) {
     const QuicVersion& version = kSupportedQuicVersions[i];
@@ -127,16 +127,16 @@
 }
 
 TEST(QuicProtocolTest, QuicVersionToString) {
-  EXPECT_EQ("QUIC_VERSION_6",
-            QuicVersionToString(QUIC_VERSION_6));
+  EXPECT_EQ("QUIC_VERSION_7",
+            QuicVersionToString(QUIC_VERSION_7));
   EXPECT_EQ("QUIC_VERSION_UNSUPPORTED",
             QuicVersionToString(QUIC_VERSION_UNSUPPORTED));
 
-  QuicVersion single_version[] = {QUIC_VERSION_6};
-  EXPECT_EQ("QUIC_VERSION_6,", QuicVersionArrayToString(single_version,
+  QuicVersion single_version[] = {QUIC_VERSION_7};
+  EXPECT_EQ("QUIC_VERSION_7,", QuicVersionArrayToString(single_version,
                                    arraysize(single_version)));
-  QuicVersion multiple_versions[] = {QUIC_VERSION_7, QUIC_VERSION_6};
-  EXPECT_EQ("QUIC_VERSION_7,QUIC_VERSION_6,",
+  QuicVersion multiple_versions[] = {QUIC_VERSION_8, QUIC_VERSION_7};
+  EXPECT_EQ("QUIC_VERSION_8,QUIC_VERSION_7,",
             QuicVersionArrayToString(multiple_versions,
                                      arraysize(multiple_versions)));
 }
diff --git a/net/quic/quic_received_packet_manager.cc b/net/quic/quic_received_packet_manager.cc
index 3ade8fb..9a136db 100644
--- a/net/quic/quic_received_packet_manager.cc
+++ b/net/quic/quic_received_packet_manager.cc
@@ -116,9 +116,7 @@
 void QuicReceivedPacketManager::RecalculateEntropyHash(
     QuicPacketSequenceNumber peer_least_unacked,
     QuicPacketEntropyHash entropy_hash) {
-  DLOG_IF(WARNING, peer_least_unacked > received_info_.largest_observed)
-      << "Prematurely updating the entropy manager before registering the "
-      << "entropy of the containing packet creates a temporary inconsistency.";
+  DCHECK_LE(peer_least_unacked, received_info_.largest_observed);
   if (peer_least_unacked < largest_sequence_number_) {
     DLOG(INFO) << "Ignoring received peer_least_unacked:" << peer_least_unacked
                << " less than largest_peer_sequence_number:"
diff --git a/net/quic/quic_session.cc b/net/quic/quic_session.cc
index 9fb44d4..a07f413 100644
--- a/net/quic/quic_session.cc
+++ b/net/quic/quic_session.cc
@@ -77,19 +77,20 @@
     : connection_(connection),
       visitor_shim_(new VisitorShim(this)),
       config_(config),
-      max_open_streams_(kDefaultMaxStreamsPerConnection),
+      max_open_streams_(config_.max_streams_per_connection()),
       next_stream_id_(is_server ? 2 : 3),
       is_server_(is_server),
       largest_peer_created_stream_id_(0),
       error_(QUIC_NO_ERROR),
       goaway_received_(false),
       goaway_sent_(false) {
-  set_max_open_streams(config_.max_streams_per_connection());
 
   connection_->set_visitor(visitor_shim_.get());
   connection_->SetIdleNetworkTimeout(config_.idle_connection_state_lifetime());
-  connection_->SetOverallConnectionTimeout(
-      config_.max_time_before_crypto_handshake());
+  if (connection_->connected()) {
+    connection_->SetOverallConnectionTimeout(
+        config_.max_time_before_crypto_handshake());
+  }
   // TODO(satyamshekhar): Set congestion control and ICSL also.
 }
 
@@ -149,6 +150,7 @@
     if (!stream) {
       connection()->SendConnectionClose(
           QUIC_STREAM_RST_BEFORE_HEADERS_DECOMPRESSED);
+      return false;
     }
     stream->OnDecompressorAvailable();
   }
diff --git a/net/quic/quic_session.h b/net/quic/quic_session.h
index 3f0f99f..9f7aceb 100644
--- a/net/quic/quic_session.h
+++ b/net/quic/quic_session.h
@@ -197,10 +197,6 @@
     return max_open_streams_;
   }
 
-  void set_max_open_streams(size_t max_open_streams) {
-    max_open_streams_ = max_open_streams;
-  }
-
  private:
   friend class test::QuicSessionPeer;
   friend class VisitorShim;
diff --git a/net/quic/test_tools/quic_connection_peer.cc b/net/quic/test_tools/quic_connection_peer.cc
index bb6b3fc..610c505 100644
--- a/net/quic/test_tools/quic_connection_peer.cc
+++ b/net/quic/test_tools/quic_connection_peer.cc
@@ -145,11 +145,37 @@
   return connection->helper_.get();
 }
 
+// static
+QuicFramer* QuicConnectionPeer::GetFramer(QuicConnection* connection) {
+  return &connection->framer_;
+}
+
 QuicFecGroup* QuicConnectionPeer::GetFecGroup(QuicConnection* connection,
                                               int fec_group) {
   connection->last_header_.fec_group = fec_group;
   return connection->GetFecGroup();
 }
 
+// static
+QuicAlarm* QuicConnectionPeer::GetAckAlarm(QuicConnection* connection) {
+  return connection->ack_alarm_.get();
+}
+
+// static
+QuicAlarm* QuicConnectionPeer::GetRetransmissionAlarm(
+    QuicConnection* connection) {
+  return connection->retransmission_alarm_.get();
+}
+
+// static
+QuicAlarm* QuicConnectionPeer::GetSendAlarm(QuicConnection* connection) {
+  return connection->send_alarm_.get();
+}
+
+// static
+QuicAlarm* QuicConnectionPeer::GetTimeoutAlarm(QuicConnection* connection) {
+  return connection->timeout_alarm_.get();
+}
+
 }  // namespace test
 }  // namespace net
diff --git a/net/quic/test_tools/quic_connection_peer.h b/net/quic/test_tools/quic_connection_peer.h
index 7ce3c5b..4438353 100644
--- a/net/quic/test_tools/quic_connection_peer.h
+++ b/net/quic/test_tools/quic_connection_peer.h
@@ -14,6 +14,7 @@
 
 struct QuicAckFrame;
 struct QuicPacketHeader;
+class QuicAlarm;
 class QuicConnection;
 class QuicConnectionHelperInterface;
 class QuicConnectionVisitorInterface;
@@ -84,9 +85,16 @@
 
   static QuicConnectionHelperInterface* GetHelper(QuicConnection* connection);
 
+  static QuicFramer* GetFramer(QuicConnection* connection);
+
   // Set last_header_->fec_group = fec_group and return connection->GetFecGroup
   static QuicFecGroup* GetFecGroup(QuicConnection* connection, int fec_group);
 
+  static QuicAlarm* GetAckAlarm(QuicConnection* connection);
+  static QuicAlarm* GetRetransmissionAlarm(QuicConnection* connection);
+  static QuicAlarm* GetSendAlarm(QuicConnection* connection);
+  static QuicAlarm* GetTimeoutAlarm(QuicConnection* connection);
+
  private:
   DISALLOW_COPY_AND_ASSIGN(QuicConnectionPeer);
 };
diff --git a/net/quic/test_tools/quic_test_utils.cc b/net/quic/test_tools/quic_test_utils.cc
index 5d1b3a0..810abdc 100644
--- a/net/quic/test_tools/quic_test_utils.cc
+++ b/net/quic/test_tools/quic_test_utils.cc
@@ -23,6 +23,20 @@
 
 namespace net {
 namespace test {
+namespace {
+
+// No-op alarm implementation used by MockHelper.
+class TestAlarm : public QuicAlarm {
+ public:
+  explicit TestAlarm(QuicAlarm::Delegate* delegate)
+      : QuicAlarm(delegate) {
+  }
+
+  virtual void SetImpl() OVERRIDE {}
+  virtual void CancelImpl() OVERRIDE {}
+};
+
+}  // namespace
 
 MockFramerVisitor::MockFramerVisitor() {
   // By default, we want to accept packets.
@@ -181,6 +195,10 @@
   return &random_generator_;
 }
 
+QuicAlarm* MockHelper::CreateAlarm(QuicAlarm::Delegate* delegate) {
+  return new TestAlarm(delegate);
+}
+
 void MockHelper::AdvanceTime(QuicTime::Delta delta) {
   clock_.AdvanceTime(delta);
 }
diff --git a/net/quic/test_tools/quic_test_utils.h b/net/quic/test_tools/quic_test_utils.h
index f6172c9..65fba73 100644
--- a/net/quic/test_tools/quic_test_utils.h
+++ b/net/quic/test_tools/quic_test_utils.h
@@ -206,13 +206,8 @@
                                       int* error));
   MOCK_METHOD0(IsWriteBlockedDataBuffered, bool());
   MOCK_METHOD1(IsWriteBlocked, bool(int));
-  MOCK_METHOD1(SetRetransmissionAlarm, void(QuicTime::Delta delay));
-  MOCK_METHOD1(SetAckAlarm, void(QuicTime::Delta delay));
-  MOCK_METHOD1(SetSendAlarm, void(QuicTime alarm_time));
-  MOCK_METHOD1(SetTimeoutAlarm, void(QuicTime::Delta delay));
-  MOCK_METHOD0(IsSendAlarmSet, bool());
-  MOCK_METHOD0(UnregisterSendAlarmIfRegistered, void());
-  MOCK_METHOD0(ClearAckAlarm, void());
+  virtual QuicAlarm* CreateAlarm(QuicAlarm::Delegate* delegate);
+
  private:
   MockClock clock_;
   MockRandom random_generator_;
diff --git a/net/server/http_server.cc b/net/server/http_server.cc
index 4217aa0..373025c 100644
--- a/net/server/http_server.cc
+++ b/net/server/http_server.cc
@@ -12,6 +12,7 @@
 #include "base/strings/stringprintf.h"
 #include "base/sys_byteorder.h"
 #include "build/build_config.h"
+#include "net/base/net_errors.h"
 #include "net/server/http_connection.h"
 #include "net/server/http_server_request_info.h"
 #include "net/server/http_server_response_info.h"
@@ -24,7 +25,6 @@
                        HttpServer::Delegate* delegate)
     : delegate_(delegate),
       server_(factory.CreateAndListen(this)) {
-  DCHECK(server_.get());
 }
 
 void HttpServer::AcceptWebSocket(
@@ -89,6 +89,8 @@
 }
 
 int HttpServer::GetLocalAddress(IPEndPoint* address) {
+  if (!server_)
+    return ERR_SOCKET_NOT_CONNECTED;
   return server_->GetLocalAddress(address);
 }
 
diff --git a/net/socket/ssl_client_socket_nss.cc b/net/socket/ssl_client_socket_nss.cc
index d1f2832..72154bb 100644
--- a/net/socket/ssl_client_socket_nss.cc
+++ b/net/socket/ssl_client_socket_nss.cc
@@ -1861,15 +1861,6 @@
       net_error = ERR_SSL_PROTOCOL_ERROR;
     }
 
-    // Some broken SSL devices negotiate TLS 1.0 when sent a TLS 1.1 or 1.2
-    // ClientHello, but then return a bad-record-MAC alert. See
-    // crbug.com/260358. In order to make the fallback as minimal as possible,
-    // this fallback is only triggered for >= TLS 1.1.
-    if (net_error == ERR_SSL_BAD_RECORD_MAC_ALERT &&
-        ssl_config_.version_max >= SSL_PROTOCOL_VERSION_TLS1_1) {
-      net_error = ERR_SSL_PROTOCOL_ERROR;
-    }
-
     // If not done, stay in this state
     if (net_error == ERR_IO_PENDING) {
       GotoState(STATE_HANDSHAKE);
diff --git a/net/third_party/nss/patches/alpn.patch b/net/third_party/nss/patches/alpn.patch
index f93c92a..ad21798 100644
--- a/net/third_party/nss/patches/alpn.patch
+++ b/net/third_party/nss/patches/alpn.patch
@@ -16,7 +16,7 @@
 diff -pu a/nss/lib/ssl/ssl3ext.c b/nss/lib/ssl/ssl3ext.c
 --- a/nss/lib/ssl/ssl3ext.c	2013-07-31 14:10:00.342814862 -0700
 +++ b/nss/lib/ssl/ssl3ext.c	2013-07-31 14:28:56.549496061 -0700
-@@ -52,8 +52,12 @@ static SECStatus ssl3_HandleRenegotiatio
+@@ -53,8 +53,12 @@ static SECStatus ssl3_HandleRenegotiationInfoXtn(sslSocket *ss,
      PRUint16 ex_type, SECItem *data);
  static SECStatus ssl3_ClientHandleNextProtoNegoXtn(sslSocket *ss,
  			PRUint16 ex_type, SECItem *data);
@@ -29,30 +29,15 @@
  static PRInt32 ssl3_ClientSendNextProtoNegoXtn(sslSocket *ss, PRBool append,
  					       PRUint32 maxBytes);
  static PRInt32 ssl3_SendUseSRTPXtn(sslSocket *ss, PRBool append,
-@@ -246,14 +250,15 @@ static const ssl3HelloExtensionHandler c
- /* These two tables are used by the client, to handle server hello
-  * extensions. */
- static const ssl3HelloExtensionHandler serverHelloHandlersTLS[] = {
--    { ssl_server_name_xtn,        &ssl3_HandleServerNameXtn },
-+    { ssl_server_name_xtn,            &ssl3_HandleServerNameXtn },
-     /* TODO: add a handler for ssl_ec_point_formats_xtn */
--    { ssl_session_ticket_xtn,     &ssl3_ClientHandleSessionTicketXtn },
--    { ssl_renegotiation_info_xtn, &ssl3_HandleRenegotiationInfoXtn },
--    { ssl_next_proto_nego_xtn,    &ssl3_ClientHandleNextProtoNegoXtn },
--    { ssl_use_srtp_xtn,           &ssl3_HandleUseSRTPXtn },
--    { ssl_channel_id_xtn,         &ssl3_ClientHandleChannelIDXtn },
--    { ssl_cert_status_xtn,        &ssl3_ClientHandleStatusRequestXtn },
-+    { ssl_session_ticket_xtn,         &ssl3_ClientHandleSessionTicketXtn },
-+    { ssl_renegotiation_info_xtn,     &ssl3_HandleRenegotiationInfoXtn },
-+    { ssl_next_proto_nego_xtn,        &ssl3_ClientHandleNextProtoNegoXtn },
-+    { ssl_app_layer_protocol_xtn,     &ssl3_ClientHandleAppProtoXtn },
-+    { ssl_use_srtp_xtn,               &ssl3_HandleUseSRTPXtn },
-+    { ssl_channel_id_xtn,             &ssl3_ClientHandleChannelIDXtn },
-+    { ssl_cert_status_xtn,            &ssl3_ClientHandleStatusRequestXtn },
-     { -1, NULL }
- };
- 
-@@ -270,17 +275,18 @@ static const ssl3HelloExtensionHandler s
+@@ -252,6 +256,7 @@ static const ssl3HelloExtensionHandler serverHelloHandlersTLS[] = {
+     { ssl_session_ticket_xtn,     &ssl3_ClientHandleSessionTicketXtn },
+     { ssl_renegotiation_info_xtn, &ssl3_HandleRenegotiationInfoXtn },
+     { ssl_next_proto_nego_xtn,    &ssl3_ClientHandleNextProtoNegoXtn },
++    { ssl_app_layer_protocol_xtn, &ssl3_ClientHandleAppProtoXtn },
+     { ssl_use_srtp_xtn,           &ssl3_HandleUseSRTPXtn },
+     { ssl_channel_id_xtn,         &ssl3_ClientHandleChannelIDXtn },
+     { ssl_cert_status_xtn,        &ssl3_ClientHandleStatusRequestXtn },
+@@ -271,18 +276,19 @@ static const ssl3HelloExtensionHandler serverHelloHandlersSSL3[] = {
   */
  static const 
  ssl3HelloExtensionSender clientHelloSendersTLS[SSL_MAX_EXTENSIONS] = {
@@ -71,16 +56,18 @@
 -    { ssl_use_srtp_xtn,           &ssl3_SendUseSRTPXtn },
 -    { ssl_channel_id_xtn,         &ssl3_ClientSendChannelIDXtn },
 -    { ssl_cert_status_xtn,        &ssl3_ClientSendStatusRequestXtn },
+-    { ssl_signature_algorithms_xtn, &ssl3_ClientSendSigAlgsXtn }
 +    { ssl_session_ticket_xtn,         &ssl3_SendSessionTicketXtn },
 +    { ssl_next_proto_nego_xtn,        &ssl3_ClientSendNextProtoNegoXtn },
 +    { ssl_app_layer_protocol_xtn,     &ssl3_ClientSendAppProtoXtn },
 +    { ssl_use_srtp_xtn,               &ssl3_SendUseSRTPXtn },
 +    { ssl_channel_id_xtn,             &ssl3_ClientSendChannelIDXtn },
 +    { ssl_cert_status_xtn,            &ssl3_ClientSendStatusRequestXtn },
-     { ssl_signature_algorithms_xtn, &ssl3_ClientSendSigAlgsXtn }
++    { ssl_signature_algorithms_xtn,   &ssl3_ClientSendSigAlgsXtn }
      /* any extra entries will appear as { 0, NULL }    */
  };
-@@ -605,6 +611,11 @@ ssl3_ClientHandleNextProtoNegoXtn(sslSoc
+ 
+@@ -606,6 +612,11 @@ ssl3_ClientHandleNextProtoNegoXtn(sslSocket *ss, PRUint16 ex_type,
  
      PORT_Assert(!ss->firstHsDone);
  
@@ -92,7 +79,7 @@
      rv = ssl3_ValidateNextProtoNego(data->data, data->len);
      if (rv != SECSuccess)
  	return rv;
-@@ -638,6 +649,44 @@ ssl3_ClientHandleNextProtoNegoXtn(sslSoc
+@@ -639,6 +650,44 @@ ssl3_ClientHandleNextProtoNegoXtn(sslSocket *ss, PRUint16 ex_type,
      return SECITEM_CopyItem(NULL, &ss->ssl3.nextProto, &result);
  }
  
@@ -137,21 +124,15 @@
  static PRInt32
  ssl3_ClientSendNextProtoNegoXtn(sslSocket * ss, PRBool append,
  				PRUint32 maxBytes)
-@@ -664,6 +713,44 @@ ssl3_ClientSendNextProtoNegoXtn(sslSocke
-     } else if (maxBytes < extension_length) {
- 	return 0;
-     }
-+
-+    return extension_length;
-+
-+loser:
-+    return -1;
-+}
-+
+@@ -672,6 +721,70 @@ loser:
+     return -1;
+ }
+ 
 +static PRInt32
 +ssl3_ClientSendAppProtoXtn(sslSocket * ss, PRBool append, PRUint32 maxBytes)
 +{
 +    PRInt32 extension_length;
++    unsigned char *alpn_protos = NULL;
 +
 +    /* Renegotiations do not send this extension. */
 +    if (!ss->opt.nextProtoNego.data || ss->firstHsDone) {
@@ -163,15 +144,38 @@
 +                       ss->opt.nextProtoNego.len;
 +
 +    if (append && maxBytes >= extension_length) {
++	/* NPN requires that the client's fallback protocol is first in the
++	 * list. However, ALPN sends protocols in preference order. So we
++	 * allocate a buffer and move the first protocol to the end of the
++	 * list. */
 +	SECStatus rv;
++	const unsigned int len = ss->opt.nextProtoNego.len;
++
++	alpn_protos = PORT_Alloc(len);
++	if (alpn_protos == NULL) {
++	    return SECFailure;
++	}
++	if (len > 0) {
++	    /* Each protocol string is prefixed with a single byte length. */
++	    unsigned int i = ss->opt.nextProtoNego.data[0] + 1;
++	    if (i <= len) {
++		memcpy(alpn_protos, &ss->opt.nextProtoNego.data[i], len - i);
++		memcpy(alpn_protos + len - i, ss->opt.nextProtoNego.data, i);
++	    } else {
++		/* This seems to be invalid data so we'll send as-is. */
++		memcpy(alpn_protos, ss->opt.nextProtoNego.data, len);
++	    }
++	}
++
 +	rv = ssl3_AppendHandshakeNumber(ss, ssl_app_layer_protocol_xtn, 2);
 +	if (rv != SECSuccess)
 +	    goto loser;
 +	rv = ssl3_AppendHandshakeNumber(ss, extension_length - 4, 2);
 +	if (rv != SECSuccess)
 +	    goto loser;
-+	rv = ssl3_AppendHandshakeVariable(ss, ss->opt.nextProtoNego.data,
-+					  ss->opt.nextProtoNego.len, 2);
++	rv = ssl3_AppendHandshakeVariable(ss, alpn_protos, len, 2);
++	PORT_Free(alpn_protos);
++	alpn_protos = NULL;
 +	if (rv != SECSuccess)
 +	    goto loser;
 +	ss->xtnData.advertised[ss->xtnData.numAdvertised++] =
@@ -179,13 +183,22 @@
 +    } else if (maxBytes < extension_length) {
 +	return 0;
 +    }
- 
-     return extension_length;
- 
++
++    return extension_length;
++
++loser:
++    if (alpn_protos)
++	PORT_Free(alpn_protos);
++    return -1;
++}
++
+ static SECStatus
+ ssl3_ClientHandleChannelIDXtn(sslSocket *ss, PRUint16 ex_type,
+ 			     SECItem *data)
 diff -pu a/nss/lib/ssl/ssl.h b/nss/lib/ssl/ssl.h
 --- a/nss/lib/ssl/ssl.h	2013-07-31 14:10:35.113325316 -0700
 +++ b/nss/lib/ssl/ssl.h	2013-07-31 14:28:56.589496647 -0700
-@@ -203,6 +203,11 @@ SSL_IMPORT SECStatus SSL_SetNextProtoCal
+@@ -203,6 +203,16 @@ SSL_IMPORT SECStatus SSL_SetNextProtoCal
   * protocol in server-preference order. If no matching protocol is found it
   * selects the first supported protocol.
   *
@@ -194,6 +207,11 @@
 + * uses ALPN to select a protocol, SSL_GetNextProto will return
 + * SSL_NEXT_PROTO_SELECTED as the state.
 + *
++ * Since NPN uses the first protocol as the fallback protocol, when sending an
++ * ALPN extension, the first protocol is moved to the end of the list. This
++ * indicates that the fallback protocol is the least preferred. The other
++ * protocols should be in preference order.
++ *
   * The supported protocols are specified in |data| in wire-format (8-bit
   * length-prefixed). For example: "\010http/1.1\006spdy/2". */
  SSL_IMPORT SECStatus SSL_SetNextProtoNego(PRFileDesc *fd,
diff --git a/net/third_party/nss/ssl/ssl.h b/net/third_party/nss/ssl/ssl.h
index 7194257..c083a6b 100644
--- a/net/third_party/nss/ssl/ssl.h
+++ b/net/third_party/nss/ssl/ssl.h
@@ -208,6 +208,11 @@
  * uses ALPN to select a protocol, SSL_GetNextProto will return
  * SSL_NEXT_PROTO_SELECTED as the state.
  *
+ * Since NPN uses the first protocol as the fallback protocol, when sending an
+ * ALPN extension, the first protocol is moved to the end of the list. This
+ * indicates that the fallback protocol is the least preferred. The other
+ * protocols should be in preference order.
+ *
  * The supported protocols are specified in |data| in wire-format (8-bit
  * length-prefixed). For example: "\010http/1.1\006spdy/2". */
 SSL_IMPORT SECStatus SSL_SetNextProtoNego(PRFileDesc *fd,
diff --git a/net/third_party/nss/ssl/ssl3ext.c b/net/third_party/nss/ssl/ssl3ext.c
index 46e31c3..0415770 100644
--- a/net/third_party/nss/ssl/ssl3ext.c
+++ b/net/third_party/nss/ssl/ssl3ext.c
@@ -724,6 +724,7 @@
 ssl3_ClientSendAppProtoXtn(sslSocket * ss, PRBool append, PRUint32 maxBytes)
 {
     PRInt32 extension_length;
+    unsigned char *alpn_protos = NULL;
 
     /* Renegotiations do not send this extension. */
     if (!ss->opt.nextProtoNego.data || ss->firstHsDone) {
@@ -735,15 +736,38 @@
                        ss->opt.nextProtoNego.len;
 
     if (append && maxBytes >= extension_length) {
+	/* NPN requires that the client's fallback protocol is first in the
+	 * list. However, ALPN sends protocols in preference order. So we
+	 * allocate a buffer and move the first protocol to the end of the
+	 * list. */
 	SECStatus rv;
+	const unsigned int len = ss->opt.nextProtoNego.len;
+
+	alpn_protos = PORT_Alloc(len);
+	if (alpn_protos == NULL) {
+	    return SECFailure;
+	}
+	if (len > 0) {
+	    /* Each protocol string is prefixed with a single byte length. */
+	    unsigned int i = ss->opt.nextProtoNego.data[0] + 1;
+	    if (i <= len) {
+		memcpy(alpn_protos, &ss->opt.nextProtoNego.data[i], len - i);
+		memcpy(alpn_protos + len - i, ss->opt.nextProtoNego.data, i);
+	    } else {
+		/* This seems to be invalid data so we'll send as-is. */
+		memcpy(alpn_protos, ss->opt.nextProtoNego.data, len);
+	    }
+	}
+
 	rv = ssl3_AppendHandshakeNumber(ss, ssl_app_layer_protocol_xtn, 2);
 	if (rv != SECSuccess)
 	    goto loser;
 	rv = ssl3_AppendHandshakeNumber(ss, extension_length - 4, 2);
 	if (rv != SECSuccess)
 	    goto loser;
-	rv = ssl3_AppendHandshakeVariable(ss, ss->opt.nextProtoNego.data,
-					  ss->opt.nextProtoNego.len, 2);
+	rv = ssl3_AppendHandshakeVariable(ss, alpn_protos, len, 2);
+	PORT_Free(alpn_protos);
+	alpn_protos = NULL;
 	if (rv != SECSuccess)
 	    goto loser;
 	ss->xtnData.advertised[ss->xtnData.numAdvertised++] =
@@ -755,6 +779,8 @@
     return extension_length;
 
 loser:
+    if (alpn_protos)
+	PORT_Free(alpn_protos);
     return -1;
 }
 
diff --git a/net/tools/flip_server/balsa_frame_test.cc b/net/tools/flip_server/balsa_frame_test.cc
new file mode 100644
index 0000000..3bb9a42
--- /dev/null
+++ b/net/tools/flip_server/balsa_frame_test.cc
@@ -0,0 +1,599 @@
+// 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/tools/flip_server/balsa_frame.h"
+
+#include <iterator>
+
+#include "base/memory/scoped_ptr.h"
+#include "base/strings/string_piece.h"
+#include "net/tools/flip_server/balsa_enums.h"
+#include "net/tools/flip_server/balsa_headers.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace net {
+
+namespace {
+
+using ::base::StringPiece;
+using ::testing::_;
+using ::testing::InSequence;
+using ::testing::SaveArg;
+
+class Visitor : public BalsaVisitorInterface {
+ public:
+  virtual ~Visitor() {}
+  MOCK_METHOD2(ProcessBodyInput, void(const char*, size_t));
+  MOCK_METHOD2(ProcessBodyData, void(const char*, size_t));
+  MOCK_METHOD2(ProcessHeaderInput, void(const char*, size_t));
+  MOCK_METHOD2(ProcessTrailerInput, void(const char*, size_t));
+  MOCK_METHOD1(ProcessHeaders, void(const BalsaHeaders&));
+  MOCK_METHOD8(ProcessRequestFirstLine, void(const char*,
+                                             size_t,
+                                             const char*,
+                                             size_t,
+                                             const char*,
+                                             size_t,
+                                             const char*,
+                                             size_t));
+  MOCK_METHOD8(ProcessResponseFirstLine, void(const char*,
+                                              size_t,
+                                              const char*,
+                                              size_t,
+                                              const char*,
+                                              size_t,
+                                              const char*,
+                                              size_t));
+  MOCK_METHOD2(ProcessChunkExtensions, void(const char*, size_t));
+  MOCK_METHOD1(ProcessChunkLength, void(size_t));
+  MOCK_METHOD0(HeaderDone, void());
+  MOCK_METHOD0(MessageDone, void());
+  MOCK_METHOD1(HandleHeaderError, void(BalsaFrame*));
+  MOCK_METHOD1(HandleHeaderWarning, void(BalsaFrame*));
+  MOCK_METHOD1(HandleChunkingError, void(BalsaFrame*));
+  MOCK_METHOD1(HandleBodyError, void(BalsaFrame*));
+};
+
+class BalsaFrameTest : public ::testing::Test {
+ public:
+  virtual void SetUp() OVERRIDE {
+    frame_.reset(new BalsaFrame);
+    frame_headers_.reset(new BalsaHeaders);
+    visitor_.reset(new Visitor);
+    frame_->set_balsa_visitor(visitor_.get());
+  };
+
+ protected:
+  scoped_ptr<BalsaFrame> frame_;
+  scoped_ptr<BalsaHeaders> frame_headers_;
+  scoped_ptr<Visitor> visitor_;
+};
+
+TEST_F(BalsaFrameTest, EmptyFrame) {
+  ASSERT_EQ(BalsaFrameEnums::READING_HEADER_AND_FIRSTLINE,
+            frame_->ParseState());
+  ASSERT_FALSE(frame_->MessageFullyRead());
+  ASSERT_FALSE(frame_->Error());
+  ASSERT_EQ(NULL, frame_->const_balsa_headers());
+  ASSERT_EQ(NULL, frame_->balsa_headers());
+  ASSERT_EQ(NULL, frame_->headers());
+  ASSERT_EQ(NULL, frame_->mutable_headers());
+  ASSERT_EQ(0u, frame_->BytesSafeToSplice());
+  ASSERT_TRUE(frame_->is_request());
+  ASSERT_FALSE(frame_->request_was_head());
+}
+
+TEST_F(BalsaFrameTest, EmptyRequest) {
+  const char input[] = "\r\n";
+  frame_->set_balsa_headers(frame_headers_.get());
+
+  {
+    InSequence s;
+    // No visitor callback should be called.
+  }
+  size_t read = frame_->ProcessInput(input, strlen(input));
+  EXPECT_EQ(2u, read);
+  ASSERT_EQ(BalsaFrameEnums::READING_HEADER_AND_FIRSTLINE,
+            frame_->ParseState());
+  ASSERT_FALSE(frame_->Error());
+  ASSERT_EQ(BalsaFrameEnums::NO_ERROR, frame_->ErrorCode());
+  ASSERT_EQ(0u, frame_->BytesSafeToSplice());
+}
+
+TEST_F(BalsaFrameTest, GetRequest) {
+  const char input[] = "GET / HTTP/1.0\r\nkey1: value1\r\n\r\n";
+  const char* line = NULL;
+  size_t line_length = 0;
+  const char* method = NULL;
+  size_t method_length = 0;
+  const char* request_uri = NULL;
+  size_t request_uri_length = 0;
+  const char* version = NULL;
+  size_t version_length = 0;
+  const char* header = NULL;
+  size_t header_length = 0;
+
+  {
+    InSequence s;
+    EXPECT_CALL(*visitor_, ProcessRequestFirstLine(_, _, _, _, _, _, _, _))
+        .WillOnce(DoAll(SaveArg<0>(&line),
+                        SaveArg<1>(&line_length),
+                        SaveArg<2>(&method),
+                        SaveArg<3>(&method_length),
+                        SaveArg<4>(&request_uri),
+                        SaveArg<5>(&request_uri_length),
+                        SaveArg<6>(&version),
+                        SaveArg<7>(&version_length)));
+    EXPECT_CALL(*visitor_, ProcessHeaderInput(_, _))
+        .WillOnce(DoAll(SaveArg<0>(&header), SaveArg<1>(&header_length)));
+    EXPECT_CALL(*visitor_, ProcessHeaders(_));
+    EXPECT_CALL(*visitor_, HeaderDone());
+    EXPECT_CALL(*visitor_, MessageDone());
+  }
+
+  frame_->set_balsa_headers(frame_headers_.get());
+  ASSERT_EQ(frame_headers_.get(), frame_->const_balsa_headers());
+  ASSERT_EQ(frame_headers_.get(), frame_->balsa_headers());
+  ASSERT_EQ(frame_headers_.get(), frame_->headers());
+  ASSERT_EQ(frame_headers_.get(), frame_->mutable_headers());
+
+  size_t read = frame_->ProcessInput(input, strlen(input));
+  ASSERT_EQ(strlen(input), read);
+  ASSERT_EQ(BalsaFrameEnums::MESSAGE_FULLY_READ, frame_->ParseState());
+  ASSERT_TRUE(frame_->MessageFullyRead());
+  ASSERT_FALSE(frame_->Error());
+  ASSERT_EQ(0u, frame_->BytesSafeToSplice());
+  ASSERT_EQ("GET / HTTP/1.0", StringPiece(line, line_length));
+  ASSERT_EQ("GET", StringPiece(method, method_length));
+  ASSERT_EQ("/", StringPiece(request_uri, request_uri_length));
+  ASSERT_EQ("HTTP/1.0", StringPiece(version, version_length));
+  ASSERT_EQ(input, StringPiece(header, header_length));
+}
+
+TEST_F(BalsaFrameTest, HeadResponse) {
+  const char input[] = "HTTP/1.1 200 OK\r\n"
+      "Content-type: text/plain\r\n"
+      "Content-Length: 14\r\n\r\n";
+  const char* line = NULL;
+  size_t line_length = 0;
+  const char* version = NULL;
+  size_t version_length = 0;
+  const char* status = NULL;
+  size_t status_length = 0;
+  const char* reason = NULL;
+  size_t reason_length = 0;
+  const char* header = NULL;
+  size_t header_length = 0;
+
+  frame_->set_balsa_headers(frame_headers_.get());
+  frame_->set_is_request(false);
+  frame_->set_request_was_head(true);
+
+  {
+    InSequence s;
+    EXPECT_CALL(*visitor_, ProcessResponseFirstLine(_, _, _, _, _, _, _, _))
+        .WillOnce(DoAll(SaveArg<0>(&line),
+                        SaveArg<1>(&line_length),
+                        SaveArg<2>(&version),
+                        SaveArg<3>(&version_length),
+                        SaveArg<4>(&status),
+                        SaveArg<5>(&status_length),
+                        SaveArg<6>(&reason),
+                        SaveArg<7>(&reason_length)));
+    EXPECT_CALL(*visitor_, ProcessHeaderInput(_, _))
+        .WillOnce(DoAll(SaveArg<0>(&header), SaveArg<1>(&header_length)));
+    EXPECT_CALL(*visitor_, ProcessHeaders(_));
+    EXPECT_CALL(*visitor_, HeaderDone());
+    EXPECT_CALL(*visitor_, MessageDone());
+  }
+
+  size_t read = frame_->ProcessInput(input, strlen(input));
+  ASSERT_EQ(strlen(input), read);
+  ASSERT_EQ(BalsaFrameEnums::MESSAGE_FULLY_READ, frame_->ParseState());
+  ASSERT_TRUE(frame_->MessageFullyRead());
+  ASSERT_FALSE(frame_->Error());
+  ASSERT_EQ(0u, frame_->BytesSafeToSplice());
+
+  ASSERT_EQ("HTTP/1.1 200 OK", StringPiece(line, line_length));
+  ASSERT_EQ("HTTP/1.1", StringPiece(version, version_length));
+  ASSERT_EQ("200", StringPiece(status, status_length));
+  ASSERT_EQ("OK", StringPiece(reason, reason_length));
+  ASSERT_EQ("HTTP/1.1 200 OK\r\n"
+            "Content-type: text/plain\r\n"
+            "Content-Length: 14\r\n\r\n",
+            StringPiece(header, header_length));
+}
+
+TEST_F(BalsaFrameTest, GetResponse) {
+  const char input[] = "HTTP/1.1 200 OK\r\n"
+      "Content-type: text/plain\r\n"
+      "Content-Length: 14\r\n\r\n"
+      "hello, world\r\n";
+  const char* line = NULL;
+  size_t line_length = 0;
+  const char* version = NULL;
+  size_t version_length = 0;
+  const char* status = NULL;
+  size_t status_length = 0;
+  const char* reason = NULL;
+  size_t reason_length = 0;
+  const char* header = NULL;
+  size_t header_length = 0;
+  const char* body = NULL;
+  size_t body_length = 0;
+  const char* body_data = NULL;
+  size_t body_data_length = 0;
+  testing::MockFunction<void(int)> checkpoint;
+
+  frame_->set_balsa_headers(frame_headers_.get());
+  frame_->set_is_request(false);
+
+  {
+    InSequence s;
+    EXPECT_CALL(*visitor_, ProcessResponseFirstLine(_, _, _, _, _, _, _, _))
+        .WillOnce(DoAll(SaveArg<0>(&line),
+                        SaveArg<1>(&line_length),
+                        SaveArg<2>(&version),
+                        SaveArg<3>(&version_length),
+                        SaveArg<4>(&status),
+                        SaveArg<5>(&status_length),
+                        SaveArg<6>(&reason),
+                        SaveArg<7>(&reason_length)));
+    EXPECT_CALL(*visitor_, ProcessHeaderInput(_, _))
+        .WillOnce(DoAll(SaveArg<0>(&header), SaveArg<1>(&header_length)));
+    EXPECT_CALL(*visitor_, ProcessHeaders(_));
+    EXPECT_CALL(*visitor_, HeaderDone());
+    EXPECT_CALL(checkpoint, Call(0));
+    EXPECT_CALL(*visitor_, ProcessBodyInput(_, _))
+        .WillOnce(DoAll(SaveArg<0>(&body), SaveArg<1>(&body_length)));
+    EXPECT_CALL(*visitor_, ProcessBodyData(_, _))
+        .WillOnce(DoAll(SaveArg<0>(&body_data), SaveArg<1>(&body_data_length)));
+    EXPECT_CALL(*visitor_, MessageDone());
+  }
+
+  size_t read = frame_->ProcessInput(input, strlen(input));
+  ASSERT_EQ(65u, read);
+  ASSERT_EQ(BalsaFrameEnums::READING_CONTENT, frame_->ParseState());
+  checkpoint.Call(0);
+  read += frame_->ProcessInput(&input[read], strlen(input) - read);
+  ASSERT_EQ(strlen(input), read);
+  ASSERT_EQ(BalsaFrameEnums::MESSAGE_FULLY_READ, frame_->ParseState());
+  ASSERT_TRUE(frame_->MessageFullyRead());
+  ASSERT_FALSE(frame_->Error());
+  ASSERT_EQ(0u, frame_->BytesSafeToSplice());
+
+  ASSERT_EQ("HTTP/1.1 200 OK", StringPiece(line, line_length));
+  ASSERT_EQ("HTTP/1.1", StringPiece(version, version_length));
+  ASSERT_EQ("200", StringPiece(status, status_length));
+  ASSERT_EQ("OK", StringPiece(reason, reason_length));
+  ASSERT_EQ("HTTP/1.1 200 OK\r\n"
+            "Content-type: text/plain\r\n"
+            "Content-Length: 14\r\n\r\n",
+            StringPiece(header, header_length));
+  ASSERT_EQ("hello, world\r\n", StringPiece(body, body_length));
+  ASSERT_EQ("hello, world\r\n", StringPiece(body_data, body_data_length));
+}
+
+TEST_F(BalsaFrameTest, Reset) {
+  const char input[] = "GET / HTTP/1.0\r\nkey1: value1\r\n\r\n";
+
+  {
+    InSequence s;
+    EXPECT_CALL(*visitor_, ProcessRequestFirstLine(_, _, _, _, _, _, _, _));
+    EXPECT_CALL(*visitor_, ProcessHeaderInput(_, _));
+    EXPECT_CALL(*visitor_, ProcessHeaders(_));
+    EXPECT_CALL(*visitor_, HeaderDone());
+    EXPECT_CALL(*visitor_, MessageDone());
+  }
+
+  frame_->set_balsa_headers(frame_headers_.get());
+
+  size_t read = frame_->ProcessInput(input, strlen(input));
+  ASSERT_EQ(strlen(input), read);
+  ASSERT_EQ(BalsaFrameEnums::MESSAGE_FULLY_READ, frame_->ParseState());
+  ASSERT_TRUE(frame_->MessageFullyRead());
+  ASSERT_FALSE(frame_->Error());
+
+  frame_->Reset();
+  ASSERT_EQ(BalsaFrameEnums::READING_HEADER_AND_FIRSTLINE,
+            frame_->ParseState());
+  ASSERT_FALSE(frame_->MessageFullyRead());
+  ASSERT_FALSE(frame_->Error());
+}
+
+TEST_F(BalsaFrameTest, InvalidStatusCode) {
+  const char input[] = "HTTP/1.1 InvalidStatusCode OK\r\n"
+      "Content-type: text/plain\r\n"
+      "Content-Length: 14\r\n\r\n"
+      "hello, world\r\n";
+
+  frame_->set_balsa_headers(frame_headers_.get());
+  frame_->set_is_request(false);
+
+  {
+    InSequence s;
+    EXPECT_CALL(*visitor_, HandleHeaderError(frame_.get()));
+  }
+
+  size_t read = frame_->ProcessInput(input, strlen(input));
+  ASSERT_EQ(30u, read);
+  ASSERT_EQ(BalsaFrameEnums::PARSE_ERROR, frame_->ParseState());
+  ASSERT_EQ(BalsaFrameEnums::FAILED_CONVERTING_STATUS_CODE_TO_INT,
+            frame_->ErrorCode());
+  ASSERT_FALSE(frame_->MessageFullyRead());
+  ASSERT_TRUE(frame_->Error());
+  ASSERT_EQ(0u, frame_->BytesSafeToSplice());
+}
+
+TEST_F(BalsaFrameTest, ResetError) {
+  const char input[] = "HTTP/1.1 InvalidStatusCode OK\r\n"
+      "Content-type: text/plain\r\n"
+      "Content-Length: 14\r\n\r\n"
+      "hello, world\r\n";
+
+  frame_->set_balsa_headers(frame_headers_.get());
+  frame_->set_is_request(false);
+
+  {
+    InSequence s;
+    EXPECT_CALL(*visitor_, HandleHeaderError(frame_.get()));
+  }
+
+  size_t read = frame_->ProcessInput(input, strlen(input));
+  ASSERT_EQ(30u, read);
+  ASSERT_EQ(BalsaFrameEnums::PARSE_ERROR, frame_->ParseState());
+  ASSERT_EQ(BalsaFrameEnums::FAILED_CONVERTING_STATUS_CODE_TO_INT,
+            frame_->ErrorCode());
+  ASSERT_FALSE(frame_->MessageFullyRead());
+  ASSERT_TRUE(frame_->Error());
+  ASSERT_EQ(0u, frame_->BytesSafeToSplice());
+
+  frame_->Reset();
+  ASSERT_EQ(BalsaFrameEnums::READING_HEADER_AND_FIRSTLINE,
+            frame_->ParseState());
+  ASSERT_FALSE(frame_->MessageFullyRead());
+  ASSERT_FALSE(frame_->Error());
+}
+
+TEST_F(BalsaFrameTest, RequestURITooLong) {
+  const char input[] = "GET / HTTP/1.0\r\n\r\n";
+
+  frame_->set_balsa_headers(frame_headers_.get());
+  frame_->set_max_request_uri_length(0);
+
+  {
+    InSequence s;
+    EXPECT_CALL(*visitor_, HandleHeaderError(frame_.get()));
+  }
+
+  size_t read = frame_->ProcessInput(input, strlen(input));
+  ASSERT_EQ(15u, read);
+  ASSERT_EQ(BalsaFrameEnums::PARSE_ERROR, frame_->ParseState());
+  ASSERT_EQ(BalsaFrameEnums::REQUEST_URI_TOO_LONG, frame_->ErrorCode());
+  ASSERT_FALSE(frame_->MessageFullyRead());
+  ASSERT_TRUE(frame_->Error());
+  ASSERT_EQ(0u, frame_->BytesSafeToSplice());
+}
+
+TEST_F(BalsaFrameTest, HeadersTooLong) {
+  const char input[] = "GET / HTTP/1.0\r\n\r\n";
+
+  frame_->set_balsa_headers(frame_headers_.get());
+  frame_->set_max_header_length(0);
+
+  {
+    InSequence s;
+    EXPECT_CALL(*visitor_, HandleHeaderError(frame_.get()));
+  }
+
+  size_t read = frame_->ProcessInput(input, strlen(input));
+  ASSERT_EQ(0u, read);
+  ASSERT_EQ(BalsaFrameEnums::PARSE_ERROR, frame_->ParseState());
+  ASSERT_EQ(BalsaFrameEnums::HEADERS_TOO_LONG, frame_->ErrorCode());
+  ASSERT_FALSE(frame_->MessageFullyRead());
+  ASSERT_TRUE(frame_->Error());
+  ASSERT_EQ(0u, frame_->BytesSafeToSplice());
+}
+
+TEST_F(BalsaFrameTest, InvalidHeader) {
+  const char input[] = "GET / HTTP/1.0\r\n"
+      "foo bar baz\r\n"
+      "Content-Type: text/plain\r\n\r\n";
+  const char* line = NULL;
+  size_t line_length = 0;
+  const char* method = NULL;
+  size_t method_length = 0;
+  const char* request_uri = NULL;
+  size_t request_uri_length = 0;
+  const char* version = NULL;
+  size_t version_length = 0;
+
+  frame_->set_balsa_headers(frame_headers_.get());
+
+  {
+    InSequence s;
+    EXPECT_CALL(*visitor_, ProcessRequestFirstLine(_, _, _, _, _, _, _, _))
+        .WillOnce(DoAll(SaveArg<0>(&line),
+                        SaveArg<1>(&line_length),
+                        SaveArg<2>(&method),
+                        SaveArg<3>(&method_length),
+                        SaveArg<4>(&request_uri),
+                        SaveArg<5>(&request_uri_length),
+                        SaveArg<6>(&version),
+                        SaveArg<7>(&version_length)));
+    EXPECT_CALL(*visitor_, ProcessHeaderInput(_, _));
+    EXPECT_CALL(*visitor_, HandleHeaderWarning(frame_.get()));
+    EXPECT_CALL(*visitor_, ProcessHeaders(_));
+    EXPECT_CALL(*visitor_, HeaderDone());
+    EXPECT_CALL(*visitor_, MessageDone());
+  }
+
+  size_t read = frame_->ProcessInput(input, strlen(input));
+  ASSERT_EQ(strlen(input), read);
+  ASSERT_EQ(BalsaFrameEnums::MESSAGE_FULLY_READ, frame_->ParseState());
+  ASSERT_EQ(BalsaFrameEnums::HEADER_MISSING_COLON, frame_->ErrorCode());
+  ASSERT_TRUE(frame_->MessageFullyRead());
+  ASSERT_FALSE(frame_->Error());
+  ASSERT_EQ(0u, frame_->BytesSafeToSplice());
+  ASSERT_EQ("GET / HTTP/1.0", StringPiece(line, line_length));
+  ASSERT_EQ("GET", StringPiece(method, method_length));
+  ASSERT_EQ("/", StringPiece(request_uri, request_uri_length));
+  ASSERT_EQ("HTTP/1.0", StringPiece(version, version_length));
+  ASSERT_EQ(2, std::distance(frame_headers_->header_lines_begin(),
+                              frame_headers_->header_lines_end()));
+}
+
+TEST_F(BalsaFrameTest, GetResponseSplit) {
+  const char input[] = "HTTP/1.1 200 OK\r\n"
+      "Content-type: text/plain\r\n"
+      "Content-Length: 14\r\n\r\n"
+      "hello";
+  const char input2[] = ", world\r\n";
+  const char* body1 = NULL;
+  size_t body1_length = 0;
+  const char* body1_data = NULL;
+  size_t body1_data_length = 0;
+  const char* body2 = NULL;
+  size_t body2_length = 0;
+  const char* body2_data = NULL;
+  size_t body2_data_length = 0;
+  testing::MockFunction<void(int)> checkpoint;
+
+  frame_->set_balsa_headers(frame_headers_.get());
+  frame_->set_is_request(false);
+
+  {
+    InSequence s;
+    EXPECT_CALL(*visitor_, ProcessResponseFirstLine(_, _, _, _, _, _, _, _));
+    EXPECT_CALL(*visitor_, ProcessHeaderInput(_, _));
+    EXPECT_CALL(*visitor_, ProcessHeaders(_));
+    EXPECT_CALL(*visitor_, HeaderDone());
+    EXPECT_CALL(checkpoint, Call(0));
+    EXPECT_CALL(*visitor_, ProcessBodyInput(_, _))
+        .WillOnce(DoAll(SaveArg<0>(&body1), SaveArg<1>(&body1_length)));
+    EXPECT_CALL(*visitor_, ProcessBodyData(_, _))
+        .WillOnce(DoAll(SaveArg<0>(&body1_data),
+                        SaveArg<1>(&body1_data_length)));
+    EXPECT_CALL(checkpoint, Call(1));
+    EXPECT_CALL(*visitor_, ProcessBodyInput(_, _))
+        .WillOnce(DoAll(SaveArg<0>(&body2), SaveArg<1>(&body2_length)));
+    EXPECT_CALL(*visitor_, ProcessBodyData(_, _))
+        .WillOnce(DoAll(SaveArg<0>(&body2_data),
+                        SaveArg<1>(&body2_data_length)));
+    EXPECT_CALL(*visitor_, MessageDone());
+  }
+
+  size_t read = frame_->ProcessInput(input, strlen(input));
+  ASSERT_EQ(65u, read);
+  ASSERT_EQ(BalsaFrameEnums::READING_CONTENT, frame_->ParseState());
+  checkpoint.Call(0);
+  read += frame_->ProcessInput(&input[read], strlen(input) - read);
+  ASSERT_EQ(strlen(input), read);
+  ASSERT_EQ(BalsaFrameEnums::READING_CONTENT, frame_->ParseState());
+  checkpoint.Call(1);
+  ASSERT_EQ(9u, frame_->BytesSafeToSplice());
+  read = frame_->ProcessInput(input2, strlen(input2));
+  ASSERT_EQ(strlen(input2), read);
+
+  ASSERT_EQ(BalsaFrameEnums::MESSAGE_FULLY_READ, frame_->ParseState());
+  ASSERT_TRUE(frame_->MessageFullyRead());
+  ASSERT_FALSE(frame_->Error());
+  ASSERT_EQ(0u, frame_->BytesSafeToSplice());
+  ASSERT_EQ("hello", StringPiece(body1, body1_length));
+  ASSERT_EQ("hello", StringPiece(body1_data, body1_data_length));
+  ASSERT_EQ(", world\r\n", StringPiece(body2, body2_length));
+  ASSERT_EQ(", world\r\n", StringPiece(body2_data, body2_data_length));
+}
+
+TEST_F(BalsaFrameTest, GetResponseBytesSpliced) {
+  const char input[] = "HTTP/1.1 200 OK\r\n"
+      "Content-type: text/plain\r\n"
+      "Content-Length: 14\r\n\r\n"
+      "hello";
+  testing::MockFunction<void(int)> checkpoint;
+
+  frame_->set_balsa_headers(frame_headers_.get());
+  frame_->set_is_request(false);
+
+  {
+    InSequence s;
+    EXPECT_CALL(*visitor_, ProcessResponseFirstLine(_, _, _, _, _, _, _, _));
+    EXPECT_CALL(*visitor_, ProcessHeaderInput(_, _));
+    EXPECT_CALL(*visitor_, ProcessHeaders(_));
+    EXPECT_CALL(*visitor_, HeaderDone());
+    EXPECT_CALL(checkpoint, Call(0));
+    EXPECT_CALL(*visitor_, ProcessBodyInput(_, _));
+    EXPECT_CALL(*visitor_, ProcessBodyData(_, _));
+    EXPECT_CALL(checkpoint, Call(1));
+    EXPECT_CALL(checkpoint, Call(2));
+    EXPECT_CALL(*visitor_, MessageDone());
+  }
+
+  size_t read = frame_->ProcessInput(input, strlen(input));
+  ASSERT_EQ(65u, read);
+  ASSERT_EQ(BalsaFrameEnums::READING_CONTENT, frame_->ParseState());
+  checkpoint.Call(0);
+  read += frame_->ProcessInput(&input[read], strlen(input) - read);
+  ASSERT_EQ(strlen(input), read);
+  ASSERT_EQ(BalsaFrameEnums::READING_CONTENT, frame_->ParseState());
+  ASSERT_EQ(9u, frame_->BytesSafeToSplice());
+  checkpoint.Call(1);
+  frame_->BytesSpliced(5);
+  ASSERT_EQ(BalsaFrameEnums::READING_CONTENT, frame_->ParseState());
+  ASSERT_EQ(4u, frame_->BytesSafeToSplice());
+  checkpoint.Call(2);
+  frame_->BytesSpliced(4);
+  ASSERT_EQ(BalsaFrameEnums::MESSAGE_FULLY_READ, frame_->ParseState());
+
+  ASSERT_TRUE(frame_->MessageFullyRead());
+  ASSERT_FALSE(frame_->Error());
+  ASSERT_EQ(0u, frame_->BytesSafeToSplice());
+}
+
+TEST_F(BalsaFrameTest, GetResponseBytesSplicedTooMany) {
+  const char input[] = "HTTP/1.1 200 OK\r\n"
+      "Content-type: text/plain\r\n"
+      "Content-Length: 14\r\n\r\n"
+      "hello";
+  testing::MockFunction<void(int)> checkpoint;
+
+  frame_->set_balsa_headers(frame_headers_.get());
+  frame_->set_is_request(false);
+
+  {
+    InSequence s;
+    EXPECT_CALL(*visitor_, ProcessResponseFirstLine(_, _, _, _, _, _, _, _));
+    EXPECT_CALL(*visitor_, ProcessHeaderInput(_, _));
+    EXPECT_CALL(*visitor_, ProcessHeaders(_));
+    EXPECT_CALL(*visitor_, HeaderDone());
+    EXPECT_CALL(checkpoint, Call(0));
+    EXPECT_CALL(*visitor_, ProcessBodyInput(_, _));
+    EXPECT_CALL(*visitor_, ProcessBodyData(_, _));
+    EXPECT_CALL(checkpoint, Call(1));
+    EXPECT_CALL(*visitor_, HandleBodyError(frame_.get()));
+  }
+
+  size_t read = frame_->ProcessInput(input, strlen(input));
+  ASSERT_EQ(65u, read);
+  ASSERT_EQ(BalsaFrameEnums::READING_CONTENT, frame_->ParseState());
+  checkpoint.Call(0);
+  read += frame_->ProcessInput(&input[read], strlen(input) - read);
+  ASSERT_EQ(strlen(input), read);
+  ASSERT_EQ(BalsaFrameEnums::READING_CONTENT, frame_->ParseState());
+  ASSERT_EQ(9u, frame_->BytesSafeToSplice());
+  checkpoint.Call(1);
+  frame_->BytesSpliced(99);
+  ASSERT_EQ(BalsaFrameEnums::PARSE_ERROR, frame_->ParseState());
+  ASSERT_FALSE(frame_->MessageFullyRead());
+  ASSERT_TRUE(frame_->Error());
+  ASSERT_EQ(
+      BalsaFrameEnums::CALLED_BYTES_SPLICED_AND_EXCEEDED_SAFE_SPLICE_AMOUNT,
+      frame_->ErrorCode());
+  ASSERT_EQ(0u, frame_->BytesSafeToSplice());
+}
+
+}  // namespace
+
+}  // namespace net
diff --git a/net/tools/flip_server/balsa_headers.h b/net/tools/flip_server/balsa_headers.h
index 6fabdd4..2c8b083 100644
--- a/net/tools/flip_server/balsa_headers.h
+++ b/net/tools/flip_server/balsa_headers.h
@@ -64,6 +64,7 @@
   // BalsaHeaders implementation, yet be testable.
   friend class BalsaBufferTestSpouse;
   friend class BalsaHeaders;
+  friend class BalsaBufferTest;
 
   // The BufferBlock is a structure used internally by the
   // BalsaBuffer class to store the base buffer pointers to
diff --git a/net/tools/flip_server/balsa_headers_test.cc b/net/tools/flip_server/balsa_headers_test.cc
new file mode 100644
index 0000000..241fee1
--- /dev/null
+++ b/net/tools/flip_server/balsa_headers_test.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.
+
+#include "net/tools/flip_server/balsa_headers.h"
+
+#include <iterator>
+#include <string>
+#include <vector>
+
+#include "base/memory/scoped_ptr.h"
+#include "base/strings/string_piece.h"
+#include "net/tools/flip_server/balsa_enums.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace net {
+
+using ::base::StringPiece;
+
+class BalsaBufferTest : public ::testing::Test {
+ public:
+  virtual void SetUp() OVERRIDE {
+    buffer_.reset(new BalsaBuffer);
+    anotherBuffer_.reset(new BalsaBuffer);
+  }
+
+ protected:
+  scoped_ptr<BalsaBuffer> buffer_;
+  scoped_ptr<BalsaBuffer> anotherBuffer_;
+};
+
+namespace {
+
+class BalsaHeadersTest: public ::testing::Test {
+ public:
+  virtual void SetUp() OVERRIDE {
+    headers_.reset(new BalsaHeaders);
+  }
+
+ protected:
+  scoped_ptr<BalsaHeaders> headers_;
+};
+
+class StringBuffer {
+ public:
+  void Write(const char* p, size_t size) {
+    string_ += std::string(p, size);
+  }
+  const std::string& string() {return string_;}
+
+ private:
+  std::string string_;
+};
+
+TEST_F(BalsaBufferTest, EmptyBuffer) {
+  ASSERT_EQ(1u, buffer_->num_blocks());
+}
+
+TEST_F(BalsaBufferTest, Write) {
+  size_t index1, index2;
+  StringPiece sp1 = buffer_->Write(StringPiece("hello"), &index1);
+  StringPiece sp2 = buffer_->Write(StringPiece(", world"), &index2);
+
+  ASSERT_EQ(2u, buffer_->num_blocks());
+  ASSERT_EQ("hello", sp1);
+  ASSERT_EQ(", world", sp2);
+  ASSERT_EQ(1u, index1);
+  ASSERT_EQ(1u, index2);
+  ASSERT_EQ("hello, world",
+            StringPiece(buffer_->GetPtr(1), buffer_->bytes_used(1)));
+}
+
+TEST_F(BalsaBufferTest, WriteLongData) {
+  size_t index1, index2, index3;
+  std::string as(2, 'a');
+  std::string bs(BalsaBuffer::kDefaultBlocksize + 1, 'b');
+  std::string cs(4, 'c');
+
+  StringPiece sp1 = buffer_->Write(as, &index1);
+  StringPiece sp2 = buffer_->Write(bs, &index2);
+  StringPiece sp3 = buffer_->Write(cs, &index3);
+
+  ASSERT_EQ(3u, buffer_->num_blocks());
+  ASSERT_EQ(as, sp1);
+  ASSERT_EQ(bs, sp2);
+  ASSERT_EQ(cs, sp3);
+  ASSERT_EQ(1u, index1);
+  ASSERT_EQ(2u, index2);
+  ASSERT_EQ(1u, index3);
+  ASSERT_EQ("aacccc", StringPiece(buffer_->GetPtr(1), buffer_->bytes_used(1)));
+  ASSERT_EQ(sp2, StringPiece(buffer_->GetPtr(2), buffer_->bytes_used(2)));
+}
+
+TEST_F(BalsaBufferTest, WriteToContiguousBuffer) {
+  std::string as(2, 'a');
+  std::string bs(BalsaBuffer::kDefaultBlocksize + 1, 'b');
+  std::string cs(4, 'c');
+
+  buffer_->WriteToContiguousBuffer(as);
+  buffer_->WriteToContiguousBuffer(bs);
+  buffer_->WriteToContiguousBuffer(cs);
+
+  ASSERT_EQ(1u, buffer_->num_blocks());
+  ASSERT_EQ(as + bs + cs,
+            StringPiece(buffer_->GetPtr(0), buffer_->bytes_used(0)));
+}
+
+TEST_F(BalsaBufferTest, NoMoreWriteToContiguousBuffer) {
+  size_t index1, index2;
+  StringPiece sp1 = buffer_->Write(StringPiece("hello"), &index1);
+  buffer_->NoMoreWriteToContiguousBuffer();
+  StringPiece sp2 = buffer_->Write(StringPiece(", world"), &index2);
+
+  ASSERT_EQ(2u, buffer_->num_blocks());
+  ASSERT_EQ("hello", sp1);
+  ASSERT_EQ(", world", sp2);
+  ASSERT_EQ(1u, index1);
+  ASSERT_EQ(0u, index2);
+  ASSERT_EQ(sp1, StringPiece(buffer_->GetPtr(1), buffer_->bytes_used(1)));
+  ASSERT_EQ(sp2, StringPiece(buffer_->GetPtr(0), buffer_->bytes_used(0)));
+}
+
+TEST_F(BalsaBufferTest, Clear) {
+  buffer_->Write("hello", NULL);
+  ASSERT_EQ(2u, buffer_->num_blocks());
+  buffer_->Clear();
+  ASSERT_EQ(1u, buffer_->num_blocks());
+}
+
+TEST_F(BalsaBufferTest, Swap) {
+  buffer_->Write("hello", NULL);
+
+  ASSERT_EQ(2u, buffer_->num_blocks());
+  ASSERT_EQ(1u, anotherBuffer_->num_blocks());
+
+  buffer_->Swap(anotherBuffer_.get());
+
+  ASSERT_EQ(1u, buffer_->num_blocks());
+  ASSERT_EQ(2u, anotherBuffer_->num_blocks());
+  ASSERT_EQ("hello",
+            StringPiece(anotherBuffer_->GetPtr(1),
+                        anotherBuffer_->bytes_used(1)));
+}
+
+TEST_F(BalsaBufferTest, CopyFrom) {
+  buffer_->Write("hello", NULL);
+
+  ASSERT_EQ(2u, buffer_->num_blocks());
+  ASSERT_EQ(1u, anotherBuffer_->num_blocks());
+
+  anotherBuffer_->CopyFrom(*buffer_);
+
+  ASSERT_EQ(2u, buffer_->num_blocks());
+  ASSERT_EQ(2u, anotherBuffer_->num_blocks());
+  ASSERT_EQ("hello", StringPiece(buffer_->GetPtr(1), buffer_->bytes_used(1)));
+  ASSERT_EQ("hello",
+            StringPiece(anotherBuffer_->GetPtr(1),
+                        anotherBuffer_->bytes_used(1)));
+}
+
+TEST_F(BalsaHeadersTest, AppendHeader) {
+  headers_->AppendHeader("key1", "value1");
+  headers_->AppendHeader("key2", "value2");
+  headers_->AppendHeader("key3", "value3");
+  headers_->AppendHeader("key3", "value3.1");
+  headers_->AppendHeader("key3", "value3.2");
+
+  ASSERT_EQ(5, std::distance(headers_->header_lines_begin(),
+                             headers_->header_lines_end()));
+  ASSERT_EQ("value1", headers_->GetHeader("key1"));
+  ASSERT_EQ("value2", headers_->GetHeader("key2"));
+  ASSERT_EQ("value3", headers_->GetHeader("key3"));
+
+  std::vector<base::StringPiece> v1, v2, v3;
+  std::string s1, s2, s3;
+  headers_->GetAllOfHeader("key1", &v1);
+  headers_->GetAllOfHeader("key2", &v2);
+  headers_->GetAllOfHeader("key3", &v3);
+  headers_->GetAllOfHeaderAsString("key1", &s1);
+  headers_->GetAllOfHeaderAsString("key2", &s2);
+  headers_->GetAllOfHeaderAsString("key3", &s3);
+
+  ASSERT_EQ(1u, v1.size());
+  ASSERT_EQ(1u, v2.size());
+  ASSERT_EQ(3u, v3.size());
+  ASSERT_EQ("value1", v1[0]);
+  ASSERT_EQ("value2", v2[0]);
+  ASSERT_EQ("value3", v3[0]);
+  ASSERT_EQ("value3.1", v3[1]);
+  ASSERT_EQ("value3.2", v3[2]);
+  ASSERT_EQ("value1", s1);
+  ASSERT_EQ("value2", s2);
+  ASSERT_EQ("value3,value3.1,value3.2", s3);
+}
+
+TEST_F(BalsaHeadersTest, ReplaceOrAppendHeader) {
+  headers_->ReplaceOrAppendHeader("key1", "value1");
+  headers_->ReplaceOrAppendHeader("key1", "value2");
+
+  ASSERT_EQ(1, std::distance(headers_->header_lines_begin(),
+                             headers_->header_lines_end()));
+  ASSERT_EQ("value2", headers_->GetHeader("key1"));
+
+  std::vector<base::StringPiece> v;
+  headers_->GetAllOfHeader("key1", &v);
+
+  ASSERT_EQ(1u, v.size());
+  ASSERT_EQ("value2", v[0]);
+}
+
+TEST_F(BalsaHeadersTest, AppendToHeader) {
+  headers_->AppendToHeader("key1", "value1");
+  headers_->AppendToHeader("keY1", "value2");
+
+  ASSERT_EQ(1, std::distance(headers_->header_lines_begin(),
+                             headers_->header_lines_end()));
+  ASSERT_EQ("value1,value2", headers_->GetHeader("key1"));
+
+  std::vector<base::StringPiece> v;
+  std::string s;
+  headers_->GetAllOfHeader("key1", &v);
+  headers_->GetAllOfHeaderAsString("keY1", &s);
+
+  ASSERT_EQ(1u, v.size());
+  ASSERT_EQ("value1,value2", v[0]);
+  ASSERT_EQ("value1,value2", s);
+}
+
+TEST_F(BalsaHeadersTest, PrepentToHeader) {
+  headers_->PrependToHeader("key1", "value1");
+  headers_->PrependToHeader("key1", "value2");
+
+  ASSERT_EQ(1, std::distance(headers_->header_lines_begin(),
+                             headers_->header_lines_end()));
+  ASSERT_EQ("value2,value1", headers_->GetHeader("key1"));
+
+  std::vector<base::StringPiece> v;
+  std::string s;
+  headers_->GetAllOfHeader("key1", &v);
+  headers_->GetAllOfHeaderAsString("key1", &s);
+
+  ASSERT_EQ(1u, v.size());
+  ASSERT_EQ("value2,value1", v[0]);
+  ASSERT_EQ("value2,value1", s);
+}
+
+TEST_F(BalsaHeadersTest, HasHeader) {
+  headers_->AppendHeader("key1", "value1");
+
+  ASSERT_TRUE(headers_->HasHeader("key1"));
+  ASSERT_FALSE(headers_->HasHeader("value1"));
+  ASSERT_FALSE(headers_->HasHeader("key2"));
+}
+
+TEST_F(BalsaHeadersTest, HasNonEmptyHeader) {
+  headers_->AppendHeader("key1", "value1");
+  headers_->AppendHeader("key2", "");
+
+  ASSERT_TRUE(headers_->HasNonEmptyHeader("key1"));
+  ASSERT_FALSE(headers_->HasNonEmptyHeader("key2"));
+  ASSERT_FALSE(headers_->HasNonEmptyHeader("key3"));
+}
+
+TEST_F(BalsaHeadersTest, GetHeaderPosition) {
+  headers_->AppendHeader("key1", "value1");
+  headers_->AppendHeader("key2", "value2");
+  headers_->AppendHeader("key3", "value3");
+
+  BalsaHeaders::const_header_lines_iterator i =
+      headers_->GetHeaderPosition("key2");
+
+  ASSERT_EQ(headers_->header_lines_end(),
+            headers_->GetHeaderPosition("foobar"));
+  ASSERT_EQ(headers_->header_lines_begin(),
+            headers_->GetHeaderPosition("key1"));
+  ASSERT_NE(headers_->header_lines_end(), i);
+  ASSERT_EQ("key2", i->first);
+  ASSERT_EQ("value2", i->second);
+  ++i;
+  ASSERT_EQ("key3", i->first);
+  ASSERT_EQ("value3", i->second);
+  ++i;
+  ASSERT_EQ(headers_->header_lines_end(), i);
+}
+
+TEST_F(BalsaHeadersTest, GetIteratorForKey) {
+  headers_->AppendHeader("key1", "value1");
+  headers_->AppendHeader("key2", "value2");
+  headers_->AppendHeader("key1", "value1.1");
+  headers_->AppendHeader("key3", "value3");
+  headers_->AppendHeader("KEY1", "value1.2");
+
+  BalsaHeaders::const_header_lines_key_iterator i =
+      headers_->GetIteratorForKey("key1");
+
+  ASSERT_EQ(headers_->header_lines_key_end(),
+            headers_->GetIteratorForKey("foobar"));
+  ASSERT_NE(headers_->header_lines_key_end(), i);
+  ASSERT_EQ("key1", i->first);
+  ASSERT_EQ("value1", i->second);
+  ++i;
+  ASSERT_EQ("key1", i->first);
+  ASSERT_EQ("value1.1", i->second);
+  ++i;
+  ASSERT_EQ("KEY1", i->first);
+  ASSERT_EQ("value1.2", i->second);
+  ++i;
+  ASSERT_EQ(headers_->header_lines_key_end(), i);
+}
+
+TEST_F(BalsaHeadersTest, RemoveAllOfHeader) {
+  headers_->AppendHeader("key1", "value1");
+  headers_->AppendHeader("key2", "value2");
+  headers_->AppendHeader("key1", "value1.1");
+  headers_->AppendHeader("key3", "value3");
+  headers_->AppendHeader("key1", "value1.2");
+  headers_->AppendHeader("kEY1", "value1.3");
+
+  ASSERT_EQ(6, std::distance(headers_->header_lines_begin(),
+                             headers_->header_lines_end()));
+  headers_->RemoveAllOfHeader("key1");
+  ASSERT_EQ(2, std::distance(headers_->header_lines_begin(),
+                             headers_->header_lines_end()));
+}
+
+TEST_F(BalsaHeadersTest, RemoveAllHeadersWithPrefix) {
+  headers_->AppendHeader("1key", "value1");
+  headers_->AppendHeader("2key", "value2");
+  headers_->AppendHeader("1kEz", "value1.1");
+  headers_->AppendHeader("key3", "value3");
+  headers_->AppendHeader("1KEEjkladf", "value1.2");
+
+  ASSERT_EQ(5, std::distance(headers_->header_lines_begin(),
+                             headers_->header_lines_end()));
+  headers_->RemoveAllHeadersWithPrefix("1ke");
+  ASSERT_EQ(2, std::distance(headers_->header_lines_begin(),
+                             headers_->header_lines_end()));
+}
+
+TEST_F(BalsaHeadersTest, WriteRequestHeaderAndEndingToBuffer) {
+  headers_->AppendHeader("key1", "value1");
+  headers_->AppendHeader("key2", "value2");
+  headers_->AppendHeader("key1", "value1.1");
+
+  headers_->SetRequestFirstlineFromStringPieces("GET", "/", "HTTP/1.0");
+
+  std::string expected = "GET / HTTP/1.0\r\n"
+      "key1: value1\r\n"
+      "key2: value2\r\n"
+      "key1: value1.1\r\n\r\n";
+  StringBuffer buffer;
+  headers_->WriteHeaderAndEndingToBuffer(&buffer);
+  ASSERT_EQ(expected, buffer.string());
+}
+
+TEST_F(BalsaHeadersTest, WriteResponseHeaderAndEndingToBuffer) {
+  headers_->AppendHeader("key1", "value1");
+  headers_->AppendHeader("key2", "value2");
+  headers_->AppendHeader("key1", "value1.1");
+
+  headers_->SetResponseFirstlineFromStringPieces("HTTP/1.0", "200", "OK");
+
+  std::string expected = "HTTP/1.0 200 OK\r\n"
+      "key1: value1\r\n"
+      "key2: value2\r\n"
+      "key1: value1.1\r\n\r\n";
+  StringBuffer buffer;
+  headers_->WriteHeaderAndEndingToBuffer(&buffer);
+  ASSERT_EQ(expected, buffer.string());
+}
+
+TEST_F(BalsaHeadersTest, RequestFirstLine) {
+  headers_->SetRequestFirstlineFromStringPieces("HEAD", "/path", "HTTP/1.1");
+
+  ASSERT_EQ("HEAD /path HTTP/1.1", headers_->first_line());
+  ASSERT_EQ("HEAD", headers_->request_method());
+  ASSERT_EQ("/path", headers_->request_uri());
+  ASSERT_EQ("HTTP/1.1", headers_->request_version());
+}
+
+TEST_F(BalsaHeadersTest, ResponseFirstLine) {
+  headers_->SetRequestFirstlineFromStringPieces("HTTP/1.0", "403", "FORBIDDEN");
+
+  ASSERT_EQ("HTTP/1.0 403 FORBIDDEN", headers_->first_line());
+  ASSERT_EQ("HTTP/1.0", headers_->response_version());
+  ASSERT_EQ("403", headers_->response_code());
+  ASSERT_EQ("FORBIDDEN", headers_->response_reason_phrase());
+}
+
+}  // namespace
+
+}  // namespace net
diff --git a/net/tools/flip_server/http_interface.cc b/net/tools/flip_server/http_interface.cc
index 9cd1331..7a44c03 100644
--- a/net/tools/flip_server/http_interface.cc
+++ b/net/tools/flip_server/http_interface.cc
@@ -332,13 +332,13 @@
   }
   if (!mci->transformed_header) {
     mci->bytes_sent = SendSynReply(mci->stream_id,
-                                   *(mci->file_data->headers));
+                                   *(mci->file_data->headers()));
     mci->transformed_header = true;
     VLOG(2) << ACCEPTOR_CLIENT_IDENT << "HttpSM: GetOutput transformed "
             << "header stream_id: [" << mci->stream_id << "]";
     return;
   }
-  if (mci->body_bytes_consumed >= mci->file_data->body.size()) {
+  if (mci->body_bytes_consumed >= mci->file_data->body().size()) {
     SendEOF(mci->stream_id);
     output_ordering_.RemoveStreamId(mci->stream_id);
     VLOG(2) << ACCEPTOR_CLIENT_IDENT << "GetOutput remove_stream_id: ["
@@ -346,12 +346,12 @@
     return;
   }
   size_t num_to_write =
-    mci->file_data->body.size() - mci->body_bytes_consumed;
+      mci->file_data->body().size() - mci->body_bytes_consumed;
   if (num_to_write > mci->max_segment_size)
     num_to_write = mci->max_segment_size;
 
   SendDataFrame(mci->stream_id,
-                mci->file_data->body.data() + mci->body_bytes_consumed,
+                mci->file_data->body().data() + mci->body_bytes_consumed,
                 num_to_write, 0, true);
   VLOG(2) << ACCEPTOR_CLIENT_IDENT << "HttpSM: GetOutput SendDataFrame["
           << mci->stream_id << "]: " << num_to_write;
@@ -360,4 +360,3 @@
 }
 
 }  // namespace net
-
diff --git a/net/tools/flip_server/mem_cache.cc b/net/tools/flip_server/mem_cache.cc
index 0af21e0..9249208 100644
--- a/net/tools/flip_server/mem_cache.cc
+++ b/net/tools/flip_server/mem_cache.cc
@@ -13,15 +13,19 @@
 #include <unistd.h>
 
 #include <deque>
+#include <map>
+#include <string>
 
-#include "base/strings/string_piece.h"
+#include "base/strings/string_util.h"
 #include "net/tools/dump_cache/url_to_filename_encoder.h"
 #include "net/tools/dump_cache/url_utilities.h"
 #include "net/tools/flip_server/balsa_frame.h"
 #include "net/tools/flip_server/balsa_headers.h"
 
+namespace {
 // The directory where cache locates);
-std::string FLAGS_cache_base_dir = ".";
+const char FLAGS_cache_base_dir[] = ".";
+}  // namespace
 
 namespace net {
 
@@ -46,40 +50,36 @@
   HandleError();
 }
 
-FileData::FileData(BalsaHeaders* h, const std::string& b)
-    : headers(h), body(b) {
+FileData::FileData(const BalsaHeaders* headers,
+                   const std::string& filename,
+                   const std::string& body)
+    : filename_(filename)
+    , body_(body) {
+  if (headers) {
+    headers_.reset(new BalsaHeaders);
+    headers_->CopyFrom(*headers);
+  }
 }
 
 FileData::FileData() {}
 
 FileData::~FileData() {}
 
-void FileData::CopyFrom(const FileData& file_data) {
-    headers = new BalsaHeaders;
-    headers->CopyFrom(*(file_data.headers));
-    filename = file_data.filename;
-    related_files = file_data.related_files;
-    body = file_data.body;
-  }
+MemoryCache::MemoryCache() : cwd_(FLAGS_cache_base_dir) {}
 
-MemoryCache::MemoryCache() {}
-
-MemoryCache::~MemoryCache() {}
+MemoryCache::~MemoryCache() {
+  ClearFiles();
+}
 
 void MemoryCache::CloneFrom(const MemoryCache& mc) {
-  for (Files::const_iterator i = mc.files_.begin();
-       i != mc.files_.end();
-       ++i) {
-    Files::iterator out_i =
-        files_.insert(make_pair(i->first, FileData())).first;
-    out_i->second.CopyFrom(i->second);
-    cwd_ = mc.cwd_;
-  }
+  DCHECK_NE(this, &mc);
+  ClearFiles();
+  files_ = mc.files_;
+  cwd_ = mc.cwd_;
 }
 
 void MemoryCache::AddFiles() {
   std::deque<std::string> paths;
-  cwd_ = FLAGS_cache_base_dir;
   paths.push_back(cwd_ + "/GET_");
   DIR* current_dir = NULL;
   while (!paths.empty()) {
@@ -192,24 +192,33 @@
                                "Fri, 30 Aug, 2019 12:00:00 GMT");
   }
 #endif
-  BalsaHeaders* headers = new BalsaHeaders;
-  headers->CopyFrom(visitor.headers);
+  DCHECK_GE(std::string(filename).size(), cwd_.size() + 1);
+  DCHECK_EQ(std::string(filename).substr(0, cwd_.size()), cwd_);
+  DCHECK_EQ(filename[cwd_.size()], '/');
   std::string filename_stripped = std::string(filename).substr(cwd_.size() + 1);
   LOG(INFO) << "Adding file (" << visitor.body.length() << " bytes): "
             << filename_stripped;
-  files_[filename_stripped] = FileData();
-  FileData& fd = files_[filename_stripped];
-  fd = FileData(headers, visitor.body);
-  fd.filename = std::string(filename_stripped,
-                            filename_stripped.find_first_of('/'));
+  size_t slash_pos = filename_stripped.find('/');
+  if (slash_pos == std::string::npos) {
+    slash_pos = filename_stripped.size();
+  }
+  FileData* data =
+      new FileData(&visitor.headers,
+                   filename_stripped.substr(0, slash_pos),
+                   visitor.body);
+  Files::iterator it = files_.find(filename_stripped);
+  if (it != files_.end()) {
+    delete it->second;
+    it->second = data;
+  } else {
+    files_.insert(std::make_pair(filename_stripped, data));
+  }
 }
 
 FileData* MemoryCache::GetFileData(const std::string& filename) {
   Files::iterator fi = files_.end();
-  if (filename.compare(filename.length() - 5, 5, ".html", 5) == 0) {
-    std::string new_filename(filename.data(), filename.size() - 5);
-    new_filename += ".http";
-    fi = files_.find(new_filename);
+  if (EndsWith(filename, ".html", true)) {
+    fi = files_.find(filename.substr(0, filename.size() - 5) + ".http");
   }
   if (fi == files_.end())
     fi = files_.find(filename);
@@ -217,7 +226,7 @@
   if (fi == files_.end()) {
     return NULL;
   }
-  return &(fi->second);
+  return fi->second;
 }
 
 bool MemoryCache::AssignFileData(const std::string& filename,
@@ -230,5 +239,11 @@
   return true;
 }
 
-}  // namespace net
+void MemoryCache::ClearFiles() {
+  for (Files::const_iterator i = files_.begin(); i != files_.end(); ++i) {
+    delete i->second;
+  }
+  files_.clear();
+}
 
+}  // namespace net
diff --git a/net/tools/flip_server/mem_cache.h b/net/tools/flip_server/mem_cache.h
index cf5b9bd..806ae53 100644
--- a/net/tools/flip_server/mem_cache.h
+++ b/net/tools/flip_server/mem_cache.h
@@ -7,9 +7,9 @@
 
 #include <map>
 #include <string>
-#include <vector>
 
 #include "base/compiler_specific.h"
+#include "base/memory/scoped_ptr.h"
 #include "net/tools/flip_server/balsa_headers.h"
 #include "net/tools/flip_server/balsa_visitor_interface.h"
 #include "net/tools/flip_server/constants.h"
@@ -61,18 +61,26 @@
 };
 
 ////////////////////////////////////////////////////////////////////////////////
-
-struct FileData {
+class FileData {
+ public:
   FileData();
-  FileData(BalsaHeaders* h, const std::string& b);
+  FileData(const BalsaHeaders* headers,
+           const std::string& filename,
+           const std::string& body);
   ~FileData();
-  void CopyFrom(const FileData& file_data);
 
-  BalsaHeaders* headers;
-  std::string filename;
-  // priority, filename
-  std::vector< std::pair<int, std::string> > related_files;
-  std::string body;
+  BalsaHeaders* headers() { return headers_.get(); }
+  const BalsaHeaders* headers() const { return headers_.get(); }
+
+  const std::string& filename() { return filename_; }
+  const std::string& body() { return body_; }
+
+ private:
+  scoped_ptr<BalsaHeaders> headers_;
+  std::string filename_;
+  std::string body_;
+
+  DISALLOW_COPY_AND_ASSIGN(FileData);
 };
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -108,17 +116,18 @@
 
 class MemoryCache {
  public:
-  typedef std::map<std::string, FileData> Files;
+  typedef std::map<std::string, FileData*> Files;
 
  public:
   MemoryCache();
-  ~MemoryCache();
+  virtual ~MemoryCache();
 
   void CloneFrom(const MemoryCache& mc);
 
   void AddFiles();
 
-  void ReadToString(const char* filename, std::string* output);
+  // virtual for unittests
+  virtual void ReadToString(const char* filename, std::string* output);
 
   void ReadAndStoreFileContents(const char* filename);
 
@@ -126,6 +135,9 @@
 
   bool AssignFileData(const std::string& filename, MemCacheIter* mci);
 
+ private:
+  void ClearFiles();
+
   Files files_;
   std::string cwd_;
 };
@@ -139,4 +151,3 @@
 }  // namespace net
 
 #endif  // NET_TOOLS_FLIP_SERVER_MEM_CACHE_H_
-
diff --git a/net/tools/flip_server/mem_cache_test.cc b/net/tools/flip_server/mem_cache_test.cc
new file mode 100644
index 0000000..d5601ac
--- /dev/null
+++ b/net/tools/flip_server/mem_cache_test.cc
@@ -0,0 +1,98 @@
+// 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/tools/flip_server/mem_cache.h"
+
+#include "net/tools/flip_server/balsa_headers.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace net {
+
+namespace {
+
+class MemoryCacheWithFakeReadToString : public MemoryCache {
+ public:
+  virtual ~MemoryCacheWithFakeReadToString() {}
+
+  virtual void ReadToString(const char* filename, std::string* output)
+      OVERRIDE {
+    *output = data_map_[filename];
+  }
+
+  std::map<std::string, std::string> data_map_;
+};
+
+class FlipMemoryCacheTest : public ::testing::Test {
+ public:
+  FlipMemoryCacheTest(): mem_cache_(new MemoryCacheWithFakeReadToString) {}
+
+ protected:
+  scoped_ptr<MemoryCacheWithFakeReadToString> mem_cache_;
+};
+
+TEST_F(FlipMemoryCacheTest, EmptyCache) {
+  MemCacheIter mci;
+  mci.stream_id = 0;
+  ASSERT_EQ(NULL, mem_cache_->GetFileData("./foo"));
+  ASSERT_EQ(NULL, mem_cache_->GetFileData("./bar"));
+  ASSERT_FALSE(mem_cache_->AssignFileData("./hello", &mci));
+}
+
+TEST_F(FlipMemoryCacheTest, ReadAndStoreFileContents) {
+  FileData* foo;
+  FileData* hello;
+
+  mem_cache_->data_map_["./foo"] = "bar";
+  mem_cache_->data_map_["./hello"] = "HTTP/1.0 200 OK\r\n"
+      "key1: value1\r\n"
+      "key2: value2\r\n\r\n"
+      "body: body\r\n";
+  mem_cache_->ReadAndStoreFileContents("./foo");
+  mem_cache_->ReadAndStoreFileContents("./hello");
+
+  foo = mem_cache_->GetFileData("foo");
+  hello = mem_cache_->GetFileData("hello");
+
+  // "./foo" content is broken.
+  ASSERT_EQ(NULL, foo);
+  ASSERT_FALSE(NULL == hello);
+  ASSERT_EQ(hello, mem_cache_->GetFileData("hello"));
+
+  // "HTTP/1.0" is rewritten to "HTTP/1.1".
+  ASSERT_EQ("HTTP/1.1", hello->headers()->response_version());
+  ASSERT_EQ("200", hello->headers()->response_code());
+  ASSERT_EQ("OK", hello->headers()->response_reason_phrase());
+  ASSERT_EQ(4, std::distance(hello->headers()->header_lines_begin(),
+                             hello->headers()->header_lines_end()));
+  ASSERT_TRUE(hello->headers()->HasHeader("key1"));
+  ASSERT_TRUE(hello->headers()->HasHeader("key2"));
+  ASSERT_TRUE(hello->headers()->HasHeader("transfer-encoding"));
+  ASSERT_TRUE(hello->headers()->HasHeader("connection"));
+  ASSERT_EQ("value1", hello->headers()->GetHeaderPosition("key1")->second);
+  ASSERT_EQ("value2", hello->headers()->GetHeaderPosition("key2")->second);
+  ASSERT_EQ("chunked",
+            hello->headers()->GetHeaderPosition("transfer-encoding")->second);
+  ASSERT_EQ("keep-alive",
+            hello->headers()->GetHeaderPosition("connection")->second);
+  ASSERT_EQ("body: body\r\n", hello->body());
+  ASSERT_EQ("hello", hello->filename());
+}
+
+TEST_F(FlipMemoryCacheTest, GetFileDataForHtmlFile) {
+  FileData* hello_html;
+
+  mem_cache_->data_map_["./hello.http"] = "HTTP/1.0 200 OK\r\n"
+      "key1: value1\r\n"
+      "key2: value2\r\n\r\n"
+      "body: body\r\n";
+
+  mem_cache_->ReadAndStoreFileContents("./hello.http");
+  hello_html = mem_cache_->GetFileData("hello.html");
+  ASSERT_FALSE(NULL == hello_html);
+  ASSERT_EQ(hello_html, mem_cache_->GetFileData("hello.http"));
+}
+
+}  // namespace
+
+}  // namespace net
diff --git a/net/tools/flip_server/output_ordering.cc b/net/tools/flip_server/output_ordering.cc
index dd11962..22fd08a 100644
--- a/net/tools/flip_server/output_ordering.cc
+++ b/net/tools/flip_server/output_ordering.cc
@@ -99,14 +99,14 @@
 
   double think_time_in_s = server_think_time_in_s_;
   std::string x_server_latency =
-    mci.file_data->headers->GetHeader("X-Server-Latency").as_string();
+      mci.file_data->headers()->GetHeader("X-Server-Latency").as_string();
   if (!x_server_latency.empty()) {
     char* endp;
     double tmp_think_time_in_s = strtod(x_server_latency.c_str(), &endp);
     if (endp != x_server_latency.c_str() + x_server_latency.size()) {
       LOG(ERROR) << "Unable to understand X-Server-Latency of: "
                  << x_server_latency << " for resource: "
-                 <<  mci.file_data->filename.c_str();
+                 <<  mci.file_data->filename().c_str();
     } else {
       think_time_in_s = tmp_think_time_in_s;
     }
diff --git a/net/tools/flip_server/spdy_interface.cc b/net/tools/flip_server/spdy_interface.cc
index 16023a5..b4e36be 100644
--- a/net/tools/flip_server/spdy_interface.cc
+++ b/net/tools/flip_server/spdy_interface.cc
@@ -521,43 +521,43 @@
         // this is a server initiated stream.
         // Ideally, we'd do a 'syn-push' here, instead of a syn-reply.
         BalsaHeaders headers;
-        headers.CopyFrom(*(mci->file_data->headers));
+        headers.CopyFrom(*(mci->file_data->headers()));
         headers.ReplaceOrAppendHeader("status", "200");
         headers.ReplaceOrAppendHeader("version", "http/1.1");
         headers.SetRequestFirstlineFromStringPieces("PUSH",
-                                                    mci->file_data->filename,
+                                                    mci->file_data->filename(),
                                                     "");
         mci->bytes_sent = SendSynStream(mci->stream_id, headers);
       } else {
         BalsaHeaders headers;
-        headers.CopyFrom(*(mci->file_data->headers));
+        headers.CopyFrom(*(mci->file_data->headers()));
         mci->bytes_sent = SendSynReply(mci->stream_id, headers);
       }
       return;
     }
-    if (mci->body_bytes_consumed >= mci->file_data->body.size()) {
+    if (mci->body_bytes_consumed >= mci->file_data->body().size()) {
       VLOG(2) << ACCEPTOR_CLIENT_IDENT << "SpdySM: GetOutput "
               << "remove_stream_id: [" << mci->stream_id << "]";
       SendEOF(mci->stream_id);
       return;
     }
     size_t num_to_write =
-      mci->file_data->body.size() - mci->body_bytes_consumed;
+        mci->file_data->body().size() - mci->body_bytes_consumed;
     if (num_to_write > mci->max_segment_size)
       num_to_write = mci->max_segment_size;
 
     bool should_compress = false;
-    if (!mci->file_data->headers->HasHeader("content-encoding")) {
-      if (mci->file_data->headers->HasHeader("content-type")) {
+    if (!mci->file_data->headers()->HasHeader("content-encoding")) {
+      if (mci->file_data->headers()->HasHeader("content-type")) {
         std::string content_type =
-            mci->file_data->headers->GetHeader("content-type").as_string();
+            mci->file_data->headers()->GetHeader("content-type").as_string();
         if (content_type.find("image") == content_type.npos)
           should_compress = true;
       }
     }
 
     SendDataFrame(mci->stream_id,
-                  mci->file_data->body.data() + mci->body_bytes_consumed,
+                  mci->file_data->body().data() + mci->body_bytes_consumed,
                   num_to_write, 0, should_compress);
     VLOG(2) << ACCEPTOR_CLIENT_IDENT << "SpdySM: GetOutput SendDataFrame["
             << mci->stream_id << "]: " << num_to_write;
diff --git a/net/tools/quic/end_to_end_test.cc b/net/tools/quic/end_to_end_test.cc
index 40449b3..65e50f7 100644
--- a/net/tools/quic/end_to_end_test.cc
+++ b/net/tools/quic/end_to_end_test.cc
@@ -422,9 +422,15 @@
     return;
   }
 
-  // FLAGS_fake_packet_loss_percentage = 30;
+  // Connect with lower fake packet loss than we'd like to test.  Until
+  // b/10126687 is fixed, losing handshake packets is pretty brutal.
+  // FLAGS_fake_packet_loss_percentage = 5;
   ASSERT_TRUE(Initialize());
 
+  // Wait for the server SHLO before upping the packet loss.
+  client_->client()->WaitForCryptoHandshakeConfirmed();
+  // FLAGS_fake_packet_loss_percentage = 30;
+
   string body;
   GenerateBody(&body, 10240);
 
@@ -493,7 +499,7 @@
   HTTPMessage request(HttpConstants::HTTP_1_1,
                       HttpConstants::POST, "/foo");
   request.AddBody(body, true);
-  // Force the client to write with a stream ID belonging to a nonexistant
+  // Force the client to write with a stream ID belonging to a nonexistent
   // server-side stream.
   QuicSessionPeer::SetNextStreamId(client_->client()->session(), 2);
 
diff --git a/net/tools/quic/quic_epoll_connection_helper.cc b/net/tools/quic/quic_epoll_connection_helper.cc
index ba72087..4db1d4c 100644
--- a/net/tools/quic/quic_epoll_connection_helper.cc
+++ b/net/tools/quic/quic_epoll_connection_helper.cc
@@ -17,80 +17,50 @@
 namespace net {
 namespace tools {
 
-// This alarm will be scheduled any time a data-bearing packet is sent out.
-// When the alarm goes off, the connection checks to see if the oldest packets
-// have been acked, and retransmit them if they have not.
-class RetransmissionAlarm : public EpollAlarm {
+namespace {
+
+class QuicEpollAlarm : public QuicAlarm {
  public:
-  explicit RetransmissionAlarm(QuicConnection* connection)
-      : connection_(connection) {
+  QuicEpollAlarm(EpollServer* epoll_server,
+                 QuicAlarm::Delegate* delegate)
+      : QuicAlarm(delegate),
+        epoll_server_(epoll_server),
+        epoll_alarm_impl_(this) {}
+
+ protected:
+  virtual void SetImpl() OVERRIDE {
+    DCHECK(deadline().IsInitialized());
+    epoll_server_->RegisterAlarm(
+        deadline().Subtract(QuicTime::Zero()).ToMicroseconds(),
+        &epoll_alarm_impl_);
   }
 
-  virtual int64 OnAlarm() OVERRIDE {
-    EpollAlarm::OnAlarm();
-    // This is safe because this code is Google3 specific, and the
-    // Google3 QuicTime's epoch is the unix epoch.
-    return connection_->OnRetransmissionTimeout().Subtract(
-        QuicTime::Zero()).ToMicroseconds();
+  virtual void CancelImpl() OVERRIDE {
+    DCHECK(!deadline().IsInitialized());
+    epoll_alarm_impl_.UnregisterIfRegistered();
   }
 
  private:
-  QuicConnection* connection_;
+  class EpollAlarmImpl : public EpollAlarm {
+   public:
+    explicit EpollAlarmImpl(QuicEpollAlarm* alarm) : alarm_(alarm) {}
+
+    virtual int64 OnAlarm() OVERRIDE {
+      EpollAlarm::OnAlarm();
+      alarm_->Fire();
+      // Fire will take care of registering the alarm, if needed.
+      return 0;
+    }
+
+   private:
+    QuicEpollAlarm* alarm_;
+  };
+
+  EpollServer* epoll_server_;
+  EpollAlarmImpl epoll_alarm_impl_;
 };
 
-// An alarm that is scheduled when the sent scheduler requires a
-// a delay before sending packets and fires when the packet may be sent.
-class SendAlarm : public EpollAlarm {
- public:
-  explicit SendAlarm(QuicConnection* connection)
-      : connection_(connection) {
-  }
-
-  virtual int64 OnAlarm() OVERRIDE {
-    EpollAlarm::OnAlarm();
-    connection_->OnCanWrite();
-    // Never reschedule the alarm, since OnCanWrite does that.
-    return 0;
-  }
-
- private:
-  QuicConnection* connection_;
-};
-
-// An alarm which fires when the connection may have timed out.
-class TimeoutAlarm : public EpollAlarm {
- public:
-  explicit TimeoutAlarm(QuicConnection* connection)
-      : connection_(connection) {
-  }
-
-  virtual int64 OnAlarm() OVERRIDE {
-    EpollAlarm::OnAlarm();
-    connection_->CheckForTimeout();
-    // Never reschedule the alarm, since CheckForTimeout does that.
-    return 0;
-  }
-
- private:
-  QuicConnection* connection_;
-};
-
-// An alarm that is scheduled to send an ack if a timeout occurs.
-class AckAlarm : public EpollAlarm {
- public:
-  explicit AckAlarm(QuicConnection* connection)
-      : connection_(connection) {
-  }
-
-  virtual int64 OnAlarm() OVERRIDE {
-    EpollAlarm::OnAlarm();
-    connection_->SendAck();
-    return 0;
-  }
-
- private:
-  QuicConnection* connection_;
-};
+}  // namespace
 
 QuicEpollConnectionHelper::QuicEpollConnectionHelper(
   int fd, EpollServer* epoll_server)
@@ -118,10 +88,6 @@
 void QuicEpollConnectionHelper::SetConnection(QuicConnection* connection) {
   DCHECK(!connection_);
   connection_ = connection;
-  timeout_alarm_.reset(new TimeoutAlarm(connection));
-  send_alarm_.reset(new SendAlarm(connection));
-  ack_alarm_.reset(new AckAlarm(connection));
-  retransmission_alarm_.reset(new RetransmissionAlarm(connection_));
 }
 
 const QuicClock* QuicEpollConnectionHelper::GetClock() const {
@@ -165,43 +131,9 @@
   return error == EAGAIN || error == EWOULDBLOCK;
 }
 
-void QuicEpollConnectionHelper::SetRetransmissionAlarm(QuicTime::Delta delay) {
-  if (!retransmission_alarm_->registered()) {
-    epoll_server_->RegisterAlarmApproximateDelta(delay.ToMicroseconds(),
-                                                 retransmission_alarm_.get());
-  }
-}
-
-void QuicEpollConnectionHelper::SetAckAlarm(QuicTime::Delta delay) {
-  if (!ack_alarm_->registered()) {
-    epoll_server_->RegisterAlarmApproximateDelta(
-        delay.ToMicroseconds(), ack_alarm_.get());
-  }
-}
-
-void QuicEpollConnectionHelper::ClearAckAlarm() {
-  ack_alarm_->UnregisterIfRegistered();
-}
-
-void QuicEpollConnectionHelper::SetSendAlarm(QuicTime alarm_time) {
-  send_alarm_->UnregisterIfRegistered();
-  epoll_server_->RegisterAlarm(
-      alarm_time.Subtract(QuicTime::Zero()).ToMicroseconds(),
-      send_alarm_.get());
-}
-
-void QuicEpollConnectionHelper::SetTimeoutAlarm(QuicTime::Delta delay) {
-  timeout_alarm_->UnregisterIfRegistered();
-  epoll_server_->RegisterAlarmApproximateDelta(delay.ToMicroseconds(),
-                                               timeout_alarm_.get());
-}
-
-bool QuicEpollConnectionHelper::IsSendAlarmSet() {
-  return send_alarm_->registered();
-}
-
-void QuicEpollConnectionHelper::UnregisterSendAlarmIfRegistered() {
-  send_alarm_->UnregisterIfRegistered();
+QuicAlarm* QuicEpollConnectionHelper::CreateAlarm(
+    QuicAlarm::Delegate* delegate) {
+  return new QuicEpollAlarm(epoll_server_, delegate);
 }
 
 }  // namespace tools
diff --git a/net/tools/quic/quic_epoll_connection_helper.h b/net/tools/quic/quic_epoll_connection_helper.h
index 9ddef2f..5bd526f 100644
--- a/net/tools/quic/quic_epoll_connection_helper.h
+++ b/net/tools/quic/quic_epoll_connection_helper.h
@@ -11,7 +11,6 @@
 #include <sys/types.h>
 #include <set>
 
-#include "base/memory/scoped_ptr.h"
 #include "net/quic/quic_connection.h"
 #include "net/quic/quic_protocol.h"
 #include "net/quic/quic_time.h"
@@ -48,13 +47,7 @@
                                 int* error) OVERRIDE;
   virtual bool IsWriteBlockedDataBuffered() OVERRIDE;
   virtual bool IsWriteBlocked(int error) OVERRIDE;
-  virtual void SetRetransmissionAlarm(QuicTime::Delta delay) OVERRIDE;
-  virtual void SetSendAlarm(QuicTime alarm_time) OVERRIDE;
-  virtual void SetTimeoutAlarm(QuicTime::Delta delay) OVERRIDE;
-  virtual bool IsSendAlarmSet() OVERRIDE;
-  virtual void UnregisterSendAlarmIfRegistered() OVERRIDE;
-  virtual void SetAckAlarm(QuicTime::Delta delay) OVERRIDE;
-  virtual void ClearAckAlarm() OVERRIDE;
+  virtual QuicAlarm* CreateAlarm(QuicAlarm::Delegate* delegate) OVERRIDE;
 
   EpollServer* epoll_server() { return epoll_server_; }
 
@@ -66,18 +59,6 @@
   EpollServer* epoll_server_;  // Not owned.
   int fd_;
 
-  // An alarm which fires if we've hit a timeout on sending an ack.
-  scoped_ptr<AckAlarm> ack_alarm_;
-
-  scoped_ptr<RetransmissionAlarm> retransmission_alarm_;
-
-  // An alarm which fires when the connection may have timed out.
-  scoped_ptr<TimeoutAlarm> timeout_alarm_;
-
-  // An alarm that is scheduled when the sent scheduler requires a
-  // a delay before sending packets and fires when the packet may be sent.
-  scoped_ptr<SendAlarm> send_alarm_;
-
   QuicConnection* connection_;
   const QuicEpollClock clock_;
   QuicRandom* random_generator_;
diff --git a/net/tools/quic/quic_time_wait_list_manager.cc b/net/tools/quic/quic_time_wait_list_manager.cc
index fe538e9..a2fc4f8 100644
--- a/net/tools/quic/quic_time_wait_list_manager.cc
+++ b/net/tools/quic/quic_time_wait_list_manager.cc
@@ -275,7 +275,8 @@
     if (error == EAGAIN || error == EWOULDBLOCK) {
       is_write_blocked_ = true;
     } else {
-      LOG(WARNING) << "Received unknown error while sending reset packet:"
+      LOG(WARNING) << "Received unknown error while sending reset packet to "
+                   << queued_packet->client_address().ToString() << ": "
                    << strerror(error);
     }
   }
diff --git a/net/tools/quic/test_tools/quic_test_client.cc b/net/tools/quic/test_tools/quic_test_client.cc
index 03600f2..859d7a5 100644
--- a/net/tools/quic/test_tools/quic_test_client.cc
+++ b/net/tools/quic/test_tools/quic_test_client.cc
@@ -26,6 +26,7 @@
  public:
   // ProofVerifier interface.
   virtual net::ProofVerifier::Status VerifyProof(
+      net::QuicVersion version,
       const string& hostname,
       const string& server_config,
       const vector<string>& certs,
diff --git a/ppapi/DEPS b/ppapi/DEPS
index 7d05cd9..4b60426 100644
--- a/ppapi/DEPS
+++ b/ppapi/DEPS
@@ -1,5 +1,4 @@
 include_rules = [
-  "+media",
   "+third_party/WebKit/public/platform",
   "+third_party/WebKit/public/web",
   "+third_party/skia",
diff --git a/ppapi/api/private/ppb_flash_device_id.idl b/ppapi/api/private/ppb_flash_device_id.idl
index 16b0d3d..b4ba3ca 100644
--- a/ppapi/api/private/ppb_flash_device_id.idl
+++ b/ppapi/api/private/ppb_flash_device_id.idl
@@ -8,8 +8,7 @@
  */
 
 label Chrome {
-  M21 = 1.0,
-  M29 = 1.1
+  M21 = 1.0
 };
 
 // TODO(raymes): This is deprecated by the PPB_Flash_DRM interface. Remove this
@@ -22,7 +21,7 @@
    * string in |*id| and will call the completion callback. On failure the
    * given var will be PP_VARTYPE_UNDEFINED.
    */
-  [version=1.0, deprecate=1.1]
+  [version=1.0]
   int32_t GetDeviceID([in] PP_Resource device_id,
                       [out] PP_Var id,
                       [in] PP_CompletionCallback callback);
diff --git a/ppapi/host/resource_message_filter.cc b/ppapi/host/resource_message_filter.cc
index 6d947e3..ff56cac 100644
--- a/ppapi/host/resource_message_filter.cc
+++ b/ppapi/host/resource_message_filter.cc
@@ -42,11 +42,16 @@
                                           HostMessageContext* context) {
   scoped_refptr<base::TaskRunner> runner = OverrideTaskRunnerForMessage(msg);
   if (runner.get()) {
-    // TODO(raymes): We need to make a copy so the context can be used on other
-    // threads. It would be better to have a thread-safe refcounted context.
-    HostMessageContext context_copy = *context;
-    runner->PostTask(FROM_HERE, base::Bind(
-        &ResourceMessageFilter::DispatchMessage, this, msg, context_copy));
+    if (runner->RunsTasksOnCurrentThread()) {
+      DispatchMessage(msg, *context);
+    } else {
+      // TODO(raymes): We need to make a copy so the context can be used on
+      // other threads. It would be better to have a thread-safe refcounted
+      // context.
+      HostMessageContext context_copy = *context;
+      runner->PostTask(FROM_HERE, base::Bind(
+          &ResourceMessageFilter::DispatchMessage, this, msg, context_copy));
+    }
     return true;
   }
 
diff --git a/ppapi/native_client/src/trusted/plugin/module_ppapi.cc b/ppapi/native_client/src/trusted/plugin/module_ppapi.cc
index 90fe0f1..4204ed4 100644
--- a/ppapi/native_client/src/trusted/plugin/module_ppapi.cc
+++ b/ppapi/native_client/src/trusted/plugin/module_ppapi.cc
@@ -8,81 +8,95 @@
 #include "native_client/src/shared/platform/nacl_time.h"
 #include "native_client/src/trusted/desc/nrd_all_modules.h"
 
-#include "ppapi/c/private/ppb_nacl_private.h"
-#include "ppapi/cpp/module.h"
 
+#include "ppapi/native_client/src/trusted/plugin/module_ppapi.h"
 #include "ppapi/native_client/src/trusted/plugin/nacl_entry_points.h"
 #include "ppapi/native_client/src/trusted/plugin/plugin.h"
 
 namespace plugin {
 
-class ModulePpapi : public pp::Module {
- public:
-  ModulePpapi() : pp::Module(),
-                  init_was_successful_(false),
-                  private_interface_(NULL) {
-    MODULE_PRINTF(("ModulePpapi::ModulePpapi (this=%p)\n",
-                   static_cast<void*>(this)));
+ModulePpapi::ModulePpapi() : pp::Module(),
+                             init_was_successful_(false),
+                             private_interface_(NULL) {
+  MODULE_PRINTF(("ModulePpapi::ModulePpapi (this=%p)\n",
+                 static_cast<void*>(this)));
+}
+
+ModulePpapi::~ModulePpapi() {
+  if (init_was_successful_) {
+    NaClSrpcModuleFini();
+    NaClNrdAllModulesFini();
+  }
+  MODULE_PRINTF(("ModulePpapi::~ModulePpapi (this=%p)\n",
+                 static_cast<void*>(this)));
+}
+
+bool ModulePpapi::Init() {
+  // Ask the browser for an interface which provides missing functions
+  private_interface_ = reinterpret_cast<const PPB_NaCl_Private*>(
+      GetBrowserInterface(PPB_NACL_PRIVATE_INTERFACE));
+
+  if (NULL == private_interface_) {
+    MODULE_PRINTF(("ModulePpapi::Init failed: "
+                   "GetBrowserInterface returned NULL\n"));
+    return false;
   }
 
-  virtual ~ModulePpapi() {
-    if (init_was_successful_) {
-      NaClSrpcModuleFini();
-      NaClNrdAllModulesFini();
-    }
-    MODULE_PRINTF(("ModulePpapi::~ModulePpapi (this=%p)\n",
-                   static_cast<void*>(this)));
-  }
-
-  virtual bool Init() {
-    // Ask the browser for an interface which provides missing functions
-    private_interface_ = reinterpret_cast<const PPB_NaCl_Private*>(
-        GetBrowserInterface(PPB_NACL_PRIVATE_INTERFACE));
-
-    if (NULL == private_interface_) {
-      MODULE_PRINTF(("ModulePpapi::Init failed: "
-                     "GetBrowserInterface returned NULL\n"));
-      return false;
-    }
-
-    launch_nacl_process = reinterpret_cast<LaunchNaClProcessFunc>(
-        private_interface_->LaunchSelLdr);
+  launch_nacl_process = reinterpret_cast<LaunchNaClProcessFunc>(
+      private_interface_->LaunchSelLdr);
 
 #if NACL_LINUX || NACL_OSX
-    // Note that currently we do not need random numbers inside the
-    // NaCl trusted plugin on Unix, but NaClSecureRngModuleInit() is
-    // strict and will raise a fatal error unless we provide it with a
-    // /dev/urandom FD beforehand.
-    NaClSecureRngModuleSetUrandomFd(dup(private_interface_->UrandomFD()));
+  // Note that currently we do not need random numbers inside the
+  // NaCl trusted plugin on Unix, but NaClSecureRngModuleInit() is
+  // strict and will raise a fatal error unless we provide it with a
+  // /dev/urandom FD beforehand.
+  NaClSecureRngModuleSetUrandomFd(dup(private_interface_->UrandomFD()));
 #endif
 
-    // In the plugin, we don't need high resolution time of day.
-    NaClAllowLowResolutionTimeOfDay();
-    NaClNrdAllModulesInit();
-    NaClSrpcModuleInit();
+  // In the plugin, we don't need high resolution time of day.
+  NaClAllowLowResolutionTimeOfDay();
+  NaClNrdAllModulesInit();
+  NaClSrpcModuleInit();
 
 #if NACL_WINDOWS
-    NaClSetBrokerDuplicateHandleFunc(private_interface_->BrokerDuplicateHandle);
+  NaClSetBrokerDuplicateHandleFunc(private_interface_->BrokerDuplicateHandle);
 #endif
 
-    init_was_successful_ = true;
-    return true;
-  }
+  init_was_successful_ = true;
+  return true;
+}
 
-  virtual pp::Instance* CreateInstance(PP_Instance pp_instance) {
-    MODULE_PRINTF(("ModulePpapi::CreateInstance (pp_instance=%" NACL_PRId32
-                   ")\n",
-                   pp_instance));
-    Plugin* plugin = Plugin::New(pp_instance);
-    MODULE_PRINTF(("ModulePpapi::CreateInstance (return %p)\n",
-                   static_cast<void* >(plugin)));
-    return plugin;
-  }
+pp::Instance* ModulePpapi::CreateInstance(PP_Instance pp_instance) {
+  MODULE_PRINTF(("ModulePpapi::CreateInstance (pp_instance=%" NACL_PRId32
+                 ")\n",
+                 pp_instance));
+  Plugin* plugin = Plugin::New(pp_instance);
+  MODULE_PRINTF(("ModulePpapi::CreateInstance (return %p)\n",
+                 static_cast<void* >(plugin)));
+  return plugin;
+}
 
- private:
-  bool init_was_successful_;
-  const PPB_NaCl_Private* private_interface_;
-};
+const uint64_t kMaxCrashesPerInterval = 3;
+const uint64_t kCrashesIntervalInSeconds = 120;
+
+void ModulePpapi::RegisterPluginCrash() {
+  PLUGIN_PRINTF(("ModulePpapi::RegisterPluginCrash ()\n"));
+  if (crash_times_.size() == kMaxCrashesPerInterval) {
+    crash_times_.pop_front();
+  }
+  int64_t time = NaClGetTimeOfDayMicroseconds();
+  crash_times_.push_back(time);
+}
+
+bool ModulePpapi::IsPluginUnstable() {
+  PLUGIN_PRINTF(("ModulePpapi::IsPluginUnstable ()\n"));
+  if (crash_times_.size() != kMaxCrashesPerInterval) {
+    return false;
+  }
+  int64_t now = NaClGetTimeOfDayMicroseconds();
+  int64_t delta = now - crash_times_.front();
+  return delta / (1000.0 * 1000.0) <= kCrashesIntervalInSeconds;
+}
 
 }  // namespace plugin
 
diff --git a/ppapi/native_client/src/trusted/plugin/module_ppapi.h b/ppapi/native_client/src/trusted/plugin/module_ppapi.h
new file mode 100644
index 0000000..b2e7564
--- /dev/null
+++ b/ppapi/native_client/src/trusted/plugin/module_ppapi.h
@@ -0,0 +1,45 @@
+/*
+ * 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 <deque>
+
+#include "ppapi/c/private/ppb_nacl_private.h"
+#include "ppapi/cpp/module.h"
+
+namespace plugin {
+
+class ModulePpapi : public pp::Module {
+ public:
+  ModulePpapi();
+
+  virtual ~ModulePpapi();
+
+  virtual bool Init();
+
+  virtual pp::Instance* CreateInstance(PP_Instance pp_instance);
+
+  // NaCl crash throttling.  If RegisterPluginCrash is called too many times
+  // within a time period, IsPluginUnstable reports true.  As long as
+  // IsPluginUnstable returns true, NaCl modules will fail to load.
+  void RegisterPluginCrash();
+  bool IsPluginUnstable();
+
+ private:
+  bool init_was_successful_;
+  const PPB_NaCl_Private* private_interface_;
+
+  // Crash throttling support.
+  std::deque<int64_t> crash_times_;
+};
+
+}  // namespace plugin
+
+
+namespace pp {
+
+Module* CreateModule();
+
+}  // namespace pp
diff --git a/ppapi/native_client/src/trusted/plugin/plugin.cc b/ppapi/native_client/src/trusted/plugin/plugin.cc
index 5cbb9d7..a4833ee 100644
--- a/ppapi/native_client/src/trusted/plugin/plugin.cc
+++ b/ppapi/native_client/src/trusted/plugin/plugin.cc
@@ -55,6 +55,7 @@
 
 #include "ppapi/native_client/src/trusted/plugin/file_utils.h"
 #include "ppapi/native_client/src/trusted/plugin/json_manifest.h"
+#include "ppapi/native_client/src/trusted/plugin/module_ppapi.h"
 #include "ppapi/native_client/src/trusted/plugin/nacl_entry_points.h"
 #include "ppapi/native_client/src/trusted/plugin/nacl_subprocess.h"
 #include "ppapi/native_client/src/trusted/plugin/nexe_arch.h"
@@ -1009,6 +1010,10 @@
   // invocation will just be a no-op, since all the crash log will
   // have been received and we'll just get an EOF indication.
   CopyCrashLogToJsConsole();
+
+  // Remember the nexe crash time, which helps determine the need to throttle.
+  ModulePpapi* module_ppapi = static_cast<ModulePpapi*>(pp::Module::Get());
+  module_ppapi->RegisterPluginCrash();
 }
 
 void Plugin::BitcodeDidTranslate(int32_t pp_error) {
@@ -1204,15 +1209,25 @@
     EnqueueProgressEvent(kProgressEventProgress);
     if (pnacl_options.translate()) {
       if (this->nacl_interface()->IsPnaclEnabled()) {
-        pp::CompletionCallback translate_callback =
-            callback_factory_.NewCallback(&Plugin::BitcodeDidTranslate);
-        // Will always call the callback on success or failure.
-        pnacl_coordinator_.reset(
-            PnaclCoordinator::BitcodeToNative(this,
-                                              program_url,
-                                              pnacl_options,
-                                              translate_callback));
-        return;
+        // Check whether PNaCl has been crashing "frequently".  If so, report
+        // a load error.
+        ModulePpapi* module_ppapi =
+            static_cast<ModulePpapi*>(pp::Module::Get());
+        if (module_ppapi->IsPluginUnstable()) {
+          error_info.SetReport(ERROR_PNACL_CRASH_THROTTLED,
+                               "PNaCl has been temporarily disabled because too"
+                               " many crashes have been observed.");
+        } else {
+          pp::CompletionCallback translate_callback =
+              callback_factory_.NewCallback(&Plugin::BitcodeDidTranslate);
+          // Will always call the callback on success or failure.
+          pnacl_coordinator_.reset(
+              PnaclCoordinator::BitcodeToNative(this,
+                                                program_url,
+                                                pnacl_options,
+                                                translate_callback));
+          return;
+        }
       } else {
         error_info.SetReport(ERROR_PNACL_NOT_ENABLED,
                              "PNaCl has been disabled (e.g., by setting "
diff --git a/ppapi/native_client/src/trusted/plugin/plugin_error.h b/ppapi/native_client/src/trusted/plugin/plugin_error.h
index b5eb4d8..ac3fbf4 100644
--- a/ppapi/native_client/src/trusted/plugin/plugin_error.h
+++ b/ppapi/native_client/src/trusted/plugin/plugin_error.h
@@ -96,6 +96,7 @@
   ERROR_PNACL_NOT_ENABLED = 68,
   ERROR_MANIFEST_NOACCESS_URL = 69,
   ERROR_NEXE_NOACCESS_URL = 70,
+  ERROR_PNACL_CRASH_THROTTLED = 71,
   // If you add a code, read the enum comment above on how to update histograms.
   ERROR_MAX
 };
diff --git a/ppapi/native_client/src/trusted/plugin/pnacl_coordinator.cc b/ppapi/native_client/src/trusted/plugin/pnacl_coordinator.cc
index 18b4fae..4362ec4 100644
--- a/ppapi/native_client/src/trusted/plugin/pnacl_coordinator.cc
+++ b/ppapi/native_client/src/trusted/plugin/pnacl_coordinator.cc
@@ -263,7 +263,7 @@
     manifest_(new PnaclManifest()),
     pexe_url_(pexe_url),
     pnacl_options_(pnacl_options),
-    use_new_cache_(false),
+    use_new_cache_(true),
     is_cache_hit_(PP_FALSE),
     nexe_handle_(PP_kInvalidFileHandle),
     error_already_reported_(false),
@@ -275,9 +275,9 @@
   PLUGIN_PRINTF(("PnaclCoordinator::PnaclCoordinator (this=%p, plugin=%p)\n",
                  static_cast<void*>(this), static_cast<void*>(plugin)));
   callback_factory_.Initialize(this);
-  if (getenv("PNACL_USE_NEW_CACHE")) {
-    PLUGIN_PRINTF(("PnaclCoordinator using new translation cache\n"));
-    use_new_cache_ = true;
+  if (getenv("PNACL_USE_OLD_CACHE")) {
+    PLUGIN_PRINTF(("PnaclCoordinator using old translation cache\n"));
+    use_new_cache_ = false;
   }
 }
 
@@ -397,6 +397,15 @@
     // care of caching.
     plugin_->nacl_interface()->ReportTranslationFinished(
         plugin_->pp_instance(), PP_TRUE);
+
+    // These can maybe move up with the rest of the UMA stats when we remove
+    // the old cache code
+    int64_t total_time = NaClGetTimeOfDayMicroseconds() - pnacl_init_time_;
+    HistogramTime("NaCl.Perf.PNaClLoadTime.TotalUncachedTime",
+                  total_time / NACL_MICROS_PER_MILLI);
+    HistogramKBPerSec("NaCl.Perf.PNaClLoadTime.TotalUncachedKBPerSec",
+                      pexe_size_ / 1024.0,
+                      total_time / 1000000.0);
     NexeReadDidOpen(PP_OK);
     return;
   }
@@ -839,7 +848,7 @@
     return;
   }
 
-  if (!off_the_record_) {
+  if (!off_the_record_ || use_new_cache_) {
     // Get the cache key and try to open an existing entry.
     nacl::string headers = streaming_downloader_->GetResponseHeaders();
     NaClHttpResponseHeaders parser;
@@ -866,8 +875,9 @@
           plugin_->nacl_interface()->GetNexeFd(
               plugin_->pp_instance(),
               streaming_downloader_->url().c_str(),
-              // TODO(dschuff): use the right abi version here.
-              0,
+              // TODO(dschuff): Get this value from the pnacl json file after it
+              // rolls in from NaCl.
+              1,
               pnacl_options_.opt_level(),
               parser.GetHeader("last-modified").c_str(),
               parser.GetHeader("etag").c_str(),
@@ -912,11 +922,11 @@
             "PnaclCoordinator: Got bad temp file handle from GetNexeFd"));
     return;
   }
+  HistogramEnumerateTranslationCache(is_cache_hit_);
+
   if (is_cache_hit_ == PP_TRUE) {
     // Cache hit -- no need to stream the rest of the file.
     streaming_downloader_.reset(NULL);
-    // TODO(dschuff): update UMA stats for hit/miss once there could actually
-    // be hits/misses.
     // Open it for reading as the cached nexe file.
     pp::CompletionCallback cb =
         callback_factory_.NewCallback(&PnaclCoordinator::NexeReadDidOpen);
diff --git a/ppapi/native_client/src/trusted/plugin/pnacl_coordinator.h b/ppapi/native_client/src/trusted/plugin/pnacl_coordinator.h
index 06ff7c7..42f1207 100644
--- a/ppapi/native_client/src/trusted/plugin/pnacl_coordinator.h
+++ b/ppapi/native_client/src/trusted/plugin/pnacl_coordinator.h
@@ -79,9 +79,6 @@
 // TRANSLATION_COMPLETE
 //     Complete when TranslateFinished is invoked.
 //
-// If cache is enabled:
-// TODO: notify browser of finished translation (and re-open read-only?)
-//
 // OPEN_NEXE_FOR_SEL_LDR
 //   Complete when NexeReadDidOpen is invoked.
 class PnaclCoordinator: public CallbackSource<FileStreamData> {
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 aa68044..8bb17f7 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
@@ -2699,8 +2699,6 @@
 
 /* End wrapper methods for PPB_Flash_DeviceID_1_0 */
 
-/* Not generating wrapper methods for PPB_Flash_DeviceID_1_1 */
-
 /* Begin wrapper methods for PPB_Flash_DRM_1_0 */
 
 static PP_Resource Pnacl_M29_PPB_Flash_DRM_Create(PP_Instance instance) {
@@ -4616,8 +4614,6 @@
     .GetDeviceID = (int32_t (*)(PP_Resource device_id, struct PP_Var* id, struct PP_CompletionCallback callback))&Pnacl_M21_PPB_Flash_DeviceID_GetDeviceID
 };
 
-/* Not generating wrapper interface for PPB_Flash_DeviceID_1_1 */
-
 struct PPB_Flash_DRM_1_0 Pnacl_Wrappers_PPB_Flash_DRM_1_0 = {
     .Create = (PP_Resource (*)(PP_Instance instance))&Pnacl_M29_PPB_Flash_DRM_Create,
     .GetDeviceID = (int32_t (*)(PP_Resource drm, struct PP_Var* id, struct PP_CompletionCallback callback))&Pnacl_M29_PPB_Flash_DRM_GetDeviceID,
diff --git a/ppapi/native_client/src/untrusted/pnacl_irt_shim/shim_ppapi.c b/ppapi/native_client/src/untrusted/pnacl_irt_shim/shim_ppapi.c
index c6409cf..e73326e 100644
--- a/ppapi/native_client/src/untrusted/pnacl_irt_shim/shim_ppapi.c
+++ b/ppapi/native_client/src/untrusted/pnacl_irt_shim/shim_ppapi.c
@@ -70,7 +70,7 @@
   NACL_IRT_CLOCK_v0_1,
   /* Allowed for debugging purposes: */
   NACL_IRT_DEV_FDIO_v0_1,
-  NACL_IRT_DEV_FILENAME_v0_1,
+  NACL_IRT_DEV_FILENAME_v0_2,
 };
 
 /* Use local strcmp to avoid dependency on libc. */
diff --git a/ppapi/native_client/src/untrusted/pnacl_support_extension/pnacl_component_crx_gen.py b/ppapi/native_client/src/untrusted/pnacl_support_extension/pnacl_component_crx_gen.py
index 4a12c4a..3d35b3f 100755
--- a/ppapi/native_client/src/untrusted/pnacl_support_extension/pnacl_component_crx_gen.py
+++ b/ppapi/native_client/src/untrusted/pnacl_support_extension/pnacl_component_crx_gen.py
@@ -12,6 +12,7 @@
    it depends on the pnacl_irt_shim.
 """
 
+import json
 import logging
 import optparse
 import os
@@ -121,21 +122,13 @@
 
 ######################################################################
 
-def IsValidVersion(version):
-  """ Return true if the version is a valid ID (a quad like 0.0.0.0).
-  """
-  pat = re.compile('^\d+\.\d+\.\d+\.\d+$')
-  return pat.search(version)
-
-
-######################################################################
-
 class PnaclPackaging(object):
 
   package_base = os.path.dirname(__file__)
 
-  # Pnacl-specific info - set from the command line.
+  # File paths that are set from the command line.
   pnacl_template = None
+  tool_revisions = None
 
   # Agreed-upon name for pnacl-specific info.
   pnacl_json = 'pnacl.json'
@@ -145,20 +138,40 @@
     PnaclPackaging.pnacl_template = path
 
   @staticmethod
-  def GeneratePnaclInfo(target_dir, version, arch, is_installer=False):
-    pnacl_template_fd = open(PnaclPackaging.pnacl_template, 'r')
-    pnacl_template = pnacl_template_fd.read()
-    pnacl_template_fd.close()
-    if is_installer:
+  def SetToolsRevisionPath(path):
+    PnaclPackaging.tool_revisions = path
+
+  @staticmethod
+  def PnaclToolsRevision():
+    with open(PnaclPackaging.tool_revisions, 'r') as f:
+      for line in f.read().splitlines():
+        if line.startswith('PNACL_VERSION'):
+          _, version = line.split('=')
+          # CWS happens to use version quads, so make it a quad too.
+          # However, each component of the quad is limited to 64K max.
+          # Try to handle a bit more.
+          max_version = 2 ** 16
+          version = int(version)
+          version_more = version / max_version
+          version = version % max_version
+          return '0.1.%d.%d' % (version_more, version)
+    raise Exception('Cannot find PNACL_VERSION in TOOL_REVISIONS file: %s' %
+                    PnaclPackaging.tool_revisions)
+
+  @staticmethod
+  def GeneratePnaclInfo(target_dir, abi_version, arch):
+    # A note on versions: pnacl_version is the version of translator built
+    # by the NaCl repo, while abi_version is bumped when the NaCl sandbox
+    # actually changes.
+    pnacl_version = PnaclPackaging.PnaclToolsRevision()
+    with open(PnaclPackaging.pnacl_template, 'r') as pnacl_template_fd:
+      pnacl_template = json.load(pnacl_template_fd)
       out_name = J(target_dir, UseWhitelistedChars(PnaclPackaging.pnacl_json,
                                                    None))
-    else:
-      out_name = J(target_dir, PnaclPackaging.pnacl_json)
-    output_fd = open(out_name, 'w')
-    output_fd.write(pnacl_template % { "abi-version" : version,
-                                       "arch" : arch, })
-    output_fd.close()
-
+      with open(out_name, 'w') as output_fd:
+        pnacl_template['pnacl-arch'] = arch
+        pnacl_template['pnacl-version'] = pnacl_version
+        json.dump(pnacl_template, output_fd, sort_keys=True, indent=4)
 
 
 ######################################################################
@@ -286,8 +299,7 @@
   # Hack around the fact that there may be more than one arch, on Windows.
   if len(arches) == 1:
     arches = arches[0]
-  PnaclPackaging.GeneratePnaclInfo(PnaclDirs.OutputDir(), version_quad,
-                                   arches, is_installer=True)
+  PnaclPackaging.GeneratePnaclInfo(PnaclDirs.OutputDir(), version_quad, arches)
 
 
 ######################################################################
@@ -314,6 +326,8 @@
   parser.add_option('--info_template_path',
                     dest='info_template_path', default=None,
                     help='Path of the info template file')
+  parser.add_option('--tool_revisions_path', dest='tool_revisions_path',
+                    default=None, help='Location of NaCl TOOL_REVISIONS file.')
   parser.add_option('-v', '--verbose', dest='verbose', default=False,
                     action='store_true',
                     help='Print verbose debug messages.')
@@ -336,6 +350,9 @@
   if options.info_template_path:
     PnaclPackaging.SetPnaclInfoTemplatePath(options.info_template_path)
 
+  if options.tool_revisions_path:
+    PnaclPackaging.SetToolsRevisionPath(options.tool_revisions_path)
+
   lib_overrides = {}
   for o in options.lib_overrides:
     arch, override_lib = o.split(',')
@@ -353,13 +370,10 @@
     parser.print_help()
     parser.error('Incorrect number of arguments')
 
-  version_quad = args[0]
-  if not IsValidVersion(version_quad):
-    print 'Invalid version format: %s\n' % version_quad
-    return 1
+  abi_version = int(args[0])
 
   arches = DetermineInstallerArches(options.target_arch)
-  BuildInstallerStyle(version_quad, lib_overrides, arches)
+  BuildInstallerStyle(abi_version, lib_overrides, arches)
   return 0
 
 
diff --git a/ppapi/native_client/src/untrusted/pnacl_support_extension/pnacl_support_extension.gyp b/ppapi/native_client/src/untrusted/pnacl_support_extension/pnacl_support_extension.gyp
index ece4452..e290eae 100644
--- a/ppapi/native_client/src/untrusted/pnacl_support_extension/pnacl_support_extension.gyp
+++ b/ppapi/native_client/src/untrusted/pnacl_support_extension/pnacl_support_extension.gyp
@@ -19,7 +19,7 @@
           '../../../../../native_client/tools.gyp:prep_toolchain',
         ],
         'sources': [
-          '../../../../../native_client/pnacl/driver/pnacl_info_template.json',
+          'pnacl_component_crx_gen.py',
         ],
         # We could use 'copies', but we want to rename the files
         # in a white-listed way first.  Thus use a script.
@@ -30,6 +30,8 @@
               'pnacl_component_crx_gen.py',
               # A stamp file representing the contents of pnacl_translator.
               '<(DEPTH)/native_client/toolchain/pnacl_translator/SOURCE_SHA1',
+              '<(DEPTH)/native_client/pnacl/driver/pnacl_info_template.json',
+              '<(DEPTH)/native_client/TOOL_REVISIONS',
             ],
             'conditions': [
                 # On windows we need both ia32 and x64.
@@ -142,9 +144,10 @@
               '--dest=<(PRODUCT_DIR)/pnacl',
               '<@(lib_overrides)',
               '--target_arch=<(target_arch)',
-              '--info_template_path=../../../../../native_client/pnacl/driver/pnacl_info_template.json',
+              '--info_template_path=<(DEPTH)/native_client/pnacl/driver/pnacl_info_template.json',
+              '--tool_revisions_path=<(DEPTH)/native_client/TOOL_REVISIONS',
               # ABI Version Number.
-              '0.0.0.1',
+              '1',
             ],
           },
         ],
diff --git a/ppapi/ppapi_c.target.darwin-arm.mk b/ppapi/ppapi_c.target.darwin-arm.mk
deleted file mode 100644
index 1ca820d..0000000
--- a/ppapi/ppapi_c.target.darwin-arm.mk
+++ /dev/null
@@ -1,205 +0,0 @@
-# This file is generated by gyp; do not edit.
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_CLASS := GYP
-LOCAL_MODULE := ppapi_ppapi_c_gyp
-LOCAL_MODULE_STEM := ppapi_c
-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 \
-	-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 \
-	-Os \
-	-g \
-	-fomit-frame-pointer \
-	-fdata-sections \
-	-ffunction-sections
-
-MY_DEFS_Debug := \
-	'-DANGLE_DX11' \
-	'-D_FILE_OFFSET_BITS=64' \
-	'-DNO_TCMALLOC' \
-	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
-	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
-	'-DDISABLE_NACL' \
-	'-DCHROMIUM_BUILD' \
-	'-DUSE_LIBJPEG_TURBO=1' \
-	'-DUSE_PROPRIETARY_CODECS' \
-	'-DENABLE_CONFIGURATION_POLICY' \
-	'-DENABLE_GPU=1' \
-	'-DUSE_OPENSSL=1' \
-	'-DENABLE_EGLIMAGE=1' \
-	'-D__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-abi \
-	-Wno-error=c++0x-compat \
-	-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 \
-	-Os \
-	-fno-ident \
-	-fdata-sections \
-	-ffunction-sections \
-	-fomit-frame-pointer
-
-MY_DEFS_Release := \
-	'-DANGLE_DX11' \
-	'-D_FILE_OFFSET_BITS=64' \
-	'-DNO_TCMALLOC' \
-	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
-	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
-	'-DDISABLE_NACL' \
-	'-DCHROMIUM_BUILD' \
-	'-DUSE_LIBJPEG_TURBO=1' \
-	'-DUSE_PROPRIETARY_CODECS' \
-	'-DENABLE_CONFIGURATION_POLICY' \
-	'-DENABLE_GPU=1' \
-	'-DUSE_OPENSSL=1' \
-	'-DENABLE_EGLIMAGE=1' \
-	'-D__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-abi \
-	-Wno-error=c++0x-compat \
-	-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))
-### Rules for final target.
-# Add target alias to "gyp_all_modules" target.
-.PHONY: gyp_all_modules
-gyp_all_modules: ppapi_ppapi_c_gyp
-
-# Alias gyp target name.
-.PHONY: ppapi_c
-ppapi_c: ppapi_ppapi_c_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/ppapi/ppapi_c.target.darwin-mips.mk b/ppapi/ppapi_c.target.darwin-mips.mk
deleted file mode 100644
index 12a949b..0000000
--- a/ppapi/ppapi_c.target.darwin-mips.mk
+++ /dev/null
@@ -1,203 +0,0 @@
-# This file is generated by gyp; do not edit.
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_CLASS := GYP
-LOCAL_MODULE := ppapi_ppapi_c_gyp
-LOCAL_MODULE_STEM := ppapi_c
-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 \
-	-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 \
-	-Os \
-	-g \
-	-fomit-frame-pointer \
-	-fdata-sections \
-	-ffunction-sections
-
-MY_DEFS_Debug := \
-	'-DANGLE_DX11' \
-	'-D_FILE_OFFSET_BITS=64' \
-	'-DNO_TCMALLOC' \
-	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
-	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
-	'-DDISABLE_NACL' \
-	'-DCHROMIUM_BUILD' \
-	'-DUSE_LIBJPEG_TURBO=1' \
-	'-DUSE_PROPRIETARY_CODECS' \
-	'-DENABLE_CONFIGURATION_POLICY' \
-	'-DENABLE_GPU=1' \
-	'-DUSE_OPENSSL=1' \
-	'-DENABLE_EGLIMAGE=1' \
-	'-D__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-uninitialized \
-	-Wno-error=c++0x-compat \
-	-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 \
-	-Os \
-	-fno-ident \
-	-fdata-sections \
-	-ffunction-sections \
-	-fomit-frame-pointer
-
-MY_DEFS_Release := \
-	'-DANGLE_DX11' \
-	'-D_FILE_OFFSET_BITS=64' \
-	'-DNO_TCMALLOC' \
-	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
-	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
-	'-DDISABLE_NACL' \
-	'-DCHROMIUM_BUILD' \
-	'-DUSE_LIBJPEG_TURBO=1' \
-	'-DUSE_PROPRIETARY_CODECS' \
-	'-DENABLE_CONFIGURATION_POLICY' \
-	'-DENABLE_GPU=1' \
-	'-DUSE_OPENSSL=1' \
-	'-DENABLE_EGLIMAGE=1' \
-	'-D__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-uninitialized \
-	-Wno-error=c++0x-compat \
-	-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))
-### Rules for final target.
-# Add target alias to "gyp_all_modules" target.
-.PHONY: gyp_all_modules
-gyp_all_modules: ppapi_ppapi_c_gyp
-
-# Alias gyp target name.
-.PHONY: ppapi_c
-ppapi_c: ppapi_ppapi_c_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/ppapi/ppapi_c.target.darwin-x86.mk b/ppapi/ppapi_c.target.darwin-x86.mk
deleted file mode 100644
index d8d46e0..0000000
--- a/ppapi/ppapi_c.target.darwin-x86.mk
+++ /dev/null
@@ -1,209 +0,0 @@
-# This file is generated by gyp; do not edit.
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_CLASS := GYP
-LOCAL_MODULE := ppapi_ppapi_c_gyp
-LOCAL_MODULE_STEM := ppapi_c
-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 := \
-	--param=ssp-buffer-size=4 \
-	-Werror \
-	-fno-exceptions \
-	-fno-strict-aliasing \
-	-Wall \
-	-Wno-unused-parameter \
-	-Wno-missing-field-initializers \
-	-fvisibility=hidden \
-	-pipe \
-	-fPIC \
-	-m32 \
-	-mmmx \
-	-march=pentium4 \
-	-msse2 \
-	-mfpmath=sse \
-	-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 \
-	-fno-stack-protector \
-	-Os \
-	-g \
-	-fomit-frame-pointer \
-	-fdata-sections \
-	-ffunction-sections
-
-MY_DEFS_Debug := \
-	'-DANGLE_DX11' \
-	'-D_FILE_OFFSET_BITS=64' \
-	'-DNO_TCMALLOC' \
-	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
-	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
-	'-DDISABLE_NACL' \
-	'-DCHROMIUM_BUILD' \
-	'-DUSE_LIBJPEG_TURBO=1' \
-	'-DUSE_PROPRIETARY_CODECS' \
-	'-DENABLE_CONFIGURATION_POLICY' \
-	'-DENABLE_GPU=1' \
-	'-DUSE_OPENSSL=1' \
-	'-DENABLE_EGLIMAGE=1' \
-	'-D__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-error=c++0x-compat \
-	-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 \
-	-m32 \
-	-mmmx \
-	-march=pentium4 \
-	-msse2 \
-	-mfpmath=sse \
-	-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 \
-	-fno-stack-protector \
-	-Os \
-	-fno-ident \
-	-fdata-sections \
-	-ffunction-sections \
-	-fomit-frame-pointer \
-	-fno-unwind-tables \
-	-fno-asynchronous-unwind-tables
-
-MY_DEFS_Release := \
-	'-DANGLE_DX11' \
-	'-D_FILE_OFFSET_BITS=64' \
-	'-DNO_TCMALLOC' \
-	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
-	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
-	'-DDISABLE_NACL' \
-	'-DCHROMIUM_BUILD' \
-	'-DUSE_LIBJPEG_TURBO=1' \
-	'-DUSE_PROPRIETARY_CODECS' \
-	'-DENABLE_CONFIGURATION_POLICY' \
-	'-DENABLE_GPU=1' \
-	'-DUSE_OPENSSL=1' \
-	'-DENABLE_EGLIMAGE=1' \
-	'-D__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-error=c++0x-compat \
-	-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))
-### Rules for final target.
-# Add target alias to "gyp_all_modules" target.
-.PHONY: gyp_all_modules
-gyp_all_modules: ppapi_ppapi_c_gyp
-
-# Alias gyp target name.
-.PHONY: ppapi_c
-ppapi_c: ppapi_ppapi_c_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/ppapi/ppapi_c.target.linux-arm.mk b/ppapi/ppapi_c.target.linux-arm.mk
deleted file mode 100644
index 1ca820d..0000000
--- a/ppapi/ppapi_c.target.linux-arm.mk
+++ /dev/null
@@ -1,205 +0,0 @@
-# This file is generated by gyp; do not edit.
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_CLASS := GYP
-LOCAL_MODULE := ppapi_ppapi_c_gyp
-LOCAL_MODULE_STEM := ppapi_c
-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 \
-	-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 \
-	-Os \
-	-g \
-	-fomit-frame-pointer \
-	-fdata-sections \
-	-ffunction-sections
-
-MY_DEFS_Debug := \
-	'-DANGLE_DX11' \
-	'-D_FILE_OFFSET_BITS=64' \
-	'-DNO_TCMALLOC' \
-	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
-	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
-	'-DDISABLE_NACL' \
-	'-DCHROMIUM_BUILD' \
-	'-DUSE_LIBJPEG_TURBO=1' \
-	'-DUSE_PROPRIETARY_CODECS' \
-	'-DENABLE_CONFIGURATION_POLICY' \
-	'-DENABLE_GPU=1' \
-	'-DUSE_OPENSSL=1' \
-	'-DENABLE_EGLIMAGE=1' \
-	'-D__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-abi \
-	-Wno-error=c++0x-compat \
-	-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 \
-	-Os \
-	-fno-ident \
-	-fdata-sections \
-	-ffunction-sections \
-	-fomit-frame-pointer
-
-MY_DEFS_Release := \
-	'-DANGLE_DX11' \
-	'-D_FILE_OFFSET_BITS=64' \
-	'-DNO_TCMALLOC' \
-	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
-	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
-	'-DDISABLE_NACL' \
-	'-DCHROMIUM_BUILD' \
-	'-DUSE_LIBJPEG_TURBO=1' \
-	'-DUSE_PROPRIETARY_CODECS' \
-	'-DENABLE_CONFIGURATION_POLICY' \
-	'-DENABLE_GPU=1' \
-	'-DUSE_OPENSSL=1' \
-	'-DENABLE_EGLIMAGE=1' \
-	'-D__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-abi \
-	-Wno-error=c++0x-compat \
-	-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))
-### Rules for final target.
-# Add target alias to "gyp_all_modules" target.
-.PHONY: gyp_all_modules
-gyp_all_modules: ppapi_ppapi_c_gyp
-
-# Alias gyp target name.
-.PHONY: ppapi_c
-ppapi_c: ppapi_ppapi_c_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/ppapi/ppapi_c.target.linux-mips.mk b/ppapi/ppapi_c.target.linux-mips.mk
deleted file mode 100644
index 12a949b..0000000
--- a/ppapi/ppapi_c.target.linux-mips.mk
+++ /dev/null
@@ -1,203 +0,0 @@
-# This file is generated by gyp; do not edit.
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_CLASS := GYP
-LOCAL_MODULE := ppapi_ppapi_c_gyp
-LOCAL_MODULE_STEM := ppapi_c
-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 \
-	-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 \
-	-Os \
-	-g \
-	-fomit-frame-pointer \
-	-fdata-sections \
-	-ffunction-sections
-
-MY_DEFS_Debug := \
-	'-DANGLE_DX11' \
-	'-D_FILE_OFFSET_BITS=64' \
-	'-DNO_TCMALLOC' \
-	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
-	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
-	'-DDISABLE_NACL' \
-	'-DCHROMIUM_BUILD' \
-	'-DUSE_LIBJPEG_TURBO=1' \
-	'-DUSE_PROPRIETARY_CODECS' \
-	'-DENABLE_CONFIGURATION_POLICY' \
-	'-DENABLE_GPU=1' \
-	'-DUSE_OPENSSL=1' \
-	'-DENABLE_EGLIMAGE=1' \
-	'-D__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-uninitialized \
-	-Wno-error=c++0x-compat \
-	-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 \
-	-Os \
-	-fno-ident \
-	-fdata-sections \
-	-ffunction-sections \
-	-fomit-frame-pointer
-
-MY_DEFS_Release := \
-	'-DANGLE_DX11' \
-	'-D_FILE_OFFSET_BITS=64' \
-	'-DNO_TCMALLOC' \
-	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
-	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
-	'-DDISABLE_NACL' \
-	'-DCHROMIUM_BUILD' \
-	'-DUSE_LIBJPEG_TURBO=1' \
-	'-DUSE_PROPRIETARY_CODECS' \
-	'-DENABLE_CONFIGURATION_POLICY' \
-	'-DENABLE_GPU=1' \
-	'-DUSE_OPENSSL=1' \
-	'-DENABLE_EGLIMAGE=1' \
-	'-D__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-uninitialized \
-	-Wno-error=c++0x-compat \
-	-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))
-### Rules for final target.
-# Add target alias to "gyp_all_modules" target.
-.PHONY: gyp_all_modules
-gyp_all_modules: ppapi_ppapi_c_gyp
-
-# Alias gyp target name.
-.PHONY: ppapi_c
-ppapi_c: ppapi_ppapi_c_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/ppapi/ppapi_c.target.linux-x86.mk b/ppapi/ppapi_c.target.linux-x86.mk
deleted file mode 100644
index d8d46e0..0000000
--- a/ppapi/ppapi_c.target.linux-x86.mk
+++ /dev/null
@@ -1,209 +0,0 @@
-# This file is generated by gyp; do not edit.
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_CLASS := GYP
-LOCAL_MODULE := ppapi_ppapi_c_gyp
-LOCAL_MODULE_STEM := ppapi_c
-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 := \
-	--param=ssp-buffer-size=4 \
-	-Werror \
-	-fno-exceptions \
-	-fno-strict-aliasing \
-	-Wall \
-	-Wno-unused-parameter \
-	-Wno-missing-field-initializers \
-	-fvisibility=hidden \
-	-pipe \
-	-fPIC \
-	-m32 \
-	-mmmx \
-	-march=pentium4 \
-	-msse2 \
-	-mfpmath=sse \
-	-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 \
-	-fno-stack-protector \
-	-Os \
-	-g \
-	-fomit-frame-pointer \
-	-fdata-sections \
-	-ffunction-sections
-
-MY_DEFS_Debug := \
-	'-DANGLE_DX11' \
-	'-D_FILE_OFFSET_BITS=64' \
-	'-DNO_TCMALLOC' \
-	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
-	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
-	'-DDISABLE_NACL' \
-	'-DCHROMIUM_BUILD' \
-	'-DUSE_LIBJPEG_TURBO=1' \
-	'-DUSE_PROPRIETARY_CODECS' \
-	'-DENABLE_CONFIGURATION_POLICY' \
-	'-DENABLE_GPU=1' \
-	'-DUSE_OPENSSL=1' \
-	'-DENABLE_EGLIMAGE=1' \
-	'-D__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-error=c++0x-compat \
-	-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 \
-	-m32 \
-	-mmmx \
-	-march=pentium4 \
-	-msse2 \
-	-mfpmath=sse \
-	-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 \
-	-fno-stack-protector \
-	-Os \
-	-fno-ident \
-	-fdata-sections \
-	-ffunction-sections \
-	-fomit-frame-pointer \
-	-fno-unwind-tables \
-	-fno-asynchronous-unwind-tables
-
-MY_DEFS_Release := \
-	'-DANGLE_DX11' \
-	'-D_FILE_OFFSET_BITS=64' \
-	'-DNO_TCMALLOC' \
-	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
-	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
-	'-DDISABLE_NACL' \
-	'-DCHROMIUM_BUILD' \
-	'-DUSE_LIBJPEG_TURBO=1' \
-	'-DUSE_PROPRIETARY_CODECS' \
-	'-DENABLE_CONFIGURATION_POLICY' \
-	'-DENABLE_GPU=1' \
-	'-DUSE_OPENSSL=1' \
-	'-DENABLE_EGLIMAGE=1' \
-	'-D__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-error=c++0x-compat \
-	-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))
-### Rules for final target.
-# Add target alias to "gyp_all_modules" target.
-.PHONY: gyp_all_modules
-gyp_all_modules: ppapi_ppapi_c_gyp
-
-# Alias gyp target name.
-.PHONY: ppapi_c
-ppapi_c: ppapi_ppapi_c_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/ppapi/ppapi_proxy.gypi b/ppapi/ppapi_proxy.gypi
index 884dc15..e700d2c 100644
--- a/ppapi/ppapi_proxy.gypi
+++ b/ppapi/ppapi_proxy.gypi
@@ -113,8 +113,6 @@
           'proxy/ppb_buffer_proxy.h',
           'proxy/ppb_core_proxy.cc',
           'proxy/ppb_core_proxy.h',
-          'proxy/ppb_file_ref_proxy.cc',
-          'proxy/ppb_file_ref_proxy.h',
           'proxy/ppb_flash_message_loop_proxy.cc',
           'proxy/ppb_flash_message_loop_proxy.h',
           'proxy/ppb_graphics_3d_proxy.cc',
diff --git a/ppapi/ppapi_shared.gypi b/ppapi/ppapi_shared.gypi
index 1160143..f3129f8 100644
--- a/ppapi/ppapi_shared.gypi
+++ b/ppapi/ppapi_shared.gypi
@@ -23,7 +23,9 @@
           'shared_impl/file_io_state_manager.h',
           'shared_impl/file_path.cc',
           'shared_impl/file_path.h',
+          'shared_impl/file_ref_create_info.cc',
           'shared_impl/file_ref_create_info.h',
+          'shared_impl/file_ref_detailed_info.h',
           'shared_impl/file_ref_util.cc',
           'shared_impl/file_ref_util.h',
           'shared_impl/file_type_conversion.cc',
@@ -53,8 +55,6 @@
           'shared_impl/ppb_crypto_shared.cc',
           'shared_impl/ppb_device_ref_shared.cc',
           'shared_impl/ppb_device_ref_shared.h',
-          'shared_impl/ppb_file_ref_shared.cc',
-          'shared_impl/ppb_file_ref_shared.h',
           'shared_impl/ppb_gamepad_shared.cc',
           'shared_impl/ppb_gamepad_shared.h',
           'shared_impl/ppb_graphics_3d_shared.cc',
diff --git a/ppapi/ppapi_shared.target.darwin-arm.mk b/ppapi/ppapi_shared.target.darwin-arm.mk
deleted file mode 100644
index 2ad0583..0000000
--- a/ppapi/ppapi_shared.target.darwin-arm.mk
+++ /dev/null
@@ -1,459 +0,0 @@
-# This file is generated by gyp; do not edit.
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_CLASS := STATIC_LIBRARIES
-LOCAL_MODULE := ppapi_ppapi_shared_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_icuuc_gyp)/icuuc.stamp \
-	$(call intermediates-dir-for,GYP,ppapi_ppapi_c_gyp)/ppapi_c.stamp \
-	$(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 := \
-	ppapi/shared_impl/array_var.cc \
-	ppapi/shared_impl/array_writer.cc \
-	ppapi/shared_impl/callback_tracker.cc \
-	ppapi/shared_impl/dictionary_var.cc \
-	ppapi/shared_impl/file_io_state_manager.cc \
-	ppapi/shared_impl/file_path.cc \
-	ppapi/shared_impl/file_ref_util.cc \
-	ppapi/shared_impl/file_type_conversion.cc \
-	ppapi/shared_impl/flash_clipboard_format_registry.cc \
-	ppapi/shared_impl/host_resource.cc \
-	ppapi/shared_impl/id_assignment.cc \
-	ppapi/shared_impl/platform_file.cc \
-	ppapi/shared_impl/ppapi_globals.cc \
-	ppapi/shared_impl/ppapi_nacl_channel_args.cc \
-	ppapi/shared_impl/ppapi_permissions.cc \
-	ppapi/shared_impl/ppapi_preferences.cc \
-	ppapi/shared_impl/ppapi_switches.cc \
-	ppapi/shared_impl/ppb_audio_config_shared.cc \
-	ppapi/shared_impl/ppb_audio_shared.cc \
-	ppapi/shared_impl/ppb_crypto_shared.cc \
-	ppapi/shared_impl/ppb_device_ref_shared.cc \
-	ppapi/shared_impl/ppb_file_ref_shared.cc \
-	ppapi/shared_impl/ppb_gamepad_shared.cc \
-	ppapi/shared_impl/ppb_graphics_3d_shared.cc \
-	ppapi/shared_impl/ppb_image_data_shared.cc \
-	ppapi/shared_impl/ppb_input_event_shared.cc \
-	ppapi/shared_impl/ppb_instance_shared.cc \
-	ppapi/shared_impl/ppb_memory_shared.cc \
-	ppapi/shared_impl/ppb_message_loop_shared.cc \
-	ppapi/shared_impl/ppb_network_list_private_shared.cc \
-	ppapi/shared_impl/ppb_opengles2_shared.cc \
-	ppapi/shared_impl/ppb_resource_array_shared.cc \
-	ppapi/shared_impl/ppb_trace_event_impl.cc \
-	ppapi/shared_impl/ppb_url_util_shared.cc \
-	ppapi/shared_impl/ppb_var_shared.cc \
-	ppapi/shared_impl/ppb_video_decoder_shared.cc \
-	ppapi/shared_impl/ppb_view_shared.cc \
-	ppapi/shared_impl/ppp_instance_combined.cc \
-	ppapi/shared_impl/proxy_lock.cc \
-	ppapi/shared_impl/resource.cc \
-	ppapi/shared_impl/resource_tracker.cc \
-	ppapi/shared_impl/scoped_pp_resource.cc \
-	ppapi/shared_impl/scoped_pp_var.cc \
-	ppapi/shared_impl/socket_option_data.cc \
-	ppapi/shared_impl/tcp_socket_shared.cc \
-	ppapi/shared_impl/thread_aware_callback.cc \
-	ppapi/shared_impl/time_conversion.cc \
-	ppapi/shared_impl/tracked_callback.cc \
-	ppapi/shared_impl/url_request_info_data.cc \
-	ppapi/shared_impl/url_response_info_data.cc \
-	ppapi/shared_impl/var.cc \
-	ppapi/shared_impl/var_tracker.cc \
-	ppapi/shared_impl/var_value_conversions.cc \
-	ppapi/shared_impl/private/net_address_private_impl.cc \
-	ppapi/shared_impl/private/net_address_private_impl_constants.cc \
-	ppapi/shared_impl/private/ppb_char_set_shared.cc \
-	ppapi/shared_impl/private/ppb_x509_certificate_private_shared.cc \
-	ppapi/shared_impl/private/tcp_socket_private_impl.cc \
-	ppapi/thunk/enter.cc \
-	ppapi/thunk/ppb_audio_config_thunk.cc \
-	ppapi/thunk/ppb_audio_input_dev_thunk.cc \
-	ppapi/thunk/ppb_audio_thunk.cc \
-	ppapi/thunk/ppb_broker_thunk.cc \
-	ppapi/thunk/ppb_browser_font_trusted_thunk.cc \
-	ppapi/thunk/ppb_buffer_thunk.cc \
-	ppapi/thunk/ppb_char_set_thunk.cc \
-	ppapi/thunk/ppb_console_thunk.cc \
-	ppapi/thunk/ppb_content_decryptor_private_thunk.cc \
-	ppapi/thunk/ppb_cursor_control_thunk.cc \
-	ppapi/thunk/ppb_device_ref_dev_thunk.cc \
-	ppapi/thunk/ppb_ext_alarms_thunk.cc \
-	ppapi/thunk/ppb_ext_crx_file_system_private_thunk.cc \
-	ppapi/thunk/ppb_ext_socket_thunk.cc \
-	ppapi/thunk/ppb_file_chooser_dev_thunk.cc \
-	ppapi/thunk/ppb_file_chooser_trusted_thunk.cc \
-	ppapi/thunk/ppb_file_io_private_thunk.cc \
-	ppapi/thunk/ppb_file_io_thunk.cc \
-	ppapi/thunk/ppb_file_io_trusted_thunk.cc \
-	ppapi/thunk/ppb_file_ref_thunk.cc \
-	ppapi/thunk/ppb_file_system_thunk.cc \
-	ppapi/thunk/ppb_find_dev_thunk.cc \
-	ppapi/thunk/ppb_flash_clipboard_thunk.cc \
-	ppapi/thunk/ppb_flash_device_id_thunk.cc \
-	ppapi/thunk/ppb_flash_drm_thunk.cc \
-	ppapi/thunk/ppb_flash_file_fileref_thunk.cc \
-	ppapi/thunk/ppb_flash_file_modulelocal_thunk.cc \
-	ppapi/thunk/ppb_flash_font_file_thunk.cc \
-	ppapi/thunk/ppb_flash_fullscreen_thunk.cc \
-	ppapi/thunk/ppb_flash_menu_thunk.cc \
-	ppapi/thunk/ppb_flash_message_loop_thunk.cc \
-	ppapi/thunk/ppb_flash_print_thunk.cc \
-	ppapi/thunk/ppb_flash_thunk.cc \
-	ppapi/thunk/ppb_fullscreen_thunk.cc \
-	ppapi/thunk/ppb_gamepad_thunk.cc \
-	ppapi/thunk/ppb_gles_chromium_texture_mapping_thunk.cc \
-	ppapi/thunk/ppb_graphics_2d_dev_thunk.cc \
-	ppapi/thunk/ppb_graphics_2d_thunk.cc \
-	ppapi/thunk/ppb_graphics_3d_thunk.cc \
-	ppapi/thunk/ppb_host_resolver_thunk.cc \
-	ppapi/thunk/ppb_host_resolver_private_thunk.cc \
-	ppapi/thunk/ppb_image_data_thunk.cc \
-	ppapi/thunk/ppb_input_event_thunk.cc \
-	ppapi/thunk/ppb_instance_private_thunk.cc \
-	ppapi/thunk/ppb_instance_thunk.cc \
-	ppapi/thunk/ppb_messaging_thunk.cc \
-	ppapi/thunk/ppb_mouse_cursor_thunk.cc \
-	ppapi/thunk/ppb_mouse_lock_thunk.cc \
-	ppapi/thunk/ppb_net_address_thunk.cc \
-	ppapi/thunk/ppb_network_list_private_thunk.cc \
-	ppapi/thunk/ppb_network_monitor_private_thunk.cc \
-	ppapi/thunk/ppb_network_proxy_thunk.cc \
-	ppapi/thunk/ppb_pdf_thunk.cc \
-	ppapi/thunk/ppb_printing_dev_thunk.cc \
-	ppapi/thunk/ppb_resource_array_dev_thunk.cc \
-	ppapi/thunk/ppb_scrollbar_thunk.cc \
-	ppapi/thunk/ppb_talk_private_thunk.cc \
-	ppapi/thunk/ppb_tcp_server_socket_private_thunk.cc \
-	ppapi/thunk/ppb_tcp_socket_private_thunk.cc \
-	ppapi/thunk/ppb_tcp_socket_thunk.cc \
-	ppapi/thunk/ppb_text_input_thunk.cc \
-	ppapi/thunk/ppb_truetype_font_dev_thunk.cc \
-	ppapi/thunk/ppb_udp_socket_thunk.cc \
-	ppapi/thunk/ppb_udp_socket_private_thunk.cc \
-	ppapi/thunk/ppb_url_loader_thunk.cc \
-	ppapi/thunk/ppb_url_loader_trusted_thunk.cc \
-	ppapi/thunk/ppb_url_request_info_thunk.cc \
-	ppapi/thunk/ppb_url_response_info_thunk.cc \
-	ppapi/thunk/ppb_url_util_thunk.cc \
-	ppapi/thunk/ppb_var_array_thunk.cc \
-	ppapi/thunk/ppb_var_dictionary_thunk.cc \
-	ppapi/thunk/ppb_video_capture_thunk.cc \
-	ppapi/thunk/ppb_video_decoder_thunk.cc \
-	ppapi/thunk/ppb_video_destination_private_thunk.cc \
-	ppapi/thunk/ppb_video_source_private_thunk.cc \
-	ppapi/thunk/ppb_view_dev_thunk.cc \
-	ppapi/thunk/ppb_view_thunk.cc \
-	ppapi/thunk/ppb_websocket_thunk.cc \
-	ppapi/thunk/ppb_widget_dev_thunk.cc \
-	ppapi/thunk/ppb_x509_certificate_private_thunk.cc \
-	ppapi/thunk/ppb_zoom_dev_thunk.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 \
-	-Os \
-	-g \
-	-fomit-frame-pointer \
-	-fdata-sections \
-	-ffunction-sections
-
-MY_DEFS_Debug := \
-	'-DANGLE_DX11' \
-	'-D_FILE_OFFSET_BITS=64' \
-	'-DNO_TCMALLOC' \
-	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
-	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
-	'-DDISABLE_NACL' \
-	'-DCHROMIUM_BUILD' \
-	'-DUSE_LIBJPEG_TURBO=1' \
-	'-DUSE_PROPRIETARY_CODECS' \
-	'-DENABLE_CONFIGURATION_POLICY' \
-	'-DENABLE_GPU=1' \
-	'-DUSE_OPENSSL=1' \
-	'-DENABLE_EGLIMAGE=1' \
-	'-DSK_ENABLE_INST_COUNT=0' \
-	'-DSK_SUPPORT_GPU=1' \
-	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
-	'-DSK_BUILD_FOR_ANDROID' \
-	'-DUSE_CHROMIUM_SKIA' \
-	'-DSK_USE_POSIX_THREADS' \
-	'-DU_USING_ICU_NAMESPACE=0' \
-	'-D__STDC_CONSTANT_MACROS' \
-	'-D__STDC_FORMAT_MACROS' \
-	'-DPPAPI_SHARED_IMPLEMENTATION' \
-	'-DPPAPI_THUNK_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)/third_party/khronos \
-	$(LOCAL_PATH)/gpu \
-	$(LOCAL_PATH) \
-	$(LOCAL_PATH)/third_party/skia/src/core \
-	$(LOCAL_PATH)/skia/config \
-	$(LOCAL_PATH)/third_party/skia/include/config \
-	$(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/gpu/gl \
-	$(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)/third_party/npapi \
-	$(LOCAL_PATH)/third_party/npapi/bindings \
-	$(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-abi \
-	-Wno-error=c++0x-compat \
-	-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 \
-	-Os \
-	-fno-ident \
-	-fdata-sections \
-	-ffunction-sections \
-	-fomit-frame-pointer
-
-MY_DEFS_Release := \
-	'-DANGLE_DX11' \
-	'-D_FILE_OFFSET_BITS=64' \
-	'-DNO_TCMALLOC' \
-	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
-	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
-	'-DDISABLE_NACL' \
-	'-DCHROMIUM_BUILD' \
-	'-DUSE_LIBJPEG_TURBO=1' \
-	'-DUSE_PROPRIETARY_CODECS' \
-	'-DENABLE_CONFIGURATION_POLICY' \
-	'-DENABLE_GPU=1' \
-	'-DUSE_OPENSSL=1' \
-	'-DENABLE_EGLIMAGE=1' \
-	'-DSK_ENABLE_INST_COUNT=0' \
-	'-DSK_SUPPORT_GPU=1' \
-	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
-	'-DSK_BUILD_FOR_ANDROID' \
-	'-DUSE_CHROMIUM_SKIA' \
-	'-DSK_USE_POSIX_THREADS' \
-	'-DU_USING_ICU_NAMESPACE=0' \
-	'-D__STDC_CONSTANT_MACROS' \
-	'-D__STDC_FORMAT_MACROS' \
-	'-DPPAPI_SHARED_IMPLEMENTATION' \
-	'-DPPAPI_THUNK_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)/third_party/khronos \
-	$(LOCAL_PATH)/gpu \
-	$(LOCAL_PATH) \
-	$(LOCAL_PATH)/third_party/skia/src/core \
-	$(LOCAL_PATH)/skia/config \
-	$(LOCAL_PATH)/third_party/skia/include/config \
-	$(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/gpu/gl \
-	$(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)/third_party/npapi \
-	$(LOCAL_PATH)/third_party/npapi/bindings \
-	$(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-abi \
-	-Wno-error=c++0x-compat \
-	-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))
-### Rules for final target.
-
-LOCAL_LDFLAGS_Debug := \
-	-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,-O1 \
-	-Wl,--as-needed
-
-
-LOCAL_LDFLAGS_Release := \
-	-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
-
-
-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: ppapi_ppapi_shared_gyp
-
-# Alias gyp target name.
-.PHONY: ppapi_shared
-ppapi_shared: ppapi_ppapi_shared_gyp
-
-include $(BUILD_STATIC_LIBRARY)
diff --git a/ppapi/ppapi_shared.target.darwin-mips.mk b/ppapi/ppapi_shared.target.darwin-mips.mk
deleted file mode 100644
index d785a4c..0000000
--- a/ppapi/ppapi_shared.target.darwin-mips.mk
+++ /dev/null
@@ -1,453 +0,0 @@
-# This file is generated by gyp; do not edit.
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_CLASS := STATIC_LIBRARIES
-LOCAL_MODULE := ppapi_ppapi_shared_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_icuuc_gyp)/icuuc.stamp \
-	$(call intermediates-dir-for,GYP,ppapi_ppapi_c_gyp)/ppapi_c.stamp \
-	$(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 := \
-	ppapi/shared_impl/array_var.cc \
-	ppapi/shared_impl/array_writer.cc \
-	ppapi/shared_impl/callback_tracker.cc \
-	ppapi/shared_impl/dictionary_var.cc \
-	ppapi/shared_impl/file_io_state_manager.cc \
-	ppapi/shared_impl/file_path.cc \
-	ppapi/shared_impl/file_ref_util.cc \
-	ppapi/shared_impl/file_type_conversion.cc \
-	ppapi/shared_impl/flash_clipboard_format_registry.cc \
-	ppapi/shared_impl/host_resource.cc \
-	ppapi/shared_impl/id_assignment.cc \
-	ppapi/shared_impl/platform_file.cc \
-	ppapi/shared_impl/ppapi_globals.cc \
-	ppapi/shared_impl/ppapi_nacl_channel_args.cc \
-	ppapi/shared_impl/ppapi_permissions.cc \
-	ppapi/shared_impl/ppapi_preferences.cc \
-	ppapi/shared_impl/ppapi_switches.cc \
-	ppapi/shared_impl/ppb_audio_config_shared.cc \
-	ppapi/shared_impl/ppb_audio_shared.cc \
-	ppapi/shared_impl/ppb_crypto_shared.cc \
-	ppapi/shared_impl/ppb_device_ref_shared.cc \
-	ppapi/shared_impl/ppb_file_ref_shared.cc \
-	ppapi/shared_impl/ppb_gamepad_shared.cc \
-	ppapi/shared_impl/ppb_graphics_3d_shared.cc \
-	ppapi/shared_impl/ppb_image_data_shared.cc \
-	ppapi/shared_impl/ppb_input_event_shared.cc \
-	ppapi/shared_impl/ppb_instance_shared.cc \
-	ppapi/shared_impl/ppb_memory_shared.cc \
-	ppapi/shared_impl/ppb_message_loop_shared.cc \
-	ppapi/shared_impl/ppb_network_list_private_shared.cc \
-	ppapi/shared_impl/ppb_opengles2_shared.cc \
-	ppapi/shared_impl/ppb_resource_array_shared.cc \
-	ppapi/shared_impl/ppb_trace_event_impl.cc \
-	ppapi/shared_impl/ppb_url_util_shared.cc \
-	ppapi/shared_impl/ppb_var_shared.cc \
-	ppapi/shared_impl/ppb_video_decoder_shared.cc \
-	ppapi/shared_impl/ppb_view_shared.cc \
-	ppapi/shared_impl/ppp_instance_combined.cc \
-	ppapi/shared_impl/proxy_lock.cc \
-	ppapi/shared_impl/resource.cc \
-	ppapi/shared_impl/resource_tracker.cc \
-	ppapi/shared_impl/scoped_pp_resource.cc \
-	ppapi/shared_impl/scoped_pp_var.cc \
-	ppapi/shared_impl/socket_option_data.cc \
-	ppapi/shared_impl/tcp_socket_shared.cc \
-	ppapi/shared_impl/thread_aware_callback.cc \
-	ppapi/shared_impl/time_conversion.cc \
-	ppapi/shared_impl/tracked_callback.cc \
-	ppapi/shared_impl/url_request_info_data.cc \
-	ppapi/shared_impl/url_response_info_data.cc \
-	ppapi/shared_impl/var.cc \
-	ppapi/shared_impl/var_tracker.cc \
-	ppapi/shared_impl/var_value_conversions.cc \
-	ppapi/shared_impl/private/net_address_private_impl.cc \
-	ppapi/shared_impl/private/net_address_private_impl_constants.cc \
-	ppapi/shared_impl/private/ppb_char_set_shared.cc \
-	ppapi/shared_impl/private/ppb_x509_certificate_private_shared.cc \
-	ppapi/shared_impl/private/tcp_socket_private_impl.cc \
-	ppapi/thunk/enter.cc \
-	ppapi/thunk/ppb_audio_config_thunk.cc \
-	ppapi/thunk/ppb_audio_input_dev_thunk.cc \
-	ppapi/thunk/ppb_audio_thunk.cc \
-	ppapi/thunk/ppb_broker_thunk.cc \
-	ppapi/thunk/ppb_browser_font_trusted_thunk.cc \
-	ppapi/thunk/ppb_buffer_thunk.cc \
-	ppapi/thunk/ppb_char_set_thunk.cc \
-	ppapi/thunk/ppb_console_thunk.cc \
-	ppapi/thunk/ppb_content_decryptor_private_thunk.cc \
-	ppapi/thunk/ppb_cursor_control_thunk.cc \
-	ppapi/thunk/ppb_device_ref_dev_thunk.cc \
-	ppapi/thunk/ppb_ext_alarms_thunk.cc \
-	ppapi/thunk/ppb_ext_crx_file_system_private_thunk.cc \
-	ppapi/thunk/ppb_ext_socket_thunk.cc \
-	ppapi/thunk/ppb_file_chooser_dev_thunk.cc \
-	ppapi/thunk/ppb_file_chooser_trusted_thunk.cc \
-	ppapi/thunk/ppb_file_io_private_thunk.cc \
-	ppapi/thunk/ppb_file_io_thunk.cc \
-	ppapi/thunk/ppb_file_io_trusted_thunk.cc \
-	ppapi/thunk/ppb_file_ref_thunk.cc \
-	ppapi/thunk/ppb_file_system_thunk.cc \
-	ppapi/thunk/ppb_find_dev_thunk.cc \
-	ppapi/thunk/ppb_flash_clipboard_thunk.cc \
-	ppapi/thunk/ppb_flash_device_id_thunk.cc \
-	ppapi/thunk/ppb_flash_drm_thunk.cc \
-	ppapi/thunk/ppb_flash_file_fileref_thunk.cc \
-	ppapi/thunk/ppb_flash_file_modulelocal_thunk.cc \
-	ppapi/thunk/ppb_flash_font_file_thunk.cc \
-	ppapi/thunk/ppb_flash_fullscreen_thunk.cc \
-	ppapi/thunk/ppb_flash_menu_thunk.cc \
-	ppapi/thunk/ppb_flash_message_loop_thunk.cc \
-	ppapi/thunk/ppb_flash_print_thunk.cc \
-	ppapi/thunk/ppb_flash_thunk.cc \
-	ppapi/thunk/ppb_fullscreen_thunk.cc \
-	ppapi/thunk/ppb_gamepad_thunk.cc \
-	ppapi/thunk/ppb_gles_chromium_texture_mapping_thunk.cc \
-	ppapi/thunk/ppb_graphics_2d_dev_thunk.cc \
-	ppapi/thunk/ppb_graphics_2d_thunk.cc \
-	ppapi/thunk/ppb_graphics_3d_thunk.cc \
-	ppapi/thunk/ppb_host_resolver_thunk.cc \
-	ppapi/thunk/ppb_host_resolver_private_thunk.cc \
-	ppapi/thunk/ppb_image_data_thunk.cc \
-	ppapi/thunk/ppb_input_event_thunk.cc \
-	ppapi/thunk/ppb_instance_private_thunk.cc \
-	ppapi/thunk/ppb_instance_thunk.cc \
-	ppapi/thunk/ppb_messaging_thunk.cc \
-	ppapi/thunk/ppb_mouse_cursor_thunk.cc \
-	ppapi/thunk/ppb_mouse_lock_thunk.cc \
-	ppapi/thunk/ppb_net_address_thunk.cc \
-	ppapi/thunk/ppb_network_list_private_thunk.cc \
-	ppapi/thunk/ppb_network_monitor_private_thunk.cc \
-	ppapi/thunk/ppb_network_proxy_thunk.cc \
-	ppapi/thunk/ppb_pdf_thunk.cc \
-	ppapi/thunk/ppb_printing_dev_thunk.cc \
-	ppapi/thunk/ppb_resource_array_dev_thunk.cc \
-	ppapi/thunk/ppb_scrollbar_thunk.cc \
-	ppapi/thunk/ppb_talk_private_thunk.cc \
-	ppapi/thunk/ppb_tcp_server_socket_private_thunk.cc \
-	ppapi/thunk/ppb_tcp_socket_private_thunk.cc \
-	ppapi/thunk/ppb_tcp_socket_thunk.cc \
-	ppapi/thunk/ppb_text_input_thunk.cc \
-	ppapi/thunk/ppb_truetype_font_dev_thunk.cc \
-	ppapi/thunk/ppb_udp_socket_thunk.cc \
-	ppapi/thunk/ppb_udp_socket_private_thunk.cc \
-	ppapi/thunk/ppb_url_loader_thunk.cc \
-	ppapi/thunk/ppb_url_loader_trusted_thunk.cc \
-	ppapi/thunk/ppb_url_request_info_thunk.cc \
-	ppapi/thunk/ppb_url_response_info_thunk.cc \
-	ppapi/thunk/ppb_url_util_thunk.cc \
-	ppapi/thunk/ppb_var_array_thunk.cc \
-	ppapi/thunk/ppb_var_dictionary_thunk.cc \
-	ppapi/thunk/ppb_video_capture_thunk.cc \
-	ppapi/thunk/ppb_video_decoder_thunk.cc \
-	ppapi/thunk/ppb_video_destination_private_thunk.cc \
-	ppapi/thunk/ppb_video_source_private_thunk.cc \
-	ppapi/thunk/ppb_view_dev_thunk.cc \
-	ppapi/thunk/ppb_view_thunk.cc \
-	ppapi/thunk/ppb_websocket_thunk.cc \
-	ppapi/thunk/ppb_widget_dev_thunk.cc \
-	ppapi/thunk/ppb_x509_certificate_private_thunk.cc \
-	ppapi/thunk/ppb_zoom_dev_thunk.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 \
-	-Os \
-	-g \
-	-fomit-frame-pointer \
-	-fdata-sections \
-	-ffunction-sections
-
-MY_DEFS_Debug := \
-	'-DANGLE_DX11' \
-	'-D_FILE_OFFSET_BITS=64' \
-	'-DNO_TCMALLOC' \
-	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
-	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
-	'-DDISABLE_NACL' \
-	'-DCHROMIUM_BUILD' \
-	'-DUSE_LIBJPEG_TURBO=1' \
-	'-DUSE_PROPRIETARY_CODECS' \
-	'-DENABLE_CONFIGURATION_POLICY' \
-	'-DENABLE_GPU=1' \
-	'-DUSE_OPENSSL=1' \
-	'-DENABLE_EGLIMAGE=1' \
-	'-DSK_ENABLE_INST_COUNT=0' \
-	'-DSK_SUPPORT_GPU=1' \
-	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
-	'-DSK_BUILD_FOR_ANDROID' \
-	'-DUSE_CHROMIUM_SKIA' \
-	'-DSK_USE_POSIX_THREADS' \
-	'-DU_USING_ICU_NAMESPACE=0' \
-	'-D__STDC_CONSTANT_MACROS' \
-	'-D__STDC_FORMAT_MACROS' \
-	'-DPPAPI_SHARED_IMPLEMENTATION' \
-	'-DPPAPI_THUNK_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)/third_party/khronos \
-	$(LOCAL_PATH)/gpu \
-	$(LOCAL_PATH) \
-	$(LOCAL_PATH)/third_party/skia/src/core \
-	$(LOCAL_PATH)/skia/config \
-	$(LOCAL_PATH)/third_party/skia/include/config \
-	$(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/gpu/gl \
-	$(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)/third_party/npapi \
-	$(LOCAL_PATH)/third_party/npapi/bindings \
-	$(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-uninitialized \
-	-Wno-error=c++0x-compat \
-	-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 \
-	-Os \
-	-fno-ident \
-	-fdata-sections \
-	-ffunction-sections \
-	-fomit-frame-pointer
-
-MY_DEFS_Release := \
-	'-DANGLE_DX11' \
-	'-D_FILE_OFFSET_BITS=64' \
-	'-DNO_TCMALLOC' \
-	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
-	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
-	'-DDISABLE_NACL' \
-	'-DCHROMIUM_BUILD' \
-	'-DUSE_LIBJPEG_TURBO=1' \
-	'-DUSE_PROPRIETARY_CODECS' \
-	'-DENABLE_CONFIGURATION_POLICY' \
-	'-DENABLE_GPU=1' \
-	'-DUSE_OPENSSL=1' \
-	'-DENABLE_EGLIMAGE=1' \
-	'-DSK_ENABLE_INST_COUNT=0' \
-	'-DSK_SUPPORT_GPU=1' \
-	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
-	'-DSK_BUILD_FOR_ANDROID' \
-	'-DUSE_CHROMIUM_SKIA' \
-	'-DSK_USE_POSIX_THREADS' \
-	'-DU_USING_ICU_NAMESPACE=0' \
-	'-D__STDC_CONSTANT_MACROS' \
-	'-D__STDC_FORMAT_MACROS' \
-	'-DPPAPI_SHARED_IMPLEMENTATION' \
-	'-DPPAPI_THUNK_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)/third_party/khronos \
-	$(LOCAL_PATH)/gpu \
-	$(LOCAL_PATH) \
-	$(LOCAL_PATH)/third_party/skia/src/core \
-	$(LOCAL_PATH)/skia/config \
-	$(LOCAL_PATH)/third_party/skia/include/config \
-	$(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/gpu/gl \
-	$(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)/third_party/npapi \
-	$(LOCAL_PATH)/third_party/npapi/bindings \
-	$(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-uninitialized \
-	-Wno-error=c++0x-compat \
-	-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))
-### Rules for final target.
-
-LOCAL_LDFLAGS_Debug := \
-	-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,-O1 \
-	-Wl,--as-needed
-
-
-LOCAL_LDFLAGS_Release := \
-	-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
-
-
-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: ppapi_ppapi_shared_gyp
-
-# Alias gyp target name.
-.PHONY: ppapi_shared
-ppapi_shared: ppapi_ppapi_shared_gyp
-
-include $(BUILD_STATIC_LIBRARY)
diff --git a/ppapi/ppapi_shared.target.darwin-x86.mk b/ppapi/ppapi_shared.target.darwin-x86.mk
deleted file mode 100644
index 3cac2e9..0000000
--- a/ppapi/ppapi_shared.target.darwin-x86.mk
+++ /dev/null
@@ -1,459 +0,0 @@
-# This file is generated by gyp; do not edit.
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_CLASS := STATIC_LIBRARIES
-LOCAL_MODULE := ppapi_ppapi_shared_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_icuuc_gyp)/icuuc.stamp \
-	$(call intermediates-dir-for,GYP,ppapi_ppapi_c_gyp)/ppapi_c.stamp \
-	$(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 := \
-	ppapi/shared_impl/array_var.cc \
-	ppapi/shared_impl/array_writer.cc \
-	ppapi/shared_impl/callback_tracker.cc \
-	ppapi/shared_impl/dictionary_var.cc \
-	ppapi/shared_impl/file_io_state_manager.cc \
-	ppapi/shared_impl/file_path.cc \
-	ppapi/shared_impl/file_ref_util.cc \
-	ppapi/shared_impl/file_type_conversion.cc \
-	ppapi/shared_impl/flash_clipboard_format_registry.cc \
-	ppapi/shared_impl/host_resource.cc \
-	ppapi/shared_impl/id_assignment.cc \
-	ppapi/shared_impl/platform_file.cc \
-	ppapi/shared_impl/ppapi_globals.cc \
-	ppapi/shared_impl/ppapi_nacl_channel_args.cc \
-	ppapi/shared_impl/ppapi_permissions.cc \
-	ppapi/shared_impl/ppapi_preferences.cc \
-	ppapi/shared_impl/ppapi_switches.cc \
-	ppapi/shared_impl/ppb_audio_config_shared.cc \
-	ppapi/shared_impl/ppb_audio_shared.cc \
-	ppapi/shared_impl/ppb_crypto_shared.cc \
-	ppapi/shared_impl/ppb_device_ref_shared.cc \
-	ppapi/shared_impl/ppb_file_ref_shared.cc \
-	ppapi/shared_impl/ppb_gamepad_shared.cc \
-	ppapi/shared_impl/ppb_graphics_3d_shared.cc \
-	ppapi/shared_impl/ppb_image_data_shared.cc \
-	ppapi/shared_impl/ppb_input_event_shared.cc \
-	ppapi/shared_impl/ppb_instance_shared.cc \
-	ppapi/shared_impl/ppb_memory_shared.cc \
-	ppapi/shared_impl/ppb_message_loop_shared.cc \
-	ppapi/shared_impl/ppb_network_list_private_shared.cc \
-	ppapi/shared_impl/ppb_opengles2_shared.cc \
-	ppapi/shared_impl/ppb_resource_array_shared.cc \
-	ppapi/shared_impl/ppb_trace_event_impl.cc \
-	ppapi/shared_impl/ppb_url_util_shared.cc \
-	ppapi/shared_impl/ppb_var_shared.cc \
-	ppapi/shared_impl/ppb_video_decoder_shared.cc \
-	ppapi/shared_impl/ppb_view_shared.cc \
-	ppapi/shared_impl/ppp_instance_combined.cc \
-	ppapi/shared_impl/proxy_lock.cc \
-	ppapi/shared_impl/resource.cc \
-	ppapi/shared_impl/resource_tracker.cc \
-	ppapi/shared_impl/scoped_pp_resource.cc \
-	ppapi/shared_impl/scoped_pp_var.cc \
-	ppapi/shared_impl/socket_option_data.cc \
-	ppapi/shared_impl/tcp_socket_shared.cc \
-	ppapi/shared_impl/thread_aware_callback.cc \
-	ppapi/shared_impl/time_conversion.cc \
-	ppapi/shared_impl/tracked_callback.cc \
-	ppapi/shared_impl/url_request_info_data.cc \
-	ppapi/shared_impl/url_response_info_data.cc \
-	ppapi/shared_impl/var.cc \
-	ppapi/shared_impl/var_tracker.cc \
-	ppapi/shared_impl/var_value_conversions.cc \
-	ppapi/shared_impl/private/net_address_private_impl.cc \
-	ppapi/shared_impl/private/net_address_private_impl_constants.cc \
-	ppapi/shared_impl/private/ppb_char_set_shared.cc \
-	ppapi/shared_impl/private/ppb_x509_certificate_private_shared.cc \
-	ppapi/shared_impl/private/tcp_socket_private_impl.cc \
-	ppapi/thunk/enter.cc \
-	ppapi/thunk/ppb_audio_config_thunk.cc \
-	ppapi/thunk/ppb_audio_input_dev_thunk.cc \
-	ppapi/thunk/ppb_audio_thunk.cc \
-	ppapi/thunk/ppb_broker_thunk.cc \
-	ppapi/thunk/ppb_browser_font_trusted_thunk.cc \
-	ppapi/thunk/ppb_buffer_thunk.cc \
-	ppapi/thunk/ppb_char_set_thunk.cc \
-	ppapi/thunk/ppb_console_thunk.cc \
-	ppapi/thunk/ppb_content_decryptor_private_thunk.cc \
-	ppapi/thunk/ppb_cursor_control_thunk.cc \
-	ppapi/thunk/ppb_device_ref_dev_thunk.cc \
-	ppapi/thunk/ppb_ext_alarms_thunk.cc \
-	ppapi/thunk/ppb_ext_crx_file_system_private_thunk.cc \
-	ppapi/thunk/ppb_ext_socket_thunk.cc \
-	ppapi/thunk/ppb_file_chooser_dev_thunk.cc \
-	ppapi/thunk/ppb_file_chooser_trusted_thunk.cc \
-	ppapi/thunk/ppb_file_io_private_thunk.cc \
-	ppapi/thunk/ppb_file_io_thunk.cc \
-	ppapi/thunk/ppb_file_io_trusted_thunk.cc \
-	ppapi/thunk/ppb_file_ref_thunk.cc \
-	ppapi/thunk/ppb_file_system_thunk.cc \
-	ppapi/thunk/ppb_find_dev_thunk.cc \
-	ppapi/thunk/ppb_flash_clipboard_thunk.cc \
-	ppapi/thunk/ppb_flash_device_id_thunk.cc \
-	ppapi/thunk/ppb_flash_drm_thunk.cc \
-	ppapi/thunk/ppb_flash_file_fileref_thunk.cc \
-	ppapi/thunk/ppb_flash_file_modulelocal_thunk.cc \
-	ppapi/thunk/ppb_flash_font_file_thunk.cc \
-	ppapi/thunk/ppb_flash_fullscreen_thunk.cc \
-	ppapi/thunk/ppb_flash_menu_thunk.cc \
-	ppapi/thunk/ppb_flash_message_loop_thunk.cc \
-	ppapi/thunk/ppb_flash_print_thunk.cc \
-	ppapi/thunk/ppb_flash_thunk.cc \
-	ppapi/thunk/ppb_fullscreen_thunk.cc \
-	ppapi/thunk/ppb_gamepad_thunk.cc \
-	ppapi/thunk/ppb_gles_chromium_texture_mapping_thunk.cc \
-	ppapi/thunk/ppb_graphics_2d_dev_thunk.cc \
-	ppapi/thunk/ppb_graphics_2d_thunk.cc \
-	ppapi/thunk/ppb_graphics_3d_thunk.cc \
-	ppapi/thunk/ppb_host_resolver_thunk.cc \
-	ppapi/thunk/ppb_host_resolver_private_thunk.cc \
-	ppapi/thunk/ppb_image_data_thunk.cc \
-	ppapi/thunk/ppb_input_event_thunk.cc \
-	ppapi/thunk/ppb_instance_private_thunk.cc \
-	ppapi/thunk/ppb_instance_thunk.cc \
-	ppapi/thunk/ppb_messaging_thunk.cc \
-	ppapi/thunk/ppb_mouse_cursor_thunk.cc \
-	ppapi/thunk/ppb_mouse_lock_thunk.cc \
-	ppapi/thunk/ppb_net_address_thunk.cc \
-	ppapi/thunk/ppb_network_list_private_thunk.cc \
-	ppapi/thunk/ppb_network_monitor_private_thunk.cc \
-	ppapi/thunk/ppb_network_proxy_thunk.cc \
-	ppapi/thunk/ppb_pdf_thunk.cc \
-	ppapi/thunk/ppb_printing_dev_thunk.cc \
-	ppapi/thunk/ppb_resource_array_dev_thunk.cc \
-	ppapi/thunk/ppb_scrollbar_thunk.cc \
-	ppapi/thunk/ppb_talk_private_thunk.cc \
-	ppapi/thunk/ppb_tcp_server_socket_private_thunk.cc \
-	ppapi/thunk/ppb_tcp_socket_private_thunk.cc \
-	ppapi/thunk/ppb_tcp_socket_thunk.cc \
-	ppapi/thunk/ppb_text_input_thunk.cc \
-	ppapi/thunk/ppb_truetype_font_dev_thunk.cc \
-	ppapi/thunk/ppb_udp_socket_thunk.cc \
-	ppapi/thunk/ppb_udp_socket_private_thunk.cc \
-	ppapi/thunk/ppb_url_loader_thunk.cc \
-	ppapi/thunk/ppb_url_loader_trusted_thunk.cc \
-	ppapi/thunk/ppb_url_request_info_thunk.cc \
-	ppapi/thunk/ppb_url_response_info_thunk.cc \
-	ppapi/thunk/ppb_url_util_thunk.cc \
-	ppapi/thunk/ppb_var_array_thunk.cc \
-	ppapi/thunk/ppb_var_dictionary_thunk.cc \
-	ppapi/thunk/ppb_video_capture_thunk.cc \
-	ppapi/thunk/ppb_video_decoder_thunk.cc \
-	ppapi/thunk/ppb_video_destination_private_thunk.cc \
-	ppapi/thunk/ppb_video_source_private_thunk.cc \
-	ppapi/thunk/ppb_view_dev_thunk.cc \
-	ppapi/thunk/ppb_view_thunk.cc \
-	ppapi/thunk/ppb_websocket_thunk.cc \
-	ppapi/thunk/ppb_widget_dev_thunk.cc \
-	ppapi/thunk/ppb_x509_certificate_private_thunk.cc \
-	ppapi/thunk/ppb_zoom_dev_thunk.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 \
-	-m32 \
-	-mmmx \
-	-march=pentium4 \
-	-msse2 \
-	-mfpmath=sse \
-	-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 \
-	-fno-stack-protector \
-	-Os \
-	-g \
-	-fomit-frame-pointer \
-	-fdata-sections \
-	-ffunction-sections
-
-MY_DEFS_Debug := \
-	'-DANGLE_DX11' \
-	'-D_FILE_OFFSET_BITS=64' \
-	'-DNO_TCMALLOC' \
-	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
-	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
-	'-DDISABLE_NACL' \
-	'-DCHROMIUM_BUILD' \
-	'-DUSE_LIBJPEG_TURBO=1' \
-	'-DUSE_PROPRIETARY_CODECS' \
-	'-DENABLE_CONFIGURATION_POLICY' \
-	'-DENABLE_GPU=1' \
-	'-DUSE_OPENSSL=1' \
-	'-DENABLE_EGLIMAGE=1' \
-	'-DSK_ENABLE_INST_COUNT=0' \
-	'-DSK_SUPPORT_GPU=1' \
-	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
-	'-DSK_BUILD_FOR_ANDROID' \
-	'-DUSE_CHROMIUM_SKIA' \
-	'-DSK_USE_POSIX_THREADS' \
-	'-DU_USING_ICU_NAMESPACE=0' \
-	'-D__STDC_CONSTANT_MACROS' \
-	'-D__STDC_FORMAT_MACROS' \
-	'-DPPAPI_SHARED_IMPLEMENTATION' \
-	'-DPPAPI_THUNK_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)/third_party/khronos \
-	$(LOCAL_PATH)/gpu \
-	$(LOCAL_PATH) \
-	$(LOCAL_PATH)/third_party/skia/src/core \
-	$(LOCAL_PATH)/skia/config \
-	$(LOCAL_PATH)/third_party/skia/include/config \
-	$(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/gpu/gl \
-	$(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)/third_party/npapi \
-	$(LOCAL_PATH)/third_party/npapi/bindings \
-	$(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-error=c++0x-compat \
-	-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 \
-	-m32 \
-	-mmmx \
-	-march=pentium4 \
-	-msse2 \
-	-mfpmath=sse \
-	-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 \
-	-fno-stack-protector \
-	-Os \
-	-fno-ident \
-	-fdata-sections \
-	-ffunction-sections \
-	-fomit-frame-pointer \
-	-fno-unwind-tables \
-	-fno-asynchronous-unwind-tables
-
-MY_DEFS_Release := \
-	'-DANGLE_DX11' \
-	'-D_FILE_OFFSET_BITS=64' \
-	'-DNO_TCMALLOC' \
-	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
-	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
-	'-DDISABLE_NACL' \
-	'-DCHROMIUM_BUILD' \
-	'-DUSE_LIBJPEG_TURBO=1' \
-	'-DUSE_PROPRIETARY_CODECS' \
-	'-DENABLE_CONFIGURATION_POLICY' \
-	'-DENABLE_GPU=1' \
-	'-DUSE_OPENSSL=1' \
-	'-DENABLE_EGLIMAGE=1' \
-	'-DSK_ENABLE_INST_COUNT=0' \
-	'-DSK_SUPPORT_GPU=1' \
-	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
-	'-DSK_BUILD_FOR_ANDROID' \
-	'-DUSE_CHROMIUM_SKIA' \
-	'-DSK_USE_POSIX_THREADS' \
-	'-DU_USING_ICU_NAMESPACE=0' \
-	'-D__STDC_CONSTANT_MACROS' \
-	'-D__STDC_FORMAT_MACROS' \
-	'-DPPAPI_SHARED_IMPLEMENTATION' \
-	'-DPPAPI_THUNK_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)/third_party/khronos \
-	$(LOCAL_PATH)/gpu \
-	$(LOCAL_PATH) \
-	$(LOCAL_PATH)/third_party/skia/src/core \
-	$(LOCAL_PATH)/skia/config \
-	$(LOCAL_PATH)/third_party/skia/include/config \
-	$(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/gpu/gl \
-	$(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)/third_party/npapi \
-	$(LOCAL_PATH)/third_party/npapi/bindings \
-	$(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-error=c++0x-compat \
-	-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))
-### Rules for final target.
-
-LOCAL_LDFLAGS_Debug := \
-	-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,-O1 \
-	-Wl,--as-needed
-
-
-LOCAL_LDFLAGS_Release := \
-	-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
-
-
-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: ppapi_ppapi_shared_gyp
-
-# Alias gyp target name.
-.PHONY: ppapi_shared
-ppapi_shared: ppapi_ppapi_shared_gyp
-
-include $(BUILD_STATIC_LIBRARY)
diff --git a/ppapi/ppapi_shared.target.linux-arm.mk b/ppapi/ppapi_shared.target.linux-arm.mk
deleted file mode 100644
index 2ad0583..0000000
--- a/ppapi/ppapi_shared.target.linux-arm.mk
+++ /dev/null
@@ -1,459 +0,0 @@
-# This file is generated by gyp; do not edit.
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_CLASS := STATIC_LIBRARIES
-LOCAL_MODULE := ppapi_ppapi_shared_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_icuuc_gyp)/icuuc.stamp \
-	$(call intermediates-dir-for,GYP,ppapi_ppapi_c_gyp)/ppapi_c.stamp \
-	$(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 := \
-	ppapi/shared_impl/array_var.cc \
-	ppapi/shared_impl/array_writer.cc \
-	ppapi/shared_impl/callback_tracker.cc \
-	ppapi/shared_impl/dictionary_var.cc \
-	ppapi/shared_impl/file_io_state_manager.cc \
-	ppapi/shared_impl/file_path.cc \
-	ppapi/shared_impl/file_ref_util.cc \
-	ppapi/shared_impl/file_type_conversion.cc \
-	ppapi/shared_impl/flash_clipboard_format_registry.cc \
-	ppapi/shared_impl/host_resource.cc \
-	ppapi/shared_impl/id_assignment.cc \
-	ppapi/shared_impl/platform_file.cc \
-	ppapi/shared_impl/ppapi_globals.cc \
-	ppapi/shared_impl/ppapi_nacl_channel_args.cc \
-	ppapi/shared_impl/ppapi_permissions.cc \
-	ppapi/shared_impl/ppapi_preferences.cc \
-	ppapi/shared_impl/ppapi_switches.cc \
-	ppapi/shared_impl/ppb_audio_config_shared.cc \
-	ppapi/shared_impl/ppb_audio_shared.cc \
-	ppapi/shared_impl/ppb_crypto_shared.cc \
-	ppapi/shared_impl/ppb_device_ref_shared.cc \
-	ppapi/shared_impl/ppb_file_ref_shared.cc \
-	ppapi/shared_impl/ppb_gamepad_shared.cc \
-	ppapi/shared_impl/ppb_graphics_3d_shared.cc \
-	ppapi/shared_impl/ppb_image_data_shared.cc \
-	ppapi/shared_impl/ppb_input_event_shared.cc \
-	ppapi/shared_impl/ppb_instance_shared.cc \
-	ppapi/shared_impl/ppb_memory_shared.cc \
-	ppapi/shared_impl/ppb_message_loop_shared.cc \
-	ppapi/shared_impl/ppb_network_list_private_shared.cc \
-	ppapi/shared_impl/ppb_opengles2_shared.cc \
-	ppapi/shared_impl/ppb_resource_array_shared.cc \
-	ppapi/shared_impl/ppb_trace_event_impl.cc \
-	ppapi/shared_impl/ppb_url_util_shared.cc \
-	ppapi/shared_impl/ppb_var_shared.cc \
-	ppapi/shared_impl/ppb_video_decoder_shared.cc \
-	ppapi/shared_impl/ppb_view_shared.cc \
-	ppapi/shared_impl/ppp_instance_combined.cc \
-	ppapi/shared_impl/proxy_lock.cc \
-	ppapi/shared_impl/resource.cc \
-	ppapi/shared_impl/resource_tracker.cc \
-	ppapi/shared_impl/scoped_pp_resource.cc \
-	ppapi/shared_impl/scoped_pp_var.cc \
-	ppapi/shared_impl/socket_option_data.cc \
-	ppapi/shared_impl/tcp_socket_shared.cc \
-	ppapi/shared_impl/thread_aware_callback.cc \
-	ppapi/shared_impl/time_conversion.cc \
-	ppapi/shared_impl/tracked_callback.cc \
-	ppapi/shared_impl/url_request_info_data.cc \
-	ppapi/shared_impl/url_response_info_data.cc \
-	ppapi/shared_impl/var.cc \
-	ppapi/shared_impl/var_tracker.cc \
-	ppapi/shared_impl/var_value_conversions.cc \
-	ppapi/shared_impl/private/net_address_private_impl.cc \
-	ppapi/shared_impl/private/net_address_private_impl_constants.cc \
-	ppapi/shared_impl/private/ppb_char_set_shared.cc \
-	ppapi/shared_impl/private/ppb_x509_certificate_private_shared.cc \
-	ppapi/shared_impl/private/tcp_socket_private_impl.cc \
-	ppapi/thunk/enter.cc \
-	ppapi/thunk/ppb_audio_config_thunk.cc \
-	ppapi/thunk/ppb_audio_input_dev_thunk.cc \
-	ppapi/thunk/ppb_audio_thunk.cc \
-	ppapi/thunk/ppb_broker_thunk.cc \
-	ppapi/thunk/ppb_browser_font_trusted_thunk.cc \
-	ppapi/thunk/ppb_buffer_thunk.cc \
-	ppapi/thunk/ppb_char_set_thunk.cc \
-	ppapi/thunk/ppb_console_thunk.cc \
-	ppapi/thunk/ppb_content_decryptor_private_thunk.cc \
-	ppapi/thunk/ppb_cursor_control_thunk.cc \
-	ppapi/thunk/ppb_device_ref_dev_thunk.cc \
-	ppapi/thunk/ppb_ext_alarms_thunk.cc \
-	ppapi/thunk/ppb_ext_crx_file_system_private_thunk.cc \
-	ppapi/thunk/ppb_ext_socket_thunk.cc \
-	ppapi/thunk/ppb_file_chooser_dev_thunk.cc \
-	ppapi/thunk/ppb_file_chooser_trusted_thunk.cc \
-	ppapi/thunk/ppb_file_io_private_thunk.cc \
-	ppapi/thunk/ppb_file_io_thunk.cc \
-	ppapi/thunk/ppb_file_io_trusted_thunk.cc \
-	ppapi/thunk/ppb_file_ref_thunk.cc \
-	ppapi/thunk/ppb_file_system_thunk.cc \
-	ppapi/thunk/ppb_find_dev_thunk.cc \
-	ppapi/thunk/ppb_flash_clipboard_thunk.cc \
-	ppapi/thunk/ppb_flash_device_id_thunk.cc \
-	ppapi/thunk/ppb_flash_drm_thunk.cc \
-	ppapi/thunk/ppb_flash_file_fileref_thunk.cc \
-	ppapi/thunk/ppb_flash_file_modulelocal_thunk.cc \
-	ppapi/thunk/ppb_flash_font_file_thunk.cc \
-	ppapi/thunk/ppb_flash_fullscreen_thunk.cc \
-	ppapi/thunk/ppb_flash_menu_thunk.cc \
-	ppapi/thunk/ppb_flash_message_loop_thunk.cc \
-	ppapi/thunk/ppb_flash_print_thunk.cc \
-	ppapi/thunk/ppb_flash_thunk.cc \
-	ppapi/thunk/ppb_fullscreen_thunk.cc \
-	ppapi/thunk/ppb_gamepad_thunk.cc \
-	ppapi/thunk/ppb_gles_chromium_texture_mapping_thunk.cc \
-	ppapi/thunk/ppb_graphics_2d_dev_thunk.cc \
-	ppapi/thunk/ppb_graphics_2d_thunk.cc \
-	ppapi/thunk/ppb_graphics_3d_thunk.cc \
-	ppapi/thunk/ppb_host_resolver_thunk.cc \
-	ppapi/thunk/ppb_host_resolver_private_thunk.cc \
-	ppapi/thunk/ppb_image_data_thunk.cc \
-	ppapi/thunk/ppb_input_event_thunk.cc \
-	ppapi/thunk/ppb_instance_private_thunk.cc \
-	ppapi/thunk/ppb_instance_thunk.cc \
-	ppapi/thunk/ppb_messaging_thunk.cc \
-	ppapi/thunk/ppb_mouse_cursor_thunk.cc \
-	ppapi/thunk/ppb_mouse_lock_thunk.cc \
-	ppapi/thunk/ppb_net_address_thunk.cc \
-	ppapi/thunk/ppb_network_list_private_thunk.cc \
-	ppapi/thunk/ppb_network_monitor_private_thunk.cc \
-	ppapi/thunk/ppb_network_proxy_thunk.cc \
-	ppapi/thunk/ppb_pdf_thunk.cc \
-	ppapi/thunk/ppb_printing_dev_thunk.cc \
-	ppapi/thunk/ppb_resource_array_dev_thunk.cc \
-	ppapi/thunk/ppb_scrollbar_thunk.cc \
-	ppapi/thunk/ppb_talk_private_thunk.cc \
-	ppapi/thunk/ppb_tcp_server_socket_private_thunk.cc \
-	ppapi/thunk/ppb_tcp_socket_private_thunk.cc \
-	ppapi/thunk/ppb_tcp_socket_thunk.cc \
-	ppapi/thunk/ppb_text_input_thunk.cc \
-	ppapi/thunk/ppb_truetype_font_dev_thunk.cc \
-	ppapi/thunk/ppb_udp_socket_thunk.cc \
-	ppapi/thunk/ppb_udp_socket_private_thunk.cc \
-	ppapi/thunk/ppb_url_loader_thunk.cc \
-	ppapi/thunk/ppb_url_loader_trusted_thunk.cc \
-	ppapi/thunk/ppb_url_request_info_thunk.cc \
-	ppapi/thunk/ppb_url_response_info_thunk.cc \
-	ppapi/thunk/ppb_url_util_thunk.cc \
-	ppapi/thunk/ppb_var_array_thunk.cc \
-	ppapi/thunk/ppb_var_dictionary_thunk.cc \
-	ppapi/thunk/ppb_video_capture_thunk.cc \
-	ppapi/thunk/ppb_video_decoder_thunk.cc \
-	ppapi/thunk/ppb_video_destination_private_thunk.cc \
-	ppapi/thunk/ppb_video_source_private_thunk.cc \
-	ppapi/thunk/ppb_view_dev_thunk.cc \
-	ppapi/thunk/ppb_view_thunk.cc \
-	ppapi/thunk/ppb_websocket_thunk.cc \
-	ppapi/thunk/ppb_widget_dev_thunk.cc \
-	ppapi/thunk/ppb_x509_certificate_private_thunk.cc \
-	ppapi/thunk/ppb_zoom_dev_thunk.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 \
-	-Os \
-	-g \
-	-fomit-frame-pointer \
-	-fdata-sections \
-	-ffunction-sections
-
-MY_DEFS_Debug := \
-	'-DANGLE_DX11' \
-	'-D_FILE_OFFSET_BITS=64' \
-	'-DNO_TCMALLOC' \
-	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
-	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
-	'-DDISABLE_NACL' \
-	'-DCHROMIUM_BUILD' \
-	'-DUSE_LIBJPEG_TURBO=1' \
-	'-DUSE_PROPRIETARY_CODECS' \
-	'-DENABLE_CONFIGURATION_POLICY' \
-	'-DENABLE_GPU=1' \
-	'-DUSE_OPENSSL=1' \
-	'-DENABLE_EGLIMAGE=1' \
-	'-DSK_ENABLE_INST_COUNT=0' \
-	'-DSK_SUPPORT_GPU=1' \
-	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
-	'-DSK_BUILD_FOR_ANDROID' \
-	'-DUSE_CHROMIUM_SKIA' \
-	'-DSK_USE_POSIX_THREADS' \
-	'-DU_USING_ICU_NAMESPACE=0' \
-	'-D__STDC_CONSTANT_MACROS' \
-	'-D__STDC_FORMAT_MACROS' \
-	'-DPPAPI_SHARED_IMPLEMENTATION' \
-	'-DPPAPI_THUNK_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)/third_party/khronos \
-	$(LOCAL_PATH)/gpu \
-	$(LOCAL_PATH) \
-	$(LOCAL_PATH)/third_party/skia/src/core \
-	$(LOCAL_PATH)/skia/config \
-	$(LOCAL_PATH)/third_party/skia/include/config \
-	$(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/gpu/gl \
-	$(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)/third_party/npapi \
-	$(LOCAL_PATH)/third_party/npapi/bindings \
-	$(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-abi \
-	-Wno-error=c++0x-compat \
-	-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 \
-	-Os \
-	-fno-ident \
-	-fdata-sections \
-	-ffunction-sections \
-	-fomit-frame-pointer
-
-MY_DEFS_Release := \
-	'-DANGLE_DX11' \
-	'-D_FILE_OFFSET_BITS=64' \
-	'-DNO_TCMALLOC' \
-	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
-	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
-	'-DDISABLE_NACL' \
-	'-DCHROMIUM_BUILD' \
-	'-DUSE_LIBJPEG_TURBO=1' \
-	'-DUSE_PROPRIETARY_CODECS' \
-	'-DENABLE_CONFIGURATION_POLICY' \
-	'-DENABLE_GPU=1' \
-	'-DUSE_OPENSSL=1' \
-	'-DENABLE_EGLIMAGE=1' \
-	'-DSK_ENABLE_INST_COUNT=0' \
-	'-DSK_SUPPORT_GPU=1' \
-	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
-	'-DSK_BUILD_FOR_ANDROID' \
-	'-DUSE_CHROMIUM_SKIA' \
-	'-DSK_USE_POSIX_THREADS' \
-	'-DU_USING_ICU_NAMESPACE=0' \
-	'-D__STDC_CONSTANT_MACROS' \
-	'-D__STDC_FORMAT_MACROS' \
-	'-DPPAPI_SHARED_IMPLEMENTATION' \
-	'-DPPAPI_THUNK_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)/third_party/khronos \
-	$(LOCAL_PATH)/gpu \
-	$(LOCAL_PATH) \
-	$(LOCAL_PATH)/third_party/skia/src/core \
-	$(LOCAL_PATH)/skia/config \
-	$(LOCAL_PATH)/third_party/skia/include/config \
-	$(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/gpu/gl \
-	$(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)/third_party/npapi \
-	$(LOCAL_PATH)/third_party/npapi/bindings \
-	$(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-abi \
-	-Wno-error=c++0x-compat \
-	-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))
-### Rules for final target.
-
-LOCAL_LDFLAGS_Debug := \
-	-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,-O1 \
-	-Wl,--as-needed
-
-
-LOCAL_LDFLAGS_Release := \
-	-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
-
-
-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: ppapi_ppapi_shared_gyp
-
-# Alias gyp target name.
-.PHONY: ppapi_shared
-ppapi_shared: ppapi_ppapi_shared_gyp
-
-include $(BUILD_STATIC_LIBRARY)
diff --git a/ppapi/ppapi_shared.target.linux-mips.mk b/ppapi/ppapi_shared.target.linux-mips.mk
deleted file mode 100644
index d785a4c..0000000
--- a/ppapi/ppapi_shared.target.linux-mips.mk
+++ /dev/null
@@ -1,453 +0,0 @@
-# This file is generated by gyp; do not edit.
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_CLASS := STATIC_LIBRARIES
-LOCAL_MODULE := ppapi_ppapi_shared_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_icuuc_gyp)/icuuc.stamp \
-	$(call intermediates-dir-for,GYP,ppapi_ppapi_c_gyp)/ppapi_c.stamp \
-	$(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 := \
-	ppapi/shared_impl/array_var.cc \
-	ppapi/shared_impl/array_writer.cc \
-	ppapi/shared_impl/callback_tracker.cc \
-	ppapi/shared_impl/dictionary_var.cc \
-	ppapi/shared_impl/file_io_state_manager.cc \
-	ppapi/shared_impl/file_path.cc \
-	ppapi/shared_impl/file_ref_util.cc \
-	ppapi/shared_impl/file_type_conversion.cc \
-	ppapi/shared_impl/flash_clipboard_format_registry.cc \
-	ppapi/shared_impl/host_resource.cc \
-	ppapi/shared_impl/id_assignment.cc \
-	ppapi/shared_impl/platform_file.cc \
-	ppapi/shared_impl/ppapi_globals.cc \
-	ppapi/shared_impl/ppapi_nacl_channel_args.cc \
-	ppapi/shared_impl/ppapi_permissions.cc \
-	ppapi/shared_impl/ppapi_preferences.cc \
-	ppapi/shared_impl/ppapi_switches.cc \
-	ppapi/shared_impl/ppb_audio_config_shared.cc \
-	ppapi/shared_impl/ppb_audio_shared.cc \
-	ppapi/shared_impl/ppb_crypto_shared.cc \
-	ppapi/shared_impl/ppb_device_ref_shared.cc \
-	ppapi/shared_impl/ppb_file_ref_shared.cc \
-	ppapi/shared_impl/ppb_gamepad_shared.cc \
-	ppapi/shared_impl/ppb_graphics_3d_shared.cc \
-	ppapi/shared_impl/ppb_image_data_shared.cc \
-	ppapi/shared_impl/ppb_input_event_shared.cc \
-	ppapi/shared_impl/ppb_instance_shared.cc \
-	ppapi/shared_impl/ppb_memory_shared.cc \
-	ppapi/shared_impl/ppb_message_loop_shared.cc \
-	ppapi/shared_impl/ppb_network_list_private_shared.cc \
-	ppapi/shared_impl/ppb_opengles2_shared.cc \
-	ppapi/shared_impl/ppb_resource_array_shared.cc \
-	ppapi/shared_impl/ppb_trace_event_impl.cc \
-	ppapi/shared_impl/ppb_url_util_shared.cc \
-	ppapi/shared_impl/ppb_var_shared.cc \
-	ppapi/shared_impl/ppb_video_decoder_shared.cc \
-	ppapi/shared_impl/ppb_view_shared.cc \
-	ppapi/shared_impl/ppp_instance_combined.cc \
-	ppapi/shared_impl/proxy_lock.cc \
-	ppapi/shared_impl/resource.cc \
-	ppapi/shared_impl/resource_tracker.cc \
-	ppapi/shared_impl/scoped_pp_resource.cc \
-	ppapi/shared_impl/scoped_pp_var.cc \
-	ppapi/shared_impl/socket_option_data.cc \
-	ppapi/shared_impl/tcp_socket_shared.cc \
-	ppapi/shared_impl/thread_aware_callback.cc \
-	ppapi/shared_impl/time_conversion.cc \
-	ppapi/shared_impl/tracked_callback.cc \
-	ppapi/shared_impl/url_request_info_data.cc \
-	ppapi/shared_impl/url_response_info_data.cc \
-	ppapi/shared_impl/var.cc \
-	ppapi/shared_impl/var_tracker.cc \
-	ppapi/shared_impl/var_value_conversions.cc \
-	ppapi/shared_impl/private/net_address_private_impl.cc \
-	ppapi/shared_impl/private/net_address_private_impl_constants.cc \
-	ppapi/shared_impl/private/ppb_char_set_shared.cc \
-	ppapi/shared_impl/private/ppb_x509_certificate_private_shared.cc \
-	ppapi/shared_impl/private/tcp_socket_private_impl.cc \
-	ppapi/thunk/enter.cc \
-	ppapi/thunk/ppb_audio_config_thunk.cc \
-	ppapi/thunk/ppb_audio_input_dev_thunk.cc \
-	ppapi/thunk/ppb_audio_thunk.cc \
-	ppapi/thunk/ppb_broker_thunk.cc \
-	ppapi/thunk/ppb_browser_font_trusted_thunk.cc \
-	ppapi/thunk/ppb_buffer_thunk.cc \
-	ppapi/thunk/ppb_char_set_thunk.cc \
-	ppapi/thunk/ppb_console_thunk.cc \
-	ppapi/thunk/ppb_content_decryptor_private_thunk.cc \
-	ppapi/thunk/ppb_cursor_control_thunk.cc \
-	ppapi/thunk/ppb_device_ref_dev_thunk.cc \
-	ppapi/thunk/ppb_ext_alarms_thunk.cc \
-	ppapi/thunk/ppb_ext_crx_file_system_private_thunk.cc \
-	ppapi/thunk/ppb_ext_socket_thunk.cc \
-	ppapi/thunk/ppb_file_chooser_dev_thunk.cc \
-	ppapi/thunk/ppb_file_chooser_trusted_thunk.cc \
-	ppapi/thunk/ppb_file_io_private_thunk.cc \
-	ppapi/thunk/ppb_file_io_thunk.cc \
-	ppapi/thunk/ppb_file_io_trusted_thunk.cc \
-	ppapi/thunk/ppb_file_ref_thunk.cc \
-	ppapi/thunk/ppb_file_system_thunk.cc \
-	ppapi/thunk/ppb_find_dev_thunk.cc \
-	ppapi/thunk/ppb_flash_clipboard_thunk.cc \
-	ppapi/thunk/ppb_flash_device_id_thunk.cc \
-	ppapi/thunk/ppb_flash_drm_thunk.cc \
-	ppapi/thunk/ppb_flash_file_fileref_thunk.cc \
-	ppapi/thunk/ppb_flash_file_modulelocal_thunk.cc \
-	ppapi/thunk/ppb_flash_font_file_thunk.cc \
-	ppapi/thunk/ppb_flash_fullscreen_thunk.cc \
-	ppapi/thunk/ppb_flash_menu_thunk.cc \
-	ppapi/thunk/ppb_flash_message_loop_thunk.cc \
-	ppapi/thunk/ppb_flash_print_thunk.cc \
-	ppapi/thunk/ppb_flash_thunk.cc \
-	ppapi/thunk/ppb_fullscreen_thunk.cc \
-	ppapi/thunk/ppb_gamepad_thunk.cc \
-	ppapi/thunk/ppb_gles_chromium_texture_mapping_thunk.cc \
-	ppapi/thunk/ppb_graphics_2d_dev_thunk.cc \
-	ppapi/thunk/ppb_graphics_2d_thunk.cc \
-	ppapi/thunk/ppb_graphics_3d_thunk.cc \
-	ppapi/thunk/ppb_host_resolver_thunk.cc \
-	ppapi/thunk/ppb_host_resolver_private_thunk.cc \
-	ppapi/thunk/ppb_image_data_thunk.cc \
-	ppapi/thunk/ppb_input_event_thunk.cc \
-	ppapi/thunk/ppb_instance_private_thunk.cc \
-	ppapi/thunk/ppb_instance_thunk.cc \
-	ppapi/thunk/ppb_messaging_thunk.cc \
-	ppapi/thunk/ppb_mouse_cursor_thunk.cc \
-	ppapi/thunk/ppb_mouse_lock_thunk.cc \
-	ppapi/thunk/ppb_net_address_thunk.cc \
-	ppapi/thunk/ppb_network_list_private_thunk.cc \
-	ppapi/thunk/ppb_network_monitor_private_thunk.cc \
-	ppapi/thunk/ppb_network_proxy_thunk.cc \
-	ppapi/thunk/ppb_pdf_thunk.cc \
-	ppapi/thunk/ppb_printing_dev_thunk.cc \
-	ppapi/thunk/ppb_resource_array_dev_thunk.cc \
-	ppapi/thunk/ppb_scrollbar_thunk.cc \
-	ppapi/thunk/ppb_talk_private_thunk.cc \
-	ppapi/thunk/ppb_tcp_server_socket_private_thunk.cc \
-	ppapi/thunk/ppb_tcp_socket_private_thunk.cc \
-	ppapi/thunk/ppb_tcp_socket_thunk.cc \
-	ppapi/thunk/ppb_text_input_thunk.cc \
-	ppapi/thunk/ppb_truetype_font_dev_thunk.cc \
-	ppapi/thunk/ppb_udp_socket_thunk.cc \
-	ppapi/thunk/ppb_udp_socket_private_thunk.cc \
-	ppapi/thunk/ppb_url_loader_thunk.cc \
-	ppapi/thunk/ppb_url_loader_trusted_thunk.cc \
-	ppapi/thunk/ppb_url_request_info_thunk.cc \
-	ppapi/thunk/ppb_url_response_info_thunk.cc \
-	ppapi/thunk/ppb_url_util_thunk.cc \
-	ppapi/thunk/ppb_var_array_thunk.cc \
-	ppapi/thunk/ppb_var_dictionary_thunk.cc \
-	ppapi/thunk/ppb_video_capture_thunk.cc \
-	ppapi/thunk/ppb_video_decoder_thunk.cc \
-	ppapi/thunk/ppb_video_destination_private_thunk.cc \
-	ppapi/thunk/ppb_video_source_private_thunk.cc \
-	ppapi/thunk/ppb_view_dev_thunk.cc \
-	ppapi/thunk/ppb_view_thunk.cc \
-	ppapi/thunk/ppb_websocket_thunk.cc \
-	ppapi/thunk/ppb_widget_dev_thunk.cc \
-	ppapi/thunk/ppb_x509_certificate_private_thunk.cc \
-	ppapi/thunk/ppb_zoom_dev_thunk.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 \
-	-Os \
-	-g \
-	-fomit-frame-pointer \
-	-fdata-sections \
-	-ffunction-sections
-
-MY_DEFS_Debug := \
-	'-DANGLE_DX11' \
-	'-D_FILE_OFFSET_BITS=64' \
-	'-DNO_TCMALLOC' \
-	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
-	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
-	'-DDISABLE_NACL' \
-	'-DCHROMIUM_BUILD' \
-	'-DUSE_LIBJPEG_TURBO=1' \
-	'-DUSE_PROPRIETARY_CODECS' \
-	'-DENABLE_CONFIGURATION_POLICY' \
-	'-DENABLE_GPU=1' \
-	'-DUSE_OPENSSL=1' \
-	'-DENABLE_EGLIMAGE=1' \
-	'-DSK_ENABLE_INST_COUNT=0' \
-	'-DSK_SUPPORT_GPU=1' \
-	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
-	'-DSK_BUILD_FOR_ANDROID' \
-	'-DUSE_CHROMIUM_SKIA' \
-	'-DSK_USE_POSIX_THREADS' \
-	'-DU_USING_ICU_NAMESPACE=0' \
-	'-D__STDC_CONSTANT_MACROS' \
-	'-D__STDC_FORMAT_MACROS' \
-	'-DPPAPI_SHARED_IMPLEMENTATION' \
-	'-DPPAPI_THUNK_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)/third_party/khronos \
-	$(LOCAL_PATH)/gpu \
-	$(LOCAL_PATH) \
-	$(LOCAL_PATH)/third_party/skia/src/core \
-	$(LOCAL_PATH)/skia/config \
-	$(LOCAL_PATH)/third_party/skia/include/config \
-	$(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/gpu/gl \
-	$(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)/third_party/npapi \
-	$(LOCAL_PATH)/third_party/npapi/bindings \
-	$(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-uninitialized \
-	-Wno-error=c++0x-compat \
-	-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 \
-	-Os \
-	-fno-ident \
-	-fdata-sections \
-	-ffunction-sections \
-	-fomit-frame-pointer
-
-MY_DEFS_Release := \
-	'-DANGLE_DX11' \
-	'-D_FILE_OFFSET_BITS=64' \
-	'-DNO_TCMALLOC' \
-	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
-	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
-	'-DDISABLE_NACL' \
-	'-DCHROMIUM_BUILD' \
-	'-DUSE_LIBJPEG_TURBO=1' \
-	'-DUSE_PROPRIETARY_CODECS' \
-	'-DENABLE_CONFIGURATION_POLICY' \
-	'-DENABLE_GPU=1' \
-	'-DUSE_OPENSSL=1' \
-	'-DENABLE_EGLIMAGE=1' \
-	'-DSK_ENABLE_INST_COUNT=0' \
-	'-DSK_SUPPORT_GPU=1' \
-	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
-	'-DSK_BUILD_FOR_ANDROID' \
-	'-DUSE_CHROMIUM_SKIA' \
-	'-DSK_USE_POSIX_THREADS' \
-	'-DU_USING_ICU_NAMESPACE=0' \
-	'-D__STDC_CONSTANT_MACROS' \
-	'-D__STDC_FORMAT_MACROS' \
-	'-DPPAPI_SHARED_IMPLEMENTATION' \
-	'-DPPAPI_THUNK_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)/third_party/khronos \
-	$(LOCAL_PATH)/gpu \
-	$(LOCAL_PATH) \
-	$(LOCAL_PATH)/third_party/skia/src/core \
-	$(LOCAL_PATH)/skia/config \
-	$(LOCAL_PATH)/third_party/skia/include/config \
-	$(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/gpu/gl \
-	$(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)/third_party/npapi \
-	$(LOCAL_PATH)/third_party/npapi/bindings \
-	$(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-uninitialized \
-	-Wno-error=c++0x-compat \
-	-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))
-### Rules for final target.
-
-LOCAL_LDFLAGS_Debug := \
-	-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,-O1 \
-	-Wl,--as-needed
-
-
-LOCAL_LDFLAGS_Release := \
-	-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
-
-
-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: ppapi_ppapi_shared_gyp
-
-# Alias gyp target name.
-.PHONY: ppapi_shared
-ppapi_shared: ppapi_ppapi_shared_gyp
-
-include $(BUILD_STATIC_LIBRARY)
diff --git a/ppapi/ppapi_shared.target.linux-x86.mk b/ppapi/ppapi_shared.target.linux-x86.mk
deleted file mode 100644
index 3cac2e9..0000000
--- a/ppapi/ppapi_shared.target.linux-x86.mk
+++ /dev/null
@@ -1,459 +0,0 @@
-# This file is generated by gyp; do not edit.
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_CLASS := STATIC_LIBRARIES
-LOCAL_MODULE := ppapi_ppapi_shared_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_icuuc_gyp)/icuuc.stamp \
-	$(call intermediates-dir-for,GYP,ppapi_ppapi_c_gyp)/ppapi_c.stamp \
-	$(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 := \
-	ppapi/shared_impl/array_var.cc \
-	ppapi/shared_impl/array_writer.cc \
-	ppapi/shared_impl/callback_tracker.cc \
-	ppapi/shared_impl/dictionary_var.cc \
-	ppapi/shared_impl/file_io_state_manager.cc \
-	ppapi/shared_impl/file_path.cc \
-	ppapi/shared_impl/file_ref_util.cc \
-	ppapi/shared_impl/file_type_conversion.cc \
-	ppapi/shared_impl/flash_clipboard_format_registry.cc \
-	ppapi/shared_impl/host_resource.cc \
-	ppapi/shared_impl/id_assignment.cc \
-	ppapi/shared_impl/platform_file.cc \
-	ppapi/shared_impl/ppapi_globals.cc \
-	ppapi/shared_impl/ppapi_nacl_channel_args.cc \
-	ppapi/shared_impl/ppapi_permissions.cc \
-	ppapi/shared_impl/ppapi_preferences.cc \
-	ppapi/shared_impl/ppapi_switches.cc \
-	ppapi/shared_impl/ppb_audio_config_shared.cc \
-	ppapi/shared_impl/ppb_audio_shared.cc \
-	ppapi/shared_impl/ppb_crypto_shared.cc \
-	ppapi/shared_impl/ppb_device_ref_shared.cc \
-	ppapi/shared_impl/ppb_file_ref_shared.cc \
-	ppapi/shared_impl/ppb_gamepad_shared.cc \
-	ppapi/shared_impl/ppb_graphics_3d_shared.cc \
-	ppapi/shared_impl/ppb_image_data_shared.cc \
-	ppapi/shared_impl/ppb_input_event_shared.cc \
-	ppapi/shared_impl/ppb_instance_shared.cc \
-	ppapi/shared_impl/ppb_memory_shared.cc \
-	ppapi/shared_impl/ppb_message_loop_shared.cc \
-	ppapi/shared_impl/ppb_network_list_private_shared.cc \
-	ppapi/shared_impl/ppb_opengles2_shared.cc \
-	ppapi/shared_impl/ppb_resource_array_shared.cc \
-	ppapi/shared_impl/ppb_trace_event_impl.cc \
-	ppapi/shared_impl/ppb_url_util_shared.cc \
-	ppapi/shared_impl/ppb_var_shared.cc \
-	ppapi/shared_impl/ppb_video_decoder_shared.cc \
-	ppapi/shared_impl/ppb_view_shared.cc \
-	ppapi/shared_impl/ppp_instance_combined.cc \
-	ppapi/shared_impl/proxy_lock.cc \
-	ppapi/shared_impl/resource.cc \
-	ppapi/shared_impl/resource_tracker.cc \
-	ppapi/shared_impl/scoped_pp_resource.cc \
-	ppapi/shared_impl/scoped_pp_var.cc \
-	ppapi/shared_impl/socket_option_data.cc \
-	ppapi/shared_impl/tcp_socket_shared.cc \
-	ppapi/shared_impl/thread_aware_callback.cc \
-	ppapi/shared_impl/time_conversion.cc \
-	ppapi/shared_impl/tracked_callback.cc \
-	ppapi/shared_impl/url_request_info_data.cc \
-	ppapi/shared_impl/url_response_info_data.cc \
-	ppapi/shared_impl/var.cc \
-	ppapi/shared_impl/var_tracker.cc \
-	ppapi/shared_impl/var_value_conversions.cc \
-	ppapi/shared_impl/private/net_address_private_impl.cc \
-	ppapi/shared_impl/private/net_address_private_impl_constants.cc \
-	ppapi/shared_impl/private/ppb_char_set_shared.cc \
-	ppapi/shared_impl/private/ppb_x509_certificate_private_shared.cc \
-	ppapi/shared_impl/private/tcp_socket_private_impl.cc \
-	ppapi/thunk/enter.cc \
-	ppapi/thunk/ppb_audio_config_thunk.cc \
-	ppapi/thunk/ppb_audio_input_dev_thunk.cc \
-	ppapi/thunk/ppb_audio_thunk.cc \
-	ppapi/thunk/ppb_broker_thunk.cc \
-	ppapi/thunk/ppb_browser_font_trusted_thunk.cc \
-	ppapi/thunk/ppb_buffer_thunk.cc \
-	ppapi/thunk/ppb_char_set_thunk.cc \
-	ppapi/thunk/ppb_console_thunk.cc \
-	ppapi/thunk/ppb_content_decryptor_private_thunk.cc \
-	ppapi/thunk/ppb_cursor_control_thunk.cc \
-	ppapi/thunk/ppb_device_ref_dev_thunk.cc \
-	ppapi/thunk/ppb_ext_alarms_thunk.cc \
-	ppapi/thunk/ppb_ext_crx_file_system_private_thunk.cc \
-	ppapi/thunk/ppb_ext_socket_thunk.cc \
-	ppapi/thunk/ppb_file_chooser_dev_thunk.cc \
-	ppapi/thunk/ppb_file_chooser_trusted_thunk.cc \
-	ppapi/thunk/ppb_file_io_private_thunk.cc \
-	ppapi/thunk/ppb_file_io_thunk.cc \
-	ppapi/thunk/ppb_file_io_trusted_thunk.cc \
-	ppapi/thunk/ppb_file_ref_thunk.cc \
-	ppapi/thunk/ppb_file_system_thunk.cc \
-	ppapi/thunk/ppb_find_dev_thunk.cc \
-	ppapi/thunk/ppb_flash_clipboard_thunk.cc \
-	ppapi/thunk/ppb_flash_device_id_thunk.cc \
-	ppapi/thunk/ppb_flash_drm_thunk.cc \
-	ppapi/thunk/ppb_flash_file_fileref_thunk.cc \
-	ppapi/thunk/ppb_flash_file_modulelocal_thunk.cc \
-	ppapi/thunk/ppb_flash_font_file_thunk.cc \
-	ppapi/thunk/ppb_flash_fullscreen_thunk.cc \
-	ppapi/thunk/ppb_flash_menu_thunk.cc \
-	ppapi/thunk/ppb_flash_message_loop_thunk.cc \
-	ppapi/thunk/ppb_flash_print_thunk.cc \
-	ppapi/thunk/ppb_flash_thunk.cc \
-	ppapi/thunk/ppb_fullscreen_thunk.cc \
-	ppapi/thunk/ppb_gamepad_thunk.cc \
-	ppapi/thunk/ppb_gles_chromium_texture_mapping_thunk.cc \
-	ppapi/thunk/ppb_graphics_2d_dev_thunk.cc \
-	ppapi/thunk/ppb_graphics_2d_thunk.cc \
-	ppapi/thunk/ppb_graphics_3d_thunk.cc \
-	ppapi/thunk/ppb_host_resolver_thunk.cc \
-	ppapi/thunk/ppb_host_resolver_private_thunk.cc \
-	ppapi/thunk/ppb_image_data_thunk.cc \
-	ppapi/thunk/ppb_input_event_thunk.cc \
-	ppapi/thunk/ppb_instance_private_thunk.cc \
-	ppapi/thunk/ppb_instance_thunk.cc \
-	ppapi/thunk/ppb_messaging_thunk.cc \
-	ppapi/thunk/ppb_mouse_cursor_thunk.cc \
-	ppapi/thunk/ppb_mouse_lock_thunk.cc \
-	ppapi/thunk/ppb_net_address_thunk.cc \
-	ppapi/thunk/ppb_network_list_private_thunk.cc \
-	ppapi/thunk/ppb_network_monitor_private_thunk.cc \
-	ppapi/thunk/ppb_network_proxy_thunk.cc \
-	ppapi/thunk/ppb_pdf_thunk.cc \
-	ppapi/thunk/ppb_printing_dev_thunk.cc \
-	ppapi/thunk/ppb_resource_array_dev_thunk.cc \
-	ppapi/thunk/ppb_scrollbar_thunk.cc \
-	ppapi/thunk/ppb_talk_private_thunk.cc \
-	ppapi/thunk/ppb_tcp_server_socket_private_thunk.cc \
-	ppapi/thunk/ppb_tcp_socket_private_thunk.cc \
-	ppapi/thunk/ppb_tcp_socket_thunk.cc \
-	ppapi/thunk/ppb_text_input_thunk.cc \
-	ppapi/thunk/ppb_truetype_font_dev_thunk.cc \
-	ppapi/thunk/ppb_udp_socket_thunk.cc \
-	ppapi/thunk/ppb_udp_socket_private_thunk.cc \
-	ppapi/thunk/ppb_url_loader_thunk.cc \
-	ppapi/thunk/ppb_url_loader_trusted_thunk.cc \
-	ppapi/thunk/ppb_url_request_info_thunk.cc \
-	ppapi/thunk/ppb_url_response_info_thunk.cc \
-	ppapi/thunk/ppb_url_util_thunk.cc \
-	ppapi/thunk/ppb_var_array_thunk.cc \
-	ppapi/thunk/ppb_var_dictionary_thunk.cc \
-	ppapi/thunk/ppb_video_capture_thunk.cc \
-	ppapi/thunk/ppb_video_decoder_thunk.cc \
-	ppapi/thunk/ppb_video_destination_private_thunk.cc \
-	ppapi/thunk/ppb_video_source_private_thunk.cc \
-	ppapi/thunk/ppb_view_dev_thunk.cc \
-	ppapi/thunk/ppb_view_thunk.cc \
-	ppapi/thunk/ppb_websocket_thunk.cc \
-	ppapi/thunk/ppb_widget_dev_thunk.cc \
-	ppapi/thunk/ppb_x509_certificate_private_thunk.cc \
-	ppapi/thunk/ppb_zoom_dev_thunk.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 \
-	-m32 \
-	-mmmx \
-	-march=pentium4 \
-	-msse2 \
-	-mfpmath=sse \
-	-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 \
-	-fno-stack-protector \
-	-Os \
-	-g \
-	-fomit-frame-pointer \
-	-fdata-sections \
-	-ffunction-sections
-
-MY_DEFS_Debug := \
-	'-DANGLE_DX11' \
-	'-D_FILE_OFFSET_BITS=64' \
-	'-DNO_TCMALLOC' \
-	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
-	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
-	'-DDISABLE_NACL' \
-	'-DCHROMIUM_BUILD' \
-	'-DUSE_LIBJPEG_TURBO=1' \
-	'-DUSE_PROPRIETARY_CODECS' \
-	'-DENABLE_CONFIGURATION_POLICY' \
-	'-DENABLE_GPU=1' \
-	'-DUSE_OPENSSL=1' \
-	'-DENABLE_EGLIMAGE=1' \
-	'-DSK_ENABLE_INST_COUNT=0' \
-	'-DSK_SUPPORT_GPU=1' \
-	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
-	'-DSK_BUILD_FOR_ANDROID' \
-	'-DUSE_CHROMIUM_SKIA' \
-	'-DSK_USE_POSIX_THREADS' \
-	'-DU_USING_ICU_NAMESPACE=0' \
-	'-D__STDC_CONSTANT_MACROS' \
-	'-D__STDC_FORMAT_MACROS' \
-	'-DPPAPI_SHARED_IMPLEMENTATION' \
-	'-DPPAPI_THUNK_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)/third_party/khronos \
-	$(LOCAL_PATH)/gpu \
-	$(LOCAL_PATH) \
-	$(LOCAL_PATH)/third_party/skia/src/core \
-	$(LOCAL_PATH)/skia/config \
-	$(LOCAL_PATH)/third_party/skia/include/config \
-	$(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/gpu/gl \
-	$(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)/third_party/npapi \
-	$(LOCAL_PATH)/third_party/npapi/bindings \
-	$(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-error=c++0x-compat \
-	-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 \
-	-m32 \
-	-mmmx \
-	-march=pentium4 \
-	-msse2 \
-	-mfpmath=sse \
-	-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 \
-	-fno-stack-protector \
-	-Os \
-	-fno-ident \
-	-fdata-sections \
-	-ffunction-sections \
-	-fomit-frame-pointer \
-	-fno-unwind-tables \
-	-fno-asynchronous-unwind-tables
-
-MY_DEFS_Release := \
-	'-DANGLE_DX11' \
-	'-D_FILE_OFFSET_BITS=64' \
-	'-DNO_TCMALLOC' \
-	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
-	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
-	'-DDISABLE_NACL' \
-	'-DCHROMIUM_BUILD' \
-	'-DUSE_LIBJPEG_TURBO=1' \
-	'-DUSE_PROPRIETARY_CODECS' \
-	'-DENABLE_CONFIGURATION_POLICY' \
-	'-DENABLE_GPU=1' \
-	'-DUSE_OPENSSL=1' \
-	'-DENABLE_EGLIMAGE=1' \
-	'-DSK_ENABLE_INST_COUNT=0' \
-	'-DSK_SUPPORT_GPU=1' \
-	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
-	'-DSK_BUILD_FOR_ANDROID' \
-	'-DUSE_CHROMIUM_SKIA' \
-	'-DSK_USE_POSIX_THREADS' \
-	'-DU_USING_ICU_NAMESPACE=0' \
-	'-D__STDC_CONSTANT_MACROS' \
-	'-D__STDC_FORMAT_MACROS' \
-	'-DPPAPI_SHARED_IMPLEMENTATION' \
-	'-DPPAPI_THUNK_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)/third_party/khronos \
-	$(LOCAL_PATH)/gpu \
-	$(LOCAL_PATH) \
-	$(LOCAL_PATH)/third_party/skia/src/core \
-	$(LOCAL_PATH)/skia/config \
-	$(LOCAL_PATH)/third_party/skia/include/config \
-	$(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/gpu/gl \
-	$(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)/third_party/npapi \
-	$(LOCAL_PATH)/third_party/npapi/bindings \
-	$(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-error=c++0x-compat \
-	-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))
-### Rules for final target.
-
-LOCAL_LDFLAGS_Debug := \
-	-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,-O1 \
-	-Wl,--as-needed
-
-
-LOCAL_LDFLAGS_Release := \
-	-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
-
-
-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: ppapi_ppapi_shared_gyp
-
-# Alias gyp target name.
-.PHONY: ppapi_shared
-ppapi_shared: ppapi_ppapi_shared_gyp
-
-include $(BUILD_STATIC_LIBRARY)
diff --git a/ppapi/proxy/file_chooser_resource.cc b/ppapi/proxy/file_chooser_resource.cc
index ebd545c..9847e29 100644
--- a/ppapi/proxy/file_chooser_resource.cc
+++ b/ppapi/proxy/file_chooser_resource.cc
@@ -9,8 +9,8 @@
 #include "ipc/ipc_message.h"
 #include "ppapi/c/pp_errors.h"
 #include "ppapi/proxy/dispatch_reply_message.h"
+#include "ppapi/proxy/file_ref_resource.h"
 #include "ppapi/proxy/ppapi_messages.h"
-#include "ppapi/proxy/ppb_file_ref_proxy.h"
 #include "ppapi/shared_impl/var.h"
 
 namespace ppapi {
@@ -100,19 +100,25 @@
 
 void FileChooserResource::OnPluginMsgShowReply(
     const ResourceMessageReplyParams& params,
-    const std::vector<PPB_FileRef_CreateInfo>& chosen_files) {
+    const std::vector<FileRefCreateInfo>& chosen_files) {
   if (output_.is_valid()) {
     // Using v0.6 of the API with the output array.
     std::vector<PP_Resource> files;
-    for (size_t i = 0; i < chosen_files.size(); i++)
-      files.push_back(PPB_FileRef_Proxy::DeserializeFileRef(chosen_files[i]));
+    for (size_t i = 0; i < chosen_files.size(); i++) {
+      files.push_back(FileRefResource::CreateFileRef(
+          connection(),
+          pp_instance(),
+          chosen_files[i]));
+    }
     output_.StoreResourceVector(files);
   } else {
     // Convert each of the passed in file infos to resources. These will be
     // owned by the FileChooser object until they're passed to the plugin.
     DCHECK(file_queue_.empty());
     for (size_t i = 0; i < chosen_files.size(); i++) {
-      file_queue_.push(PPB_FileRef_Proxy::DeserializeFileRef(
+      file_queue_.push(FileRefResource::CreateFileRef(
+          connection(),
+          pp_instance(),
           chosen_files[i]));
     }
   }
diff --git a/ppapi/proxy/file_chooser_resource.h b/ppapi/proxy/file_chooser_resource.h
index 58331db..b744e91 100644
--- a/ppapi/proxy/file_chooser_resource.h
+++ b/ppapi/proxy/file_chooser_resource.h
@@ -17,7 +17,7 @@
 
 namespace ppapi {
 
-struct PPB_FileRef_CreateInfo;
+struct FileRefCreateInfo;
 
 namespace proxy {
 
@@ -56,7 +56,7 @@
  private:
   void OnPluginMsgShowReply(
       const ResourceMessageReplyParams& params,
-      const std::vector<PPB_FileRef_CreateInfo>& chosen_files);
+      const std::vector<FileRefCreateInfo>& chosen_files);
 
   int32_t ShowInternal(PP_Bool save_as,
                        const PP_Var& suggested_file_name,
diff --git a/ppapi/proxy/file_chooser_resource_unittest.cc b/ppapi/proxy/file_chooser_resource_unittest.cc
index a5801ee..e563bf4 100644
--- a/ppapi/proxy/file_chooser_resource_unittest.cc
+++ b/ppapi/proxy/file_chooser_resource_unittest.cc
@@ -5,6 +5,7 @@
 #include "base/message_loop/message_loop.h"
 #include "ppapi/c/dev/ppb_file_chooser_dev.h"
 #include "ppapi/c/pp_errors.h"
+#include "ppapi/c/ppb_file_ref.h"
 #include "ppapi/proxy/file_chooser_resource.h"
 #include "ppapi/proxy/locking_resource_releaser.h"
 #include "ppapi/proxy/ppapi_messages.h"
@@ -91,13 +92,13 @@
   reply_params.set_result(PP_OK);
 
   // Synthesize a response with one file ref in it. Note that it must have a
-  // host resource value set or deserialization will fail. Since there isn't
-  // actually a host, this can be whatever we want.
-  std::vector<PPB_FileRef_CreateInfo> create_info_array;
-  PPB_FileRef_CreateInfo create_info;
-  create_info.resource.SetHostResource(pp_instance(), 123);
-  create_info.path = "foo/bar";
-  create_info.name = "baz";
+  // pending_host_resource_id set. Since there isn't actually a host, this can
+  // be whatever we want.
+  std::vector<FileRefCreateInfo> create_info_array;
+  FileRefCreateInfo create_info;
+  create_info.file_system_type = PP_FILESYSTEMTYPE_EXTERNAL;
+  create_info.display_name = "bar";
+  create_info.pending_host_resource_id = 12;
   create_info_array.push_back(create_info);
   ASSERT_TRUE(plugin_dispatcher()->OnMessageReceived(
       PpapiPluginMsg_ResourceReply(reply_params,
@@ -115,9 +116,8 @@
   {
     ProxyAutoLock lock;
     ScopedPPVar release_name_var(ScopedPPVar::PassRef(), name_var);
-    EXPECT_VAR_IS_STRING(create_info.name, name_var);
+    EXPECT_VAR_IS_STRING("bar", name_var);
   }
-  // Path should be undefined since it's external filesystem.
   PP_Var path_var(file_ref_iface->GetPath(dest[0]));
   {
     ProxyAutoLock lock;
diff --git a/ppapi/proxy/file_io_resource.cc b/ppapi/proxy/file_io_resource.cc
index 7d98356..4459199 100644
--- a/ppapi/proxy/file_io_resource.cc
+++ b/ppapi/proxy/file_io_resource.cc
@@ -5,11 +5,14 @@
 #include "ppapi/proxy/file_io_resource.h"
 
 #include "base/bind.h"
+#include "base/task_runner_util.h"
 #include "ipc/ipc_message.h"
 #include "ppapi/c/pp_errors.h"
 #include "ppapi/proxy/ppapi_messages.h"
 #include "ppapi/shared_impl/array_writer.h"
+#include "ppapi/shared_impl/file_type_conversion.h"
 #include "ppapi/shared_impl/ppapi_globals.h"
+#include "ppapi/shared_impl/proxy_lock.h"
 #include "ppapi/shared_impl/resource_tracker.h"
 #include "ppapi/thunk/enter.h"
 #include "ppapi/thunk/ppb_file_ref_api.h"
@@ -20,22 +23,65 @@
 
 namespace {
 
+// We must allocate a buffer sized according to the request of the plugin. To
+// reduce the chance of out-of-memory errors, we cap the read size to 32MB.
+// This is OK since the API specifies that it may perform a partial read.
+static const int32_t kMaxReadSize = 32 * 1024 * 1024;  // 32MB
+
 // An adapter to let Read() share the same implementation with ReadToArray().
 void* DummyGetDataBuffer(void* user_data, uint32_t count, uint32_t size) {
   return user_data;
 }
 
+// File thread task to close the file handle.
+void DoClose(base::PlatformFile file) {
+  base::ClosePlatformFile(file);
+}
+
 }  // namespace
 
 namespace ppapi {
 namespace proxy {
 
+FileIOResource::QueryOp::QueryOp(PP_FileHandle file_handle)
+    : file_handle_(file_handle) {
+}
+
+FileIOResource::QueryOp::~QueryOp() {
+}
+
+int32_t FileIOResource::QueryOp::DoWork() {
+  return base::GetPlatformFileInfo(file_handle_, &file_info_) ?
+      PP_OK : PP_ERROR_FAILED;
+}
+
+FileIOResource::ReadOp::ReadOp(PP_FileHandle file_handle,
+                               int64_t offset,
+                               int32_t bytes_to_read)
+  : file_handle_(file_handle),
+    offset_(offset),
+    bytes_to_read_(bytes_to_read) {
+}
+
+FileIOResource::ReadOp::~ReadOp() {
+}
+
+int32_t FileIOResource::ReadOp::DoWork() {
+  DCHECK(!buffer_.get());
+  buffer_.reset(new char[bytes_to_read_]);
+  return base::ReadPlatformFile(
+      file_handle_, offset_, buffer_.get(), bytes_to_read_);
+}
+
 FileIOResource::FileIOResource(Connection connection, PP_Instance instance)
-    : PluginResource(connection, instance) {
+    : PluginResource(connection, instance),
+      file_handle_(base::kInvalidPlatformFileValue),
+      file_system_type_(PP_FILESYSTEMTYPE_INVALID) {
   SendCreate(RENDERER, PpapiHostMsg_FileIO_Create());
 }
 
 FileIOResource::~FileIOResource() {
+  CloseFileHandle();
 }
 
 PPB_FileIO_API* FileIOResource::AsPPB_FileIO_API() {
@@ -49,6 +95,17 @@
   if (enter.failed())
     return PP_ERROR_BADRESOURCE;
 
+  PPB_FileRef_API* file_ref_api = enter.object();
+  PP_FileSystemType type = file_ref_api->GetFileSystemType();
+  if (type != PP_FILESYSTEMTYPE_LOCALPERSISTENT &&
+      type != PP_FILESYSTEMTYPE_LOCALTEMPORARY &&
+      type != PP_FILESYSTEMTYPE_EXTERNAL &&
+      type != PP_FILESYSTEMTYPE_ISOLATED) {
+    NOTREACHED();
+    return PP_ERROR_FAILED;
+  }
+  file_system_type_ = type;
+
   int32_t rv = state_manager_.CheckOperationState(
       FileIOStateManager::OPERATION_EXCLUSIVE, false);
   if (rv != PP_OK)
@@ -56,7 +113,7 @@
 
   Call<PpapiPluginMsg_FileIO_OpenReply>(RENDERER,
       PpapiHostMsg_FileIO_Open(
-          enter.resource()->host_resource().host_resource(),
+          file_ref,
           open_flags),
       base::Bind(&FileIOResource::OnPluginMsgOpenFileComplete, this,
                  callback));
@@ -71,13 +128,35 @@
       FileIOStateManager::OPERATION_EXCLUSIVE, true);
   if (rv != PP_OK)
     return rv;
-
-  Call<PpapiPluginMsg_FileIO_QueryReply>(RENDERER,
-      PpapiHostMsg_FileIO_Query(),
-      base::Bind(&FileIOResource::OnPluginMsgQueryComplete, this,
-                 callback, info));
+  if (!info)
+    return PP_ERROR_BADARGUMENT;
+  if (file_handle_ == base::kInvalidPlatformFileValue)
+    return PP_ERROR_FAILED;
 
   state_manager_.SetPendingOperation(FileIOStateManager::OPERATION_EXCLUSIVE);
+  scoped_refptr<QueryOp> query_op(new QueryOp(file_handle_));
+
+  // If the callback is blocking, perform the task on the calling thread.
+  if (callback->is_blocking()) {
+    int32_t result;
+    {
+      // Release the proxy lock while making a potentially slow file call.
+      ProxyAutoUnlock unlock;
+      result = query_op->DoWork();
+    }
+    return OnQueryComplete(query_op, info, result);
+  }
+
+  // For the non-blocking case, post a task to the file thread and add a
+  // completion task to write the result.
+  base::PostTaskAndReplyWithResult(
+      PpapiGlobals::Get()->GetFileTaskRunner(pp_instance()),
+      FROM_HERE,
+      Bind(&FileIOResource::QueryOp::DoWork, query_op),
+      RunWhileLocked(Bind(&TrackedCallback::Run, callback)));
+  callback->set_completion_task(
+      Bind(&FileIOResource::OnQueryComplete, this, query_op, info));
+
   return PP_OK_COMPLETIONPENDING;
 }
 
@@ -110,7 +189,6 @@
   PP_ArrayOutput output_adapter;
   output_adapter.GetDataBuffer = &DummyGetDataBuffer;
   output_adapter.user_data = buffer;
-  state_manager_.SetPendingOperation(FileIOStateManager::OPERATION_READ);
   return ReadValidated(offset, bytes_to_read, output_adapter, callback);
 }
 
@@ -124,7 +202,6 @@
   if (rv != PP_OK)
     return rv;
 
-  state_manager_.SetPendingOperation(FileIOStateManager::OPERATION_READ);
   return ReadValidated(offset, max_read_length, *array_output, callback);
 }
 
@@ -181,6 +258,7 @@
 }
 
 void FileIOResource::Close() {
+  CloseFileHandle();
   Post(RENDERER, PpapiHostMsg_FileIO_Close());
 }
 
@@ -192,38 +270,6 @@
   return file_descriptor;
 }
 
-int32_t FileIOResource::WillWrite(int64_t offset,
-                                  int32_t bytes_to_write,
-                                  scoped_refptr<TrackedCallback> callback) {
-  Call<PpapiPluginMsg_FileIO_GeneralReply>(RENDERER,
-      PpapiHostMsg_FileIO_WillWrite(offset, bytes_to_write),
-      base::Bind(&FileIOResource::OnPluginMsgGeneralComplete, this,
-                 callback));
-  state_manager_.SetPendingOperation(FileIOStateManager::OPERATION_EXCLUSIVE);
-  return PP_OK_COMPLETIONPENDING;
-}
-
-int32_t FileIOResource::WillSetLength(int64_t length,
-                                      scoped_refptr<TrackedCallback> callback) {
-  Call<PpapiPluginMsg_FileIO_GeneralReply>(RENDERER,
-      PpapiHostMsg_FileIO_WillSetLength(length),
-      base::Bind(&FileIOResource::OnPluginMsgGeneralComplete, this,
-                 callback));
-  state_manager_.SetPendingOperation(FileIOStateManager::OPERATION_EXCLUSIVE);
-  return PP_OK_COMPLETIONPENDING;
-}
-
-int32_t FileIOResource::ReadValidated(int64_t offset,
-                                      int32_t bytes_to_read,
-                                      const PP_ArrayOutput& array_output,
-                                      scoped_refptr<TrackedCallback> callback) {
-  Call<PpapiPluginMsg_FileIO_ReadReply>(RENDERER,
-      PpapiHostMsg_FileIO_Read(offset, bytes_to_read),
-      base::Bind(&FileIOResource::OnPluginMsgReadComplete, this,
-                 callback, array_output));
-  return PP_OK_COMPLETIONPENDING;
-}
-
 int32_t FileIOResource::RequestOSFileHandle(
     PP_FileHandle* handle,
     scoped_refptr<TrackedCallback> callback) {
@@ -241,6 +287,111 @@
   return PP_OK_COMPLETIONPENDING;
 }
 
+int32_t FileIOResource::WillWrite(int64_t offset,
+                                  int32_t bytes_to_write,
+                                  scoped_refptr<TrackedCallback> callback) {
+  Call<PpapiPluginMsg_FileIO_GeneralReply>(RENDERER,
+      PpapiHostMsg_FileIO_WillWrite(offset, bytes_to_write),
+      base::Bind(&FileIOResource::OnPluginMsgGeneralComplete, this, callback));
+
+  state_manager_.SetPendingOperation(FileIOStateManager::OPERATION_EXCLUSIVE);
+  return PP_OK_COMPLETIONPENDING;
+}
+
+int32_t FileIOResource::WillSetLength(int64_t length,
+                                      scoped_refptr<TrackedCallback> callback) {
+  Call<PpapiPluginMsg_FileIO_GeneralReply>(RENDERER,
+      PpapiHostMsg_FileIO_WillSetLength(length),
+      base::Bind(&FileIOResource::OnPluginMsgGeneralComplete, this, callback));
+
+  state_manager_.SetPendingOperation(FileIOStateManager::OPERATION_EXCLUSIVE);
+  return PP_OK_COMPLETIONPENDING;
+}
+
+int32_t FileIOResource::ReadValidated(int64_t offset,
+                                      int32_t bytes_to_read,
+                                      const PP_ArrayOutput& array_output,
+                                      scoped_refptr<TrackedCallback> callback) {
+  if (bytes_to_read < 0)
+    return PP_ERROR_FAILED;
+  if (file_handle_ == base::kInvalidPlatformFileValue)
+    return PP_ERROR_FAILED;
+
+  state_manager_.SetPendingOperation(FileIOStateManager::OPERATION_READ);
+
+  bytes_to_read = std::min(bytes_to_read, kMaxReadSize);
+  scoped_refptr<ReadOp> read_op(
+      new ReadOp(file_handle_, offset, bytes_to_read));
+  if (callback->is_blocking()) {
+    int32_t result;
+    {
+      // Release the proxy lock while making a potentially slow file call.
+      ProxyAutoUnlock unlock;
+      result = read_op->DoWork();
+    }
+    return OnReadComplete(read_op, array_output, result);
+  }
+
+  // For the non-blocking case, post a task to the file thread.
+  base::PostTaskAndReplyWithResult(
+      PpapiGlobals::Get()->GetFileTaskRunner(pp_instance()),
+      FROM_HERE,
+      Bind(&FileIOResource::ReadOp::DoWork, read_op),
+      RunWhileLocked(Bind(&TrackedCallback::Run, callback)));
+  callback->set_completion_task(
+      Bind(&FileIOResource::OnReadComplete, this, read_op, array_output));
+
+  return PP_OK_COMPLETIONPENDING;
+}
+
+void FileIOResource::CloseFileHandle() {
+  if (file_handle_ != base::kInvalidPlatformFileValue) {
+    // Close our local fd on the file thread.
+    base::TaskRunner* file_task_runner =
+        PpapiGlobals::Get()->GetFileTaskRunner(pp_instance());
+    file_task_runner->PostTask(FROM_HERE,
+                               base::Bind(&DoClose, file_handle_));
+
+    file_handle_ = base::kInvalidPlatformFileValue;
+  }
+}
+
+int32_t FileIOResource::OnQueryComplete(scoped_refptr<QueryOp> query_op,
+                                        PP_FileInfo* info,
+                                        int32_t result) {
+  DCHECK(state_manager_.get_pending_operation() ==
+         FileIOStateManager::OPERATION_EXCLUSIVE);
+
+  if (result == PP_OK) {
+    // This writes the file info into the plugin's PP_FileInfo struct.
+    ppapi::PlatformFileInfoToPepperFileInfo(query_op->file_info(),
+                                            file_system_type_,
+                                            info);
+  }
+  state_manager_.SetOperationFinished();
+  return result;
+}
+
+int32_t FileIOResource::OnReadComplete(scoped_refptr<ReadOp> read_op,
+                                       PP_ArrayOutput array_output,
+                                       int32_t result) {
+  DCHECK(state_manager_.get_pending_operation() ==
+         FileIOStateManager::OPERATION_READ);
+  if (result >= 0) {
+    ArrayWriter output;
+    output.set_pp_array_output(array_output);
+    if (output.is_valid())
+      output.StoreArray(read_op->buffer(), result);
+    else
+      result = PP_ERROR_FAILED;
+  } else {
+    // The read operation failed.
+    result = PP_ERROR_FAILED;
+  }
+  state_manager_.SetOperationFinished();
+  return result;
+}
+
 void FileIOResource::OnPluginMsgGeneralComplete(
     scoped_refptr<TrackedCallback> callback,
     const ResourceMessageReplyParams& params) {
@@ -248,7 +399,8 @@
          FileIOStateManager::OPERATION_EXCLUSIVE ||
          state_manager_.get_pending_operation() ==
          FileIOStateManager::OPERATION_WRITE);
-  // End the operation now. The callback may perform another file operation.
+  // End this operation now, so the user's callback can execute another FileIO
+  // operation, assuming there are no other pending operations.
   state_manager_.SetOperationFinished();
   callback->Run(params.result());
 }
@@ -260,45 +412,13 @@
          FileIOStateManager::OPERATION_EXCLUSIVE);
   if (params.result() == PP_OK)
     state_manager_.SetOpenSucceed();
-  // End the operation now. The callback may perform another file operation.
-  state_manager_.SetOperationFinished();
-  callback->Run(params.result());
-}
 
-void FileIOResource::OnPluginMsgQueryComplete(
-    scoped_refptr<TrackedCallback> callback,
-    PP_FileInfo* output_info,
-    const ResourceMessageReplyParams& params,
-    const PP_FileInfo& info) {
-  DCHECK(state_manager_.get_pending_operation() ==
-         FileIOStateManager::OPERATION_EXCLUSIVE);
-  *output_info = info;
-  // End the operation now. The callback may perform another file operation.
-  state_manager_.SetOperationFinished();
-  callback->Run(params.result());
-}
-
-void FileIOResource::OnPluginMsgReadComplete(
-    scoped_refptr<TrackedCallback> callback,
-    PP_ArrayOutput array_output,
-    const ResourceMessageReplyParams& params,
-    const std::string& data) {
-  DCHECK(state_manager_.get_pending_operation() ==
-         FileIOStateManager::OPERATION_READ);
-
-  // The result code should contain the data size if it's positive.
   int32_t result = params.result();
-  DCHECK((result < 0 && data.size() == 0) ||
-         result == static_cast<int32_t>(data.size()));
-
-  ArrayWriter output;
-  output.set_pp_array_output(array_output);
-  if (output.is_valid())
-    output.StoreArray(data.data(), std::max(0, result));
-  else
-    result = PP_ERROR_FAILED;
-
-  // End the operation now. The callback may perform another file operation.
+  IPC::PlatformFileForTransit transit_file;
+  if ((result == PP_OK) && params.TakeFileHandleAtIndex(0, &transit_file))
+    file_handle_ = IPC::PlatformFileForTransitToPlatformFile(transit_file);
+  // End this operation now, so the user's callback can execute another FileIO
+  // operation, assuming there are no other pending operations.
   state_manager_.SetOperationFinished();
   callback->Run(result);
 }
@@ -321,7 +441,8 @@
     result = PP_ERROR_FAILED;
   *output_handle = IPC::PlatformFileForTransitToPlatformFile(transit_file);
 
-  // End the operation now. The callback may perform another file operation.
+  // End this operation now, so the user's callback can execute another FileIO
+  // operation, assuming there are no other pending operations.
   state_manager_.SetOperationFinished();
   callback->Run(result);
 }
diff --git a/ppapi/proxy/file_io_resource.h b/ppapi/proxy/file_io_resource.h
index a2b928d..1a888d1 100644
--- a/ppapi/proxy/file_io_resource.h
+++ b/ppapi/proxy/file_io_resource.h
@@ -67,30 +67,74 @@
       scoped_refptr<TrackedCallback> callback) OVERRIDE;
 
  private:
+  // Class to perform file query operations across multiple threads.
+  class QueryOp : public base::RefCountedThreadSafe<QueryOp> {
+   public:
+    explicit QueryOp(PP_FileHandle file_handle);
+
+    // Queries the file. Called on the file thread (non-blocking) or the plugin
+    // thread (blocking). This should not be called when we hold the proxy lock.
+    int32_t DoWork();
+
+    const base::PlatformFileInfo& file_info() const { return file_info_; }
+
+   private:
+    friend class base::RefCountedThreadSafe<QueryOp>;
+    ~QueryOp();
+
+    PP_FileHandle file_handle_;
+    base::PlatformFileInfo file_info_;
+  };
+
+  // Class to perform file read operations across multiple threads.
+  class ReadOp : public base::RefCountedThreadSafe<ReadOp> {
+   public:
+    ReadOp(PP_FileHandle file_handle, int64_t offset, int32_t bytes_to_read);
+
+    // Reads the file. Called on the file thread (non-blocking) or the plugin
+    // thread (blocking). This should not be called when we hold the proxy lock.
+    int32_t DoWork();
+
+    char* buffer() const { return buffer_.get(); }
+
+   private:
+    friend class base::RefCountedThreadSafe<ReadOp>;
+    ~ReadOp();
+
+    PP_FileHandle file_handle_;
+    int64_t offset_;
+    int32_t bytes_to_read_;
+    scoped_ptr<char[]> buffer_;
+  };
+
   int32_t ReadValidated(int64_t offset,
                         int32_t bytes_to_read,
                         const PP_ArrayOutput& array_output,
                         scoped_refptr<TrackedCallback> callback);
 
-  // Handlers of reply messages. Note that all of them have a callback
-  // parameters bound when call to the host.
+  void CloseFileHandle();
+
+
+  // Completion tasks for file operations that are done in the plugin.
+  int32_t OnQueryComplete(scoped_refptr<QueryOp> query_op,
+                          PP_FileInfo* info,
+                          int32_t result);
+  int32_t OnReadComplete(scoped_refptr<ReadOp> read_op,
+                         PP_ArrayOutput array_output,
+                         int32_t result);
+
+  // Reply message handlers for operations that are done in the host.
   void OnPluginMsgGeneralComplete(scoped_refptr<TrackedCallback> callback,
                                   const ResourceMessageReplyParams& params);
   void OnPluginMsgOpenFileComplete(scoped_refptr<TrackedCallback> callback,
                                    const ResourceMessageReplyParams& params);
-  void OnPluginMsgQueryComplete(scoped_refptr<TrackedCallback> callback,
-                                PP_FileInfo* output_info_,
-                                const ResourceMessageReplyParams& params,
-                                const PP_FileInfo& info);
-  void OnPluginMsgReadComplete(scoped_refptr<TrackedCallback> callback,
-                               PP_ArrayOutput array_output,
-                               const ResourceMessageReplyParams& params,
-                               const std::string& data);
   void OnPluginMsgRequestOSFileHandleComplete(
       scoped_refptr<TrackedCallback> callback,
       PP_FileHandle* output_handle,
       const ResourceMessageReplyParams& params);
 
+  PP_FileHandle file_handle_;
+  PP_FileSystemType file_system_type_;
   FileIOStateManager state_manager_;
 
   DISALLOW_COPY_AND_ASSIGN(FileIOResource);
diff --git a/ppapi/proxy/file_ref_resource.cc b/ppapi/proxy/file_ref_resource.cc
index 4c098a5..ae4df85 100644
--- a/ppapi/proxy/file_ref_resource.cc
+++ b/ppapi/proxy/file_ref_resource.cc
@@ -22,7 +22,7 @@
 FileRefResource::FileRefResource(
     Connection connection,
     PP_Instance instance,
-    const FileRef_CreateInfo& create_info)
+    const FileRefCreateInfo& create_info)
     : PluginResource(connection, instance),
       create_info_(create_info),
       file_system_resource_(create_info.file_system_plugin_resource) {
@@ -34,7 +34,6 @@
       create_info_.internal_path.erase(path_size - 1, 1);
 
     path_var_ = new StringVar(create_info_.internal_path);
-
     create_info_.display_name = GetNameForInternalFilePath(
         create_info_.internal_path);
   }
@@ -57,7 +56,7 @@
 PP_Resource FileRefResource::CreateFileRef(
     Connection connection,
     PP_Instance instance,
-    const FileRef_CreateInfo& create_info) {
+    const FileRefCreateInfo& create_info) {
   // If we have a valid file_system resource, ensure that its type matches that
   // of the fs_type parameter.
   if (create_info.file_system_plugin_resource != 0) {
@@ -82,9 +81,7 @@
 }
 
 thunk::PPB_FileRef_API* FileRefResource::AsPPB_FileRef_API() {
-  // TODO: return "this" once we update PPB_FileRef_API.
-  NOTREACHED();
-  return NULL;
+  return this;
 }
 
 PP_FileSystemType FileRefResource::GetFileSystemType() const {
@@ -111,7 +108,7 @@
     pos++;
   std::string parent_path = create_info_.internal_path.substr(0, pos);
 
-  ppapi::FileRef_CreateInfo parent_info;
+  ppapi::FileRefCreateInfo parent_info;
   parent_info.file_system_type = create_info_.file_system_type;
   parent_info.internal_path = parent_path;
   parent_info.display_name = GetNameForInternalFilePath(parent_path);
@@ -184,33 +181,9 @@
   return PP_OK_COMPLETIONPENDING;
 }
 
-/*
-const FileRef_CreateInfo& FileRefResource::GetCreateInfo() const {
+const FileRefCreateInfo& FileRefResource::GetCreateInfo() const {
   return create_info_;
 }
-*/
-const PPB_FileRef_CreateInfo& FileRefResource::GetCreateInfo() const {
-  // FIXME
-  NOTREACHED();
-  PPB_FileRef_CreateInfo *info = new PPB_FileRef_CreateInfo();
-  return *info;
-}
-
-// TODO(teravest): Remove this when we are finished moving to the new proxy.
-int32_t FileRefResource::QueryInHost(linked_ptr<PP_FileInfo> info,
-                                    scoped_refptr<TrackedCallback> callback) {
-  NOTREACHED();
-  return PP_ERROR_FAILED;
-}
-
-// TODO(teravest): Remove this when we are finished moving to the new proxy.
-int32_t FileRefResource::ReadDirectoryEntriesInHost(
-    linked_ptr<std::vector<ppapi::PPB_FileRef_CreateInfo> > files,
-    linked_ptr<std::vector<PP_FileType> > file_types,
-    scoped_refptr<TrackedCallback> callback) {
-  NOTREACHED();
-  return PP_ERROR_FAILED;
-}
 
 PP_Var FileRefResource::GetAbsolutePath() {
   if (!absolute_path_var_.get()) {
@@ -248,7 +221,7 @@
     const PP_ArrayOutput& output,
     scoped_refptr<TrackedCallback> callback,
     const ResourceMessageReplyParams& params,
-    const std::vector<ppapi::FileRef_CreateInfo>& infos,
+    const std::vector<ppapi::FileRefCreateInfo>& infos,
     const std::vector<PP_FileType>& file_types) {
   if (!TrackedCallback::IsPending(callback))
     return;
diff --git a/ppapi/proxy/file_ref_resource.h b/ppapi/proxy/file_ref_resource.h
index 82570fb..f982438 100644
--- a/ppapi/proxy/file_ref_resource.h
+++ b/ppapi/proxy/file_ref_resource.h
@@ -29,7 +29,7 @@
  public:
   static PP_Resource CreateFileRef(Connection connection,
                                    PP_Instance instance,
-                                   const FileRef_CreateInfo& info);
+                                   const FileRefCreateInfo& info);
 
   virtual ~FileRefResource();
 
@@ -55,13 +55,7 @@
   virtual int32_t ReadDirectoryEntries(
       const PP_ArrayOutput& output,
       scoped_refptr<TrackedCallback> callback) OVERRIDE;
-  virtual const PPB_FileRef_CreateInfo& GetCreateInfo() const OVERRIDE;
-  virtual int32_t QueryInHost(linked_ptr<PP_FileInfo> info,
-                              scoped_refptr<TrackedCallback> callback) OVERRIDE;
-  virtual int32_t ReadDirectoryEntriesInHost(
-      linked_ptr<std::vector<ppapi::PPB_FileRef_CreateInfo> > files,
-      linked_ptr<std::vector<PP_FileType> > file_types,
-      scoped_refptr<TrackedCallback> callback) OVERRIDE;
+  virtual const FileRefCreateInfo& GetCreateInfo() const OVERRIDE;
 
   // Private API
   virtual PP_Var GetAbsolutePath() OVERRIDE;
@@ -69,7 +63,7 @@
  private:
   FileRefResource(Connection connection,
                   PP_Instance instance,
-                  const FileRef_CreateInfo& info);
+                  const FileRefCreateInfo& info);
 
   void RunTrackedCallback(scoped_refptr<TrackedCallback> callback,
                           const ResourceMessageReplyParams& params);
@@ -83,11 +77,11 @@
       const PP_ArrayOutput& output,
       scoped_refptr<TrackedCallback> callback,
       const ResourceMessageReplyParams& params,
-      const std::vector<ppapi::FileRef_CreateInfo>& infos,
+      const std::vector<ppapi::FileRefCreateInfo>& infos,
       const std::vector<PP_FileType>& file_types);
 
   // Populated after creation.
-  FileRef_CreateInfo create_info_;
+  FileRefCreateInfo create_info_;
 
   // Some file ref operations may fail if the the file system resource inside
   // create_info_ is destroyed. Therefore, we explicitly hold a reference to
diff --git a/ppapi/proxy/flash_drm_resource.cc b/ppapi/proxy/flash_drm_resource.cc
index a4be23b..889aa72 100644
--- a/ppapi/proxy/flash_drm_resource.cc
+++ b/ppapi/proxy/flash_drm_resource.cc
@@ -7,9 +7,8 @@
 #include "base/bind.h"
 #include "ppapi/c/pp_errors.h"
 #include "ppapi/proxy/dispatch_reply_message.h"
+#include "ppapi/proxy/file_ref_resource.h"
 #include "ppapi/proxy/ppapi_messages.h"
-#include "ppapi/proxy/ppb_file_ref_proxy.h"
-#include "ppapi/shared_impl/ppb_file_ref_shared.h"
 #include "ppapi/shared_impl/var.h"
 
 namespace ppapi {
@@ -88,10 +87,14 @@
     PP_Resource* dest,
     scoped_refptr<TrackedCallback> callback,
     const ResourceMessageReplyParams& params,
-    const PPB_FileRef_CreateInfo& file_info) {
+    const FileRefCreateInfo& file_info) {
   if (TrackedCallback::IsPending(callback)) {
-    if (params.result() == PP_OK)
-      *dest = PPB_FileRef_Proxy::DeserializeFileRef(file_info);
+    if (params.result() == PP_OK) {
+      *dest = FileRefResource::CreateFileRef(
+          connection(),
+          pp_instance(),
+          file_info);
+    }
     callback->Run(params.result());
   }
 }
diff --git a/ppapi/proxy/flash_drm_resource.h b/ppapi/proxy/flash_drm_resource.h
index 12c71e8..9a4b31c 100644
--- a/ppapi/proxy/flash_drm_resource.h
+++ b/ppapi/proxy/flash_drm_resource.h
@@ -11,7 +11,7 @@
 #include "ppapi/thunk/ppb_flash_drm_api.h"
 
 namespace ppapi {
-struct PPB_FileRef_CreateInfo;
+struct FileRefCreateInfo;
 }
 
 namespace ppapi {
@@ -44,7 +44,7 @@
   void OnPluginMsgGetVoucherFileReply(PP_Resource* dest,
                                       scoped_refptr<TrackedCallback> callback,
                                       const ResourceMessageReplyParams& params,
-                                      const PPB_FileRef_CreateInfo& file_info);
+                                      const FileRefCreateInfo& file_info);
 
   DISALLOW_COPY_AND_ASSIGN(FlashDRMResource);
 };
diff --git a/ppapi/proxy/flash_file_resource.cc b/ppapi/proxy/flash_file_resource.cc
index 1387eb7..ce7a2ce 100644
--- a/ppapi/proxy/flash_file_resource.cc
+++ b/ppapi/proxy/flash_file_resource.cc
@@ -13,6 +13,7 @@
 #include "ppapi/shared_impl/time_conversion.h"
 #include "ppapi/shared_impl/var.h"
 #include "ppapi/thunk/enter.h"
+#include "ppapi/thunk/ppb_file_ref_api.h"
 
 namespace ppapi {
 namespace proxy {
diff --git a/ppapi/proxy/interface_list.cc b/ppapi/proxy/interface_list.cc
index d9feb89..49ec0eb 100644
--- a/ppapi/proxy/interface_list.cc
+++ b/ppapi/proxy/interface_list.cc
@@ -101,7 +101,6 @@
 #include "ppapi/proxy/ppb_broker_proxy.h"
 #include "ppapi/proxy/ppb_buffer_proxy.h"
 #include "ppapi/proxy/ppb_core_proxy.h"
-#include "ppapi/proxy/ppb_file_ref_proxy.h"
 #include "ppapi/proxy/ppb_flash_message_loop_proxy.h"
 #include "ppapi/proxy/ppb_graphics_3d_proxy.h"
 #include "ppapi/proxy/ppb_image_data_proxy.h"
diff --git a/ppapi/proxy/ppapi_messages.h b/ppapi/proxy/ppapi_messages.h
index 7ee568f..c97ae7a 100644
--- a/ppapi/proxy/ppapi_messages.h
+++ b/ppapi/proxy/ppapi_messages.h
@@ -57,6 +57,7 @@
 #include "ppapi/shared_impl/dir_contents.h"
 #include "ppapi/shared_impl/file_path.h"
 #include "ppapi/shared_impl/file_ref_create_info.h"
+#include "ppapi/shared_impl/file_ref_detailed_info.h"
 #include "ppapi/shared_impl/ppapi_nacl_channel_args.h"
 #include "ppapi/shared_impl/ppapi_preferences.h"
 #include "ppapi/shared_impl/ppb_device_ref_shared.h"
@@ -202,7 +203,7 @@
   IPC_STRUCT_TRAITS_MEMBER(is_dir)
 IPC_STRUCT_TRAITS_END()
 
-IPC_STRUCT_TRAITS_BEGIN(ppapi::FileRef_CreateInfo)
+IPC_STRUCT_TRAITS_BEGIN(ppapi::FileRefCreateInfo)
   IPC_STRUCT_TRAITS_MEMBER(file_system_type)
   IPC_STRUCT_TRAITS_MEMBER(internal_path)
   IPC_STRUCT_TRAITS_MEMBER(display_name)
@@ -210,6 +211,13 @@
   IPC_STRUCT_TRAITS_MEMBER(file_system_plugin_resource)
 IPC_STRUCT_TRAITS_END()
 
+IPC_STRUCT_TRAITS_BEGIN(ppapi::FileRefDetailedInfo)
+  IPC_STRUCT_TRAITS_MEMBER(resource)
+  IPC_STRUCT_TRAITS_MEMBER(file_system_type)
+  IPC_STRUCT_TRAITS_MEMBER(file_system_url_spec)
+  IPC_STRUCT_TRAITS_MEMBER(external_path)
+IPC_STRUCT_TRAITS_END()
+
 IPC_STRUCT_TRAITS_BEGIN(ppapi::FlashSiteSetting)
   IPC_STRUCT_TRAITS_MEMBER(site)
   IPC_STRUCT_TRAITS_MEMBER(permission)
@@ -298,8 +306,7 @@
 IPC_STRUCT_TRAITS_BEGIN(ppapi::URLRequestInfoData::BodyItem)
   IPC_STRUCT_TRAITS_MEMBER(is_file)
   IPC_STRUCT_TRAITS_MEMBER(data)
-  // Note: we don't serialize file_ref.
-  IPC_STRUCT_TRAITS_MEMBER(file_ref_host_resource)
+  IPC_STRUCT_TRAITS_MEMBER(file_ref_pp_resource)
   IPC_STRUCT_TRAITS_MEMBER(start_offset)
   IPC_STRUCT_TRAITS_MEMBER(number_of_bytes)
   IPC_STRUCT_TRAITS_MEMBER(expected_last_modified_time)
@@ -486,30 +493,6 @@
                     ppapi::proxy::SerializedHandle /* socket_handle */,
                     ppapi::proxy::SerializedHandle /* handle */)
 
-// PPB_FileRef.
-// TODO(teravest): Remove these messages when we've switched over to the "new"
-// proxy.
-IPC_MESSAGE_ROUTED3(
-    PpapiMsg_PPBFileRef_CallbackComplete,
-    ppapi::HostResource /* resource */,
-    uint32_t /* callback_id */,
-    int32_t /* result */)
-
-IPC_MESSAGE_ROUTED4(
-    PpapiMsg_PPBFileRef_QueryCallbackComplete,
-    ppapi::HostResource /* resource */,
-    PP_FileInfo /* file_info */,
-    uint32_t /* callback_id */,
-    int32_t /* result */)
-
-IPC_MESSAGE_ROUTED5(
-    PpapiMsg_PPBFileRef_ReadDirectoryEntriesCallbackComplete,
-    ppapi::HostResource /* resource */,
-    std::vector<ppapi::PPB_FileRef_CreateInfo> /* files */,
-    std::vector<PP_FileType> /* file_types */,
-    uint32_t /* callback_id */,
-    int32_t /* result */)
-
 // PPB_FileSystem.
 IPC_MESSAGE_ROUTED2(
     PpapiMsg_PPBFileSystem_OpenComplete,
@@ -798,43 +781,6 @@
 IPC_MESSAGE_ROUTED1(PpapiHostMsg_PPBCore_ReleaseResource,
                     ppapi::HostResource)
 
-// PPB_FileRef.
-// TODO(teravest): Remove these messages when we've switched over to the "new"
-// proxy.
-IPC_SYNC_MESSAGE_ROUTED3_1(PpapiHostMsg_PPBFileRef_Create,
-                           PP_Instance /* instance */,
-                           PP_Resource /* file_system */,
-                           std::string /* path */,
-                           ppapi::PPB_FileRef_CreateInfo /* result */)
-IPC_SYNC_MESSAGE_ROUTED1_1(PpapiHostMsg_PPBFileRef_GetParent,
-                           ppapi::HostResource /* file_ref */,
-                           ppapi::PPB_FileRef_CreateInfo /* result */)
-IPC_MESSAGE_ROUTED3(PpapiHostMsg_PPBFileRef_MakeDirectory,
-                    ppapi::HostResource /* file_ref */,
-                    PP_Bool /* make_ancestors */,
-                    uint32_t /* callback_id */)
-IPC_MESSAGE_ROUTED4(PpapiHostMsg_PPBFileRef_Touch,
-                    ppapi::HostResource /* file_ref */,
-                    PP_Time /* last_access */,
-                    PP_Time /* last_modified */,
-                    uint32_t /* callback_id */)
-IPC_MESSAGE_ROUTED2(PpapiHostMsg_PPBFileRef_Delete,
-                    ppapi::HostResource /* file_ref */,
-                    uint32_t /* callback_id */)
-IPC_MESSAGE_ROUTED3(PpapiHostMsg_PPBFileRef_Rename,
-                    ppapi::HostResource /* file_ref */,
-                    ppapi::HostResource /* new_file_ref */,
-                    uint32_t /* callback_id */)
-IPC_MESSAGE_ROUTED2(PpapiHostMsg_PPBFileRef_Query,
-                    ppapi::HostResource /* file_ref */,
-                    uint32_t /* callback_id */)
-IPC_SYNC_MESSAGE_ROUTED1_1(PpapiHostMsg_PPBFileRef_GetAbsolutePath,
-                           ppapi::HostResource /* file_ref */,
-                           ppapi::proxy::SerializedVar /* result */)
-IPC_MESSAGE_ROUTED2(PpapiHostMsg_PPBFileRef_ReadDirectoryEntries,
-                    ppapi::HostResource /* file_ref */,
-                    uint32_t /* callback_id */)
-
 // PPB_Graphics3D.
 IPC_SYNC_MESSAGE_ROUTED3_1(PpapiHostMsg_PPBGraphics3D_Create,
                            PP_Instance /* instance */,
@@ -1267,7 +1213,6 @@
     ppapi::proxy::ResourceMessageReplyParams /* reply_params */,
     IPC::Message /* nested_msg */)
 
-
 IPC_SYNC_MESSAGE_CONTROL2_2(PpapiHostMsg_ResourceSyncCall,
     ppapi::proxy::ResourceMessageCallParams /* call_params */,
     IPC::Message /* nested_msg */,
@@ -1341,7 +1286,7 @@
                      std::string /* suggested_file_name */,
                      std::vector<std::string> /* accept_mime_types */)
 IPC_MESSAGE_CONTROL1(PpapiPluginMsg_FileChooser_ShowReply,
-                     std::vector<ppapi::PPB_FileRef_CreateInfo> /* files */)
+                     std::vector<ppapi::FileRefCreateInfo> /* files */)
 
 // FileIO
 IPC_MESSAGE_CONTROL0(PpapiHostMsg_FileIO_Create)
@@ -1350,15 +1295,9 @@
                      int32_t /* open_flags */)
 IPC_MESSAGE_CONTROL0(PpapiPluginMsg_FileIO_OpenReply)
 IPC_MESSAGE_CONTROL0(PpapiHostMsg_FileIO_Close)
-IPC_MESSAGE_CONTROL0(PpapiHostMsg_FileIO_Query)
-IPC_MESSAGE_CONTROL1(PpapiPluginMsg_FileIO_QueryReply, PP_FileInfo /* info */)
 IPC_MESSAGE_CONTROL2(PpapiHostMsg_FileIO_Touch,
                      PP_Time /* last_access_time */,
                      PP_Time /* last_modified_time */)
-IPC_MESSAGE_CONTROL2(PpapiHostMsg_FileIO_Read,
-                     int64_t /* offset */,
-                     int32_t /* bytes_to_read */)
-IPC_MESSAGE_CONTROL1(PpapiPluginMsg_FileIO_ReadReply, std::string /* data */)
 IPC_MESSAGE_CONTROL2(PpapiHostMsg_FileIO_Write,
                      int64_t /* offset */,
                      std::string /* data */)
@@ -1423,10 +1362,10 @@
 // location indicated by the FileRef.
 IPC_MESSAGE_CONTROL0(PpapiHostMsg_FileRef_ReadDirectoryEntries)
 
-// FileRef_CreateInfo does not provide file type information, so two
+// FileRefCreateInfo does not provide file type information, so two
 // corresponding vectors are returned.
 IPC_MESSAGE_CONTROL2(PpapiPluginMsg_FileRef_ReadDirectoryEntriesReply,
-                     std::vector<ppapi::FileRef_CreateInfo> /* files */,
+                     std::vector<ppapi::FileRefCreateInfo> /* files */,
                      std::vector<PP_FileType> /* file_types */)
 
 // Requests that the browser reply with the absolute path to the indicated
@@ -1466,7 +1405,7 @@
 // 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::PPB_FileRef_CreateInfo /* file_info */)
+                     ppapi::FileRefCreateInfo /* file_info */)
 
 // Gamepad.
 IPC_MESSAGE_CONTROL0(PpapiHostMsg_Gamepad_Create)
@@ -1828,12 +1767,18 @@
 // path information in either |file_system_url_spec| (for internal file systems)
 // or |external_path| (for external file systems).
 // Only sent from the browser to the renderer.
-IPC_MESSAGE_ROUTED5(PpapiHostMsg_FileRef_GetInfoForRendererReply,
-                    int32_t /* sequence */,
-                    std::vector<PP_Resource> /* resources */,
-                    std::vector<PP_FileSystemType> /* fs_type */,
-                    std::vector<std::string> /* file_system_url_spec */,
-                    std::vector<base::FilePath> /* external_path */)
+IPC_MESSAGE_ROUTED2(
+    PpapiHostMsg_FileRef_GetInfoForRendererReply,
+    int32_t /* sequence */,
+    std::vector<ppapi::FileRefDetailedInfo> /* detailed_info */)
+
+// A synchronous version of the two above messages. This is required to support
+// some URL loading routes which must be executed synchronously.
+IPC_SYNC_MESSAGE_ROUTED2_1(
+    PpapiHostMsg_FileRef_SyncGetInfoForRenderer,
+    int /* child_process_id */,
+    std::vector<PP_Resource> /* resources */,
+    std::vector<ppapi::FileRefDetailedInfo> /* detailed_info */)
 
 // Flash -----------------------------------------------------------------------
 
diff --git a/ppapi/proxy/ppapi_param_traits.cc b/ppapi/proxy/ppapi_param_traits.cc
index ca25f82..5d4345f 100644
--- a/ppapi/proxy/ppapi_param_traits.cc
+++ b/ppapi/proxy/ppapi_param_traits.cc
@@ -175,36 +175,6 @@
   l->append(" bytes)>");
 }
 
-// TODO(teravest): Remove this when FileRef is moved to the "new" proxy.
-// PPB_FileRef_CreateInfo ------------------------------------------------------
-
-// static
-void ParamTraits<ppapi::PPB_FileRef_CreateInfo>::Write(Message* m,
-                                                       const param_type& p) {
-  ParamTraits<ppapi::HostResource>::Write(m, p.resource);
-  ParamTraits<int>::Write(m, p.file_system_type);
-  ParamTraits<std::string>::Write(m, p.path);
-  ParamTraits<std::string>::Write(m, p.name);
-  ParamTraits<PP_Resource>::Write(m, p.file_system_plugin_resource);
-}
-
-// static
-bool ParamTraits<ppapi::PPB_FileRef_CreateInfo>::Read(const Message* m,
-                                                      PickleIterator* iter,
-                                                      param_type* r) {
-  return
-      ParamTraits<ppapi::HostResource>::Read(m, iter, &r->resource) &&
-      ParamTraits<int>::Read(m, iter, &r->file_system_type) &&
-      ParamTraits<std::string>::Read(m, iter, &r->path) &&
-      ParamTraits<std::string>::Read(m, iter, &r->name) &&
-      ParamTraits<PP_Resource>::Read(m, iter, &r->file_system_plugin_resource);
-}
-
-// static
-void ParamTraits<ppapi::PPB_FileRef_CreateInfo>::Log(const param_type& p,
-                                                     std::string* l) {
-}
-
 // HostResource ----------------------------------------------------------------
 
 // static
@@ -274,28 +244,6 @@
     std::string* l) {
 }
 
-// std::vector<PPB_FileRef_CreateInfo> -----------------------------------------
-
-void ParamTraits< std::vector<ppapi::PPB_FileRef_CreateInfo> >::Write(
-    Message* m,
-    const param_type& p) {
-  WriteVectorWithoutCopy(m, p);
-}
-
-// static
-bool ParamTraits< std::vector<ppapi::PPB_FileRef_CreateInfo> >::Read(
-    const Message* m,
-    PickleIterator* iter,
-    param_type* r) {
-  return ReadVectorWithoutCopy(m, iter, r);
-}
-
-// static
-void ParamTraits< std::vector<ppapi::PPB_FileRef_CreateInfo> >::Log(
-    const param_type& p,
-    std::string* l) {
-}
-
 // ppapi::PpapiPermissions -----------------------------------------------------
 
 void ParamTraits<ppapi::PpapiPermissions>::Write(Message* m,
diff --git a/ppapi/proxy/ppapi_param_traits.h b/ppapi/proxy/ppapi_param_traits.h
index f56415a..b56ec3e 100644
--- a/ppapi/proxy/ppapi_param_traits.h
+++ b/ppapi/proxy/ppapi_param_traits.h
@@ -17,7 +17,6 @@
 #include "ppapi/shared_impl/file_path.h"
 #include "ppapi/shared_impl/file_ref_create_info.h"
 #include "ppapi/shared_impl/ppapi_permissions.h"
-#include "ppapi/shared_impl/ppb_file_ref_shared.h"
 #include "ppapi/shared_impl/socket_option_data.h"
 
 struct PP_FileInfo;
@@ -77,15 +76,6 @@
   static void Log(const param_type& p, std::string* l);
 };
 
-// TODO(teravest): Remove this when we've switched over to the new proxy.
-template<>
-struct PPAPI_PROXY_EXPORT ParamTraits<ppapi::PPB_FileRef_CreateInfo> {
-  typedef ppapi::PPB_FileRef_CreateInfo param_type;
-  static void Write(Message* m, const param_type& p);
-  static bool Read(const Message* m, PickleIterator* iter, param_type* r);
-  static void Log(const param_type& p, std::string* l);
-};
-
 template<>
 struct PPAPI_PROXY_EXPORT ParamTraits<
     ppapi::proxy::PPBURLLoader_UpdateProgress_Params> {
@@ -154,15 +144,6 @@
 };
 
 template<>
-struct PPAPI_PROXY_EXPORT ParamTraits< std::vector<
-    ppapi::PPB_FileRef_CreateInfo> > {
-  typedef std::vector<ppapi::PPB_FileRef_CreateInfo> param_type;
-  static void Write(Message* m, const param_type& p);
-  static bool Read(const Message* m, PickleIterator* iter, param_type* r);
-  static void Log(const param_type& p, std::string* l);
-};
-
-template<>
 struct PPAPI_PROXY_EXPORT ParamTraits<ppapi::PpapiPermissions> {
   typedef ppapi::PpapiPermissions param_type;
   static void Write(Message* m, const param_type& p);
diff --git a/ppapi/proxy/ppb_file_ref_proxy.cc b/ppapi/proxy/ppb_file_ref_proxy.cc
deleted file mode 100644
index 62c55da..0000000
--- a/ppapi/proxy/ppb_file_ref_proxy.cc
+++ /dev/null
@@ -1,549 +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 "ppapi/proxy/ppb_file_ref_proxy.h"
-
-#include <map>
-
-#include "base/bind.h"
-#include "ppapi/c/pp_directory_entry.h"
-#include "ppapi/c/pp_errors.h"
-#include "ppapi/c/ppb_file_ref.h"
-#include "ppapi/c/private/ppb_file_ref_private.h"
-#include "ppapi/c/private/ppb_proxy_private.h"
-#include "ppapi/proxy/enter_proxy.h"
-#include "ppapi/proxy/host_dispatcher.h"
-#include "ppapi/proxy/plugin_dispatcher.h"
-#include "ppapi/proxy/ppapi_messages.h"
-#include "ppapi/proxy/serialized_var.h"
-#include "ppapi/shared_impl/array_writer.h"
-#include "ppapi/shared_impl/ppb_file_ref_shared.h"
-#include "ppapi/shared_impl/scoped_pp_resource.h"
-#include "ppapi/shared_impl/tracked_callback.h"
-#include "ppapi/thunk/resource_creation_api.h"
-#include "ppapi/thunk/thunk.h"
-
-using ppapi::thunk::EnterResourceNoLock;
-using ppapi::thunk::PPB_FileRef_API;
-using ppapi::thunk::ResourceCreationAPI;
-
-namespace ppapi {
-namespace proxy {
-
-namespace {
-
-void ReleaseEntries(const std::vector<PP_DirectoryEntry>& entries) {
-  ResourceTracker* tracker = PpapiGlobals::Get()->GetResourceTracker();
-  for (std::vector<PP_DirectoryEntry>::const_iterator it = entries.begin();
-       it != entries.end(); ++it)
-    tracker->ReleaseResource(it->file_ref);
-}
-
-}  // namespace
-
-class FileRef : public PPB_FileRef_Shared {
- public:
-  explicit FileRef(const PPB_FileRef_CreateInfo& info);
-  virtual ~FileRef();
-
-  // Resource overrides.
-  virtual void LastPluginRefWasDeleted() OVERRIDE;
-
-  // PPB_FileRef_API implementation (not provided by PPB_FileRef_Shared).
-  virtual PP_Resource GetParent() OVERRIDE;
-  virtual int32_t MakeDirectory(
-      PP_Bool make_ancestors,
-      scoped_refptr<TrackedCallback> callback) OVERRIDE;
-  virtual int32_t Touch(PP_Time last_access_time,
-                        PP_Time last_modified_time,
-                        scoped_refptr<TrackedCallback> callback) OVERRIDE;
-  virtual int32_t Delete(scoped_refptr<TrackedCallback> callback) OVERRIDE;
-  virtual int32_t Rename(PP_Resource new_file_ref,
-                         scoped_refptr<TrackedCallback> callback) OVERRIDE;
-  virtual int32_t Query(PP_FileInfo* info,
-                        scoped_refptr<TrackedCallback> callback) OVERRIDE;
-  virtual int32_t ReadDirectoryEntries(
-      const PP_ArrayOutput& output,
-      scoped_refptr<TrackedCallback> callback) OVERRIDE;
-  virtual int32_t QueryInHost(
-      linked_ptr<PP_FileInfo> info,
-      scoped_refptr<TrackedCallback> callback) OVERRIDE;
-  virtual int32_t ReadDirectoryEntriesInHost(
-      linked_ptr<std::vector<ppapi::PPB_FileRef_CreateInfo> > files,
-      linked_ptr<std::vector<PP_FileType> > file_types,
-      scoped_refptr<TrackedCallback> callback) OVERRIDE;
-  virtual PP_Var GetAbsolutePath() OVERRIDE;
-
-  // Executes the pending callback with the given ID. See pending_callbacks_.
-  void ExecuteCallback(uint32_t callback_id, int32_t result);
-  int32_t SetFileInfo(uint32_t callback_id, const PP_FileInfo& info);
-  int32_t SetReadDirectoryEntriesOutput(
-      uint32_t callback_id,
-      const std::vector<ppapi::PPB_FileRef_CreateInfo>& infos,
-      const std::vector<PP_FileType>& file_types);
-
- private:
-  PluginDispatcher* GetDispatcher() const {
-    return PluginDispatcher::GetForResource(this);
-  }
-
-  // Adds a callback to the list and returns its ID.
-  uint32_t SendCallback(scoped_refptr<TrackedCallback> callback);
-
-  // This class can have any number of out-standing requests with completion
-  // callbacks, in contrast to most resources which have one possible pending
-  // callback pending (like a Flush callback).
-  //
-  // To keep track of them, assign integer IDs to the callbacks, which is how
-  // the callback will be identified when it's passed to the host and then
-  // back here. Use unsigned so that overflow is well-defined.
-  uint32_t next_callback_id_;
-  typedef std::map<uint32_t,
-                   scoped_refptr<TrackedCallback> > PendingCallbackMap;
-  PendingCallbackMap pending_callbacks_;
-
-  // Used to keep pointers to PP_FileInfo instances that are written before
-  // callbacks are invoked. The id of a pending file info will match that of
-  // the corresponding callback.
-  typedef std::map<uint32_t, PP_FileInfo*> PendingFileInfoMap;
-  PendingFileInfoMap pending_file_infos_;
-
-  // Used to keep PP_ArrayOutput instances that are written before callbacks
-  // are invoked. The id of a pending array output will match that of the
-  // corresponding callback.
-  typedef std::map<uint32_t, PP_ArrayOutput>
-      PendingReadDirectoryEntriesOutputMap;
-  PendingReadDirectoryEntriesOutputMap pending_read_entries_outputs_;
-
-  // Holds a reference on plugin side when running out of process, so that
-  // FileSystem won't die before FileRef.  See PPB_FileRef_Impl for
-  // corresponding code for in-process mode.  Note that this workaround will
-  // be no longer needed after FileRef refactoring.
-  ScopedPPResource file_system_;
-
-  DISALLOW_IMPLICIT_CONSTRUCTORS(FileRef);
-};
-
-FileRef::FileRef(const PPB_FileRef_CreateInfo& info)
-    : PPB_FileRef_Shared(OBJECT_IS_PROXY, info),
-      next_callback_id_(0u),
-      file_system_(info.file_system_plugin_resource) {
-}
-
-FileRef::~FileRef() {
-  // The callbacks map should have been cleared by LastPluginRefWasDeleted.
-  DCHECK(pending_callbacks_.empty());
-  DCHECK(pending_file_infos_.empty());
-  DCHECK(pending_read_entries_outputs_.empty());
-}
-
-void FileRef::LastPluginRefWasDeleted() {
-  // The callback tracker will abort our callbacks for us.
-  pending_callbacks_.clear();
-  pending_file_infos_.clear();
-  pending_read_entries_outputs_.clear();
-}
-
-PP_Resource FileRef::GetParent() {
-  PPB_FileRef_CreateInfo create_info;
-  GetDispatcher()->Send(new PpapiHostMsg_PPBFileRef_GetParent(
-      API_ID_PPB_FILE_REF, host_resource(), &create_info));
-  return PPB_FileRef_Proxy::DeserializeFileRef(create_info);
-}
-
-int32_t FileRef::MakeDirectory(PP_Bool make_ancestors,
-                               scoped_refptr<TrackedCallback> callback) {
-  GetDispatcher()->Send(new PpapiHostMsg_PPBFileRef_MakeDirectory(
-      API_ID_PPB_FILE_REF, host_resource(), make_ancestors,
-      SendCallback(callback)));
-  return PP_OK_COMPLETIONPENDING;
-}
-
-int32_t FileRef::Touch(PP_Time last_access_time,
-                       PP_Time last_modified_time,
-                       scoped_refptr<TrackedCallback> callback) {
-  GetDispatcher()->Send(new PpapiHostMsg_PPBFileRef_Touch(
-      API_ID_PPB_FILE_REF, host_resource(), last_access_time,
-      last_modified_time, SendCallback(callback)));
-  return PP_OK_COMPLETIONPENDING;
-}
-
-int32_t FileRef::Delete(scoped_refptr<TrackedCallback> callback) {
-  GetDispatcher()->Send(new PpapiHostMsg_PPBFileRef_Delete(
-      API_ID_PPB_FILE_REF, host_resource(), SendCallback(callback)));
-  return PP_OK_COMPLETIONPENDING;
-}
-
-int32_t FileRef::Rename(PP_Resource new_file_ref,
-                        scoped_refptr<TrackedCallback> callback) {
-  Resource* new_file_ref_object =
-      PpapiGlobals::Get()->GetResourceTracker()->GetResource(new_file_ref);
-  if (!new_file_ref_object ||
-      new_file_ref_object->host_resource().instance() != pp_instance())
-    return PP_ERROR_BADRESOURCE;
-
-  GetDispatcher()->Send(new PpapiHostMsg_PPBFileRef_Rename(
-      API_ID_PPB_FILE_REF, host_resource(),
-      new_file_ref_object->host_resource(), SendCallback(callback)));
-  return PP_OK_COMPLETIONPENDING;
-}
-
-int32_t FileRef::Query(PP_FileInfo* info,
-                       scoped_refptr<TrackedCallback> callback) {
-  // Store the pending file info id.
-  uint32_t id = SendCallback(callback);
-  pending_file_infos_[id] = info;
-  GetDispatcher()->Send(new PpapiHostMsg_PPBFileRef_Query(
-      API_ID_PPB_FILE_REF, host_resource(), id));
-  return PP_OK_COMPLETIONPENDING;
-}
-
-int32_t FileRef::ReadDirectoryEntries(
-    const PP_ArrayOutput& output,
-    scoped_refptr<TrackedCallback> callback) {
-  // Store the pending read entries output id.
-  uint32_t id = SendCallback(callback);
-  pending_read_entries_outputs_[id] = output;
-  GetDispatcher()->Send(new PpapiHostMsg_PPBFileRef_ReadDirectoryEntries(
-      API_ID_PPB_FILE_REF, host_resource(), id));
-  return PP_OK_COMPLETIONPENDING;
-}
-
-int32_t FileRef::QueryInHost(
-    linked_ptr<PP_FileInfo> info,
-    scoped_refptr<TrackedCallback> callback) {
-  NOTREACHED();
-  return PP_ERROR_FAILED;
-}
-
-int32_t FileRef::ReadDirectoryEntriesInHost(
-    linked_ptr<std::vector<ppapi::PPB_FileRef_CreateInfo> > files,
-    linked_ptr<std::vector<PP_FileType> > file_types,
-    scoped_refptr<TrackedCallback> callback) {
-  NOTREACHED();
-  return PP_ERROR_FAILED;
-}
-
-PP_Var FileRef::GetAbsolutePath() {
-  ReceiveSerializedVarReturnValue result;
-  GetDispatcher()->Send(new PpapiHostMsg_PPBFileRef_GetAbsolutePath(
-      API_ID_PPB_FILE_REF, host_resource(), &result));
-  return result.Return(GetDispatcher());
-}
-
-void FileRef::ExecuteCallback(uint32_t callback_id, int32_t result) {
-  PendingCallbackMap::iterator found = pending_callbacks_.find(callback_id);
-  if (found == pending_callbacks_.end()) {
-    // This will happen when the plugin deletes its resource with a pending
-    // callback. The callback will be locally issued with an ABORTED call while
-    // the operation may still be pending in the renderer.
-    return;
-  }
-
-  // Executing the callback may mutate the callback list.
-  scoped_refptr<TrackedCallback> callback = found->second;
-  pending_callbacks_.erase(found);
-  callback->Run(result);
-}
-
-int32_t FileRef::SetFileInfo(uint32_t callback_id, const PP_FileInfo& info) {
-  PendingFileInfoMap::iterator found = pending_file_infos_.find(callback_id);
-  if (found == pending_file_infos_.end())
-    return PP_ERROR_FAILED;
-  PP_FileInfo* target_info = found->second;
-  *target_info = info;
-  pending_file_infos_.erase(found);
-  return PP_OK;
-}
-
-int32_t FileRef::SetReadDirectoryEntriesOutput(
-    uint32_t callback_id,
-    const std::vector<ppapi::PPB_FileRef_CreateInfo>& infos,
-    const std::vector<PP_FileType>& file_types) {
-  PendingReadDirectoryEntriesOutputMap::iterator found =
-      pending_read_entries_outputs_.find(callback_id);
-  if (found == pending_read_entries_outputs_.end())
-    return PP_ERROR_FAILED;
-
-  PP_ArrayOutput output = found->second;
-  pending_read_entries_outputs_.erase(found);
-
-  std::vector<PP_DirectoryEntry> entries;
-  for (size_t i = 0; i < infos.size(); ++i) {
-    PP_DirectoryEntry entry;
-    entry.file_ref = PPB_FileRef_Proxy::DeserializeFileRef(infos[i]);
-    entry.file_type = file_types[i];
-    entries.push_back(entry);
-  }
-
-  ArrayWriter writer(output);
-  if (!writer.is_valid()) {
-    ReleaseEntries(entries);
-    return PP_ERROR_BADARGUMENT;
-  }
-
-  writer.StoreVector(entries);
-  return PP_OK;
-}
-
-uint32_t FileRef::SendCallback(scoped_refptr<TrackedCallback> callback) {
-  // In extreme cases the IDs may wrap around, so avoid duplicates.
-  while (pending_callbacks_.count(next_callback_id_))
-    ++next_callback_id_;
-
-  pending_callbacks_[next_callback_id_] = callback;
-  return next_callback_id_++;
-}
-
-PPB_FileRef_Proxy::PPB_FileRef_Proxy(Dispatcher* dispatcher)
-    : InterfaceProxy(dispatcher),
-      callback_factory_(this) {
-}
-
-PPB_FileRef_Proxy::~PPB_FileRef_Proxy() {
-}
-
-// static
-PP_Resource PPB_FileRef_Proxy::CreateProxyResource(PP_Instance instance,
-                                                   PP_Resource file_system,
-                                                   const char* path) {
-  PPB_FileRef_CreateInfo create_info;
-  PluginDispatcher::GetForInstance(instance)->Send(
-      new PpapiHostMsg_PPBFileRef_Create(
-          API_ID_PPB_FILE_REF, instance, file_system, path, &create_info));
-  return PPB_FileRef_Proxy::DeserializeFileRef(create_info);
-}
-
-bool PPB_FileRef_Proxy::OnMessageReceived(const IPC::Message& msg) {
-  bool handled = true;
-  IPC_BEGIN_MESSAGE_MAP(PPB_FileRef_Proxy, msg)
-#if !defined(OS_NACL)
-    IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFileRef_Create, OnMsgCreate)
-    IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFileRef_GetParent, OnMsgGetParent)
-    IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFileRef_MakeDirectory,
-                        OnMsgMakeDirectory)
-    IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFileRef_Touch, OnMsgTouch)
-    IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFileRef_Delete, OnMsgDelete)
-    IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFileRef_Rename, OnMsgRename)
-    IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFileRef_Query, OnMsgQuery)
-    IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFileRef_ReadDirectoryEntries,
-                        OnMsgReadDirectoryEntries)
-    IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFileRef_GetAbsolutePath,
-                        OnMsgGetAbsolutePath)
-#endif  // !defined(OS_NACL)
-
-    IPC_MESSAGE_HANDLER(PpapiMsg_PPBFileRef_CallbackComplete,
-                        OnMsgCallbackComplete)
-    IPC_MESSAGE_HANDLER(PpapiMsg_PPBFileRef_QueryCallbackComplete,
-                        OnMsgQueryCallbackComplete)
-    IPC_MESSAGE_HANDLER(
-        PpapiMsg_PPBFileRef_ReadDirectoryEntriesCallbackComplete,
-        OnMsgReadDirectoryEntriesCallbackComplete)
-    IPC_MESSAGE_UNHANDLED(handled = false)
-  IPC_END_MESSAGE_MAP()
-  return handled;
-}
-
-// static
-void PPB_FileRef_Proxy::SerializeFileRef(PP_Resource file_ref,
-                                         PPB_FileRef_CreateInfo* result) {
-  EnterResourceNoLock<PPB_FileRef_API> enter(file_ref, false);
-  if (enter.succeeded())
-    *result = enter.object()->GetCreateInfo();
-}
-
-// static
-PP_Resource PPB_FileRef_Proxy::DeserializeFileRef(
-    const PPB_FileRef_CreateInfo& serialized) {
-  if (serialized.resource.is_null())
-    return 0;  // Resource invalid.
-  return (new FileRef(serialized))->GetReference();
-}
-
-#if !defined(OS_NACL)
-void PPB_FileRef_Proxy::OnMsgCreate(PP_Instance pp_instance,
-                                    PP_Resource file_system,
-                                    const std::string& path,
-                                    PPB_FileRef_CreateInfo* result) {
-  thunk::EnterResourceCreation enter(pp_instance);
-  if (enter.failed())
-    return;
-
-  PP_Resource resource = enter.functions()->CreateFileRef(
-      pp_instance, file_system, path.c_str());
-  if (!resource)
-    return;  // CreateInfo default constructor initializes to 0.
-  SerializeFileRef(resource, result);
-}
-
-void PPB_FileRef_Proxy::OnMsgGetParent(const HostResource& host_resource,
-                                       PPB_FileRef_CreateInfo* result) {
-  EnterHostFromHostResource<PPB_FileRef_API> enter(host_resource);
-  if (enter.succeeded())
-    SerializeFileRef(enter.object()->GetParent(), result);
-}
-
-void PPB_FileRef_Proxy::OnMsgMakeDirectory(const HostResource& host_resource,
-                                           PP_Bool make_ancestors,
-                                           uint32_t callback_id) {
-  EnterHostFromHostResourceForceCallback<PPB_FileRef_API> enter(
-      host_resource, callback_factory_,
-      &PPB_FileRef_Proxy::OnCallbackCompleteInHost, host_resource, callback_id);
-  if (enter.succeeded()) {
-    enter.SetResult(enter.object()->MakeDirectory(make_ancestors,
-                                                  enter.callback()));
-  }
-}
-
-void PPB_FileRef_Proxy::OnMsgTouch(const HostResource& host_resource,
-                                   PP_Time last_access,
-                                   PP_Time last_modified,
-                                   uint32_t callback_id) {
-  EnterHostFromHostResourceForceCallback<PPB_FileRef_API> enter(
-      host_resource, callback_factory_,
-      &PPB_FileRef_Proxy::OnCallbackCompleteInHost, host_resource, callback_id);
-  if (enter.succeeded()) {
-    enter.SetResult(enter.object()->Touch(last_access, last_modified,
-                                          enter.callback()));
-  }
-}
-
-void PPB_FileRef_Proxy::OnMsgDelete(const HostResource& host_resource,
-                                    uint32_t callback_id) {
-  EnterHostFromHostResourceForceCallback<PPB_FileRef_API> enter(
-      host_resource, callback_factory_,
-      &PPB_FileRef_Proxy::OnCallbackCompleteInHost, host_resource, callback_id);
-  if (enter.succeeded())
-    enter.SetResult(enter.object()->Delete(enter.callback()));
-}
-
-void PPB_FileRef_Proxy::OnMsgRename(const HostResource& file_ref,
-                                    const HostResource& new_file_ref,
-                                    uint32_t callback_id) {
-  EnterHostFromHostResourceForceCallback<PPB_FileRef_API> enter(
-      file_ref, callback_factory_,
-      &PPB_FileRef_Proxy::OnCallbackCompleteInHost, file_ref, callback_id);
-  if (enter.succeeded()) {
-    enter.SetResult(enter.object()->Rename(new_file_ref.host_resource(),
-                                           enter.callback()));
-  }
-}
-
-void PPB_FileRef_Proxy::OnMsgQuery(const HostResource& file_ref,
-                                   uint32_t callback_id) {
-  linked_ptr<PP_FileInfo> info(new PP_FileInfo());
-  EnterHostFromHostResourceForceCallback<PPB_FileRef_API> enter(
-      file_ref, callback_factory_,
-      &PPB_FileRef_Proxy::OnQueryCallbackCompleteInHost, file_ref,
-      info, callback_id);
-  if (enter.succeeded())
-    enter.SetResult(enter.object()->QueryInHost(info, enter.callback()));
-}
-
-void PPB_FileRef_Proxy::OnMsgGetAbsolutePath(const HostResource& host_resource,
-                                             SerializedVarReturnValue result) {
-  EnterHostFromHostResource<PPB_FileRef_API> enter(host_resource);
-  if (enter.succeeded())
-    result.Return(dispatcher(), enter.object()->GetAbsolutePath());
-}
-
-void PPB_FileRef_Proxy::OnMsgReadDirectoryEntries(const HostResource& file_ref,
-                                         uint32_t callback_id) {
-  linked_ptr<std::vector<ppapi::PPB_FileRef_CreateInfo> > files(
-      new std::vector<ppapi::PPB_FileRef_CreateInfo>());
-  linked_ptr<std::vector<PP_FileType> > file_types(
-      new std::vector<PP_FileType>());
-  HostCallbackParams params(file_ref, callback_id);
-  EnterHostFromHostResourceForceCallback<PPB_FileRef_API> enter(
-      file_ref, callback_factory_,
-      &PPB_FileRef_Proxy::OnReadDirectoryEntriesCallbackCompleteInHost,
-      params, files, file_types);
-  if (enter.succeeded()) {
-    enter.SetResult(enter.object()->ReadDirectoryEntriesInHost(
-        files, file_types, enter.callback()));
-  }
-}
-
-#endif  // !defined(OS_NACL)
-
-void PPB_FileRef_Proxy::OnMsgCallbackComplete(
-    const HostResource& host_resource,
-    uint32_t callback_id,
-    int32_t result) {
-  // Forward the callback info to the plugin resource.
-  EnterPluginFromHostResource<PPB_FileRef_API> enter(host_resource);
-  if (enter.succeeded())
-    static_cast<FileRef*>(enter.object())->ExecuteCallback(callback_id, result);
-}
-
-void PPB_FileRef_Proxy::OnMsgQueryCallbackComplete(
-    const HostResource& host_resource,
-    const PP_FileInfo& info,
-    uint32_t callback_id,
-    int32_t result) {
-  EnterPluginFromHostResource<PPB_FileRef_API> enter(host_resource);
-  if (!enter.succeeded())
-    return;
-
-  if (result == PP_OK) {
-    result = static_cast<FileRef*>(enter.object())->SetFileInfo(
-        callback_id, info);
-  }
-  static_cast<FileRef*>(enter.object())->ExecuteCallback(callback_id, result);
-}
-
-void PPB_FileRef_Proxy::OnMsgReadDirectoryEntriesCallbackComplete(
-    const HostResource& host_resource,
-    const std::vector<ppapi::PPB_FileRef_CreateInfo>& infos,
-    const std::vector<PP_FileType>& file_types,
-    uint32_t callback_id,
-    int32_t result) {
-  CHECK_EQ(infos.size(), file_types.size());
-
-  EnterPluginFromHostResource<PPB_FileRef_API> enter(host_resource);
-  if (!enter.succeeded())
-    return;
-
-  if (result == PP_OK) {
-    result =
-        static_cast<FileRef*>(enter.object())->SetReadDirectoryEntriesOutput(
-            callback_id, infos, file_types);
-  }
-  static_cast<FileRef*>(enter.object())->ExecuteCallback(
-      callback_id, result);
-}
-
-#if !defined(OS_NACL)
-void PPB_FileRef_Proxy::OnCallbackCompleteInHost(
-    int32_t result,
-    const HostResource& host_resource,
-    uint32_t callback_id) {
-  // Execute OnMsgCallbackComplete in the plugin process.
-  Send(new PpapiMsg_PPBFileRef_CallbackComplete(
-      API_ID_PPB_FILE_REF, host_resource, callback_id, result));
-}
-
-void PPB_FileRef_Proxy::OnQueryCallbackCompleteInHost(
-    int32_t result,
-    const HostResource& host_resource,
-    linked_ptr<PP_FileInfo> info,
-    uint32_t callback_id) {
-  Send(new PpapiMsg_PPBFileRef_QueryCallbackComplete(
-      API_ID_PPB_FILE_REF, host_resource, *info, callback_id, result));
-}
-
-void PPB_FileRef_Proxy::OnReadDirectoryEntriesCallbackCompleteInHost(
-    int32_t result,
-    HostCallbackParams params,
-    linked_ptr<std::vector<ppapi::PPB_FileRef_CreateInfo> > files,
-    linked_ptr<std::vector<PP_FileType> > file_types) {
-  Send(new PpapiMsg_PPBFileRef_ReadDirectoryEntriesCallbackComplete(
-      API_ID_PPB_FILE_REF, params.host_resource,
-      *files, *file_types, params.callback_id, result));
-}
-
-#endif  // !defined(OS_NACL)
-
-}  // namespace proxy
-}  // namespace ppapi
diff --git a/ppapi/proxy/ppb_file_ref_proxy.h b/ppapi/proxy/ppb_file_ref_proxy.h
deleted file mode 100644
index cbfadb5..0000000
--- a/ppapi/proxy/ppb_file_ref_proxy.h
+++ /dev/null
@@ -1,138 +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 PPAPI_PROXY_PPB_FILE_REF_PROXY_H_
-#define PPAPI_PROXY_PPB_FILE_REF_PROXY_H_
-
-#include <string>
-
-#include "base/basictypes.h"
-#include "base/memory/linked_ptr.h"
-#include "ppapi/c/pp_file_info.h"
-#include "ppapi/c/pp_module.h"
-#include "ppapi/c/pp_resource.h"
-#include "ppapi/c/pp_time.h"
-#include "ppapi/proxy/interface_proxy.h"
-#include "ppapi/proxy/ppapi_proxy_export.h"
-#include "ppapi/proxy/proxy_completion_callback_factory.h"
-#include "ppapi/shared_impl/host_resource.h"
-#include "ppapi/utility/completion_callback_factory.h"
-
-namespace ppapi {
-
-struct PPB_FileRef_CreateInfo;
-
-namespace proxy {
-
-class SerializedVarReturnValue;
-
-class PPAPI_PROXY_EXPORT PPB_FileRef_Proxy
-    : public NON_EXPORTED_BASE(InterfaceProxy) {
- public:
-  explicit PPB_FileRef_Proxy(Dispatcher* dispatcher);
-  virtual ~PPB_FileRef_Proxy();
-
-  static PP_Resource CreateProxyResource(PP_Instance instance,
-                                         PP_Resource file_system,
-                                         const char* path);
-  static PP_Resource CreateProxyResource(
-      const PPB_FileRef_CreateInfo& serialized);
-
-  // InterfaceProxy implementation.
-  virtual bool OnMessageReceived(const IPC::Message& msg);
-
-  // Takes a resource in the host and converts it into a serialized file ref
-  // "create info" for reconstitution in the plugin. This struct contains all
-  // the necessary information about the file ref.
-  //
-  // Various PPAPI functions return file refs from various interfaces, so this
-  // function is public so anybody can send a file ref.
-  static void SerializeFileRef(PP_Resource file_ref,
-                               PPB_FileRef_CreateInfo* result);
-
-  // Creates a plugin resource from the given CreateInfo sent from the host.
-  // The value will be the result of calling SerializeFileRef on the host.
-  // This represents passing the resource ownership to the plugin. This
-  // function also checks the validity of the result and returns 0 on failure.
-  //
-  // Various PPAPI functions return file refs from various interfaces, so this
-  // function is public so anybody can receive a file ref.
-  static PP_Resource DeserializeFileRef(
-      const PPB_FileRef_CreateInfo& serialized);
-
-  static const ApiID kApiID = API_ID_PPB_FILE_REF;
-
- private:
-  // Plugin -> host message handlers.
-  void OnMsgCreate(PP_Instance instance,
-                   PP_Resource file_system,
-                   const std::string& path,
-                   PPB_FileRef_CreateInfo* result);
-  void OnMsgGetParent(const HostResource& host_resource,
-                      PPB_FileRef_CreateInfo* result);
-  void OnMsgMakeDirectory(const HostResource& host_resource,
-                          PP_Bool make_ancestors,
-                          uint32_t callback_id);
-  void OnMsgTouch(const HostResource& host_resource,
-                  PP_Time last_access,
-                  PP_Time last_modified,
-                  uint32_t callback_id);
-  void OnMsgDelete(const HostResource& host_resource,
-                   uint32_t callback_id);
-  void OnMsgRename(const HostResource& file_ref,
-                   const HostResource& new_file_ref,
-                   uint32_t callback_id);
-  void OnMsgQuery(const HostResource& file_ref,
-                  uint32_t callback_id);
-  void OnMsgGetAbsolutePath(const HostResource& host_resource,
-                            SerializedVarReturnValue result);
-  void OnMsgReadDirectoryEntries(const HostResource& file_ref,
-                                 uint32_t callback_id);
-
-  // Host -> Plugin message handlers.
-  void OnMsgCallbackComplete(const HostResource& host_resource,
-                             uint32_t callback_id,
-                             int32_t result);
-  void OnMsgQueryCallbackComplete(const HostResource& host_resource,
-                                  const PP_FileInfo& info,
-                                  uint32_t callback_id,
-                                  int32_t result);
-  void OnMsgReadDirectoryEntriesCallbackComplete(
-      const HostResource& host_resource,
-      const std::vector<ppapi::PPB_FileRef_CreateInfo>& infos,
-      const std::vector<PP_FileType>& file_types,
-      uint32_t callback_id,
-      int32_t result);
-
-  struct HostCallbackParams {
-    HostCallbackParams(const HostResource& host_res, uint32_t cb_id)
-        : host_resource(host_res), callback_id(cb_id) {
-    }
-    HostResource host_resource;
-    uint32_t callback_id;
-  };
-
-  void OnCallbackCompleteInHost(int32_t result,
-                                const HostResource& host_resource,
-                                uint32_t callback_id);
-  void OnQueryCallbackCompleteInHost(
-      int32_t result,
-      const HostResource& host_resource,
-      linked_ptr<PP_FileInfo> info,
-      uint32_t callback_id);
-  void OnReadDirectoryEntriesCallbackCompleteInHost(
-      int32_t result,
-      HostCallbackParams params,
-      linked_ptr<std::vector<ppapi::PPB_FileRef_CreateInfo> > files,
-      linked_ptr<std::vector<PP_FileType> > file_types);
-
-  ProxyCompletionCallbackFactory<PPB_FileRef_Proxy> callback_factory_;
-
-  DISALLOW_COPY_AND_ASSIGN(PPB_FileRef_Proxy);
-};
-
-}  // namespace proxy
-}  // namespace ppapi
-
-#endif  // PPAPI_PROXY_PPB_FILE_REF_PROXY_H_
diff --git a/ppapi/proxy/resource_creation_proxy.cc b/ppapi/proxy/resource_creation_proxy.cc
index 53cade1..8b7eb11 100644
--- a/ppapi/proxy/resource_creation_proxy.cc
+++ b/ppapi/proxy/resource_creation_proxy.cc
@@ -11,6 +11,7 @@
 #include "ppapi/proxy/ext_crx_file_system_private_resource.h"
 #include "ppapi/proxy/file_chooser_resource.h"
 #include "ppapi/proxy/file_io_resource.h"
+#include "ppapi/proxy/file_ref_resource.h"
 #include "ppapi/proxy/file_system_resource.h"
 #include "ppapi/proxy/flash_drm_resource.h"
 #include "ppapi/proxy/flash_font_file_resource.h"
@@ -26,7 +27,6 @@
 #include "ppapi/proxy/ppb_audio_proxy.h"
 #include "ppapi/proxy/ppb_broker_proxy.h"
 #include "ppapi/proxy/ppb_buffer_proxy.h"
-#include "ppapi/proxy/ppb_file_ref_proxy.h"
 #include "ppapi/proxy/ppb_flash_message_loop_proxy.h"
 #include "ppapi/proxy/ppb_graphics_3d_proxy.h"
 #include "ppapi/proxy/ppb_image_data_proxy.h"
@@ -78,15 +78,10 @@
   return (new FileIOResource(GetConnection(), instance))->GetReference();
 }
 
-PP_Resource ResourceCreationProxy::CreateFileRef(PP_Instance instance,
-                                                 PP_Resource file_system,
-                                                 const char* path) {
-  return PPB_FileRef_Proxy::CreateProxyResource(instance, file_system, path);
-}
-
 PP_Resource ResourceCreationProxy::CreateFileRef(
-    const PPB_FileRef_CreateInfo& create_info) {
-  return PPB_FileRef_Proxy::DeserializeFileRef(create_info);
+    PP_Instance instance,
+    const FileRefCreateInfo& create_info) {
+  return FileRefResource::CreateFileRef(GetConnection(), instance, create_info);
 }
 
 PP_Resource ResourceCreationProxy::CreateFileSystem(
diff --git a/ppapi/proxy/resource_creation_proxy.h b/ppapi/proxy/resource_creation_proxy.h
index 47b40a8..2cd86d5 100644
--- a/ppapi/proxy/resource_creation_proxy.h
+++ b/ppapi/proxy/resource_creation_proxy.h
@@ -38,11 +38,9 @@
 
   // ResourceCreationAPI (called in plugin).
   virtual PP_Resource CreateFileIO(PP_Instance instance) OVERRIDE;
-  virtual PP_Resource CreateFileRef(PP_Instance instance,
-                                    PP_Resource file_system,
-                                    const char* path) OVERRIDE;
   virtual PP_Resource CreateFileRef(
-      const PPB_FileRef_CreateInfo& create_info) OVERRIDE;
+      PP_Instance instance,
+      const FileRefCreateInfo& create_info) OVERRIDE;
   virtual PP_Resource CreateFileSystem(PP_Instance instance,
                                        PP_FileSystemType type) OVERRIDE;
   virtual PP_Resource CreateIsolatedFileSystem(
diff --git a/ppapi/proxy/url_loader_resource.cc b/ppapi/proxy/url_loader_resource.cc
index 5bbc937..1ff0a5e 100644
--- a/ppapi/proxy/url_loader_resource.cc
+++ b/ppapi/proxy/url_loader_resource.cc
@@ -9,8 +9,8 @@
 #include "ppapi/c/pp_errors.h"
 #include "ppapi/c/ppb_url_loader.h"
 #include "ppapi/proxy/dispatch_reply_message.h"
+#include "ppapi/proxy/file_ref_resource.h"
 #include "ppapi/proxy/ppapi_messages.h"
-#include "ppapi/proxy/ppb_file_ref_proxy.h"
 #include "ppapi/proxy/url_request_info_resource.h"
 #include "ppapi/proxy/url_response_info_resource.h"
 #include "ppapi/shared_impl/ppapi_globals.h"
@@ -158,9 +158,14 @@
   int32_t rv = ValidateCallback(callback);
   if (rv != PP_OK)
     return rv;
-  if (!response_info_.get() ||
-      !response_info_->data().body_as_file_ref.resource.is_null())
+  if (!response_info_.get())
     return PP_ERROR_FAILED;
+
+  // Fail if we have a valid file ref.
+  // ReadResponseBody() is for reading to a user-provided buffer.
+  if (response_info_->data().body_as_file_ref.IsValid())
+    return PP_ERROR_FAILED;
+
   if (bytes_to_read <= 0 || !buffer)
     return PP_ERROR_BADARGUMENT;
 
@@ -186,8 +191,11 @@
   int32_t rv = ValidateCallback(callback);
   if (rv != PP_OK)
     return rv;
-  if (!response_info_.get() ||
-      response_info_->data().body_as_file_ref.resource.is_null())
+  if (!response_info_.get())
+    return PP_ERROR_FAILED;
+
+  // Fail if we do not have a valid file ref.
+  if (!response_info_->data().body_as_file_ref.IsValid())
     return PP_ERROR_FAILED;
 
   // We may have already reached EOF.
@@ -357,10 +365,10 @@
 void URLLoaderResource::SaveResponseInfo(const URLResponseInfoData& data) {
   // Create a proxy resource for the the file ref host resource if needed.
   PP_Resource body_as_file_ref = 0;
-  if (!data.body_as_file_ref.resource.is_null()) {
-    thunk::EnterResourceCreationNoLock enter(pp_instance());
-    body_as_file_ref =
-        enter.functions()->CreateFileRef(data.body_as_file_ref);
+  if (data.body_as_file_ref.IsValid()) {
+    body_as_file_ref = FileRefResource::CreateFileRef(connection(),
+                                                      pp_instance(),
+                                                      data.body_as_file_ref);
   }
   response_info_ = new URLResponseInfoResource(
       connection(), pp_instance(), data, body_as_file_ref);
@@ -389,4 +397,4 @@
 }
 
 }  // namespace proxy
-}  // namespace ppapi
\ No newline at end of file
+}  // namespace ppapi
diff --git a/ppapi/proxy/url_response_info_resource.cc b/ppapi/proxy/url_response_info_resource.cc
index 85dae9a..315b4a1 100644
--- a/ppapi/proxy/url_response_info_resource.cc
+++ b/ppapi/proxy/url_response_info_resource.cc
@@ -4,7 +4,7 @@
 
 #include "ppapi/proxy/url_response_info_resource.h"
 
-#include "ppapi/proxy/ppb_file_ref_proxy.h"
+#include "ppapi/proxy/file_ref_resource.h"
 #include "ppapi/shared_impl/var.h"
 #include "ppapi/thunk/enter.h"
 #include "ppapi/thunk/resource_creation_api.h"
diff --git a/ppapi/shared_impl/DEPS b/ppapi/shared_impl/DEPS
index 313cbac..ca43b89 100644
--- a/ppapi/shared_impl/DEPS
+++ b/ppapi/shared_impl/DEPS
@@ -2,6 +2,7 @@
   "+base",
   "+gpu",
   "+media/audio",
+  "+media/base",
   "+skia",
   "+webkit/common/webpreferences.h",
 
diff --git a/ppapi/shared_impl/file_ref_create_info.cc b/ppapi/shared_impl/file_ref_create_info.cc
new file mode 100644
index 0000000..68c3f17
--- /dev/null
+++ b/ppapi/shared_impl/file_ref_create_info.cc
@@ -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.
+
+#include "ppapi/shared_impl/file_ref_create_info.h"
+
+#include "base/logging.h"
+#include "base/strings/utf_string_conversions.h"
+#include "ppapi/c/pp_file_info.h"
+
+namespace ppapi {
+
+namespace {
+
+std::string GetNameForExternalFilePath(const base::FilePath& in_path) {
+  const base::FilePath::StringType& path = in_path.value();
+  size_t pos = path.rfind(base::FilePath::kSeparators[0]);
+  CHECK(pos != base::FilePath::StringType::npos);
+#if defined(OS_WIN)
+  return base::WideToUTF8(path.substr(pos + 1));
+#elif defined(OS_POSIX)
+  return path.substr(pos + 1);
+#else
+#error "Unsupported platform."
+#endif
+}
+
+}  // namespace
+
+bool FileRefCreateInfo::IsValid() const {
+  return file_system_type != PP_FILESYSTEMTYPE_INVALID;
+}
+
+FileRefCreateInfo
+MakeExternalFileRefCreateInfo(const base::FilePath& external_path,
+                              const std::string& display_name,
+                              int pending_host_resource_id) {
+  FileRefCreateInfo info;
+  info.file_system_type = PP_FILESYSTEMTYPE_EXTERNAL;
+  if (!display_name.empty())
+    info.display_name = display_name;
+  else
+    info.display_name = GetNameForExternalFilePath(external_path);
+  info.pending_host_resource_id = pending_host_resource_id;
+  return info;
+}
+
+}  // namespace ppapi
diff --git a/ppapi/shared_impl/file_ref_create_info.h b/ppapi/shared_impl/file_ref_create_info.h
index a3599f7..ae570e6 100644
--- a/ppapi/shared_impl/file_ref_create_info.h
+++ b/ppapi/shared_impl/file_ref_create_info.h
@@ -10,12 +10,19 @@
 #include "base/files/file_path.h"
 #include "ppapi/c/pp_file_info.h"
 #include "ppapi/c/pp_resource.h"
+#include "ppapi/shared_impl/ppapi_shared_export.h"
 
 namespace ppapi {
 
 // FileRefs are created in a number of places and they include a number of
 // return values. This struct encapsulates everything in one place.
-struct FileRef_CreateInfo {
+struct FileRefCreateInfo {
+  FileRefCreateInfo() : file_system_type(PP_FILESYSTEMTYPE_INVALID),
+                        pending_host_resource_id(0),
+                        file_system_plugin_resource(0) { }
+
+  PPAPI_SHARED_EXPORT bool IsValid() const;
+
   PP_FileSystemType file_system_type;
   std::string internal_path;
   std::string display_name;
@@ -24,10 +31,18 @@
   int pending_host_resource_id;
 
   // Since FileRef needs to hold a FileSystem reference, we need to pass the
-  // resource in this CreateInfo.
+  // resource in this CreateInfo. This struct doesn't hold any refrence on the
+  // file_system_plugin_resource.
   PP_Resource file_system_plugin_resource;
 };
 
+// Used in the renderer when sending a FileRefCreateInfo to a plugin for a
+// FileRef on an external filesystem.
+PPAPI_SHARED_EXPORT FileRefCreateInfo
+MakeExternalFileRefCreateInfo(const base::FilePath& external_path,
+                              const std::string& display_name,
+                              int pending_host_resource_id);
+
 }  // namespace ppapi
 
 #endif  // PPAPI_SHARED_IMPL_FILE_REF_CREATE_INFO_H
diff --git a/ppapi/shared_impl/file_ref_detailed_info.h b/ppapi/shared_impl/file_ref_detailed_info.h
new file mode 100644
index 0000000..ddf4370
--- /dev/null
+++ b/ppapi/shared_impl/file_ref_detailed_info.h
@@ -0,0 +1,28 @@
+// 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 PPAPI_SHARED_IMPL_FILE_REF_DETAILED_INFO_H
+#define PPAPI_SHARED_IMPL_FILE_REF_DETAILED_INFO_H
+
+#include <string>
+
+#include "base/files/file_path.h"
+#include "ppapi/c/pp_file_info.h"
+#include "ppapi/c/pp_resource.h"
+
+namespace ppapi {
+
+// This structure is only used for exchanging information about FileRefs from
+// the browser to the renderer.
+struct FileRefDetailedInfo {
+  // This struct doesn't hold a ref on this resource.
+  PP_Resource resource;
+  PP_FileSystemType file_system_type;
+  std::string file_system_url_spec;
+  base::FilePath external_path;
+};
+
+}  // namespace ppapi
+
+#endif  // PPAPI_SHARED_IMPL_FILE_REF_DETAILED_INFO_H
diff --git a/ppapi/shared_impl/ppb_file_ref_shared.cc b/ppapi/shared_impl/ppb_file_ref_shared.cc
deleted file mode 100644
index a47cdb8..0000000
--- a/ppapi/shared_impl/ppb_file_ref_shared.cc
+++ /dev/null
@@ -1,54 +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 "ppapi/shared_impl/ppb_file_ref_shared.h"
-
-#include "base/logging.h"
-#include "ppapi/shared_impl/var.h"
-
-namespace ppapi {
-
-PPB_FileRef_Shared::PPB_FileRef_Shared(ResourceObjectType type,
-                                       const PPB_FileRef_CreateInfo& info)
-    : Resource(type, info.resource),
-      create_info_(info) {
-  if (type == OBJECT_IS_IMPL) {
-    // Resource's constructor assigned a PP_Resource, so we can fill out our
-    // host resource now.
-    create_info_.resource = host_resource();
-  }
-}
-
-PPB_FileRef_Shared::~PPB_FileRef_Shared() {
-}
-
-thunk::PPB_FileRef_API* PPB_FileRef_Shared::AsPPB_FileRef_API() {
-  return this;
-}
-
-PP_FileSystemType PPB_FileRef_Shared::GetFileSystemType() const {
-  return static_cast<PP_FileSystemType>(create_info_.file_system_type);
-}
-
-PP_Var PPB_FileRef_Shared::GetName() const {
-  if (!name_var_.get()) {
-    name_var_ = new StringVar(create_info_.name);
-  }
-  return name_var_->GetPPVar();
-}
-
-PP_Var PPB_FileRef_Shared::GetPath() const {
-  if (create_info_.file_system_type == PP_FILESYSTEMTYPE_EXTERNAL)
-    return PP_MakeUndefined();
-  if (!path_var_.get()) {
-    path_var_ = new StringVar(create_info_.path);
-  }
-  return path_var_->GetPPVar();
-}
-
-const PPB_FileRef_CreateInfo& PPB_FileRef_Shared::GetCreateInfo() const {
-  return create_info_;
-}
-
-}  // namespace ppapi
diff --git a/ppapi/shared_impl/ppb_file_ref_shared.h b/ppapi/shared_impl/ppb_file_ref_shared.h
deleted file mode 100644
index 5025eb3..0000000
--- a/ppapi/shared_impl/ppb_file_ref_shared.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 PPAPI_SHARED_IMPL_PPB_FILE_REF_SHARED_H_
-#define PPAPI_SHARED_IMPL_PPB_FILE_REF_SHARED_H_
-
-#include <string>
-
-#include "base/compiler_specific.h"
-#include "ppapi/shared_impl/resource.h"
-#include "ppapi/thunk/ppb_file_ref_api.h"
-
-namespace ppapi {
-
-class StringVar;
-
-// FileRefs are created in a number of places and they include a number of
-// return values. This struct encapsulates everything in one place.
-struct PPB_FileRef_CreateInfo {
-  PPB_FileRef_CreateInfo()
-      : file_system_type(PP_FILESYSTEMTYPE_EXTERNAL),
-        file_system_plugin_resource(0) {}
-
-  ppapi::HostResource resource;
-  int file_system_type;  // One of PP_FileSystemType values.
-  std::string path;
-  std::string name;
-
-  // Since FileRef needs to hold a FileSystem reference, we need to pass the
-  // resource in this CreateInfo.  Note that this is a plugin resource as
-  // FileSystem is already in new design.
-  PP_Resource file_system_plugin_resource;
-};
-
-// This class provides the shared implementation of a FileRef. The functions
-// that actually "do stuff" like Touch and MakeDirectory are implemented
-// differently for the proxied and non-proxied derived classes.
-class PPAPI_SHARED_EXPORT PPB_FileRef_Shared
-    : public Resource,
-      public thunk::PPB_FileRef_API {
- public:
-  PPB_FileRef_Shared(ResourceObjectType type,
-                     const PPB_FileRef_CreateInfo& info);
-  virtual ~PPB_FileRef_Shared();
-
-  // Resource overrides.
-  virtual thunk::PPB_FileRef_API* AsPPB_FileRef_API() OVERRIDE;
-
-  // PPB_FileRef_API implementation (partial).
-  virtual PP_FileSystemType GetFileSystemType() const OVERRIDE;
-  virtual PP_Var GetName() const OVERRIDE;
-  virtual PP_Var GetPath() const OVERRIDE;
-  virtual const PPB_FileRef_CreateInfo& GetCreateInfo() const OVERRIDE;
-  virtual PP_Var GetAbsolutePath() = 0;
-
- private:
-  PPB_FileRef_CreateInfo create_info_;
-
-  // Lazily initialized vars created from the create_info_. This is so we can
-  // return the identical string object every time they're requested.
-  mutable scoped_refptr<StringVar> name_var_;
-  mutable scoped_refptr<StringVar> path_var_;
-
-  DISALLOW_IMPLICIT_CONSTRUCTORS(PPB_FileRef_Shared);
-};
-
-}  // namespace ppapi
-
-#endif  // PPAPI_SHARED_IMPL_PPB_FILE_REF_SHARED_H_
diff --git a/ppapi/shared_impl/tracked_callback.cc b/ppapi/shared_impl/tracked_callback.cc
index 854e9df..1a3ac21 100644
--- a/ppapi/shared_impl/tracked_callback.cc
+++ b/ppapi/shared_impl/tracked_callback.cc
@@ -27,6 +27,14 @@
       PpapiGlobals::Get()->GetMainThreadMessageLoop()->BelongsToCurrentThread();
 }
 
+int32_t RunCompletionTask(TrackedCallback::CompletionTask completion_task,
+                          int32_t result) {
+  int32_t task_result = completion_task.Run(result);
+  if (result != PP_ERROR_ABORTED)
+    result = task_result;
+  return result;
+}
+
 }  // namespace
 
 // TrackedCallback -------------------------------------------------------------
@@ -128,11 +136,18 @@
       PostRun(result);
       return;
     }
-    // Copy |callback_| now, since |MarkAsCompleted()| may delete us.
+
+    // Copy callback fields now, since |MarkAsCompleted()| may delete us.
     PP_CompletionCallback callback = callback_;
-    // Do this before running the callback in case of reentrancy (which
-    // shouldn't happen, but avoid strange failures).
+    CompletionTask completion_task = completion_task_;
+    completion_task_.Reset();
+    // Do this before running the callback in case of reentrancy from running
+    // the completion task.
     MarkAsCompleted();
+
+    if (!completion_task.is_null())
+      result = RunCompletionTask(completion_task, result);
+
     // TODO(dmichael): Associate a message loop with the callback; if it's not
     // the same as the current thread's loop, then post it to the right loop.
     CallWhileUnlocked(PP_RunCompletionCallback, &callback, result);
@@ -164,6 +179,12 @@
   is_scheduled_ = true;
 }
 
+void TrackedCallback::set_completion_task(
+    const CompletionTask& completion_task) {
+  DCHECK(completion_task_.is_null());
+  completion_task_ = completion_task;
+}
+
 // static
 bool TrackedCallback::IsPending(
     const scoped_refptr<TrackedCallback>& callback) {
@@ -195,6 +216,12 @@
 
   while (!completed())
     operation_completed_condvar_->Wait();
+
+  if (!completion_task_.is_null()) {
+    result_for_blocked_callback_ =
+        RunCompletionTask(completion_task_, result_for_blocked_callback_);
+    completion_task_.Reset();
+  }
   return result_for_blocked_callback_;
 }
 
diff --git a/ppapi/shared_impl/tracked_callback.h b/ppapi/shared_impl/tracked_callback.h
index c4bf5cf..92af19b 100644
--- a/ppapi/shared_impl/tracked_callback.h
+++ b/ppapi/shared_impl/tracked_callback.h
@@ -9,6 +9,7 @@
 #include <set>
 
 #include "base/basictypes.h"
+#include "base/callback.h"
 #include "base/memory/ref_counted.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/synchronization/condition_variable.h"
@@ -84,7 +85,16 @@
   // callback is targeted to run, it will *not* be run immediately.
   void PostRun(int32_t result);
 
-  void BlockUntilRun();
+  // A task to perform cleanup or write output parameters before the callback
+  // returns a result to the plugin. The |result| parameter has the result so
+  // far, e.g. whether the callback has been aborted. If the callback hasn't
+  // been aborted the return value of the task will become the callback result.
+  // The task is always called on the same thread as the callback to the plugin.
+  typedef base::Callback<int32_t(int32_t /* result */)> CompletionTask;
+
+  // Sets a task that is run just before calling back into the plugin. This
+  // should only be called once.
+  void set_completion_task(const CompletionTask& completion_task);
 
   // Returns the ID of the resource which "owns" the callback, or 0 if the
   // callback is not associated with any resource.
@@ -157,6 +167,9 @@
   bool aborted_;
   PP_CompletionCallback callback_;
 
+  // Task to run just before calling back into the plugin.
+  CompletionTask completion_task_;
+
   // The MessageLoopShared on which this callback should be run. This will be
   // NULL if we're in-process.
   scoped_refptr<MessageLoopShared> target_loop_;
diff --git a/ppapi/shared_impl/tracked_callback_unittest.cc b/ppapi/shared_impl/tracked_callback_unittest.cc
index a9961f0..9ceb96e 100644
--- a/ppapi/shared_impl/tracked_callback_unittest.cc
+++ b/ppapi/shared_impl/tracked_callback_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/bind.h"
 #include "base/memory/ref_counted.h"
 #include "base/message_loop/message_loop.h"
 #include "ppapi/c/pp_completion_callback.h"
@@ -37,11 +38,20 @@
   PP_Instance pp_instance_;
 };
 
+// All valid results (PP_OK, PP_ERROR_...) are nonpositive.
+const int32_t kInitializedResultValue = 1;
+const int32_t kOverrideResultValue = 2;
+
 struct CallbackRunInfo {
-  // All valid results (PP_OK, PP_ERROR_...) are nonpositive.
-  CallbackRunInfo() : run_count(0), result(1) {}
+  CallbackRunInfo()
+      : run_count(0),
+        result(kInitializedResultValue),
+        completion_task_run_count(0),
+        completion_task_result(kInitializedResultValue) {}
   unsigned run_count;
   int32_t result;
+  unsigned completion_task_run_count;
+  int32_t completion_task_result;
 };
 
 void TestCallback(void* user_data, int32_t result) {
@@ -144,18 +154,38 @@
         this,
         PP_MakeCompletionCallback(&TestCallback, &info_did_run_));
     EXPECT_EQ(0U, info_did_run_.run_count);
+    EXPECT_EQ(0U, info_did_run_.completion_task_run_count);
+
+    // In order to test that the completion task can override the callback
+    // result, we need to test callbacks with and without a completion task.
+    callback_did_run_with_completion_task_ = new TrackedCallback(
+        this,
+        PP_MakeCompletionCallback(&TestCallback,
+                                  &info_did_run_with_completion_task_));
+    callback_did_run_with_completion_task_->set_completion_task(
+        Bind(&CallbackMockResource::CompletionTask, this,
+             &info_did_run_with_completion_task_));
+    EXPECT_EQ(0U, info_did_run_with_completion_task_.run_count);
+    EXPECT_EQ(0U, info_did_run_with_completion_task_.completion_task_run_count);
 
     callback_did_abort_ = new TrackedCallback(
         this,
         PP_MakeCompletionCallback(&TestCallback, &info_did_abort_));
+    callback_did_abort_->set_completion_task(
+        Bind(&CallbackMockResource::CompletionTask, this, &info_did_abort_));
     EXPECT_EQ(0U, info_did_abort_.run_count);
+    EXPECT_EQ(0U, info_did_abort_.completion_task_run_count);
 
     callback_didnt_run_ = new TrackedCallback(
         this,
         PP_MakeCompletionCallback(&TestCallback, &info_didnt_run_));
+    callback_didnt_run_->set_completion_task(
+        Bind(&CallbackMockResource::CompletionTask, this, &info_didnt_run_));
     EXPECT_EQ(0U, info_didnt_run_.run_count);
+    EXPECT_EQ(0U, info_didnt_run_.completion_task_run_count);
 
     callback_did_run_->Run(PP_OK);
+    callback_did_run_with_completion_task_->Run(PP_OK);
     callback_did_abort_->Abort();
 
     CheckIntermediateState();
@@ -163,13 +193,34 @@
     return resource_id;
   }
 
+  int32_t CompletionTask(CallbackRunInfo* info, int32_t result) {
+    // We should run before the callback.
+    EXPECT_EQ(0U, info->run_count);
+    info->completion_task_run_count++;
+    if (info->completion_task_run_count == 1)
+      info->completion_task_result = result;
+    return kOverrideResultValue;
+  }
+
   void CheckIntermediateState() {
     EXPECT_EQ(1U, info_did_run_.run_count);
     EXPECT_EQ(PP_OK, info_did_run_.result);
+    EXPECT_EQ(0U, info_did_run_.completion_task_run_count);
+
+    EXPECT_EQ(1U, info_did_run_with_completion_task_.run_count);
+    // completion task should override the result.
+    EXPECT_EQ(kOverrideResultValue, info_did_run_with_completion_task_.result);
+    EXPECT_EQ(1U, info_did_run_with_completion_task_.completion_task_run_count);
+    EXPECT_EQ(PP_OK,
+              info_did_run_with_completion_task_.completion_task_result);
 
     EXPECT_EQ(1U, info_did_abort_.run_count);
+    // completion task shouldn't override an abort.
     EXPECT_EQ(PP_ERROR_ABORTED, info_did_abort_.result);
+    EXPECT_EQ(1U, info_did_abort_.completion_task_run_count);
+    EXPECT_EQ(PP_ERROR_ABORTED, info_did_abort_.completion_task_result);
 
+    EXPECT_EQ(0U, info_didnt_run_.completion_task_run_count);
     EXPECT_EQ(0U, info_didnt_run_.run_count);
   }
 
@@ -185,6 +236,9 @@
   scoped_refptr<TrackedCallback> callback_did_run_;
   CallbackRunInfo info_did_run_;
 
+  scoped_refptr<TrackedCallback> callback_did_run_with_completion_task_;
+  CallbackRunInfo info_did_run_with_completion_task_;
+
   scoped_refptr<TrackedCallback> callback_did_abort_;
   CallbackRunInfo info_did_abort_;
 
diff --git a/ppapi/shared_impl/url_request_info_data.cc b/ppapi/shared_impl/url_request_info_data.cc
index 8bb02a4..15b2787 100644
--- a/ppapi/shared_impl/url_request_info_data.cc
+++ b/ppapi/shared_impl/url_request_info_data.cc
@@ -17,6 +17,7 @@
 
 URLRequestInfoData::BodyItem::BodyItem()
     : is_file(false),
+      file_ref_pp_resource(0),
       start_offset(0),
       number_of_bytes(-1),
       expected_last_modified_time(0.0) {
@@ -25,6 +26,7 @@
 URLRequestInfoData::BodyItem::BodyItem(const std::string& data)
     : is_file(false),
       data(data),
+      file_ref_pp_resource(0),
       start_offset(0),
       number_of_bytes(-1),
       expected_last_modified_time(0.0) {
@@ -36,8 +38,8 @@
     int64_t number_of_bytes,
     PP_Time expected_last_modified_time)
     : is_file(true),
-      file_ref(file_ref),
-      file_ref_host_resource(file_ref->host_resource()),
+      file_ref_resource(file_ref),
+      file_ref_pp_resource(file_ref->pp_resource()),
       start_offset(start_offset),
       number_of_bytes(number_of_bytes),
       expected_last_modified_time(expected_last_modified_time) {
diff --git a/ppapi/shared_impl/url_request_info_data.h b/ppapi/shared_impl/url_request_info_data.h
index 501251a..d0acf4b 100644
--- a/ppapi/shared_impl/url_request_info_data.h
+++ b/ppapi/shared_impl/url_request_info_data.h
@@ -9,10 +9,12 @@
 #include <vector>
 
 #include "base/memory/ref_counted.h"
+#include "ppapi/c/pp_resource.h"
 #include "ppapi/c/pp_stdint.h"
 #include "ppapi/c/pp_time.h"
-#include "ppapi/shared_impl/host_resource.h"
+#include "ppapi/shared_impl/ppapi_globals.h"
 #include "ppapi/shared_impl/ppapi_shared_export.h"
+#include "ppapi/shared_impl/resource_tracker.h"
 
 namespace ppapi {
 
@@ -32,19 +34,12 @@
 
     std::string data;
 
-    // Is is_file is set, these variables are set. Note that the resource
-    // may still be NULL in some cases, such as deserialization errors.
-    //
-    // This is a bit tricky. In the plugin side of the proxy, both the file ref
-    // and the file_ref_host_resource will be set and valid. The scoped_refptr
-    // ensures that the resource is alive for as long as the BodyItem is.
-    //
-    // When we deserialize this in the renderer, only the
-    // file_ref_host_resource's are serialized over IPC. The file_refs won't be
-    // valid until the host resources are converted to Resource pointers in the
-    // PPB_URLRequestInfo_Impl.
-    scoped_refptr<Resource> file_ref;
-    HostResource file_ref_host_resource;
+    // Only set on the plugin-side, for refcounting purposes. Only valid when
+    // |is_file| is set.
+    scoped_refptr<Resource> file_ref_resource;
+    // This struct holds no ref to this resource. Only valid when |is_file| is
+    // set.
+    PP_Resource file_ref_pp_resource;
 
     int64_t start_offset;
     int64_t number_of_bytes;
diff --git a/ppapi/shared_impl/url_response_info_data.h b/ppapi/shared_impl/url_response_info_data.h
index a40ca50..c6f7dbd 100644
--- a/ppapi/shared_impl/url_response_info_data.h
+++ b/ppapi/shared_impl/url_response_info_data.h
@@ -8,7 +8,7 @@
 #include <string>
 
 #include "ppapi/c/pp_stdint.h"
-#include "ppapi/shared_impl/ppb_file_ref_shared.h"
+#include "ppapi/shared_impl/file_ref_create_info.h"
 #include "ppapi/shared_impl/ppapi_shared_export.h"
 
 namespace ppapi {
@@ -23,8 +23,8 @@
   std::string status_text;
   std::string redirect_url;
 
-  // Nonzero when streaming to a file.
-  PPB_FileRef_CreateInfo body_as_file_ref;
+  // Valid when streaming to a file.
+  FileRefCreateInfo body_as_file_ref;
 };
 
 }  // namespace ppapi
diff --git a/ppapi/tests/test_file_io.cc b/ppapi/tests/test_file_io.cc
index ed2183b..443f786 100644
--- a/ppapi/tests/test_file_io.cc
+++ b/ppapi/tests/test_file_io.cc
@@ -568,10 +568,14 @@
   CHECK_CALLBACK_BEHAVIOR(callback);
   ASSERT_EQ(4, callback.result());
 
-  // last_access_time's granularity is 1 day
-  // last_modified_time's granularity is 2 seconds
   const PP_Time last_access_time = 123 * 24 * 3600.0;
-  const PP_Time last_modified_time = 246.0;
+  // last_modified_time's granularity is 2 seconds
+  // NOTE: In NaCl on Windows, NaClDescIO uses _fstat64 to retrieve file info.
+  // This function returns strange values for very small time values (near the
+  // Unix Epoch). For a value like 246.0, it returns -1. For larger values, it
+  // returns values that are exactly an hour less. The value below is handled
+  // correctly, and is only 100 days after the start of Unix time.
+  const PP_Time last_modified_time = 100 * 24 * 3600.0;
   callback.WaitForResult(file_io.Touch(last_access_time, last_modified_time,
                                        callback.GetCallback()));
   CHECK_CALLBACK_BEHAVIOR(callback);
diff --git a/ppapi/tests/test_file_ref.cc b/ppapi/tests/test_file_ref.cc
index 04e8ce1..d1448ec 100644
--- a/ppapi/tests/test_file_ref.cc
+++ b/ppapi/tests/test_file_ref.cc
@@ -365,10 +365,10 @@
   ASSERT_EQ(4, callback.result());
 
   // Touch.
-  // last_access_time's granularity is 1 day
-  // last_modified_time's granularity is 2 seconds
   const PP_Time last_access_time = 123 * 24 * 3600.0;
-  const PP_Time last_modified_time = 246.0;
+  // last_modified_time's granularity is 2 seconds
+  // See note in test_file_io.cc for why we use this time.
+  const PP_Time last_modified_time = 100 * 24 * 3600.0;
   callback.WaitForResult(file_ref.Touch(last_access_time, last_modified_time,
                                         callback.GetCallback()));
   CHECK_CALLBACK_BEHAVIOR(callback);
diff --git a/ppapi/thunk/interfaces_ppb_private.h b/ppapi/thunk/interfaces_ppb_private.h
index 3e0289c..391904d 100644
--- a/ppapi/thunk/interfaces_ppb_private.h
+++ b/ppapi/thunk/interfaces_ppb_private.h
@@ -33,7 +33,7 @@
               PPB_FileChooserTrusted_0_5)
 PROXIED_IFACE(NoAPIName, PPB_FILECHOOSER_TRUSTED_INTERFACE_0_6,
               PPB_FileChooserTrusted_0_6)
-PROXIED_IFACE(PPB_FileRef, PPB_FILEREFPRIVATE_INTERFACE_0_1,
+PROXIED_IFACE(NoAPIName, PPB_FILEREFPRIVATE_INTERFACE_0_1,
               PPB_FileRefPrivate_0_1)
 // TODO(xhwang): Move PPB_Flash_DeviceID back to interfaces_ppb_private_flash.h.
 PROXIED_IFACE(NoAPIName, PPB_FLASH_DEVICEID_INTERFACE_1_0,
diff --git a/ppapi/thunk/interfaces_ppb_public_stable.h b/ppapi/thunk/interfaces_ppb_public_stable.h
index b0918a3..eac850e 100644
--- a/ppapi/thunk/interfaces_ppb_public_stable.h
+++ b/ppapi/thunk/interfaces_ppb_public_stable.h
@@ -19,7 +19,6 @@
 // that exist in the webkit/plugins/ppapi/*_impl.h, but not in the proxy.
 PROXIED_API(PPB_Audio)
 PROXIED_API(PPB_Core)
-PROXIED_API(PPB_FileRef)
 PROXIED_API(PPB_Graphics3D)
 PROXIED_API(PPB_ImageData)
 PROXIED_API(PPB_Instance)
@@ -46,8 +45,8 @@
 // interface string.
 // Note: Core is special and is registered manually.
 PROXIED_IFACE(PPB_Audio, PPB_AUDIO_INTERFACE_1_0, PPB_Audio_1_0)
-PROXIED_IFACE(PPB_FileRef, PPB_FILEREF_INTERFACE_1_0, PPB_FileRef_1_0)
-PROXIED_IFACE(PPB_FileRef, PPB_FILEREF_INTERFACE_1_1, PPB_FileRef_1_1)
+PROXIED_IFACE(NoAPIName, PPB_FILEREF_INTERFACE_1_0, PPB_FileRef_1_0)
+PROXIED_IFACE(NoAPIName, PPB_FILEREF_INTERFACE_1_1, PPB_FileRef_1_1)
 PROXIED_IFACE(NoAPIName, PPB_FILESYSTEM_INTERFACE_1_0, PPB_FileSystem_1_0)
 PROXIED_IFACE(PPB_Graphics3D, PPB_GRAPHICS_3D_INTERFACE_1_0, PPB_Graphics3D_1_0)
 PROXIED_IFACE(PPB_ImageData, PPB_IMAGEDATA_INTERFACE_1_0, PPB_ImageData_1_0)
diff --git a/ppapi/thunk/ppb_file_ref_api.h b/ppapi/thunk/ppb_file_ref_api.h
index ba92b63..b473ae2 100644
--- a/ppapi/thunk/ppb_file_ref_api.h
+++ b/ppapi/thunk/ppb_file_ref_api.h
@@ -10,11 +10,12 @@
 #include "base/memory/linked_ptr.h"
 #include "base/memory/ref_counted.h"
 #include "ppapi/c/ppb_file_ref.h"
+#include "ppapi/shared_impl/file_ref_create_info.h"
 #include "ppapi/thunk/ppapi_thunk_export.h"
 
 namespace ppapi {
 
-struct PPB_FileRef_CreateInfo;
+struct FileRefCreateInfo;
 class TrackedCallback;
 
 namespace thunk {
@@ -40,25 +41,10 @@
   virtual int32_t ReadDirectoryEntries(
       const PP_ArrayOutput& output,
       scoped_refptr<TrackedCallback> callback) = 0;
-  // We define variants of Query and ReadDirectoryEntries because
-  // 1. we need to take linked_ptr instead of raw pointers to avoid
-  // use-after-free, and 2. we don't use PP_ArrayOutput for the
-  // communication between renderers and the browser in
-  // ReadDirectoryEntries. The *InHost functions must not be called in
-  // plugins, and Query and ReadDirectoryEntries must not be called in
-  // renderers.
-  // TODO(hamaji): These functions must be removed when we move
-  // FileRef to the new resource design. http://crbug.com/225441
-  virtual int32_t QueryInHost(linked_ptr<PP_FileInfo> info,
-                              scoped_refptr<TrackedCallback> callback) = 0;
-  virtual int32_t ReadDirectoryEntriesInHost(
-      linked_ptr<std::vector<ppapi::PPB_FileRef_CreateInfo> > files,
-      linked_ptr<std::vector<PP_FileType> > file_types,
-      scoped_refptr<TrackedCallback> callback) = 0;
 
   // Internal function for use in proxying. Returns the internal CreateInfo
   // (the contained resource does not carry a ref on behalf of the caller).
-  virtual const PPB_FileRef_CreateInfo& GetCreateInfo() const = 0;
+  virtual const FileRefCreateInfo& GetCreateInfo() const = 0;
 
   // Private API
   virtual PP_Var GetAbsolutePath() = 0;
diff --git a/ppapi/thunk/ppb_file_ref_thunk.cc b/ppapi/thunk/ppb_file_ref_thunk.cc
index beb0e41..8910faf 100644
--- a/ppapi/thunk/ppb_file_ref_thunk.cc
+++ b/ppapi/thunk/ppb_file_ref_thunk.cc
@@ -7,6 +7,7 @@
 #include "ppapi/c/pp_completion_callback.h"
 #include "ppapi/c/pp_errors.h"
 #include "ppapi/c/private/ppb_file_ref_private.h"
+#include "ppapi/shared_impl/file_ref_create_info.h"
 #include "ppapi/shared_impl/proxy_lock.h"
 #include "ppapi/shared_impl/tracked_callback.h"
 #include "ppapi/thunk/enter.h"
@@ -32,7 +33,12 @@
   EnterResourceCreationNoLock enter(instance);
   if (enter.failed())
     return 0;
-  return enter.functions()->CreateFileRef(instance, file_system, path);
+  FileRefCreateInfo info;
+  info.file_system_type = enter_file_system.object()->GetType();
+  info.internal_path = std::string(path);
+  info.pending_host_resource_id = 0;
+  info.file_system_plugin_resource = file_system;
+  return enter.functions()->CreateFileRef(instance, info);
 }
 
 PP_Bool IsFileRef(PP_Resource resource) {
diff --git a/ppapi/thunk/resource_creation_api.h b/ppapi/thunk/resource_creation_api.h
index 082f1cc..bab3bb9 100644
--- a/ppapi/thunk/resource_creation_api.h
+++ b/ppapi/thunk/resource_creation_api.h
@@ -33,7 +33,7 @@
 
 namespace ppapi {
 
-struct PPB_FileRef_CreateInfo;
+struct FileRefCreateInfo;
 struct URLRequestInfoData;
 struct URLResponseInfoData;
 
@@ -49,15 +49,9 @@
   virtual ~ResourceCreationAPI() {}
 
   virtual PP_Resource CreateFileIO(PP_Instance instance) = 0;
-  virtual PP_Resource CreateFileRef(PP_Instance instance,
-                                    PP_Resource file_system,
-                                    const char* path) = 0;
-  // Like the above version but takes a serialized file ref. The resource
-  // in the serialized file ref is passed into this, which takes ownership of
-  // the reference. In the proxy, the return value will be a plugin resource.
-  // In the impl, the return value will be the same resource ID.
   virtual PP_Resource CreateFileRef(
-      const PPB_FileRef_CreateInfo& serialized) = 0;
+      PP_Instance instance,
+      const FileRefCreateInfo& serialized) = 0;
   virtual PP_Resource CreateFileSystem(PP_Instance instance,
                                        PP_FileSystemType type) = 0;
   virtual PP_Resource CreateIsolatedFileSystem(PP_Instance instance,
diff --git a/remoting/android/java/AndroidManifest.xml b/remoting/android/java/AndroidManifest.xml
index ff27b57..7a21b2d 100644
--- a/remoting/android/java/AndroidManifest.xml
+++ b/remoting/android/java/AndroidManifest.xml
@@ -1,12 +1,13 @@
 <?xml version="1.0" encoding="utf-8"?>
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
         package="org.chromium.chromoting"
-        android:versionCode="9"
-        android:versionName="0.09">
+        android:versionCode="11"
+        android:versionName="0.11">
     <uses-sdk android:minSdkVersion="14"
             android:targetSdkVersion="14"/>
     <uses-permission android:name="android.permission.GET_ACCOUNTS"/>
     <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/app_name"
             android:icon="@drawable/chromoting128">
diff --git a/remoting/android/java/src/org/chromium/chromoting/Chromoting.java b/remoting/android/java/src/org/chromium/chromoting/Chromoting.java
index cfcbf49..07d896f 100644
--- a/remoting/android/java/src/org/chromium/chromoting/Chromoting.java
+++ b/remoting/android/java/src/org/chromium/chromoting/Chromoting.java
@@ -69,6 +69,9 @@
     /** List of hosts. */
     private JSONArray mHosts;
 
+    /** Refresh button. */
+    private MenuItem mRefreshButton;
+
     /** Account switcher. */
     private MenuItem mAccountSwitcher;
 
@@ -139,8 +142,21 @@
     @Override
     public boolean onCreateOptionsMenu(Menu menu) {
         getMenuInflater().inflate(R.menu.chromoting_actionbar, menu);
+        mRefreshButton = menu.findItem(R.id.actionbar_directoryrefresh);
         mAccountSwitcher = menu.findItem(R.id.actionbar_accountswitcher);
-        if (mAccount != null) {
+
+        Account[] usableAccounts = AccountManager.get(this).getAccountsByType(ACCOUNT_TYPE);
+        if (usableAccounts.length == 1 && usableAccounts[0].equals(mAccount)) {
+            // If we're using the only available account, don't offer account switching.
+            // (If there are *no* accounts available, clicking this allows you to add a new one.)
+            mAccountSwitcher.setEnabled(false);
+        }
+
+        if (mAccount == null) {
+            // If no account has been chosen, don't allow the user to refresh the listing.
+            mRefreshButton.setEnabled(false);
+        } else {
+            // If the user has picked an account, show its name directly on the account switcher.
             mAccountSwitcher.setTitle(mAccount.name);
         }
 
@@ -150,17 +166,25 @@
     /** Called whenever an action bar button is pressed. */
     @Override
     public boolean onOptionsItemSelected(MenuItem item) {
-        // The only button is the account switcher, so defer to the android accounts system now.
-        AccountManager.get(this).getAuthTokenByFeatures(
-                ACCOUNT_TYPE,
-                TOKEN_SCOPE,
-                null,
-                this,
-                null,
-                null,
-                new HostListDirectoryGrabber(this),
-                mNetwork
-            );
+        if (item == mAccountSwitcher) {
+            // The account switcher triggers a listing of all available accounts.
+            AccountManager.get(this).getAuthTokenByFeatures(
+                    ACCOUNT_TYPE,
+                    TOKEN_SCOPE,
+                    null,
+                    this,
+                    null,
+                    null,
+                    new HostListDirectoryGrabber(this),
+                    mNetwork
+                );
+        }
+        else {
+            // The refresh button simply makes use of the currently-chosen account.
+            AccountManager.get(this).getAuthToken(mAccount, TOKEN_SCOPE, null, this,
+                    new HostListDirectoryGrabber(this), mNetwork);
+        }
+
         return true;
     }
 
@@ -235,23 +259,31 @@
                 } else if (ex instanceof AuthenticatorException) {
                     explanation = getString(R.string.error_no_accounts);
                 } else if (ex instanceof IOException) {
-                    if (!mAlreadyTried) {  // This was our first connection attempt.
-                        Log.w("auth", "Unable to authenticate with (expired?) token");
+                    if (!mAlreadyTried) {
+                        // This was our first connection attempt.
 
-                        // Ask system to renew the auth token in case it expired.
-                        AccountManager authenticator = AccountManager.get(mUi);
                         synchronized (mUi) {
-                            authenticator.invalidateAuthToken(mAccount.type, mToken);
-                            mToken = null;
-                            Log.i("auth", "Requesting auth token renewal");
-                            authenticator.getAuthToken(
-                                    mAccount, TOKEN_SCOPE, null, mUi, this, mNetwork);
+                            if (mAccount != null) {
+                                // We got an account, but couldn't log into it. We'll retry in case
+                                // the system's cached authentication token had already expired.
+                                AccountManager authenticator = AccountManager.get(mUi);
+                                mAlreadyTried = true;
+
+                                Log.w("auth", "Requesting renewal of rejected auth token");
+                                authenticator.invalidateAuthToken(mAccount.type, mToken);
+                                mToken = null;
+                                authenticator.getAuthToken(
+                                        mAccount, TOKEN_SCOPE, null, mUi, this, mNetwork);
+
+                                // We're not in an error state *yet*.
+                                return;
+                            }
                         }
 
-                        // We're not in an error state *yet*.
-                        mAlreadyTried = true;
-                        return;
-                    } else {  // Authentication truly failed.
+                        // We didn't even get an account, so the auth server is likely unreachable.
+                        explanation = getString(R.string.error_bad_connection);
+                    } else {
+                        // Authentication truly failed.
                         Log.e("auth", "Fresh auth token was also rejected");
                         explanation = getString(R.string.error_auth_failed);
                     }
@@ -287,7 +319,10 @@
         @Override
         public void run() {
             synchronized (mUi) {
-                mAccountSwitcher.setTitle(mAccount.name);
+                mRefreshButton.setEnabled(mAccount != null);
+                if (mAccount != null) {
+                    mAccountSwitcher.setTitle(mAccount.name);
+                }
             }
 
             if (mHosts == null) {
diff --git a/remoting/android/java/src/org/chromium/chromoting/Desktop.java b/remoting/android/java/src/org/chromium/chromoting/Desktop.java
index 3d59961..8a9917d 100644
--- a/remoting/android/java/src/org/chromium/chromoting/Desktop.java
+++ b/remoting/android/java/src/org/chromium/chromoting/Desktop.java
@@ -96,12 +96,6 @@
             default:
                 // We try to send all other key codes to the host directly.
                 JniInterface.keyboardAction(event.getKeyCode(), depressed);
-
-                if (event.getKeyCode() == KeyEvent.KEYCODE_ENTER ||
-                        event.getKeyCode() == KeyEvent.KEYCODE_NUMPAD_ENTER) {
-                    // We stop this key from propagating to prevent the keyboard from closing.
-                    return true;
-                }
         }
 
         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 1e18f91..b1eac42 100644
--- a/remoting/android/java/src/org/chromium/chromoting/DesktopView.java
+++ b/remoting/android/java/src/org/chromium/chromoting/DesktopView.java
@@ -13,12 +13,15 @@
 import android.graphics.Paint;
 import android.os.Bundle;
 import android.os.Looper;
+import android.text.InputType;
 import android.util.Log;
 import android.view.GestureDetector;
 import android.view.MotionEvent;
 import android.view.ScaleGestureDetector;
 import android.view.SurfaceHolder;
 import android.view.SurfaceView;
+import android.view.inputmethod.EditorInfo;
+import android.view.inputmethod.InputConnection;
 
 import org.chromium.chromoting.jni.JniInterface;
 
@@ -81,6 +84,10 @@
 
     public DesktopView(Activity context) {
         super(context);
+
+        // Give this view keyboard focus, allowing us to customize the soft keyboard's settings.
+        setFocusableInTouchMode(true);
+
         mActionBar = context.getActionBar();
 
         getHolder().addCallback(this);
@@ -265,6 +272,24 @@
         JniInterface.provideRedrawCallback(null);
     }
 
+    /** Called when a software keyboard is requested, and specifies its options. */
+    @Override
+    public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
+        // Disables rich input support and instead requests simple key events.
+        outAttrs.inputType = InputType.TYPE_NULL;
+
+        // Prevents most third-party IMEs from ignoring our Activity's adjustResize preference.
+        outAttrs.imeOptions |= EditorInfo.IME_FLAG_NO_FULLSCREEN;
+
+        // Ensures that keyboards will not decide to hide the remote desktop on small displays.
+        outAttrs.imeOptions |= EditorInfo.IME_FLAG_NO_EXTRACT_UI;
+
+        // Stops software keyboards from closing as soon as the enter key is pressed.
+        outAttrs.imeOptions |= EditorInfo.IME_MASK_ACTION | EditorInfo.IME_FLAG_NO_ENTER_ACTION;
+
+        return null;
+    }
+
     /** Called when a mouse action is made. */
     private void handleMouseMovement(float x, float y, int button, boolean pressed) {
         float[] coordinates = {x, y};
diff --git a/remoting/base/scoped_reg_key_win.h b/remoting/base/scoped_reg_key_win.h
deleted file mode 100644
index c68b99f..0000000
--- a/remoting/base/scoped_reg_key_win.h
+++ /dev/null
@@ -1,42 +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 REMOTING_BASE_SCOPED_REG_KEY_WIN_H_
-#define REMOTING_BASE_SCOPED_REG_KEY_WIN_H_
-
-#include <windows.h>
-
-#include "base/basictypes.h"
-#include "base/compiler_specific.h"
-#include "base/win/scoped_handle.h"
-
-namespace remoting {
-
-// The traits class for Win32 registry handles.
-class RegKeyTraits {
- public:
-  typedef HKEY Handle;
-
-  static bool CloseHandle(HKEY handle) {
-    return RegCloseKey(handle) == ERROR_SUCCESS;
-  }
-
-  static bool IsHandleValid(HKEY handle) {
-    return handle != NULL;
-  }
-
-  static HKEY NullHandle() {
-    return NULL;
-  }
-
- private:
-  DISALLOW_IMPLICIT_CONSTRUCTORS(RegKeyTraits);
-};
-
-typedef base::win::GenericScopedHandle<
-    RegKeyTraits, base::win::DummyVerifierTraits> ScopedRegKey;
-
-}  // namespace remoting
-
-#endif  // REMOTING_BASE_SCOPED_REG_KEY_WIN_H_
diff --git a/remoting/client/jni/android_keymap.cc b/remoting/client/jni/android_keymap.cc
index 743e15e..45d67c4 100644
--- a/remoting/client/jni/android_keymap.cc
+++ b/remoting/client/jni/android_keymap.cc
@@ -199,12 +199,15 @@
   0x0700b7,  // NUMPAD_RIGHT_PAREN
 };
 
-}
+}  // namespace
 
 namespace remoting {
 
 uint32 AndroidKeycodeToUsbKeycode(size_t android) {
-  DCHECK_LT(android, sizeof (usb_keycodes) / sizeof (uint32));
+  if (android >= sizeof (usb_keycodes) / sizeof (uint32)) {
+    LOG(WARNING) << "Attempted to decode out-of-range Android keycode";
+    return 0;
+  }
 
   return usb_keycodes[android];
 }
diff --git a/remoting/client/jni/chromoting_jni_instance.cc b/remoting/client/jni/chromoting_jni_instance.cc
index 3e11b2f..b68aab9 100644
--- a/remoting/client/jni/chromoting_jni_instance.cc
+++ b/remoting/client/jni/chromoting_jni_instance.cc
@@ -132,8 +132,7 @@
     action.set_usb_keycode(usb_code);
     action.set_pressed(key_down);
     connection_->input_stub()->InjectKeyEvent(action);
-  }
-  else {
+  } else {
     LOG(WARNING) << "Ignoring unknown keycode: " << key_code;
   }
 }
diff --git a/remoting/client/jni/chromoting_jni_runtime.cc b/remoting/client/jni/chromoting_jni_runtime.cc
index 8fa9018..8d51a83 100644
--- a/remoting/client/jni/chromoting_jni_runtime.cc
+++ b/remoting/client/jni/chromoting_jni_runtime.cc
@@ -7,6 +7,7 @@
 #include "base/android/base_jni_registrar.h"
 #include "base/android/jni_android.h"
 #include "base/memory/singleton.h"
+#include "base/synchronization/waitable_event.h"
 #include "media/base/yuv_convert.h"
 #include "net/android/net_jni_registrar.h"
 #include "remoting/base/url_request_context.h"
@@ -68,8 +69,19 @@
 
   JNIEnv* env = base::android::AttachCurrentThread();
   env->DeleteGlobalRef(class_);
-  // TODO(solb): Detach all threads from JVM here.
-  // crbug.com/259594
+
+  base::WaitableEvent done_event(false, false);
+  network_task_runner_->PostTask(FROM_HERE, base::Bind(
+      &ChromotingJniRuntime::DetachFromVmAndSignal,
+      base::Unretained(this),
+      &done_event));
+  done_event.Wait();
+  display_task_runner_->PostTask(FROM_HERE, base::Bind(
+      &ChromotingJniRuntime::DetachFromVmAndSignal,
+      base::Unretained(this),
+      &done_event));
+  done_event.Wait();
+  base::android::DetachFromVM();
 }
 
 void ChromotingJniRuntime::ConnectToHost(const char* username,
@@ -178,4 +190,9 @@
       env->GetStaticMethodID(class_, "redrawGraphicsInternal", "()V"));
 }
 
+void ChromotingJniRuntime::DetachFromVmAndSignal(base::WaitableEvent* waiter) {
+  base::android::DetachFromVM();
+  waiter->Signal();
+}
+
 }  // namespace remoting
diff --git a/remoting/client/jni/chromoting_jni_runtime.h b/remoting/client/jni/chromoting_jni_runtime.h
index 1a6952b..93f933f 100644
--- a/remoting/client/jni/chromoting_jni_runtime.h
+++ b/remoting/client/jni/chromoting_jni_runtime.h
@@ -6,6 +6,7 @@
 #define REMOTING_CLIENT_JNI_CHROMOTING_JNI_RUNTIME_H_
 
 #include <jni.h>
+#include <string>
 
 #include "base/at_exit.h"
 #include "net/url_request/url_request_context_getter.h"
@@ -94,6 +95,9 @@
   // cross-thread calls on the class.
   virtual ~ChromotingJniRuntime();
 
+  // Detaches JVM from the current thread, then signals. Doesn't own |waiter|.
+  void DetachFromVmAndSignal(base::WaitableEvent* waiter);
+
   // Reference to the Java class into which we make JNI calls.
   jclass class_;
 
diff --git a/remoting/host/host_main.cc b/remoting/host/host_main.cc
index ffff5bf..25e01e6 100644
--- a/remoting/host/host_main.cc
+++ b/remoting/host/host_main.cc
@@ -13,6 +13,7 @@
 #include "base/command_line.h"
 #include "base/files/file_path.h"
 #include "base/logging.h"
+#include "base/strings/string_util.h"
 #include "base/strings/stringize_macros.h"
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
@@ -20,6 +21,7 @@
 #include "remoting/base/resources.h"
 #include "remoting/host/host_exit_codes.h"
 #include "remoting/host/logging.h"
+#include "remoting/host/setup/native_messaging_host.h"
 #include "remoting/host/usage_stats_consent.h"
 
 #if defined(OS_MACOSX)
@@ -47,8 +49,11 @@
 const char kProcessTypeDaemon[] = "daemon";
 const char kProcessTypeDesktop[] = "desktop";
 const char kProcessTypeHost[] = "host";
+const char kProcessTypeNativeMessagingHost[] = "native_messaging_host";
 const char kProcessTypeRdpDesktopSession[] = "rdp_desktop_session";
 
+const char kExtensionOriginPrefix[] = "chrome-extension://";
+
 namespace {
 
 typedef int (*MainRoutineFn)();
@@ -83,8 +88,7 @@
 int RunElevated() {
   const CommandLine::SwitchMap& switches =
       CommandLine::ForCurrentProcess()->GetSwitches();
-  const CommandLine::StringVector& args =
-      CommandLine::ForCurrentProcess()->GetArgs();
+  CommandLine::StringVector args = CommandLine::ForCurrentProcess()->GetArgs();
 
   // Create the child process command line by copying switches from the current
   // command line.
@@ -161,6 +165,8 @@
     main_routine = &RdpDesktopSessionMain;
   } else if (process_type == kProcessTypeHost) {
     main_routine = &HostProcessMain;
+  } else if (process_type == kProcessTypeNativeMessagingHost) {
+    main_routine = &NativeMessagingHostMain;
   }
 
   return main_routine;
@@ -223,6 +229,20 @@
   std::string process_type = kProcessTypeHost;
   if (command_line->HasSwitch(kProcessTypeSwitchName)) {
     process_type = command_line->GetSwitchValueASCII(kProcessTypeSwitchName);
+  } else {
+    // Assume that it is the native messaging host starting if "--type" is
+    // missing and the first argument looks like an origin that represents
+    // an extension.
+    CommandLine::StringVector args = command_line->GetArgs();
+#if defined(OS_WIN)
+    std::string origin = UTF16ToUTF8(args[0]);
+#else
+    std::string origin = args[0];
+#endif
+    if (!args.empty() &&
+        StartsWithASCII(origin, kExtensionOriginPrefix, true)) {
+      process_type = kProcessTypeNativeMessagingHost;
+    }
   }
 
   MainRoutineFn main_routine = SelectMainRoutine(process_type);
diff --git a/remoting/host/host_main.h b/remoting/host/host_main.h
index 527e4b3..95ac3e9 100644
--- a/remoting/host/host_main.h
+++ b/remoting/host/host_main.h
@@ -20,6 +20,7 @@
 extern const char kProcessTypeDaemon[];
 extern const char kProcessTypeDesktop[];
 extern const char kProcessTypeHost[];
+extern const char kProcessTypeNativeMessagingHost[];
 extern const char kProcessTypeRdpDesktopSession[];
 
 // The common entry point exported from remoting_core.dll. It uses
diff --git a/remoting/host/installer/linux/Makefile b/remoting/host/installer/linux/Makefile
index 3bbeece..9fc36be 100644
--- a/remoting/host/installer/linux/Makefile
+++ b/remoting/host/installer/linux/Makefile
@@ -12,7 +12,6 @@
 INSTALL_DIR = $(DESTDIR)/opt/google/chrome-remote-desktop
 CHROME_MANIFEST_DIR = $(DESTDIR)/etc/opt/chrome/native-messaging-hosts
 MANIFEST = $(CHROME_MANIFEST_DIR)/com.google.chrome.remote_desktop.json
-NM_HOST_PATH = /opt/google/chrome-remote-desktop/native-messaging-host
 
 ME2ME_PROGNAME = $(RELEASE)/remoting_me2me_host
 ME2ME_DEBUGFILE = $(ME2ME_PROGNAME).debug
@@ -31,9 +30,8 @@
 	  "$(INSTALL_DIR)/chrome-remote-desktop"
 	install "$(TOOLS)/is-remoting-session" "$(INSTALL_DIR)"
 
-	install -T "$(SRC)/remoting/host/setup/native_messaging_manifest.json" \
+	install -T "$(RELEASE)/remoting/native_messaging_manifest.json" \
 	  -m 0644 "$(MANIFEST)"
-	sed -i -e "s:NATIVE_MESSAGING_HOST_PATH:$(NM_HOST_PATH):g" "$(MANIFEST)"
 
 	eu-strip -f "$(ME2ME_DEBUGFILE)" "$(ME2ME_PROGNAME)"
 	install "$(ME2ME_PROGNAME)" \
diff --git a/remoting/host/pairing_registry_delegate_linux.cc b/remoting/host/pairing_registry_delegate_linux.cc
index 0f1517a..c8c09e7 100644
--- a/remoting/host/pairing_registry_delegate_linux.cc
+++ b/remoting/host/pairing_registry_delegate_linux.cc
@@ -96,7 +96,13 @@
     return PairingRegistry::Pairing();
   }
 
-  return PairingRegistry::Pairing::CreateFromValue(*pairing);
+  base::DictionaryValue* pairing_dictionary;
+  if (!pairing->GetAsDictionary(&pairing_dictionary)) {
+    LOG(WARNING) << "Failed to parse pairing information: not a dictionary.";
+    return PairingRegistry::Pairing();
+  }
+
+  return PairingRegistry::Pairing::CreateFromValue(*pairing_dictionary);
 }
 
 bool PairingRegistryDelegateLinux::Save(
diff --git a/remoting/host/pairing_registry_delegate_linux_unittest.cc b/remoting/host/pairing_registry_delegate_linux_unittest.cc
index 5596e3b..70cd558 100644
--- a/remoting/host/pairing_registry_delegate_linux_unittest.cc
+++ b/remoting/host/pairing_registry_delegate_linux_unittest.cc
@@ -63,8 +63,8 @@
   // Verify that the only value that left is |pairing2|.
   EXPECT_EQ(delegate->LoadAll()->GetSize(), 1u);
   scoped_ptr<base::ListValue> pairings = delegate->LoadAll();
-  base::Value* json;
-  EXPECT_TRUE(pairings->Get(0, &json));
+  base::DictionaryValue* json;
+  EXPECT_TRUE(pairings->GetDictionary(0, &json));
   EXPECT_EQ(PairingRegistry::Pairing::CreateFromValue(*json), pairing2);
 
   // Delete the rest and verify.
diff --git a/remoting/host/pairing_registry_delegate_win.cc b/remoting/host/pairing_registry_delegate_win.cc
index d0527ab..c7f11d9 100644
--- a/remoting/host/pairing_registry_delegate_win.cc
+++ b/remoting/host/pairing_registry_delegate_win.cc
@@ -4,6 +4,7 @@
 
 #include "remoting/host/pairing_registry_delegate_win.h"
 
+#include "base/json/json_string_value_serializer.h"
 #include "base/logging.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/values.h"
@@ -13,14 +14,10 @@
 
 namespace {
 
-const wchar_t kClientNameKey[] = L"clientName";
-const wchar_t kCreatedTimeKey[] = L"createdTime";
-const wchar_t kSharedSecretKey[] = L"sharedSecret";
-
 // Duplicates a registry key handle (returned by RegCreateXxx/RegOpenXxx).
 // The returned handle cannot be inherited and has the same permissions as
 // the source one.
-bool DuplicateKeyHandle(HKEY source, ScopedRegKey* dest) {
+bool DuplicateKeyHandle(HKEY source, base::win::RegKey* dest) {
   HANDLE handle;
   if (!DuplicateHandle(GetCurrentProcess(),
                        source,
@@ -37,6 +34,66 @@
   return true;
 }
 
+// Reads value |value_name| from |key| as a JSON string and returns it as
+// |base::Value|.
+scoped_ptr<base::DictionaryValue> ReadValue(const base::win::RegKey& key,
+                                            const wchar_t* value_name) {
+  // presubmit: allow wstring
+  std::wstring value_json;
+  LONG result = key.ReadValue(value_name, &value_json);
+  if (result != ERROR_SUCCESS) {
+    SetLastError(result);
+    PLOG(ERROR) << "Cannot read value '" << value_name << "'";
+    return scoped_ptr<base::DictionaryValue>();
+  }
+
+  // Parse the value.
+  std::string value_json_utf8 = WideToUTF8(value_json);
+  JSONStringValueSerializer serializer(&value_json_utf8);
+  int error_code;
+  std::string error_message;
+  scoped_ptr<base::Value> value(serializer.Deserialize(&error_code,
+                                                       &error_message));
+  if (!value) {
+    LOG(ERROR) << "Failed to parse '" << value_name << "': " << error_message
+               << " (" << error_code << ").";
+    return scoped_ptr<base::DictionaryValue>();
+  }
+
+  if (value->GetType() != base::Value::TYPE_DICTIONARY) {
+    LOG(ERROR) << "Failed to parse '" << value_name << "': not a dictionary.";
+    return scoped_ptr<base::DictionaryValue>();
+  }
+
+  return scoped_ptr<base::DictionaryValue>(
+      static_cast<base::DictionaryValue*>(value.release()));
+}
+
+// Serializes |value| into a JSON string and writes it as value |value_name|
+// under |key|.
+bool WriteValue(base::win::RegKey& key,
+                const wchar_t* value_name,
+                scoped_ptr<base::DictionaryValue> value) {
+  std::string value_json_utf8;
+  JSONStringValueSerializer serializer(&value_json_utf8);
+  if (!serializer.Serialize(*value)) {
+    LOG(ERROR) << "Failed to serialize '" << value_name << "'";
+    return false;
+  }
+
+  // presubmit: allow wstring
+  std::wstring value_json = UTF8ToWide(value_json_utf8);
+  LONG result = key.WriteValue(value_name,
+                               UTF8ToWide(value_json_utf8).c_str());
+  if (result != ERROR_SUCCESS) {
+    SetLastError(result);
+    PLOG(ERROR) << "Cannot write value '" << value_name << "'";
+    return false;
+  }
+
+  return true;
+}
+
 }  // namespace
 
 using protocol::PairingRegistry;
@@ -49,8 +106,8 @@
 
 bool PairingRegistryDelegateWin::SetRootKeys(HKEY privileged,
                                              HKEY unprivileged) {
-  DCHECK(!privileged_);
-  DCHECK(!unprivileged_);
+  DCHECK(!privileged_.Valid());
+  DCHECK(!unprivileged_.Valid());
   DCHECK(unprivileged);
 
   if (!DuplicateKeyHandle(unprivileged, &unprivileged_))
@@ -67,146 +124,95 @@
 scoped_ptr<base::ListValue> PairingRegistryDelegateWin::LoadAll() {
   scoped_ptr<base::ListValue> pairings(new base::ListValue());
 
-  DWORD index = 0;
-  for (LONG result = ERROR_SUCCESS; result == ERROR_SUCCESS; ++index) {
-    wchar_t name[MAX_PATH];
-    result = RegEnumKey(unprivileged_, index, name, arraysize(name));
-    if (result == ERROR_SUCCESS) {
-      PairingRegistry::Pairing pairing = Load(WideToUTF8(name));
-      if (pairing.is_valid())
-        pairings->Append(pairing.ToValue().release());
+  // Enumerate and parse all values under the unprivileged key.
+  DWORD count = unprivileged_.GetValueCount();
+  for (DWORD index = 0; index < count; ++index) {
+    // presubmit: allow wstring
+    std::wstring value_name;
+    LONG result = unprivileged_.GetValueNameAt(index, &value_name);
+    if (result != ERROR_SUCCESS) {
+      SetLastError(result);
+      PLOG(ERROR) << "Cannot get the name of value " << index;
+      continue;
     }
+
+    PairingRegistry::Pairing pairing = Load(WideToUTF8(value_name));
+    if (pairing.is_valid())
+      pairings->Append(pairing.ToValue().release());
   }
 
   return pairings.Pass();
 }
 
 bool PairingRegistryDelegateWin::DeleteAll() {
-  LONG result = ERROR_SUCCESS;
-  bool success = true;
-  while (result == ERROR_SUCCESS) {
-    wchar_t name[MAX_PATH];
-    result = RegEnumKey(unprivileged_, 0, name, arraysize(name));
-    if (result == ERROR_SUCCESS)
-      success = success && Delete(WideToUTF8(name));
+  if (!privileged_.Valid()) {
+    LOG(ERROR) << "Cannot delete pairings: the delegate is read-only.";
+    return false;
   }
 
-  success = success && result == ERROR_NO_MORE_ITEMS;
+  bool success = true;
+  DWORD count = unprivileged_.GetValueCount();
+  while (count > 0) {
+    // presubmit: allow wstring
+    std::wstring value_name;
+    LONG result = unprivileged_.GetValueNameAt(0, &value_name);
+    if (result == ERROR_SUCCESS)
+      result = unprivileged_.DeleteValue(value_name.c_str());
+
+    success = success && (result == ERROR_SUCCESS);
+    count = unprivileged_.GetValueCount();
+  }
+
   return success;
 }
 
 PairingRegistry::Pairing PairingRegistryDelegateWin::Load(
     const std::string& client_id) {
-  string16 key_name = UTF8ToUTF16(client_id);
-
-  FILETIME created_time;
-  string16 client_name;
-  string16 shared_secret;
+  // presubmit: allow wstring
+  std::wstring value_name = UTF8ToWide(client_id);
 
   // Read unprivileged fields first.
-  base::win::RegKey pairing_key;
-  LONG result = pairing_key.Open(unprivileged_, key_name.c_str(), KEY_READ);
-  if (result != ERROR_SUCCESS) {
-    SetLastError(result);
-    PLOG(ERROR) << "Cannot open pairing entry '" << client_id << "'";
+  scoped_ptr<base::DictionaryValue> pairing = ReadValue(unprivileged_,
+                                                        value_name.c_str());
+  if (!pairing)
     return PairingRegistry::Pairing();
-  }
-  result = pairing_key.ReadValue(kClientNameKey, &client_name);
-  if (result != ERROR_SUCCESS) {
-    SetLastError(result);
-    PLOG(ERROR) << "Cannot read '" << client_id << "/" << kClientNameKey << "'";
-    return PairingRegistry::Pairing();
-  }
-  DWORD size = sizeof(created_time);
-  DWORD type;
-  result = pairing_key.ReadValue(kCreatedTimeKey,
-                                 &created_time,
-                                 &size,
-                                 &type);
-  if (result != ERROR_SUCCESS ||
-      size != sizeof(created_time) ||
-      type != REG_QWORD) {
-    SetLastError(result);
-    PLOG(ERROR) << "Cannot read '" << client_id << "/" << kCreatedTimeKey
-                << "'";
-    return PairingRegistry::Pairing();
-  }
 
   // Read the shared secret.
-  if (privileged_.IsValid()) {
-    result = pairing_key.Open(privileged_, key_name.c_str(), KEY_READ);
-    if (result != ERROR_SUCCESS) {
-      SetLastError(result);
-      PLOG(ERROR) << "Cannot open pairing entry '" << client_id << "'";
+  if (privileged_.Valid()) {
+    scoped_ptr<base::DictionaryValue> secret = ReadValue(privileged_,
+                                                         value_name.c_str());
+    if (!secret)
       return PairingRegistry::Pairing();
-    }
-    result = pairing_key.ReadValue(kSharedSecretKey, &shared_secret);
-    if (result != ERROR_SUCCESS) {
-      SetLastError(result);
-      PLOG(ERROR) << "Cannot read '" << client_id << "/" << kSharedSecretKey
-                  << "'";
-      return PairingRegistry::Pairing();
-    }
+
+    // Merge the two dictionaries.
+    pairing->MergeDictionary(secret.get());
   }
 
-  return PairingRegistry::Pairing(base::Time::FromFileTime(created_time),
-                                  UTF16ToUTF8(client_name),
-                                  client_id,
-                                  UTF16ToUTF8(shared_secret));
+  return PairingRegistry::Pairing::CreateFromValue(*pairing);
 }
 
 bool PairingRegistryDelegateWin::Save(const PairingRegistry::Pairing& pairing) {
-  string16 key_name = UTF8ToUTF16(pairing.client_id());
-
-  if (!privileged_.IsValid()) {
+  if (!privileged_.Valid()) {
     LOG(ERROR) << "Cannot save pairing entry '" << pairing.client_id()
                 << "': the delegate is read-only.";
     return false;
   }
 
-  // Store the shared secret first.
-  base::win::RegKey pairing_key;
-  LONG result = pairing_key.Create(privileged_, key_name.c_str(), KEY_WRITE);
-  if (result != ERROR_SUCCESS) {
-    SetLastError(result);
-    PLOG(ERROR) << "Cannot save pairing entry '" << pairing.client_id()
-                << "'";
-    return false;
-  }
-  result = pairing_key.WriteValue(kSharedSecretKey,
-                                  UTF8ToUTF16(pairing.shared_secret()).c_str());
-  if (result != ERROR_SUCCESS) {
-    SetLastError(result);
-    PLOG(ERROR) << "Cannot write '" << pairing.client_id() << "/"
-                << kSharedSecretKey << "'";
-    return false;
-  }
+  // Convert pairing to JSON.
+  scoped_ptr<base::DictionaryValue> pairing_json = pairing.ToValue();
 
-  // Store the rest of the fields.
-  result = pairing_key.Create(unprivileged_, key_name.c_str(), KEY_WRITE);
-  if (result != ERROR_SUCCESS) {
-    SetLastError(result);
-    PLOG(ERROR) << "Cannot save pairing entry '" << pairing.client_id()
-                << "'";
-    return false;
-  }
-  result = pairing_key.WriteValue(kClientNameKey,
-                                  UTF8ToUTF16(pairing.client_name()).c_str());
-  if (result != ERROR_SUCCESS) {
-    SetLastError(result);
-    PLOG(ERROR) << "Cannot write '" << pairing.client_id() << "/"
-                << kClientNameKey << "'";
-    return false;
-  }
-  FILETIME created_time = pairing.created_time().ToFileTime();
-  result = pairing_key.WriteValue(kCreatedTimeKey,
-                                  &created_time,
-                                  sizeof(created_time),
-                                  REG_QWORD);
-  if (result != ERROR_SUCCESS) {
-    SetLastError(result);
-    PLOG(ERROR) << "Cannot write '" << pairing.client_id() << "/"
-                << kCreatedTimeKey << "'";
+  // Extract the shared secret to a separate dictionary.
+  scoped_ptr<base::Value> secret_key;
+  CHECK(pairing_json->Remove(PairingRegistry::kSharedSecretKey, &secret_key));
+  scoped_ptr<base::DictionaryValue> secret_json(new base::DictionaryValue());
+  secret_json->Set(PairingRegistry::kSharedSecretKey, secret_key.release());
+
+  // presubmit: allow wstring
+  std::wstring value_name = UTF8ToWide(pairing.client_id());
+
+  // Write pairing to the registry.
+  if (!WriteValue(privileged_, value_name.c_str(), secret_json.Pass()) ||
+      !WriteValue(unprivileged_, value_name.c_str(), pairing_json.Pass())) {
     return false;
   }
 
@@ -214,15 +220,15 @@
 }
 
 bool PairingRegistryDelegateWin::Delete(const std::string& client_id) {
-  string16 key_name = UTF8ToUTF16(client_id);
-
-  if (!privileged_.IsValid()) {
+  if (!privileged_.Valid()) {
     LOG(ERROR) << "Cannot delete pairing entry '" << client_id
                 << "': the delegate is read-only.";
     return false;
   }
 
-  LONG result = RegDeleteKey(privileged_, key_name.c_str());
+  // presubmit: allow wstring
+  std::wstring value_name = UTF8ToWide(client_id);
+  LONG result = privileged_.DeleteValue(value_name.c_str());
   if (result != ERROR_SUCCESS &&
       result != ERROR_FILE_NOT_FOUND &&
       result != ERROR_PATH_NOT_FOUND) {
@@ -231,7 +237,7 @@
     return false;
   }
 
-  result = RegDeleteKey(unprivileged_, key_name.c_str());
+  result = unprivileged_.DeleteValue(value_name.c_str());
   if (result != ERROR_SUCCESS &&
       result != ERROR_FILE_NOT_FOUND &&
       result != ERROR_PATH_NOT_FOUND) {
diff --git a/remoting/host/pairing_registry_delegate_win.h b/remoting/host/pairing_registry_delegate_win.h
index 8dac568..ecbd4a2 100644
--- a/remoting/host/pairing_registry_delegate_win.h
+++ b/remoting/host/pairing_registry_delegate_win.h
@@ -10,7 +10,7 @@
 #include "base/basictypes.h"
 #include "base/compiler_specific.h"
 #include "base/memory/scoped_ptr.h"
-#include "remoting/base/scoped_reg_key_win.h"
+#include "base/win/registry.h"
 #include "remoting/protocol/pairing_registry.h"
 
 namespace base {
@@ -49,8 +49,8 @@
   virtual bool Delete(const std::string& client_id) OVERRIDE;
 
  private:
-  ScopedRegKey privileged_;
-  ScopedRegKey unprivileged_;
+  base::win::RegKey privileged_;
+  base::win::RegKey unprivileged_;
 
   DISALLOW_COPY_AND_ASSIGN(PairingRegistryDelegateWin);
 };
diff --git a/remoting/host/pairing_registry_delegate_win_unittest.cc b/remoting/host/pairing_registry_delegate_win_unittest.cc
index 8ba6bb1..b8b3953 100644
--- a/remoting/host/pairing_registry_delegate_win_unittest.cc
+++ b/remoting/host/pairing_registry_delegate_win_unittest.cc
@@ -75,8 +75,8 @@
   // Verify that the only remaining value is |pairing2|.
   EXPECT_EQ(delegate->LoadAll()->GetSize(), 1u);
   scoped_ptr<base::ListValue> pairings = delegate->LoadAll();
-  base::Value* json;
-  EXPECT_TRUE(pairings->Get(0, &json));
+  base::DictionaryValue* json;
+  EXPECT_TRUE(pairings->GetDictionary(0, &json));
   EXPECT_EQ(PairingRegistry::Pairing::CreateFromValue(*json), pairing2);
 
   // Delete the rest and verify.
diff --git a/remoting/host/setup/native_messaging_host.cc b/remoting/host/setup/native_messaging_host.cc
index 2240558..7bf6b7c 100644
--- a/remoting/host/setup/native_messaging_host.cc
+++ b/remoting/host/setup/native_messaging_host.cc
@@ -11,14 +11,22 @@
 #include "base/callback.h"
 #include "base/json/json_string_value_serializer.h"
 #include "base/location.h"
+#include "base/message_loop/message_loop.h"
+#include "base/run_loop.h"
 #include "base/strings/stringize_macros.h"
 #include "base/values.h"
 #include "net/base/net_util.h"
 #include "remoting/base/rsa_key_pair.h"
+#include "remoting/host/host_exit_codes.h"
+#include "remoting/host/pairing_registry_delegate.h"
 #include "remoting/host/pairing_registry_delegate.h"
 #include "remoting/host/pin_hash.h"
 #include "remoting/protocol/pairing_registry.h"
 
+#if defined(OS_POSIX)
+#include <unistd.h>
+#endif
+
 namespace {
 
 // Features supported in addition to the base protocol.
@@ -407,4 +415,29 @@
   SendResponse(response.Pass());
 }
 
+int NativeMessagingHostMain() {
+#if defined(OS_WIN)
+  base::PlatformFile read_file = GetStdHandle(STD_INPUT_HANDLE);
+  base::PlatformFile write_file = GetStdHandle(STD_OUTPUT_HANDLE);
+#elif defined(OS_POSIX)
+  base::PlatformFile read_file = STDIN_FILENO;
+  base::PlatformFile write_file = STDOUT_FILENO;
+#else
+#error Not implemented.
+#endif
+
+  base::MessageLoop message_loop(base::MessageLoop::TYPE_IO);
+  base::RunLoop run_loop;
+  scoped_refptr<protocol::PairingRegistry> pairing_registry =
+      CreatePairingRegistry(message_loop.message_loop_proxy());
+  remoting::NativeMessagingHost host(remoting::DaemonController::Create(),
+                                     pairing_registry,
+                                     read_file, write_file,
+                                     message_loop.message_loop_proxy(),
+                                     run_loop.QuitClosure());
+  host.Start();
+  run_loop.Run();
+  return kSuccessExitCode;
+}
+
 }  // namespace remoting
diff --git a/remoting/host/setup/native_messaging_host.h b/remoting/host/setup/native_messaging_host.h
index 2dd7af4..309d63c 100644
--- a/remoting/host/setup/native_messaging_host.h
+++ b/remoting/host/setup/native_messaging_host.h
@@ -126,6 +126,10 @@
   DISALLOW_COPY_AND_ASSIGN(NativeMessagingHost);
 };
 
+// Creates a NativeMessagingHost instance, attaches it to stdin/stdout and runs
+// the message loop until NativeMessagingHost signals shutdown.
+int NativeMessagingHostMain();
+
 }  // namespace remoting
 
 #endif  // REMOTING_HOST_SETUP_NATIVE_MESSAGING_HOST_H_
diff --git a/remoting/host/setup/native_messaging_host_main.cc b/remoting/host/setup/native_messaging_host_main.cc
index c227033..d9db325 100644
--- a/remoting/host/setup/native_messaging_host_main.cc
+++ b/remoting/host/setup/native_messaging_host_main.cc
@@ -2,21 +2,10 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "remoting/host/setup/native_messaging_host.h"
-
 #include "base/at_exit.h"
 #include "base/command_line.h"
-#include "base/message_loop/message_loop.h"
-#include "base/run_loop.h"
 #include "remoting/host/logging.h"
-#include "remoting/host/pairing_registry_delegate.h"
-#include "remoting/protocol/pairing_registry.h"
-
-#if defined(OS_POSIX)
-#include <unistd.h>
-#endif
-
-using remoting::protocol::PairingRegistry;
+#include "remoting/host/setup/native_messaging_host.h"
 
 int main(int argc, char** argv) {
   // This object instance is required by Chrome code (such as MessageLoop).
@@ -25,26 +14,5 @@
   CommandLine::Init(argc, argv);
   remoting::InitHostLogging();
 
-#if defined(OS_WIN)
-  base::PlatformFile read_file = GetStdHandle(STD_INPUT_HANDLE);
-  base::PlatformFile write_file = GetStdHandle(STD_OUTPUT_HANDLE);
-#elif defined(OS_POSIX)
-  base::PlatformFile read_file = STDIN_FILENO;
-  base::PlatformFile write_file = STDOUT_FILENO;
-#else
-#error Not implemented.
-#endif
-
-  base::MessageLoop message_loop(base::MessageLoop::TYPE_IO);
-  base::RunLoop run_loop;
-  scoped_refptr<PairingRegistry> pairing_registry =
-      remoting::CreatePairingRegistry(message_loop.message_loop_proxy());
-  remoting::NativeMessagingHost host(remoting::DaemonController::Create(),
-                                     pairing_registry,
-                                     read_file, write_file,
-                                     message_loop.message_loop_proxy(),
-                                     run_loop.QuitClosure());
-  host.Start();
-  run_loop.Run();
-  return 0;
+  return remoting::NativeMessagingHostMain();
 }
diff --git a/remoting/host/setup/native_messaging_manifest.json b/remoting/host/setup/native_messaging_manifest.json
index 875ba04..84884a2 100644
--- a/remoting/host/setup/native_messaging_manifest.json
+++ b/remoting/host/setup/native_messaging_manifest.json
@@ -1,8 +1,8 @@
 {
   "name": "com.google.chrome.remote_desktop",
-  "description": "Chrome Remote Desktop Host",
+  "description": "{% trans %}REMOTING_HOST_PLUGIN_NAME{% endtrans %}",
   "type": "stdio",
-  "path": "NATIVE_MESSAGING_HOST_PATH",
+  "path": "{{ NATIVE_MESSAGING_HOST_PATH }}",
   "allowed_origins": [
     "chrome-extension://ljacajndfccfgnfohlgkdphmbnpkjflk/",
     "chrome-extension://gbchcmhmhahfdphkhkmpfmihenigjmpp/",
diff --git a/remoting/host/win/entry_point.cc b/remoting/host/win/entry_point.cc
index 26ab33d..3b54069 100644
--- a/remoting/host/win/entry_point.cc
+++ b/remoting/host/win/entry_point.cc
@@ -6,8 +6,8 @@
 
 #include "remoting/host/host_main.h"
 
-// The common entry point for all Me2Me host binaries. In order to be really
-// small the app doesn't link against the CRT.
+// The common entry point for remoting_host.exe and remoting_desktop.exe. In
+// order to be really small the app doesn't link against the CRT.
 void HostEntryPoint() {
   // CommandLine::Init() ignores the passed parameters on Windows, so it is safe
   // to pass NULL here.
diff --git a/remoting/protocol/pairing_registry.cc b/remoting/protocol/pairing_registry.cc
index a6e7327..c159ce6 100644
--- a/remoting/protocol/pairing_registry.cc
+++ b/remoting/protocol/pairing_registry.cc
@@ -57,21 +57,15 @@
 }
 
 PairingRegistry::Pairing PairingRegistry::Pairing::CreateFromValue(
-    const base::Value& pairing_json) {
-  const base::DictionaryValue* pairing = NULL;
-  if (!pairing_json.GetAsDictionary(&pairing)) {
-    LOG(ERROR) << "Failed to load pairing information: not a dictionary.";
-    return Pairing();
-  }
-
+    const base::DictionaryValue& pairing) {
   std::string client_name, client_id;
   double created_time_value;
-  if (pairing->GetDouble(kCreatedTimeKey, &created_time_value) &&
-      pairing->GetString(kClientNameKey, &client_name) &&
-      pairing->GetString(kClientIdKey, &client_id)) {
+  if (pairing.GetDouble(kCreatedTimeKey, &created_time_value) &&
+      pairing.GetString(kClientNameKey, &client_name) &&
+      pairing.GetString(kClientIdKey, &client_id)) {
     // The shared secret is optional.
     std::string shared_secret;
-    pairing->GetString(kSharedSecretKey, &shared_secret);
+    pairing.GetString(kSharedSecretKey, &shared_secret);
     base::Time created_time = base::Time::FromJsTime(created_time_value);
     return Pairing(created_time, client_name, client_id, shared_secret);
   }
@@ -80,14 +74,14 @@
   return Pairing();
 }
 
-scoped_ptr<base::Value> PairingRegistry::Pairing::ToValue() const {
+scoped_ptr<base::DictionaryValue> PairingRegistry::Pairing::ToValue() const {
   scoped_ptr<base::DictionaryValue> pairing(new base::DictionaryValue());
   pairing->SetDouble(kCreatedTimeKey, created_time().ToJsTime());
   pairing->SetString(kClientNameKey, client_name());
   pairing->SetString(kClientIdKey, client_id());
   if (!shared_secret().empty())
     pairing->SetString(kSharedSecretKey, shared_secret());
-  return pairing.PassAs<base::Value>();
+  return pairing.Pass();
 }
 
 bool PairingRegistry::Pairing::operator==(const Pairing& other) const {
diff --git a/remoting/protocol/pairing_registry.h b/remoting/protocol/pairing_registry.h
index ddcd736..e9ff1ff 100644
--- a/remoting/protocol/pairing_registry.h
+++ b/remoting/protocol/pairing_registry.h
@@ -17,8 +17,8 @@
 #include "base/time/time.h"
 
 namespace base {
+class DictionaryValue;
 class ListValue;
-class Value;
 class SingleThreadTaskRunner;
 }  // namespace base
 
@@ -49,9 +49,9 @@
     ~Pairing();
 
     static Pairing Create(const std::string& client_name);
-    static Pairing CreateFromValue(const base::Value& pairing_json);
+    static Pairing CreateFromValue(const base::DictionaryValue& pairing);
 
-    scoped_ptr<base::Value> ToValue() const;
+    scoped_ptr<base::DictionaryValue> ToValue() const;
 
     bool operator==(const Pairing& other) const;
 
diff --git a/remoting/remoting.gyp b/remoting/remoting.gyp
index 48bcf44..f81cfd3 100644
--- a/remoting/remoting.gyp
+++ b/remoting/remoting.gyp
@@ -840,31 +840,6 @@
             },
           ],
         },  # end of target 'remoting_infoplist_strings'
-
-        {
-          'target_name': 'remoting_native_messaging_host',
-          'type': 'executable',
-          'variables': { 'enable_wexit_time_destructors': 1, },
-          'dependencies': [
-            '../base/base.gyp:base',
-            'remoting_host',
-            'remoting_host_logging',
-            'remoting_host_setup_base',
-          ],
-          'defines': [
-            'VERSION=<(version_full)',
-          ],
-          'sources': [
-            'host/setup/native_messaging_host_main.cc',
-          ],
-          'conditions': [
-            ['OS=="linux" and linux_use_tcmalloc==1', {
-              'dependencies': [
-                '../base/allocator/allocator.gyp:allocator',
-              ],
-            }],
-          ],
-        },  # end of target 'remoting_native_messaging_host'
       ],  # end of 'targets'
     }],  # 'enable_remoting_host==1'
 
@@ -957,6 +932,7 @@
             'remoting_host',
             'remoting_host_event_logger',
             'remoting_host_logging',
+            'remoting_host_setup_base',
             'remoting_infoplist_strings',
             'remoting_jingle_glue',
             'remoting_me2me_host_static',
@@ -1035,7 +1011,31 @@
             }],  # OS=linux
           ],  # end of 'conditions'
         },  # end of target 'remoting_me2me_host'
-
+        {
+          'target_name': 'remoting_native_messaging_host',
+          'type': 'executable',
+          'variables': { 'enable_wexit_time_destructors': 1, },
+          'dependencies': [
+            '../base/base.gyp:base',
+            'remoting_host',
+            'remoting_host_logging',
+            'remoting_host_setup_base',
+            'remoting_native_messaging_manifest',
+          ],
+          'defines': [
+            'VERSION=<(version_full)',
+          ],
+          'sources': [
+            'host/setup/native_messaging_host_main.cc',
+          ],
+          'conditions': [
+            ['OS=="linux" and linux_use_tcmalloc==1', {
+              'dependencies': [
+                '../base/allocator/allocator.gyp:allocator',
+              ],
+            }],
+          ],
+        },  # end of target 'remoting_native_messaging_host'
       ],  # end of 'targets'
     }],  # 'OS!="win" and enable_remoting_host==1'
 
@@ -1511,13 +1511,13 @@
             '../ipc/ipc.gyp:ipc',
             '../net/net.gyp:net',
             '../third_party/webrtc/modules/modules.gyp:desktop_capture',
-            '../third_party/webrtc/modules/modules.gyp:desktop_capture',
             'remoting_base',
             'remoting_breakpad',
             'remoting_core_resources',
             'remoting_host',
             'remoting_host_event_logger',
             'remoting_host_logging',
+            'remoting_host_setup_base',
             'remoting_lib_idl',
             'remoting_lib_ps',
             'remoting_lib_rc',
@@ -1937,6 +1937,7 @@
             'remoting_core',
             'remoting_desktop',
             'remoting_host_exe',
+            'remoting_native_messaging_manifest',
           ],
           'compiled_inputs': [
             '<(PRODUCT_DIR)/remoting_core.dll',
@@ -1968,11 +1969,13 @@
           'generated_files': [
             '<@(_compiled_inputs)',
             '<(sas_dll_path)/sas.dll',
+            '<(PRODUCT_DIR)/remoting/native_messaging_manifest.json',
             'resources/chromoting.ico',
           ],
           'generated_files_dst': [
             '<@(_compiled_inputs_dst)',
             'files/sas.dll',
+            'files/native_messaging_manifest.json',
             'files/chromoting.ico',
           ],
           'zip_path': '<(PRODUCT_DIR)/remoting-me2me-host-<(OS).zip',
@@ -2282,6 +2285,53 @@
       ],
     }, # end of target 'remoting_webapp'
 
+    # Generates 'native_messaging_manifest.json' to be included in the
+    # installation.
+    {
+      'target_name': 'remoting_native_messaging_manifest',
+      'type': 'none',
+      'dependencies': [
+        'remoting_resources',
+      ],
+      'variables': {
+        'input': 'host/setup/native_messaging_manifest.json',
+        'output': '<(PRODUCT_DIR)/remoting/native_messaging_manifest.json',
+      },
+      'conditions': [
+        [ 'OS=="win"', {
+          'variables': {
+            'native_messaging_host_path': 'remoting_host.exe',
+          },
+        }, {
+          'variables': {
+            'native_messaging_host_path': '/opt/google/chrome-remote-desktop/native-messaging-host',
+          },
+        }],
+      ],
+      'actions': [
+        {
+          'action_name': 'generate_manifest',
+          'inputs': [
+            '<(remoting_localize_path)',
+            '<(input)',
+          ],
+          'outputs': [
+            '<(output)',
+          ],
+          'action': [
+            'python',
+            '<(remoting_localize_path)',
+            '--define', 'NATIVE_MESSAGING_HOST_PATH=<(native_messaging_host_path)',
+            '--locale_dir', '<(webapp_locale_dir)',
+            '--template', '<(input)',
+            '--locale_output',
+            '<(output)',
+            '--encoding', 'utf-8',
+            'en',
+          ],
+        },
+      ],
+    },  # end of target 'remoting_native_messaging_manifest'
     {
       'target_name': 'remoting_resources',
       'type': 'none',
@@ -2418,7 +2468,6 @@
         'base/rsa_key_pair.h',
         'base/running_average.cc',
         'base/running_average.h',
-        'base/scoped_reg_key_win.h',
         'base/scoped_sc_handle_win.h',
         'base/socket_reader.cc',
         'base/socket_reader.h',
diff --git a/remoting/resources/menu/chromoting_actionbar.xml b/remoting/resources/menu/chromoting_actionbar.xml
index 1507dd4..e602a36 100644
--- a/remoting/resources/menu/chromoting_actionbar.xml
+++ b/remoting/resources/menu/chromoting_actionbar.xml
@@ -1,6 +1,10 @@
 <?xml version="1.0" encoding="utf-8"?>
 <!--Action bar buttons for the Android app's host listing-->
 <menu xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:id="@+id/actionbar_directoryrefresh"
+            android:title="@string/actionbar_directoryrefresh"
+            android:icon="@android:drawable/ic_popup_sync"
+            android:showAsAction="ifRoom"/>
     <item android:id="@+id/actionbar_accountswitcher"
             android:title="@string/actionbar_accountswitcher"
             android:icon="@android:drawable/ic_menu_more"
diff --git a/remoting/resources/strings.xml b/remoting/resources/strings.xml
index 949a2aa..a2c2095 100644
--- a/remoting/resources/strings.xml
+++ b/remoting/resources/strings.xml
@@ -18,6 +18,7 @@
     <string name="pin_entry_cancel">Cancel</string>
 
     <!--Action bar buttons-->
+    <string name="actionbar_directoryrefresh">Refresh</string>
     <string name="actionbar_accountswitcher">Accounts</string>
     <string name="actionbar_hide">Hide</string>
     <string name="actionbar_keyboard">Keyboard</string>
@@ -31,6 +32,7 @@
     <string name="error_auth_canceled">Authentication prompt canceled by user</string>
     <string name="error_no_accounts">Device not linked to any Google accounts</string>
     <string name="error_auth_failed">Authentication with specified account failed</string>
+    <string name="error_bad_connection">No network connection</string>
     <string name="error_cataloging_hosts">Unable to display host list</string>
     <string name="error_displaying_host">Unable to display host entry</string>
     <string name="error_unexpected_response">Account has no remote desktop hosts registered</string>
diff --git a/remoting/webapp/appsv2.patch b/remoting/webapp/appsv2.patch
index 0e643db..f03a317 100644
--- a/remoting/webapp/appsv2.patch
+++ b/remoting/webapp/appsv2.patch
@@ -42,8 +42,8 @@
      "clipboardWrite",
 -    "nativeMessaging"
 +    "nativeMessaging",
-+    "experimental",
 +    "fullscreen"
++    "identity",
    ],
 -  "plugins": [
 -    { "path": "remoting_host_plugin.dll", "public": false },
diff --git a/remoting/webapp/client_screen.js b/remoting/webapp/client_screen.js
index b2b22fe..11f6d74 100644
--- a/remoting/webapp/client_screen.js
+++ b/remoting/webapp/client_screen.js
@@ -356,6 +356,7 @@
         }
       };
       remoting.HostSettings.save(clientSession.hostId, pairingInfo);
+      remoting.connector.updatePairingInfo(clientId, sharedSecret);
     };
     // Use the platform name as a proxy for the local computer name.
     // TODO(jamiewalch): Use a descriptive name for the local computer, for
diff --git a/remoting/webapp/clipboard.js b/remoting/webapp/clipboard.js
index 4b18d57..6a29dcd 100644
--- a/remoting/webapp/clipboard.js
+++ b/remoting/webapp/clipboard.js
@@ -75,6 +75,7 @@
  */
 remoting.Clipboard.prototype.toHost = function(clipboardData) {
   if (!clipboardData || !clipboardData.types || !clipboardData.getData) {
+    console.log('Got invalid clipboardData.');
     return;
   }
   if (!remoting.clientSession || !remoting.clientSession.plugin) {
@@ -83,17 +84,22 @@
   var plugin = remoting.clientSession.plugin;
   for (var i = 0; i < clipboardData.types.length; i++) {
     var type = clipboardData.types[i];
+    var item = clipboardData.getData(type);
+    if (!item) {
+      item = "";
+    }
+    console.log('Got clipboard from OS, type: ' + type +
+                ' length: ' + item.length + ' new: ' +
+                (item != this.previousContent) + ' blocking-send: ' +
+                this.blockOneClipboardSend_);
     // The browser presents text clipboard items as 'text/plain'.
     if (type == this.ItemTypes.TEXT_TYPE) {
-      var item = clipboardData.getData(type);
-      if (!item) {
-        item = "";
-      }
       // Don't send the same item more than once. Otherwise the item may be
       // sent to and fro indefinitely.
       if (item != this.previousContent) {
         if (!this.blockOneClipboardSend_) {
           // The plugin's JSON reader emits UTF-8.
+          console.log('Sending clipboard to host.');
           plugin.sendClipboardItem(this.ItemTypes.TEXT_UTF8_TYPE, item);
         }
         this.previousContent = item;
@@ -114,6 +120,9 @@
 remoting.Clipboard.prototype.fromHost = function(mimeType, item) {
   // The plugin's JSON layer will correctly convert only UTF-8 data sent from
   // the host.
+  console.log('Got clipboard from host, type: ' + mimeType +
+              ' length: ' + item.length + ' new: ' +
+              (item != this.previousContent));
   if (mimeType != this.ItemTypes.TEXT_UTF8_TYPE) {
     return;
   }
@@ -134,12 +143,14 @@
  */
 remoting.Clipboard.prototype.toOs = function(clipboardData) {
   if (!this.itemFromHostTextPending) {
+    console.log('Got unexpected clipboard copy event.');
     return false;
   }
   // The JSON layer between the plugin and this webapp converts UTF-8 to the
   // JS string encoding. The browser will convert JS strings to the correct
   // encoding, per OS and locale conventions, provided the data type is
   // 'text/plain'.
+  console.log('Setting OS clipboard, length: ' + this.previousContent.length);
   clipboardData.setData(this.ItemTypes.TEXT_TYPE, this.previousContent);
   this.itemFromHostTextPending = false;
   return true;
@@ -156,6 +167,7 @@
 remoting.Clipboard.prototype.initiateToHost = function() {
   // It would be cleaner to send a paste command to the plugin element,
   // but that's not supported.
+  console.log('Initiating clipboard paste.');
   document.execCommand("paste");
 };
 
@@ -170,6 +182,7 @@
 remoting.Clipboard.prototype.initiateToOs = function() {
   // It would be cleaner to send a paste command to the plugin element,
   // but that's not supported.
+  console.log('Initiating clipboard copy.');
   document.execCommand("copy");
 };
 
diff --git a/remoting/webapp/identity.js b/remoting/webapp/identity.js
index cc832f2..e30e143 100644
--- a/remoting/webapp/identity.js
+++ b/remoting/webapp/identity.js
@@ -51,7 +51,7 @@
 remoting.Identity.prototype.callWithToken = function(onOk, onError) {
   this.pendingCallbacks_.push(new remoting.Identity.Callbacks(onOk, onError));
   if (this.pendingCallbacks_.length == 1) {
-    chrome.experimental.identity.getAuthToken(
+    chrome.identity.getAuthToken(
         { 'interactive': false },
         this.onAuthComplete_.bind(this, false));
   }
@@ -132,7 +132,7 @@
  * @private
  */
 remoting.Identity.prototype.onAuthContinue_ = function() {
-  chrome.experimental.identity.getAuthToken(
+  chrome.identity.getAuthToken(
       { 'interactive': true },
       this.onAuthComplete_.bind(this, true));
 };
diff --git a/remoting/webapp/jscompiler_hacks.js b/remoting/webapp/jscompiler_hacks.js
index 911d321..ad4d755 100644
--- a/remoting/webapp/jscompiler_hacks.js
+++ b/remoting/webapp/jscompiler_hacks.js
@@ -122,10 +122,7 @@
 };
 
 /** @type {Object} */
-chrome.experimental = {};
-
-/** @type {Object} */
-chrome.experimental.identity = {
+chrome.identity = {
   /**
    * @param {Object.<string>} parameters
    * @param {function(string):void} callback
diff --git a/remoting/webapp/session_connector.js b/remoting/webapp/session_connector.js
index a5facb5..5febaab 100644
--- a/remoting/webapp/session_connector.js
+++ b/remoting/webapp/session_connector.js
@@ -194,6 +194,18 @@
 };
 
 /**
+ * Update the pairing info so that the reconnect function will work correctly.
+ *
+ * @param {string} clientId The paired client id.
+ * @param {string} sharedSecret The shared secret.
+ */
+remoting.SessionConnector.prototype.updatePairingInfo =
+    function(clientId, sharedSecret) {
+  this.clientPairingId_ = clientId;
+  this.clientPairedSecret_ = sharedSecret;
+};
+
+/**
  * Initiate a Me2Me connection.
  *
  * @param {string} hostId ID of the Me2Me host.
@@ -224,8 +236,6 @@
   this.cancel();
 
   this.hostId_ = hostId;
-  this.clientPairingId_ = clientPairingId;
-  this.clientPairedSecret_ = clientPairedSecret;
   this.hostJid_ = hostJid;
   this.hostPublicKey_ = hostPublicKey;
   this.fetchPin_ = fetchPin;
@@ -233,6 +243,7 @@
   this.hostDisplayName_ = hostDisplayName;
   this.connectionMode_ = remoting.ClientSession.Mode.ME2ME;
   this.refreshHostJidIfOffline_ = refreshHostJidIfOffline;
+  this.updatePairingInfo(clientPairingId, clientPairedSecret);
   this.createSessionIfReady_();
 };
 
diff --git a/remoting/webapp/third_party_token_fetcher.js b/remoting/webapp/third_party_token_fetcher.js
index ffe9120..9c8cce1 100644
--- a/remoting/webapp/third_party_token_fetcher.js
+++ b/remoting/webapp/third_party_token_fetcher.js
@@ -44,7 +44,7 @@
   this.xsrfToken_ = remoting.generateXsrfToken();
   this.tokenUrlPatterns_ = tokenUrlPatterns;
   this.hostPublicKey_ = hostPublicKey;
-  if (chrome.experimental && chrome.experimental.identity) {
+  if (chrome.identity) {
     /** @type {function():void}
      * @private */
     this.fetchTokenInternal_ = this.fetchTokenIdentityApi_.bind(this);
@@ -93,9 +93,9 @@
     function(responseUrl) {
   var token = '';
   var sharedSecret = '';
-  if (responseUrl &&
-      responseUrl.search(this.redirectUri_ + '#') == 0) {
-    var query = responseUrl.substring(this.redirectUri_.length + 1);
+
+  if (responseUrl && responseUrl.search('#') >= 0) {
+    var query = responseUrl.substring(responseUrl.search('#') + 1);
     var parts = query.split('&');
     /** @type {Object.<string>} */
     var queryArgs = {};
@@ -105,8 +105,7 @@
     }
 
     // Check that 'state' contains the same XSRF token we sent in the request.
-    var xsrfToken = queryArgs['state'];
-    if (xsrfToken == this.xsrfToken_ &&
+    if ('state' in queryArgs && queryArgs['state'] == this.xsrfToken_ &&
         'code' in queryArgs && 'access_token' in queryArgs) {
       // Terminology note:
       // In the OAuth code/token exchange semantics, 'code' refers to the value
@@ -169,8 +168,7 @@
  */
 remoting.ThirdPartyTokenFetcher.prototype.fetchTokenIdentityApi_ = function() {
   var fullTokenUrl = this.getFullTokenUrl_();
-  // TODO(rmsousa): chrome.identity.launchWebAuthFlow is experimental.
-  chrome.experimental.identity.launchWebAuthFlow(
+  chrome.identity.launchWebAuthFlow(
     {'url': fullTokenUrl, 'interactive': true},
     this.parseRedirectUrl_.bind(this));
 };
\ No newline at end of file
diff --git a/skia/skia_chrome.target.darwin-arm.mk b/skia/skia_chrome.target.darwin-arm.mk
index f5c66a3..6d86040 100644
--- a/skia/skia_chrome.target.darwin-arm.mk
+++ b/skia/skia_chrome.target.darwin-arm.mk
@@ -101,6 +101,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -202,6 +203,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=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 749ff01..3e2989c 100644
--- a/skia/skia_chrome.target.darwin-mips.mk
+++ b/skia/skia_chrome.target.darwin-mips.mk
@@ -101,6 +101,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -202,6 +203,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=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 210fa9e..d55ec3b 100644
--- a/skia/skia_chrome.target.darwin-x86.mk
+++ b/skia/skia_chrome.target.darwin-x86.mk
@@ -103,6 +103,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -207,6 +208,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/skia/skia_chrome.target.linux-arm.mk b/skia/skia_chrome.target.linux-arm.mk
index f5c66a3..6d86040 100644
--- a/skia/skia_chrome.target.linux-arm.mk
+++ b/skia/skia_chrome.target.linux-arm.mk
@@ -101,6 +101,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -202,6 +203,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=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 749ff01..3e2989c 100644
--- a/skia/skia_chrome.target.linux-mips.mk
+++ b/skia/skia_chrome.target.linux-mips.mk
@@ -101,6 +101,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -202,6 +203,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=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 210fa9e..d55ec3b 100644
--- a/skia/skia_chrome.target.linux-x86.mk
+++ b/skia/skia_chrome.target.linux-x86.mk
@@ -103,6 +103,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -207,6 +208,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/skia/skia_library.gypi b/skia/skia_library.gypi
index 2dca283..6d3f1c5 100644
--- a/skia/skia_library.gypi
+++ b/skia/skia_library.gypi
@@ -261,9 +261,10 @@
     }],
     [ 'OS != "ios"', {
       'dependencies': [
-        # FIXME: Add a dependency on
-        # '<(DEPTH)/third_party/WebKit/public/blink_skia_config.gyp:blink_skia_config'
-        # once https://codereview.chromium.org/21137002 rolls into Chromium.
+        '../third_party/WebKit/public/blink_skia_config.gyp:blink_skia_config',
+      ],
+      'export_dependent_settings': [
+        '../third_party/WebKit/public/blink_skia_config.gyp:blink_skia_config',
       ],
     }],
     [ 'OS != "mac"', {
diff --git a/skia/skia_library.target.darwin-arm.mk b/skia/skia_library.target.darwin-arm.mk
index 7d2cb16..86d43cc 100644
--- a/skia/skia_library.target.darwin-arm.mk
+++ b/skia/skia_library.target.darwin-arm.mk
@@ -11,6 +11,7 @@
 
 # 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 :=
@@ -107,6 +108,7 @@
 	third_party/skia/src/core/SkFilterShader.cpp \
 	third_party/skia/src/core/SkFlattenable.cpp \
 	third_party/skia/src/core/SkFlattenableBuffers.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 \
@@ -246,6 +248,7 @@
 	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 \
@@ -431,6 +434,7 @@
 	'-DSK_GAMMA_CONTRAST=0.0' \
 	'-DSK_USE_POSIX_THREADS' \
 	'-D__ARM_HAVE_OPTIONAL_NEON_SUPPORT' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -553,6 +557,7 @@
 	'-DSK_GAMMA_CONTRAST=0.0' \
 	'-DSK_USE_POSIX_THREADS' \
 	'-D__ARM_HAVE_OPTIONAL_NEON_SUPPORT' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=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 34fe628..8365e9c 100644
--- a/skia/skia_library.target.darwin-mips.mk
+++ b/skia/skia_library.target.darwin-mips.mk
@@ -11,6 +11,7 @@
 
 # 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 :=
@@ -107,6 +108,7 @@
 	third_party/skia/src/core/SkFilterShader.cpp \
 	third_party/skia/src/core/SkFlattenable.cpp \
 	third_party/skia/src/core/SkFlattenableBuffers.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 \
@@ -246,6 +248,7 @@
 	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 \
@@ -429,6 +432,7 @@
 	'-DSK_GAMMA_EXPONENT=1.4' \
 	'-DSK_GAMMA_CONTRAST=0.0' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -550,6 +554,7 @@
 	'-DSK_GAMMA_EXPONENT=1.4' \
 	'-DSK_GAMMA_CONTRAST=0.0' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=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 69b4e75..22fbdae 100644
--- a/skia/skia_library.target.darwin-x86.mk
+++ b/skia/skia_library.target.darwin-x86.mk
@@ -11,6 +11,7 @@
 
 # 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 :=
@@ -108,6 +109,7 @@
 	third_party/skia/src/core/SkFilterShader.cpp \
 	third_party/skia/src/core/SkFlattenable.cpp \
 	third_party/skia/src/core/SkFlattenableBuffers.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 \
@@ -247,6 +249,7 @@
 	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 \
@@ -432,6 +435,7 @@
 	'-DSK_GAMMA_EXPONENT=1.4' \
 	'-DSK_GAMMA_CONTRAST=0.0' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -556,6 +560,7 @@
 	'-DSK_GAMMA_EXPONENT=1.4' \
 	'-DSK_GAMMA_CONTRAST=0.0' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/skia/skia_library.target.linux-arm.mk b/skia/skia_library.target.linux-arm.mk
index 7d2cb16..86d43cc 100644
--- a/skia/skia_library.target.linux-arm.mk
+++ b/skia/skia_library.target.linux-arm.mk
@@ -11,6 +11,7 @@
 
 # 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 :=
@@ -107,6 +108,7 @@
 	third_party/skia/src/core/SkFilterShader.cpp \
 	third_party/skia/src/core/SkFlattenable.cpp \
 	third_party/skia/src/core/SkFlattenableBuffers.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 \
@@ -246,6 +248,7 @@
 	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 \
@@ -431,6 +434,7 @@
 	'-DSK_GAMMA_CONTRAST=0.0' \
 	'-DSK_USE_POSIX_THREADS' \
 	'-D__ARM_HAVE_OPTIONAL_NEON_SUPPORT' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -553,6 +557,7 @@
 	'-DSK_GAMMA_CONTRAST=0.0' \
 	'-DSK_USE_POSIX_THREADS' \
 	'-D__ARM_HAVE_OPTIONAL_NEON_SUPPORT' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=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 34fe628..8365e9c 100644
--- a/skia/skia_library.target.linux-mips.mk
+++ b/skia/skia_library.target.linux-mips.mk
@@ -11,6 +11,7 @@
 
 # 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 :=
@@ -107,6 +108,7 @@
 	third_party/skia/src/core/SkFilterShader.cpp \
 	third_party/skia/src/core/SkFlattenable.cpp \
 	third_party/skia/src/core/SkFlattenableBuffers.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 \
@@ -246,6 +248,7 @@
 	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 \
@@ -429,6 +432,7 @@
 	'-DSK_GAMMA_EXPONENT=1.4' \
 	'-DSK_GAMMA_CONTRAST=0.0' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -550,6 +554,7 @@
 	'-DSK_GAMMA_EXPONENT=1.4' \
 	'-DSK_GAMMA_CONTRAST=0.0' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=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 69b4e75..22fbdae 100644
--- a/skia/skia_library.target.linux-x86.mk
+++ b/skia/skia_library.target.linux-x86.mk
@@ -11,6 +11,7 @@
 
 # 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 :=
@@ -108,6 +109,7 @@
 	third_party/skia/src/core/SkFilterShader.cpp \
 	third_party/skia/src/core/SkFlattenable.cpp \
 	third_party/skia/src/core/SkFlattenableBuffers.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 \
@@ -247,6 +249,7 @@
 	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 \
@@ -432,6 +435,7 @@
 	'-DSK_GAMMA_EXPONENT=1.4' \
 	'-DSK_GAMMA_CONTRAST=0.0' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -556,6 +560,7 @@
 	'-DSK_GAMMA_EXPONENT=1.4' \
 	'-DSK_GAMMA_CONTRAST=0.0' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/sync/android/java/src/org/chromium/sync/internal_api/pub/base/ModelType.java b/sync/android/java/src/org/chromium/sync/internal_api/pub/base/ModelType.java
index a7d4797..afec46c 100644
--- a/sync/android/java/src/org/chromium/sync/internal_api/pub/base/ModelType.java
+++ b/sync/android/java/src/org/chromium/sync/internal_api/pub/base/ModelType.java
@@ -6,14 +6,12 @@
 
 import android.util.Log;
 
-import com.google.common.collect.HashMultimap;
-import com.google.common.collect.Multimap;
+import com.google.common.annotations.VisibleForTesting;
 import com.google.common.collect.Sets;
 import com.google.ipc.invalidation.external.client.types.ObjectId;
 import com.google.protos.ipc.invalidation.Types;
 
 import java.util.Collection;
-import java.util.HashSet;
 import java.util.Set;
 
 /**
@@ -63,7 +61,7 @@
     /**
      * A proxy tabs object (placeholder for sessions).
      */
-    PROXY_TABS("NULL"),
+    PROXY_TABS("NULL", true),
     /**
      * A favicon image object.
      */
@@ -80,10 +78,25 @@
 
     private final String mModelType;
 
-    ModelType(String modelType) {
+    private final boolean mNonInvalidationType;
+
+    ModelType(String modelType, boolean nonInvalidationType) {
         mModelType = modelType;
+        mNonInvalidationType = nonInvalidationType;
     }
 
+    ModelType(String modelType) {
+        this(modelType, false);
+    }
+
+    /**
+     * Returns the {@link ObjectId} representation of this {@link ModelType}.
+     *
+     * This should be used with caution, since it converts even {@link ModelType} instances with
+     * |mNonInvalidationType| set. For automatically stripping such {@link ModelType} entries out,
+     * use {@link ModelType#modelTypesToObjectIds(java.util.Set)} instead.
+     */
+    @VisibleForTesting
     public ObjectId toObjectId() {
         return ObjectId.newInstance(Types.ObjectSource.Type.CHROME_SYNC.getNumber(),
                 mModelType.getBytes());
@@ -124,11 +137,26 @@
         }
     }
 
-    /** Converts a set of {@link ModelType} to a set of {@link ObjectId}. */
+    /**
+     * Converts a set of sync types {@link String} to a set of {@link ObjectId}.
+     *
+     * This strips out any {@link ModelType} that is not an invalidation type.
+     */
+    public static Set<ObjectId> syncTypesToObjectIds(Collection<String> syncTypes) {
+        return modelTypesToObjectIds(syncTypesToModelTypes(syncTypes));
+    }
+
+    /**
+     * Converts a set of {@link ModelType} to a set of {@link ObjectId}.
+     *
+     * This strips out any {@link ModelType} that is not an invalidation type.
+     */
     public static Set<ObjectId> modelTypesToObjectIds(Set<ModelType> modelTypes) {
         Set<ObjectId> objectIds = Sets.newHashSetWithExpectedSize(modelTypes.size());
         for (ModelType modelType : modelTypes) {
-            objectIds.add(modelType.toObjectId());
+            if (!modelType.mNonInvalidationType) {
+                objectIds.add(modelType.toObjectId());
+            }
         }
         return objectIds;
     }
diff --git a/sync/android/java/src/org/chromium/sync/notifier/InvalidationController.java b/sync/android/java/src/org/chromium/sync/notifier/InvalidationController.java
index b912599..03255d1 100644
--- a/sync/android/java/src/org/chromium/sync/notifier/InvalidationController.java
+++ b/sync/android/java/src/org/chromium/sync/notifier/InvalidationController.java
@@ -100,11 +100,7 @@
      * @param types    Set of types for which to register. Ignored if {@code allTypes == true}.
      */
     public void setRegisteredTypes(Account account, boolean allTypes, Set<ModelType> types) {
-        Set<ModelType> typesToRegister = types;
-        // Proxy types should never receive notifications.
-        typesToRegister.remove(ModelType.PROXY_TABS);
-        Intent registerIntent = IntentProtocol.createRegisterIntent(account, allTypes,
-                typesToRegister);
+        Intent registerIntent = IntentProtocol.createRegisterIntent(account, allTypes, types);
         registerIntent.setClass(mContext, InvalidationService.class);
         mContext.startService(registerIntent);
     }
diff --git a/sync/android/java/src/org/chromium/sync/notifier/InvalidationService.java b/sync/android/java/src/org/chromium/sync/notifier/InvalidationService.java
index 92ac257..963c417 100644
--- a/sync/android/java/src/org/chromium/sync/notifier/InvalidationService.java
+++ b/sync/android/java/src/org/chromium/sync/notifier/InvalidationService.java
@@ -292,16 +292,8 @@
     @VisibleForTesting
     Set<ObjectId> readRegistrationsFromPrefs() {
         Set<String> savedTypes = new InvalidationPreferences(this).getSavedSyncedTypes();
-        if (savedTypes == null) {
-            return Collections.emptySet();
-        } else {
-            Set<ModelType> modelTypes = ModelType.syncTypesToModelTypes(savedTypes);
-            Set<ObjectId> objectIds = Sets.newHashSetWithExpectedSize(modelTypes.size());
-            for (ModelType modelType : modelTypes) {
-                objectIds.add(modelType.toObjectId());
-            }
-            return objectIds;
-        }
+        if (savedTypes == null) return Collections.emptySet();
+        else return ModelType.syncTypesToObjectIds(savedTypes);
     }
 
     /**
@@ -337,13 +329,11 @@
         // expansion of the ALL_TYPES_TYPE wildcard.
         // NOTE: syncTypes MUST NOT be used below this line, since it contains an unexpanded
         // wildcard.
-        Set<ModelType> newRegisteredTypes = ModelType.syncTypesToModelTypes(syncTypes);
-
         List<ObjectId> unregistrations = Lists.newArrayList();
         List<ObjectId> registrations = Lists.newArrayList();
         computeRegistrationOps(existingRegistrations,
-                ModelType.modelTypesToObjectIds(newRegisteredTypes), registrations,
-                unregistrations);
+                ModelType.syncTypesToObjectIds(syncTypes),
+                registrations, unregistrations);
         unregister(sClientId, unregistrations);
         register(sClientId, registrations);
     }
diff --git a/sync/android/javatests/src/org/chromium/sync/notifier/InvalidationServiceTest.java b/sync/android/javatests/src/org/chromium/sync/notifier/InvalidationServiceTest.java
index 0cff98e..db27879 100644
--- a/sync/android/javatests/src/org/chromium/sync/notifier/InvalidationServiceTest.java
+++ b/sync/android/javatests/src/org/chromium/sync/notifier/InvalidationServiceTest.java
@@ -521,6 +521,70 @@
 
     @SmallTest
     @Feature({"Sync"})
+    public void testRegistrationIntentNoProxyTabsUsingReady() {
+        getService().setShouldRunStates(true, true);
+        getService().onCreate();
+
+        // Send register Intent.
+        Account account = AccountManagerHelper.createAccountFromName("test@example.com");
+        Intent registrationIntent = IntentProtocol.createRegisterIntent(account, true, null);
+        getService().onHandleIntent(registrationIntent);
+
+        // Verify client started and state written.
+        assertTrue(InvalidationService.getIsClientStartedForTest());
+        InvalidationPreferences invPrefs = new InvalidationPreferences(getContext());
+        assertEquals(account, invPrefs.getSavedSyncedAccount());
+        assertEquals(ImmutableSet.of(ModelType.ALL_TYPES_TYPE), invPrefs.getSavedSyncedTypes());
+        assertEquals(1, mStartServiceIntents.size());
+        assertTrue(isAndroidListenerStartIntent(mStartServiceIntents.get(0)));
+
+        // Set client to be ready. This triggers registrations.
+        getService().ready(CLIENT_ID);
+        assertTrue(Arrays.equals(CLIENT_ID, InvalidationService.getClientIdForTest()));
+
+        // Ensure registrations are correct.
+        Set<ObjectId> expectedTypes =
+                ModelType.modelTypesToObjectIds(Sets.newHashSet(ModelType.values()));
+        assertEquals(expectedTypes, Sets.newHashSet(getService().mRegistrations.get(0)));
+    }
+
+    @SmallTest
+    @Feature({"Sync"})
+    public void testRegistrationIntentNoProxyTabsAlreadyWithClientId() {
+        getService().setShouldRunStates(true, true);
+        getService().onCreate();
+
+        // Send register Intent with no desired types.
+        Account account = AccountManagerHelper.createAccountFromName("test@example.com");
+        Intent registrationIntent =
+                IntentProtocol.createRegisterIntent(account, false, Sets.<ModelType>newHashSet());
+        getService().onHandleIntent(registrationIntent);
+
+        // Verify client started and state written.
+        assertTrue(InvalidationService.getIsClientStartedForTest());
+        InvalidationPreferences invPrefs = new InvalidationPreferences(getContext());
+        assertEquals(account, invPrefs.getSavedSyncedAccount());
+        assertEquals(Sets.<String>newHashSet(), invPrefs.getSavedSyncedTypes());
+        assertEquals(1, mStartServiceIntents.size());
+        assertTrue(isAndroidListenerStartIntent(mStartServiceIntents.get(0)));
+
+        // Make sure client is ready.
+        getService().ready(CLIENT_ID);
+        assertTrue(Arrays.equals(CLIENT_ID, InvalidationService.getClientIdForTest()));
+
+        // Choose to register for all types in an already ready client.
+        registrationIntent = IntentProtocol.createRegisterIntent(account, true, null);
+        getService().onHandleIntent(registrationIntent);
+
+        // Ensure registrations are correct.
+        assertEquals(1, getService().mRegistrations.size());
+        Set<ObjectId> expectedTypes =
+                ModelType.modelTypesToObjectIds(Sets.newHashSet(ModelType.values()));
+        assertEquals(expectedTypes, Sets.newHashSet(getService().mRegistrations.get(0)));
+    }
+
+    @SmallTest
+    @Feature({"Sync"})
     public void testRegistrationIntentWhenClientShouldNotBeRunning() {
         /*
          * Test plan: send a registration change event when the client should not be running.
diff --git a/sync/protocol/proto_value_conversions.cc b/sync/protocol/proto_value_conversions.cc
index c145269..21db7b2 100644
--- a/sync/protocol/proto_value_conversions.cc
+++ b/sync/protocol/proto_value_conversions.cc
@@ -240,8 +240,36 @@
   return value;
 }
 
-// TODO(petewil): I will need new functions here for the SyncedNotifications
-// subtypes.
+base::DictionaryValue* SimpleCollapsedLayoutToValue(
+    const sync_pb::SimpleCollapsedLayout& proto) {
+  base::DictionaryValue* value = new base::DictionaryValue();
+  SET_STR(heading);
+  SET_STR(description);
+  return value;
+}
+
+base::DictionaryValue* CollapsedInfoToValue(
+    const sync_pb::CollapsedInfo& proto) {
+  base::DictionaryValue* value = new base::DictionaryValue();
+  SET(simple_collapsed_layout, SimpleCollapsedLayoutToValue);
+  return value;
+}
+
+base::DictionaryValue* RenderInfoToValue(
+    const sync_pb::SyncedNotificationRenderInfo& proto) {
+  base::DictionaryValue* value = new base::DictionaryValue();
+  SET(collapsed_info, CollapsedInfoToValue);
+  return value;
+}
+
+base::DictionaryValue* CoalescedNotificationToValue(
+    const sync_pb::CoalescedSyncedNotification& proto) {
+  base::DictionaryValue* value = new base::DictionaryValue();
+  SET_STR(key);
+  SET_INT32(read_state);
+  SET(render_info, RenderInfoToValue);
+  return value;
+}
 
 base::DictionaryValue* AppNotificationToValue(
     const sync_pb::AppNotification& proto) {
@@ -488,8 +516,11 @@
 
 base::DictionaryValue* SyncedNotificationSpecificsToValue(
     const sync_pb::SyncedNotificationSpecifics& proto) {
+  // There is a lot of data, for now just use heading, description, key, and
+  // the read state.
+  // TODO(petewil): Eventually add more data here.
   base::DictionaryValue* value = new base::DictionaryValue();
-  // TODO(petewil): Adjust this once we add actual types in protobuf.
+  SET(coalesced_notification, CoalescedNotificationToValue);
   return value;
 }
 
diff --git a/sync/protocol/proto_value_conversions.h b/sync/protocol/proto_value_conversions.h
index 8bcc26d..39b8e0e 100644
--- a/sync/protocol/proto_value_conversions.h
+++ b/sync/protocol/proto_value_conversions.h
@@ -24,6 +24,8 @@
 class ClientConfigParams;
 class ClientToServerMessage;
 class ClientToServerResponse;
+class CoalescedSyncedNotification;
+class CollapsedInfo;
 class DatatypeAssociationStats;
 class DebugEventInfo;
 class DebugInfo;
@@ -53,7 +55,9 @@
 class SessionSpecifics;
 class SessionTab;
 class SessionWindow;
+class SimpleCollapsedLayout;
 class SyncCycleCompletedEventInfo;
+class SyncedNotificationRenderInfo;
 class SyncedNotificationSpecifics;
 class TabNavigation;
 class ThemeSpecifics;
@@ -120,6 +124,20 @@
 base::DictionaryValue* KeystoreEncryptionToValue(
     const sync_pb::KeystoreEncryptionFlagsSpecifics& proto);
 
+// Sub protocols of SyncedNotifications.
+
+base::DictionaryValue* SimpleCollapsedLayoutToValue(
+    const sync_pb::SimpleCollapsedLayout& proto);
+
+base::DictionaryValue* CollapsedInfoToValue(
+    const sync_pb::CollapsedInfo& proto);
+
+base::DictionaryValue* RenderInfoToValue(
+    const sync_pb::SyncedNotificationRenderInfo& proto);
+
+base::DictionaryValue* CoalescedNotificationToValue(
+    const sync_pb::CoalescedSyncedNotification& proto);
+
 // Main *SpecificsToValue functions.
 
 SYNC_EXPORT_PRIVATE base::DictionaryValue* AppNotificationToValue(
diff --git a/third_party/android_testrunner/run_command.py b/third_party/android_testrunner/run_command.py
index 5c82c61..6b84156 100644
--- a/third_party/android_testrunner/run_command.py
+++ b/third_party/android_testrunner/run_command.py
@@ -22,7 +22,6 @@
 import tempfile
 import threading
 import time
-import sys
 
 # local imports
 import errors
@@ -94,15 +93,12 @@
     stdin_dest = subprocess.PIPE
   else:
     stdin_dest = None
-  stderr_dest = subprocess.STDOUT
-  if os.environ.get('ADB_TRACE'):
-    stderr_dest = sys.stdout
   pipe = subprocess.Popen(
       cmd,
       executable='/bin/bash',
       stdin=stdin_dest,
       stdout=output_dest,
-      stderr=stderr_dest,
+      stderr=subprocess.STDOUT,
       shell=True, close_fds=True,
       preexec_fn=lambda: signal.signal(signal.SIGPIPE, signal.SIG_DFL))
 
diff --git a/third_party/cld/encodings/compact_lang_det/cldutil.cc b/third_party/cld/encodings/compact_lang_det/cldutil.cc
index 06e9e97..9221d70 100644
--- a/third_party/cld/encodings/compact_lang_det/cldutil.cc
+++ b/third_party/cld/encodings/compact_lang_det/cldutil.cc
@@ -815,9 +815,10 @@
   if (lscript == ULScript_Common) {
     // We don't know the script (only happens with second-chance score)
     // Look for first non-zero mean value
-    for (int i = 0; i < 3; ++i) {
+    for (int i = 2; i >= 0; --i) {
       if (kMeanScore[lang * 4 + i] > 0) {
         expected_score = kMeanScore[lang * 4 + i];
+        break;
       }
     }
   }
@@ -843,9 +844,10 @@
   if (lscript == ULScript_Common) {
     // We don't know the script (only happens with second-chance score)
     // Look for first non-zero mean value
-    for (int i = 0; i < 3; ++i) {
+    for (int i = 2; i >= 0; --i) {
       if (kMeanScore[cur_lang * 4 + i] > 0) {
         mean_score = kMeanScore[cur_lang * 4 + i];
+        break;
       }
     }
   }
diff --git a/third_party/libjingle/README.chromium b/third_party/libjingle/README.chromium
index 5443592..45814ea 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: 4490
+Revision: 4520
 License: BSD
 License File: source/talk/COPYING
 Security Critical: yes
diff --git a/third_party/libjingle/libjingle.gyp b/third_party/libjingle/libjingle.gyp
index 37585dc..28e15c9 100644
--- a/third_party/libjingle/libjingle.gyp
+++ b/third_party/libjingle/libjingle.gyp
@@ -687,6 +687,8 @@
             '<(libjingle_source)/talk/app/webrtc/webrtcsdp.h',
             '<(libjingle_source)/talk/app/webrtc/webrtcsession.cc',
             '<(libjingle_source)/talk/app/webrtc/webrtcsession.h',
+            '<(libjingle_source)/talk/app/webrtc/webrtcsessiondescriptionfactory.cc',
+            '<(libjingle_source)/talk/app/webrtc/webrtcsessiondescriptionfactory.h',
             '<(libjingle_source)/talk/media/base/audiorenderer.h',
             '<(libjingle_source)/talk/media/base/capturemanager.cc',
             '<(libjingle_source)/talk/media/base/capturemanager.h',
diff --git a/third_party/mach_override/README.chromium b/third_party/mach_override/README.chromium
index ae82f29..adb7d47 100644
--- a/third_party/mach_override/README.chromium
+++ b/third_party/mach_override/README.chromium
@@ -16,4 +16,6 @@
 implementations at run time.
 
 
-Local Modifications: None
+Local Modifications:
+Ensure no rwx pages remain after mach_override_ptr:
+https://codereview.chromium.org/21208002/ 
diff --git a/third_party/mach_override/mach_override.c b/third_party/mach_override/mach_override.c
index 549409d..ea41569 100644
--- a/third_party/mach_override/mach_override.c
+++ b/third_party/mach_override/mach_override.c
@@ -156,7 +156,7 @@
 	mach_error_t err = err_none;
     uintptr_t page = (uintptr_t)address & ~(uintptr_t)(kPageSize-1);
     int e = err_none;
-    e |= mprotect((void *)page, kPageSize, PROT_EXEC | PROT_READ | PROT_WRITE);
+    e |= mprotect((void *)page, kPageSize, PROT_EXEC | PROT_READ);
     e |= msync((void *)page, kPageSize, MS_INVALIDATE );
     if (e) {
         err = err_cannot_override;
@@ -335,6 +335,12 @@
 #endif
 		if ( !err )
 			atomic_mov64((uint64_t *)originalFunctionPtr, jumpRelativeInstruction);
+
+		mach_error_t prot_err = err_none;	
+		prot_err = vm_protect( mach_task_self(),
+				       (vm_address_t) originalFunctionPtr, 8, false,
+				       (VM_PROT_READ | VM_PROT_EXECUTE) );
+		if (prot_err) fprintf(stderr, "err = %x %s:%d\n", prot_err, __FILE__, __LINE__);    
 	}
 #endif
 	
diff --git a/third_party/protobuf/CHANGES.txt b/third_party/protobuf/CHANGES.txt
index 737f865..a21e956 100644
--- a/third_party/protobuf/CHANGES.txt
+++ b/third_party/protobuf/CHANGES.txt
@@ -1,3 +1,61 @@
+2012-09-19 version 2.5.0:
+
+  General
+  * New notion "import public" that allows a proto file to forward the content
+    it imports to its importers. For example,
+      // foo.proto
+      import public "bar.proto";
+      import "baz.proto";
+
+      // qux.proto
+      import "foo.proto";
+      // Stuff defined in bar.proto may be used in this file, but stuff from
+      // baz.proto may NOT be used without importing it explicitly.
+    This is useful for moving proto files. To move a proto file, just leave
+    a single "import public" in the old proto file.
+  * New enum option "allow_alias" that specifies whether different symbols can
+    be assigned the same numeric value. Default value is "true". Setting it to
+    false causes the compiler to reject enum definitions where multiple symbols
+    have the same numeric value.
+
+  C++
+  * New generated method set_allocated_foo(Type* foo) for message and string
+    fields. This method allows you to set the field to a pre-allocated object
+    and the containing message takes the ownership of that object.
+  * Added SetAllocatedExtension() and ReleaseExtension() to extensions API.
+  * Custom options are now formatted correctly when descriptors are printed in
+    text format.
+  * Various speed optimizations.
+
+  Java
+  * Comments in proto files are now collected and put into generated code as
+    comments for corresponding classes and data members.
+  * Added Parser to parse directly into messages without a Builder. For
+    example,
+      Foo foo = Foo.getParser().ParseFrom(input);
+    Using Parser is ~25% faster than using Builder to parse messages.
+  * Added getters/setters to access the underlying ByteString of a string field
+    directly.
+  * ByteString now supports more operations: substring(), prepend(), and
+    append(). The implementation of ByteString uses a binary tree structure
+    to support these operations efficiently.
+  * New method findInitializationErrors() that lists all missing required
+    fields.
+  * Various code size and speed optimizations.
+
+  Python
+  * Added support for dynamic message creation. DescriptorDatabase,
+    DescriptorPool, and MessageFactory work like their C++ couterparts to
+    simplify Descriptor construction from *DescriptorProtos, and MessageFactory
+    provides a message instance from a Descriptor.
+  * Added pickle support for protobuf messages.
+  * Unknown fields are now preserved after parsing.
+  * Fixed bug where custom options were not correctly populated. Custom
+    options can be accessed now.
+  * Added EnumTypeWrapper that provides better accessibility to enum types.
+  * Added ParseMessage(descriptor, bytes) to generate a new Message instance
+    from a descriptor and a byte string.
+
 2011-05-01 version 2.4.1:
 
   C++
diff --git a/third_party/protobuf/README.chromium b/third_party/protobuf/README.chromium
index e15fcae..c8e411f 100644
--- a/third_party/protobuf/README.chromium
+++ b/third_party/protobuf/README.chromium
@@ -4,7 +4,7 @@
 License: BSD
 License File: COPYING.txt
 Version: unknown
-Revision: r423
+Revision: r428
 Security Critical: yes
 
 Local files (not taken from upstream):
@@ -26,9 +26,7 @@
 targets that depend on it can be componentized. See http://crbug.com/172800 for
 details, and r179806 for the patch.
 
-Revisions r427, r430, r475, r476 and 504 were cherry-picked from upstream.
-Patch from http://code.google.com/p/protobuf/issues/detail?id=425 was
-cherry-picked from upstream.
+Revisions r430, r475, r476 and 504 were 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/java/pom.xml b/third_party/protobuf/java/pom.xml
index e28d6db..7ec6d91 100644
--- a/third_party/protobuf/java/pom.xml
+++ b/third_party/protobuf/java/pom.xml
@@ -102,6 +102,7 @@
                   <arg value="--proto_path=src/test/java" />
                   <arg value="../src/google/protobuf/unittest.proto" />
                   <arg value="../src/google/protobuf/unittest_import.proto" />
+                  <arg value="../src/google/protobuf/unittest_import_public.proto" />
                   <arg value="../src/google/protobuf/unittest_mset.proto" />
                   <arg
                     value="src/test/java/com/google/protobuf/multiple_files_test.proto" />
@@ -117,6 +118,7 @@
                     value="../src/google/protobuf/unittest_custom_options.proto" />
                   <arg value="../src/google/protobuf/unittest_lite.proto" />
                   <arg value="../src/google/protobuf/unittest_import_lite.proto" />
+                  <arg value="../src/google/protobuf/unittest_import_public_lite.proto" />
                   <arg value="../src/google/protobuf/unittest_lite_imports_nonlite.proto" />
                   <arg value="../src/google/protobuf/unittest_enormous_descriptor.proto" />
                   <arg value="../src/google/protobuf/unittest_no_generic_services.proto" />
@@ -158,6 +160,13 @@
                 <include>**/UninitializedMessageException.java</include>
                 <include>**/UnmodifiableLazyStringList.java</include>
                 <include>**/WireFormat.java</include>
+                <include>**/Parser.java</include>
+                <include>**/AbstractParser.java</include>
+                <include>**/BoundedByteString.java</include>
+                <include>**/LiteralByteString.java</include>
+                <include>**/RopeByteString.java</include>
+                <include>**/Utf8.java</include>
+                <include>**/LazyField.java</include>
               </includes>
               <testIncludes>
                 <testInclude>**/LiteTest.java</testInclude>
diff --git a/third_party/protobuf/java/src/main/java/com/google/protobuf/AbstractMessage.java b/third_party/protobuf/java/src/main/java/com/google/protobuf/AbstractMessage.java
index b9d8301..f4d115d 100644
--- a/third_party/protobuf/java/src/main/java/com/google/protobuf/AbstractMessage.java
+++ b/third_party/protobuf/java/src/main/java/com/google/protobuf/AbstractMessage.java
@@ -32,6 +32,7 @@
 
 import com.google.protobuf.Descriptors.Descriptor;
 import com.google.protobuf.Descriptors.FieldDescriptor;
+import com.google.protobuf.GeneratedMessage.ExtendableBuilder;
 import com.google.protobuf.Internal.EnumLite;
 
 import java.io.IOException;
@@ -81,6 +82,25 @@
     return true;
   }
 
+  public List<String> findInitializationErrors() {
+    return Builder.findMissingFields(this);
+  }
+
+  public String getInitializationErrorString() {
+    return delimitWithCommas(findInitializationErrors());
+  }
+
+  private static String delimitWithCommas(List<String> parts) {
+    StringBuilder result = new StringBuilder();
+    for (String part : parts) {
+      if (result.length() > 0) {
+        result.append(", ");
+      }
+      result.append(part);
+    }
+    return result.toString();
+  }
+
   @Override
   public final String toString() {
     return TextFormat.printToString(this);
@@ -209,6 +229,15 @@
   }
 
   /**
+   * Package private helper method for AbstractParser to create
+   * UninitializedMessageException with missing field information.
+   */
+  @Override
+  UninitializedMessageException newUninitializedMessageException() {
+    return Builder.newUninitializedMessageException(this);
+  }
+
+  /**
    * Helper method for implementing {@link Message#hashCode()}.
    * <p>
    * This is needed because {@link java.lang.Enum#hashCode()} is final, but we
@@ -251,6 +280,14 @@
       return (BuilderType) this;
     }
 
+    public List<String> findInitializationErrors() {
+      return findMissingFields(this);
+    }
+
+    public String getInitializationErrorString() {
+      return delimitWithCommas(findInitializationErrors());
+    }
+
     public BuilderType mergeFrom(final Message other) {
       if (other.getDescriptorForType() != getDescriptorForType()) {
         throw new IllegalArgumentException(
@@ -314,7 +351,7 @@
         }
 
         if (!mergeFieldFrom(input, unknownFields, extensionRegistry,
-                            this, tag)) {
+                            getDescriptorForType(), this, null, tag)) {
           // end group tag
           break;
         }
@@ -323,25 +360,93 @@
       return (BuilderType) this;
     }
 
+    /** helper method to handle {@code builder} and {@code extensions}. */
+    private static void addRepeatedField(
+        Message.Builder builder,
+        FieldSet<FieldDescriptor> extensions,
+        FieldDescriptor field,
+        Object value) {
+      if (builder != null) {
+        builder.addRepeatedField(field, value);
+      } else {
+        extensions.addRepeatedField(field, value);
+      }
+    }
+
+    /** helper method to handle {@code builder} and {@code extensions}. */
+    private static void setField(
+        Message.Builder builder,
+        FieldSet<FieldDescriptor> extensions,
+        FieldDescriptor field,
+        Object value) {
+      if (builder != null) {
+        builder.setField(field, value);
+      } else {
+        extensions.setField(field, value);
+      }
+    }
+
+    /** helper method to handle {@code builder} and {@code extensions}. */
+    private static boolean hasOriginalMessage(
+        Message.Builder builder,
+        FieldSet<FieldDescriptor> extensions,
+        FieldDescriptor field) {
+      if (builder != null) {
+        return builder.hasField(field);
+      } else {
+        return extensions.hasField(field);
+      }
+    }
+
+    /** helper method to handle {@code builder} and {@code extensions}. */
+    private static Message getOriginalMessage(
+        Message.Builder builder,
+        FieldSet<FieldDescriptor> extensions,
+        FieldDescriptor field) {
+      if (builder != null) {
+        return (Message) builder.getField(field);
+      } else {
+        return (Message) extensions.getField(field);
+      }
+    }
+
+    /** helper method to handle {@code builder} and {@code extensions}. */
+    private static void mergeOriginalMessage(
+        Message.Builder builder,
+        FieldSet<FieldDescriptor> extensions,
+        FieldDescriptor field,
+        Message.Builder subBuilder) {
+      Message originalMessage = getOriginalMessage(builder, extensions, field);
+      if (originalMessage != null) {
+        subBuilder.mergeFrom(originalMessage);
+      }
+    }
+
     /**
-     * Like {@link #mergeFrom(CodedInputStream, UnknownFieldSet.Builder,
-     * ExtensionRegistryLite, Message.Builder)}, but parses a single field.
+     * Like {@link #mergeFrom(CodedInputStream, ExtensionRegistryLite)}, but
+     * parses a single field.
+     *
+     * When {@code builder} is not null, the method will parse and merge the
+     * field into {@code builder}. Otherwise, it will try to parse the field
+     * into {@code extensions}, when it's called by the parsing constructor in
+     * generated classes.
+     *
      * Package-private because it is used by GeneratedMessage.ExtendableMessage.
      * @param tag The tag, which should have already been read.
      * @return {@code true} unless the tag is an end-group tag.
      */
     static boolean mergeFieldFrom(
-        final CodedInputStream input,
-        final UnknownFieldSet.Builder unknownFields,
-        final ExtensionRegistryLite extensionRegistry,
-        final Message.Builder builder,
-        final int tag) throws IOException {
-      final Descriptor type = builder.getDescriptorForType();
-
+        CodedInputStream input,
+        UnknownFieldSet.Builder unknownFields,
+        ExtensionRegistryLite extensionRegistry,
+        Descriptor type,
+        Message.Builder builder,
+        FieldSet<FieldDescriptor> extensions,
+        int tag) throws IOException {
       if (type.getOptions().getMessageSetWireFormat() &&
           tag == WireFormat.MESSAGE_SET_ITEM_TAG) {
         mergeMessageSetExtensionFromCodedStream(
-          input, unknownFields, extensionRegistry, builder);
+            input, unknownFields, extensionRegistry, type, builder, extensions);
         return true;
       }
 
@@ -376,8 +481,10 @@
         } else {
           field = null;
         }
-      } else {
+      } else if (builder != null) {
         field = type.findFieldByNumber(fieldNumber);
+      } else {
+        field = null;
       }
 
       boolean unknown = false;
@@ -413,13 +520,13 @@
               // enum, drop it (don't even add it to unknownFields).
               return true;
             }
-            builder.addRepeatedField(field, value);
+            addRepeatedField(builder, extensions, field, value);
           }
         } else {
           while (input.getBytesUntilLimit() > 0) {
             final Object value =
               FieldSet.readPrimitiveField(input, field.getLiteType());
-            builder.addRepeatedField(field, value);
+            addRepeatedField(builder, extensions, field, value);
           }
         }
         input.popLimit(limit);
@@ -434,10 +541,10 @@
               subBuilder = builder.newBuilderForField(field);
             }
             if (!field.isRepeated()) {
-              subBuilder.mergeFrom((Message) builder.getField(field));
+              mergeOriginalMessage(builder, extensions, field, subBuilder);
             }
             input.readGroup(field.getNumber(), subBuilder, extensionRegistry);
-            value = subBuilder.build();
+            value = subBuilder.buildPartial();
             break;
           }
           case MESSAGE: {
@@ -448,10 +555,10 @@
               subBuilder = builder.newBuilderForField(field);
             }
             if (!field.isRepeated()) {
-              subBuilder.mergeFrom((Message) builder.getField(field));
+              mergeOriginalMessage(builder, extensions, field, subBuilder);
             }
             input.readMessage(subBuilder, extensionRegistry);
-            value = subBuilder.build();
+            value = subBuilder.buildPartial();
             break;
           }
           case ENUM:
@@ -470,22 +577,28 @@
         }
 
         if (field.isRepeated()) {
-          builder.addRepeatedField(field, value);
+          addRepeatedField(builder, extensions, field, value);
         } else {
-          builder.setField(field, value);
+          setField(builder, extensions, field, value);
         }
       }
 
       return true;
     }
 
-    /** Called by {@code #mergeFieldFrom()} to parse a MessageSet extension. */
+    /**
+     * Called by {@code #mergeFieldFrom()} to parse a MessageSet extension.
+     * If {@code builder} is not null, this method will merge MessageSet into
+     * the builder.  Otherwise, it will merge the MessageSet into {@code
+     * extensions}.
+     */
     private static void mergeMessageSetExtensionFromCodedStream(
-        final CodedInputStream input,
-        final UnknownFieldSet.Builder unknownFields,
-        final ExtensionRegistryLite extensionRegistry,
-        final Message.Builder builder) throws IOException {
-      final Descriptor type = builder.getDescriptorForType();
+        CodedInputStream input,
+        UnknownFieldSet.Builder unknownFields,
+        ExtensionRegistryLite extensionRegistry,
+        Descriptor type,
+        Message.Builder builder,
+        FieldSet<FieldDescriptor> extensions) throws IOException {
 
       // The wire format for MessageSet is:
       //   message MessageSet {
@@ -504,10 +617,11 @@
       // should be prepared to accept them.
 
       int typeId = 0;
-      ByteString rawBytes = null;  // If we encounter "message" before "typeId"
-      Message.Builder subBuilder = null;
-      FieldDescriptor field = null;
+      ByteString rawBytes = null; // If we encounter "message" before "typeId"
+      ExtensionRegistry.ExtensionInfo extension = null;
 
+      // Read bytes from input, if we get it's type first then parse it eagerly,
+      // otherwise we store the raw bytes in a local variable.
       while (true) {
         final int tag = input.readTag();
         if (tag == 0) {
@@ -516,75 +630,121 @@
 
         if (tag == WireFormat.MESSAGE_SET_TYPE_ID_TAG) {
           typeId = input.readUInt32();
-          // Zero is not a valid type ID.
           if (typeId != 0) {
-            final ExtensionRegistry.ExtensionInfo extension;
-
             // extensionRegistry may be either ExtensionRegistry or
-            // ExtensionRegistryLite.  Since the type we are parsing is a full
+            // ExtensionRegistryLite. Since the type we are parsing is a full
             // message, only a full ExtensionRegistry could possibly contain
-            // extensions of it.  Otherwise we will treat the registry as if it
+            // extensions of it. Otherwise we will treat the registry as if it
             // were empty.
             if (extensionRegistry instanceof ExtensionRegistry) {
               extension = ((ExtensionRegistry) extensionRegistry)
                   .findExtensionByNumber(type, typeId);
-            } else {
-              extension = null;
             }
+          }
 
-            if (extension != null) {
-              field = extension.descriptor;
-              subBuilder = extension.defaultInstance.newBuilderForType();
-              final Message originalMessage = (Message)builder.getField(field);
-              if (originalMessage != null) {
-                subBuilder.mergeFrom(originalMessage);
-              }
-              if (rawBytes != null) {
-                // We already encountered the message.  Parse it now.
-                subBuilder.mergeFrom(
-                  CodedInputStream.newInstance(rawBytes.newInput()));
-                rawBytes = null;
-              }
-            } else {
-              // Unknown extension number.  If we already saw data, put it
-              // in rawBytes.
-              if (rawBytes != null) {
-                unknownFields.mergeField(typeId,
-                  UnknownFieldSet.Field.newBuilder()
-                    .addLengthDelimited(rawBytes)
-                    .build());
-                rawBytes = null;
-              }
+        } else if (tag == WireFormat.MESSAGE_SET_MESSAGE_TAG) {
+          if (typeId != 0) {
+            if (extension != null && ExtensionRegistryLite.isEagerlyParseMessageSets()) {
+              // We already know the type, so we can parse directly from the
+              // input with no copying.  Hooray!
+              eagerlyMergeMessageSetExtension(
+                  input, extension, extensionRegistry, builder, extensions);
+              rawBytes = null;
+              continue;
             }
           }
-        } else if (tag == WireFormat.MESSAGE_SET_MESSAGE_TAG) {
-          if (typeId == 0) {
-            // We haven't seen a type ID yet, so we have to store the raw bytes
-            // for now.
-            rawBytes = input.readBytes();
-          } else if (subBuilder == null) {
-            // We don't know how to parse this.  Ignore it.
-            unknownFields.mergeField(typeId,
-              UnknownFieldSet.Field.newBuilder()
-                .addLengthDelimited(input.readBytes())
-                .build());
-          } else {
-            // We already know the type, so we can parse directly from the input
-            // with no copying.  Hooray!
-            input.readMessage(subBuilder, extensionRegistry);
-          }
-        } else {
-          // Unknown tag.  Skip it.
+          // We haven't seen a type ID yet or we want parse message lazily.
+          rawBytes = input.readBytes();
+
+        } else { // Unknown tag. Skip it.
           if (!input.skipField(tag)) {
-            break;  // end of group
+            break; // End of group
           }
         }
       }
-
       input.checkLastTagWas(WireFormat.MESSAGE_SET_ITEM_END_TAG);
 
-      if (subBuilder != null) {
-        builder.setField(field, subBuilder.build());
+      // Process the raw bytes.
+      if (rawBytes != null && typeId != 0) { // Zero is not a valid type ID.
+        if (extension != null) { // We known the type
+          mergeMessageSetExtensionFromBytes(
+              rawBytes, extension, extensionRegistry, builder, extensions);
+        } else { // We don't know how to parse this. Ignore it.
+          if (rawBytes != null) {
+            unknownFields.mergeField(typeId, UnknownFieldSet.Field.newBuilder()
+                .addLengthDelimited(rawBytes).build());
+          }
+        }
+      }
+    }
+
+    private static void eagerlyMergeMessageSetExtension(
+        CodedInputStream input,
+        ExtensionRegistry.ExtensionInfo extension,
+        ExtensionRegistryLite extensionRegistry,
+        Message.Builder builder,
+        FieldSet<FieldDescriptor> extensions) throws IOException {
+
+      FieldDescriptor field = extension.descriptor;
+      Message value = null;
+      if (hasOriginalMessage(builder, extensions, field)) {
+        Message originalMessage =
+            getOriginalMessage(builder, extensions, field);
+        Message.Builder subBuilder = originalMessage.toBuilder();
+        input.readMessage(subBuilder, extensionRegistry);
+        value = subBuilder.buildPartial();
+      } else {
+        value = input.readMessage(extension.defaultInstance.getParserForType(),
+          extensionRegistry);
+      }
+
+      if (builder != null) {
+        builder.setField(field, value);
+      } else {
+        extensions.setField(field, value);
+      }
+    }
+
+    private static void mergeMessageSetExtensionFromBytes(
+        ByteString rawBytes,
+        ExtensionRegistry.ExtensionInfo extension,
+        ExtensionRegistryLite extensionRegistry,
+        Message.Builder builder,
+        FieldSet<FieldDescriptor> extensions) throws IOException {
+
+      FieldDescriptor field = extension.descriptor;
+      boolean hasOriginalValue = hasOriginalMessage(builder, extensions, field);
+
+      if (hasOriginalValue || ExtensionRegistryLite.isEagerlyParseMessageSets()) {
+        // If the field already exists, we just parse the field.
+        Message value = null;
+        if (hasOriginalValue) {
+          Message originalMessage =
+              getOriginalMessage(builder, extensions, field);
+          Message.Builder subBuilder= originalMessage.toBuilder();
+          subBuilder.mergeFrom(rawBytes, extensionRegistry);
+          value = subBuilder.buildPartial();
+        } else {
+          value = extension.defaultInstance.getParserForType()
+              .parsePartialFrom(rawBytes, extensionRegistry);
+        }
+        setField(builder, extensions, field, value);
+      } else {
+        // Use LazyField to load MessageSet lazily.
+        LazyField lazyField = new LazyField(
+            extension.defaultInstance, extensionRegistry, rawBytes);
+        if (builder != null) {
+          // TODO(xiangl): it looks like this method can only be invoked by
+          // ExtendableBuilder, but I'm not sure. So I double check the type of
+          // builder here. It may be useless and need more investigation.
+          if (builder instanceof ExtendableBuilder) {
+            builder.setField(field, lazyField);
+          } else {
+            builder.setField(field, lazyField.getValue());
+          }
+        } else {
+          extensions.setField(field, lazyField);
+        }
       }
     }
 
@@ -596,6 +756,11 @@
       return (BuilderType) this;
     }
 
+    public Message.Builder getFieldBuilder(final FieldDescriptor field) {
+      throw new UnsupportedOperationException(
+          "getFieldBuilder() called on an unsupported message type.");
+    }
+
     /**
      * Construct an UninitializedMessageException reporting missing fields in
      * the given message.
@@ -609,14 +774,15 @@
      * Populates {@code this.missingFields} with the full "path" of each
      * missing required field in the given message.
      */
-    private static List<String> findMissingFields(final Message message) {
+    private static List<String> findMissingFields(
+        final MessageOrBuilder message) {
       final List<String> results = new ArrayList<String>();
       findMissingFields(message, "", results);
       return results;
     }
 
     /** Recursive helper implementing {@link #findMissingFields(Message)}. */
-    private static void findMissingFields(final Message message,
+    private static void findMissingFields(final MessageOrBuilder message,
                                           final String prefix,
                                           final List<String> results) {
       for (final FieldDescriptor field :
@@ -635,13 +801,13 @@
           if (field.isRepeated()) {
             int i = 0;
             for (final Object element : (List) value) {
-              findMissingFields((Message) element,
+              findMissingFields((MessageOrBuilder) element,
                                 subMessagePrefix(prefix, field, i++),
                                 results);
             }
           } else {
             if (message.hasField(field)) {
-              findMissingFields((Message) value,
+              findMissingFields((MessageOrBuilder) value,
                                 subMessagePrefix(prefix, field, -1),
                                 results);
             }
diff --git a/third_party/protobuf/java/src/main/java/com/google/protobuf/AbstractMessageLite.java b/third_party/protobuf/java/src/main/java/com/google/protobuf/AbstractMessageLite.java
index 77b2737..9926f3d 100644
--- a/third_party/protobuf/java/src/main/java/com/google/protobuf/AbstractMessageLite.java
+++ b/third_party/protobuf/java/src/main/java/com/google/protobuf/AbstractMessageLite.java
@@ -92,6 +92,14 @@
   }
 
   /**
+   * Package private helper method for AbstractParser to create
+   * UninitializedMessageException.
+   */
+  UninitializedMessageException newUninitializedMessageException() {
+    return new UninitializedMessageException(this);
+  }
+
+  /**
    * A partial implementation of the {@link Message.Builder} interface which
    * implements as many methods of that interface as possible in terms of
    * other methods.
@@ -307,10 +315,12 @@
      */
     protected static <T> void addAll(final Iterable<T> values,
                                      final Collection<? super T> list) {
-      for (final T value : values) {
-        if (value == null) {
-          throw new NullPointerException();
-        }
+      if (values instanceof LazyStringList) {
+        // For StringOrByteStringLists, check the underlying elements to avoid
+        // forcing conversions of ByteStrings to Strings.
+        checkForNullValues(((LazyStringList) values).getUnderlyingElements());
+      } else {
+        checkForNullValues(values);
       }
       if (values instanceof Collection) {
         final Collection<T> collection = (Collection<T>) values;
@@ -321,5 +331,13 @@
         }
       }
     }
+
+    private static void checkForNullValues(final Iterable<?> values) {
+      for (final Object value : values) {
+        if (value == null) {
+          throw new NullPointerException();
+        }
+      }
+    }
   }
 }
diff --git a/third_party/protobuf/java/src/main/java/com/google/protobuf/AbstractParser.java b/third_party/protobuf/java/src/main/java/com/google/protobuf/AbstractParser.java
new file mode 100644
index 0000000..9bd9d39
--- /dev/null
+++ b/third_party/protobuf/java/src/main/java/com/google/protobuf/AbstractParser.java
@@ -0,0 +1,261 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 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.
+
+package com.google.protobuf;
+
+import com.google.protobuf.AbstractMessageLite.Builder.LimitedInputStream;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+/**
+ * A partial implementation of the {@link Parser} interface which implements
+ * as many methods of that interface as possible in terms of other methods.
+ *
+ * Note: This class implements all the convenience methods in the
+ * {@link Parser} interface. See {@link Parser} for related javadocs.
+ * Subclasses need to implement
+ * {@link Parser#parsePartialFrom(CodedInputStream, ExtensionRegistryLite)}
+ *
+ * @author liujisi@google.com (Pherl Liu)
+ */
+public abstract class AbstractParser<MessageType extends MessageLite>
+    implements Parser<MessageType> {
+  /**
+   * Creates an UninitializedMessageException for MessageType.
+   */
+  private UninitializedMessageException
+      newUninitializedMessageException(MessageType message) {
+    if (message instanceof AbstractMessageLite) {
+      return ((AbstractMessageLite) message).newUninitializedMessageException();
+    }
+    return new UninitializedMessageException(message);
+  }
+
+  /**
+   * Helper method to check if message is initialized.
+   *
+   * @throws InvalidProtocolBufferException if it is not initialized.
+   * @return The message to check.
+   */
+  private MessageType checkMessageInitialized(MessageType message)
+      throws InvalidProtocolBufferException {
+    if (message != null && !message.isInitialized()) {
+      throw newUninitializedMessageException(message)
+          .asInvalidProtocolBufferException()
+          .setUnfinishedMessage(message);
+    }
+    return message;
+  }
+
+  private static final ExtensionRegistryLite EMPTY_REGISTRY
+      = ExtensionRegistryLite.getEmptyRegistry();
+
+  public MessageType parsePartialFrom(CodedInputStream input)
+      throws InvalidProtocolBufferException {
+    return parsePartialFrom(input, EMPTY_REGISTRY);
+  }
+
+  public MessageType parseFrom(CodedInputStream input,
+                               ExtensionRegistryLite extensionRegistry)
+      throws InvalidProtocolBufferException {
+    return checkMessageInitialized(
+        parsePartialFrom(input, extensionRegistry));
+  }
+
+  public MessageType parseFrom(CodedInputStream input)
+      throws InvalidProtocolBufferException {
+    return parseFrom(input, EMPTY_REGISTRY);
+  }
+
+  public MessageType parsePartialFrom(ByteString data,
+                                      ExtensionRegistryLite extensionRegistry)
+    throws InvalidProtocolBufferException {
+    MessageType message;
+    try {
+      CodedInputStream input = data.newCodedInput();
+      message = parsePartialFrom(input, extensionRegistry);
+      try {
+        input.checkLastTagWas(0);
+      } catch (InvalidProtocolBufferException e) {
+        throw e.setUnfinishedMessage(message);
+      }
+      return message;
+    } catch (InvalidProtocolBufferException e) {
+      throw e;
+    } catch (IOException e) {
+      throw new RuntimeException(
+          "Reading from a ByteString threw an IOException (should " +
+          "never happen).", e);
+    }
+  }
+
+  public MessageType parsePartialFrom(ByteString data)
+      throws InvalidProtocolBufferException {
+    return parsePartialFrom(data, EMPTY_REGISTRY);
+  }
+
+  public MessageType parseFrom(ByteString data,
+                               ExtensionRegistryLite extensionRegistry)
+      throws InvalidProtocolBufferException {
+    return checkMessageInitialized(parsePartialFrom(data, extensionRegistry));
+  }
+
+  public MessageType parseFrom(ByteString data)
+      throws InvalidProtocolBufferException {
+    return parseFrom(data, EMPTY_REGISTRY);
+  }
+
+  public MessageType parsePartialFrom(byte[] data, int off, int len,
+                                      ExtensionRegistryLite extensionRegistry)
+      throws InvalidProtocolBufferException {
+    try {
+      CodedInputStream input = CodedInputStream.newInstance(data, off, len);
+      MessageType message = parsePartialFrom(input, extensionRegistry);
+      try {
+        input.checkLastTagWas(0);
+      } catch (InvalidProtocolBufferException e) {
+        throw e.setUnfinishedMessage(message);
+      }
+      return message;
+    } catch (InvalidProtocolBufferException e) {
+      throw e;
+    } catch (IOException e) {
+      throw new RuntimeException(
+          "Reading from a byte array threw an IOException (should " +
+          "never happen).", e);
+    }
+  }
+
+  public MessageType parsePartialFrom(byte[] data, int off, int len)
+      throws InvalidProtocolBufferException {
+    return parsePartialFrom(data, off, len, EMPTY_REGISTRY);
+  }
+
+  public MessageType parsePartialFrom(byte[] data,
+                                      ExtensionRegistryLite extensionRegistry)
+      throws InvalidProtocolBufferException {
+    return parsePartialFrom(data, 0, data.length, extensionRegistry);
+  }
+
+  public MessageType parsePartialFrom(byte[] data)
+      throws InvalidProtocolBufferException {
+    return parsePartialFrom(data, 0, data.length, EMPTY_REGISTRY);
+  }
+
+  public MessageType parseFrom(byte[] data, int off, int len,
+                               ExtensionRegistryLite extensionRegistry)
+      throws InvalidProtocolBufferException {
+    return checkMessageInitialized(
+        parsePartialFrom(data, off, len, extensionRegistry));
+  }
+
+  public MessageType parseFrom(byte[] data, int off, int len)
+      throws InvalidProtocolBufferException {
+    return parseFrom(data, off, len, EMPTY_REGISTRY);
+  }
+
+  public MessageType parseFrom(byte[] data,
+                               ExtensionRegistryLite extensionRegistry)
+      throws InvalidProtocolBufferException {
+    return parseFrom(data, 0, data.length, extensionRegistry);
+  }
+
+  public MessageType parseFrom(byte[] data)
+      throws InvalidProtocolBufferException {
+    return parseFrom(data, EMPTY_REGISTRY);
+  }
+
+  public MessageType parsePartialFrom(InputStream input,
+                                      ExtensionRegistryLite extensionRegistry)
+      throws InvalidProtocolBufferException {
+    CodedInputStream codedInput = CodedInputStream.newInstance(input);
+    MessageType message = parsePartialFrom(codedInput, extensionRegistry);
+    try {
+      codedInput.checkLastTagWas(0);
+    } catch (InvalidProtocolBufferException e) {
+      throw e.setUnfinishedMessage(message);
+    }
+    return message;
+  }
+
+  public MessageType parsePartialFrom(InputStream input)
+      throws InvalidProtocolBufferException {
+    return parsePartialFrom(input, EMPTY_REGISTRY);
+  }
+
+  public MessageType parseFrom(InputStream input,
+                               ExtensionRegistryLite extensionRegistry)
+      throws InvalidProtocolBufferException {
+    return checkMessageInitialized(
+        parsePartialFrom(input, extensionRegistry));
+  }
+
+  public MessageType parseFrom(InputStream input)
+      throws InvalidProtocolBufferException {
+    return parseFrom(input, EMPTY_REGISTRY);
+  }
+
+  public MessageType parsePartialDelimitedFrom(
+      InputStream input,
+      ExtensionRegistryLite extensionRegistry)
+      throws InvalidProtocolBufferException {
+    int size;
+    try {
+      int firstByte = input.read();
+      if (firstByte == -1) {
+        return null;
+      }
+      size = CodedInputStream.readRawVarint32(firstByte, input);
+    } catch (IOException e) {
+      throw new InvalidProtocolBufferException(e.getMessage());
+    }
+    InputStream limitedInput = new LimitedInputStream(input, size);
+    return parsePartialFrom(limitedInput, extensionRegistry);
+  }
+
+  public MessageType parsePartialDelimitedFrom(InputStream input)
+      throws InvalidProtocolBufferException {
+    return parsePartialDelimitedFrom(input, EMPTY_REGISTRY);
+  }
+
+  public MessageType parseDelimitedFrom(
+      InputStream input,
+      ExtensionRegistryLite extensionRegistry)
+      throws InvalidProtocolBufferException {
+    return checkMessageInitialized(
+        parsePartialDelimitedFrom(input, extensionRegistry));
+  }
+
+  public MessageType parseDelimitedFrom(InputStream input)
+      throws InvalidProtocolBufferException {
+    return parseDelimitedFrom(input, EMPTY_REGISTRY);
+  }
+}
diff --git a/third_party/protobuf/java/src/main/java/com/google/protobuf/BoundedByteString.java b/third_party/protobuf/java/src/main/java/com/google/protobuf/BoundedByteString.java
new file mode 100644
index 0000000..cd4982c
--- /dev/null
+++ b/third_party/protobuf/java/src/main/java/com/google/protobuf/BoundedByteString.java
@@ -0,0 +1,163 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 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.
+
+package com.google.protobuf;
+
+import java.util.NoSuchElementException;
+
+/**
+ * This class is used to represent the substring of a {@link ByteString} over a
+ * single byte array. In terms of the public API of {@link ByteString}, you end
+ * up here by calling {@link ByteString#copyFrom(byte[])} followed by {@link
+ * ByteString#substring(int, int)}.
+ *
+ * <p>This class contains most of the overhead involved in creating a substring
+ * from a {@link LiteralByteString}.  The overhead involves some range-checking
+ * and two extra fields.
+ *
+ * @author carlanton@google.com (Carl Haverl)
+ */
+class BoundedByteString extends LiteralByteString {
+
+  private final int bytesOffset;
+  private final int bytesLength;
+
+  /**
+   * Creates a {@code BoundedByteString} backed by the sub-range of given array,
+   * without copying.
+   *
+   * @param bytes  array to wrap
+   * @param offset index to first byte to use in bytes
+   * @param length number of bytes to use from bytes
+   * @throws IllegalArgumentException if {@code offset < 0}, {@code length < 0},
+   *                                  or if {@code offset + length >
+   *                                  bytes.length}.
+   */
+  BoundedByteString(byte[] bytes, int offset, int length) {
+    super(bytes);
+    if (offset < 0) {
+      throw new IllegalArgumentException("Offset too small: " + offset);
+    }
+    if (length < 0) {
+      throw new IllegalArgumentException("Length too small: " + offset);
+    }
+    if ((long) offset + length > bytes.length) {
+      throw new IllegalArgumentException(
+          "Offset+Length too large: " + offset + "+" + length);
+    }
+
+    this.bytesOffset = offset;
+    this.bytesLength = length;
+  }
+
+  /**
+   * Gets the byte at the given index.
+   * Throws {@link ArrayIndexOutOfBoundsException}
+   * for backwards-compatibility reasons although it would more properly be
+   * {@link IndexOutOfBoundsException}.
+   *
+   * @param index index of byte
+   * @return the value
+   * @throws ArrayIndexOutOfBoundsException {@code index} is < 0 or >= size
+   */
+  @Override
+  public byte byteAt(int index) {
+    // We must check the index ourselves as we cannot rely on Java array index
+    // checking for substrings.
+    if (index < 0) {
+      throw new ArrayIndexOutOfBoundsException("Index too small: " + index);
+    }
+    if (index >= size()) {
+      throw new ArrayIndexOutOfBoundsException(
+          "Index too large: " + index + ", " + size());
+    }
+
+    return bytes[bytesOffset + index];
+  }
+
+  @Override
+  public int size() {
+    return bytesLength;
+  }
+
+  @Override
+  protected int getOffsetIntoBytes() {
+    return bytesOffset;
+  }
+
+  // =================================================================
+  // ByteString -> byte[]
+
+  @Override
+  protected void copyToInternal(byte[] target, int sourceOffset, 
+      int targetOffset, int numberToCopy) {
+    System.arraycopy(bytes, getOffsetIntoBytes() + sourceOffset, target,
+        targetOffset, numberToCopy);
+  }
+
+  // =================================================================
+  // ByteIterator
+
+  @Override
+  public ByteIterator iterator() {
+    return new BoundedByteIterator();
+  }
+
+  private class BoundedByteIterator implements ByteIterator {
+
+    private int position;
+    private final int limit;
+
+    private BoundedByteIterator() {
+      position = getOffsetIntoBytes();
+      limit = position + size();
+    }
+
+    public boolean hasNext() {
+      return (position < limit);
+    }
+
+    public Byte next() {
+      // Boxing calls Byte.valueOf(byte), which does not instantiate.
+      return nextByte();
+    }
+
+    public byte nextByte() {
+      if (position >= limit) {
+        throw new NoSuchElementException();
+      }
+      return bytes[position++];
+    }
+
+    public void remove() {
+      throw new UnsupportedOperationException();
+    }
+  }
+}
diff --git a/third_party/protobuf/java/src/main/java/com/google/protobuf/ByteString.java b/third_party/protobuf/java/src/main/java/com/google/protobuf/ByteString.java
index 9135635..1b18169 100644
--- a/third_party/protobuf/java/src/main/java/com/google/protobuf/ByteString.java
+++ b/third_party/protobuf/java/src/main/java/com/google/protobuf/ByteString.java
@@ -30,140 +30,413 @@
 
 package com.google.protobuf;
 
-import java.io.InputStream;
-import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
-import java.io.FilterOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
 import java.io.UnsupportedEncodingException;
 import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Iterator;
 import java.util.List;
+import java.util.NoSuchElementException;
 
 /**
- * Immutable array of bytes.
+ * Immutable sequence of bytes.  Substring is supported by sharing the reference
+ * to the immutable underlying bytes, as with {@link String}.  Concatenation is
+ * likewise supported without copying (long strings) by building a tree of
+ * pieces in {@link RopeByteString}.
+ * <p>
+ * Like {@link String}, the contents of a {@link ByteString} can never be
+ * observed to change, not even in the presence of a data race or incorrect
+ * API usage in the client code.
  *
  * @author crazybob@google.com Bob Lee
  * @author kenton@google.com Kenton Varda
+ * @author carlanton@google.com Carl Haverl
+ * @author martinrb@google.com Martin Buchholz
  */
-public final class ByteString {
-  private final byte[] bytes;
-
-  private ByteString(final byte[] bytes) {
-    this.bytes = bytes;
-  }
+public abstract class ByteString implements Iterable<Byte> {
 
   /**
-   * Gets the byte at the given index.
+   * When two strings to be concatenated have a combined length shorter than
+   * this, we just copy their bytes on {@link #concat(ByteString)}.
+   * The trade-off is copy size versus the overhead of creating tree nodes
+   * in {@link RopeByteString}.
+   */
+  static final int CONCATENATE_BY_COPY_SIZE = 128;
+
+  /**
+   * When copying an InputStream into a ByteString with .readFrom(),
+   * the chunks in the underlying rope start at 256 bytes, but double
+   * each iteration up to 8192 bytes.
+   */
+  static final int MIN_READ_FROM_CHUNK_SIZE = 0x100;  // 256b
+  static final int MAX_READ_FROM_CHUNK_SIZE = 0x2000;  // 8k
+
+  /**
+   * Empty {@code ByteString}.
+   */
+  public static final ByteString EMPTY = new LiteralByteString(new byte[0]);
+
+  // This constructor is here to prevent subclassing outside of this package,
+  ByteString() {}
+
+  /**
+   * Gets the byte at the given index. This method should be used only for
+   * random access to individual bytes. To access bytes sequentially, use the
+   * {@link ByteIterator} returned by {@link #iterator()}, and call {@link
+   * #substring(int, int)} first if necessary.
    *
+   * @param index index of byte
+   * @return the value
    * @throws ArrayIndexOutOfBoundsException {@code index} is < 0 or >= size
    */
-  public byte byteAt(final int index) {
-    return bytes[index];
+  public abstract byte byteAt(int index);
+
+  /**
+   * Return a {@link ByteString.ByteIterator} over the bytes in the ByteString.
+   * To avoid auto-boxing, you may get the iterator manually and call
+   * {@link ByteIterator#nextByte()}.
+   *
+   * @return the iterator
+   */
+  public abstract ByteIterator iterator();
+
+  /**
+   * This interface extends {@code Iterator<Byte>}, so that we can return an
+   * unboxed {@code byte}.
+   */
+  public interface ByteIterator extends Iterator<Byte> {
+    /**
+     * An alternative to {@link Iterator#next()} that returns an
+     * unboxed primitive {@code byte}.
+     *
+     * @return the next {@code byte} in the iteration
+     * @throws NoSuchElementException if the iteration has no more elements
+     */
+    byte nextByte();
   }
 
   /**
    * Gets the number of bytes.
+   *
+   * @return size in bytes
    */
-  public int size() {
-    return bytes.length;
-  }
+  public abstract int size();
 
   /**
    * Returns {@code true} if the size is {@code 0}, {@code false} otherwise.
+   *
+   * @return true if this is zero bytes long
    */
   public boolean isEmpty() {
-    return bytes.length == 0;
+    return size() == 0;
+  }
+
+  // =================================================================
+  // ByteString -> substring
+
+  /**
+   * Return the substring from {@code beginIndex}, inclusive, to the end of the
+   * string.
+   *
+   * @param beginIndex start at this index
+   * @return substring sharing underlying data
+   * @throws IndexOutOfBoundsException if {@code beginIndex < 0} or
+   *     {@code beginIndex > size()}.
+   */
+  public ByteString substring(int beginIndex) {
+    return substring(beginIndex, size());
+  }
+
+  /**
+   * Return the substring from {@code beginIndex}, inclusive, to {@code
+   * endIndex}, exclusive.
+   *
+   * @param beginIndex start at this index
+   * @param endIndex   the last character is the one before this index
+   * @return substring sharing underlying data
+   * @throws IndexOutOfBoundsException if {@code beginIndex < 0},
+   *     {@code endIndex > size()}, or {@code beginIndex > endIndex}.
+   */
+  public abstract ByteString substring(int beginIndex, int endIndex);
+
+  /**
+   * Tests if this bytestring starts with the specified prefix.
+   * Similar to {@link String#startsWith(String)}
+   *
+   * @param prefix the prefix.
+   * @return <code>true</code> if the byte sequence represented by the
+   *         argument is a prefix of the byte sequence represented by
+   *         this string; <code>false</code> otherwise.
+   */
+  public boolean startsWith(ByteString prefix) {
+    return size() >= prefix.size() &&
+           substring(0, prefix.size()).equals(prefix);
   }
 
   // =================================================================
   // byte[] -> ByteString
 
   /**
-   * Empty ByteString.
-   */
-  public static final ByteString EMPTY = new ByteString(new byte[0]);
-
-  /**
    * Copies the given bytes into a {@code ByteString}.
+   *
+   * @param bytes source array
+   * @param offset offset in source array
+   * @param size number of bytes to copy
+   * @return new {@code ByteString}
    */
-  public static ByteString copyFrom(final byte[] bytes, final int offset,
-                                    final int size) {
-    final byte[] copy = new byte[size];
+  public static ByteString copyFrom(byte[] bytes, int offset, int size) {
+    byte[] copy = new byte[size];
     System.arraycopy(bytes, offset, copy, 0, size);
-    return new ByteString(copy);
+    return new LiteralByteString(copy);
   }
 
   /**
    * Copies the given bytes into a {@code ByteString}.
+   *
+   * @param bytes to copy
+   * @return new {@code ByteString}
    */
-  public static ByteString copyFrom(final byte[] bytes) {
+  public static ByteString copyFrom(byte[] bytes) {
     return copyFrom(bytes, 0, bytes.length);
   }
 
   /**
-   * Copies {@code size} bytes from a {@code java.nio.ByteBuffer} into
+   * Copies the next {@code size} bytes from a {@code java.nio.ByteBuffer} into
    * a {@code ByteString}.
+   *
+   * @param bytes source buffer
+   * @param size number of bytes to copy
+   * @return new {@code ByteString}
    */
-  public static ByteString copyFrom(final ByteBuffer bytes, final int size) {
-    final byte[] copy = new byte[size];
+  public static ByteString copyFrom(ByteBuffer bytes, int size) {
+    byte[] copy = new byte[size];
     bytes.get(copy);
-    return new ByteString(copy);
+    return new LiteralByteString(copy);
   }
 
   /**
    * Copies the remaining bytes from a {@code java.nio.ByteBuffer} into
    * a {@code ByteString}.
+   *
+   * @param bytes sourceBuffer
+   * @return new {@code ByteString}
    */
-  public static ByteString copyFrom(final ByteBuffer bytes) {
+  public static ByteString copyFrom(ByteBuffer bytes) {
     return copyFrom(bytes, bytes.remaining());
   }
 
   /**
    * Encodes {@code text} into a sequence of bytes using the named charset
    * and returns the result as a {@code ByteString}.
+   *
+   * @param text source string
+   * @param charsetName encoding to use
+   * @return new {@code ByteString}
+   * @throws UnsupportedEncodingException if the encoding isn't found
    */
-  public static ByteString copyFrom(final String text, final String charsetName)
+  public static ByteString copyFrom(String text, String charsetName)
       throws UnsupportedEncodingException {
-    return new ByteString(text.getBytes(charsetName));
+    return new LiteralByteString(text.getBytes(charsetName));
   }
 
   /**
    * Encodes {@code text} into a sequence of UTF-8 bytes and returns the
    * result as a {@code ByteString}.
+   *
+   * @param text source string
+   * @return new {@code ByteString}
    */
-  public static ByteString copyFromUtf8(final String text) {
+  public static ByteString copyFromUtf8(String text) {
     try {
-      return new ByteString(text.getBytes("UTF-8"));
+      return new LiteralByteString(text.getBytes("UTF-8"));
     } catch (UnsupportedEncodingException e) {
       throw new RuntimeException("UTF-8 not supported?", e);
     }
   }
 
+  // =================================================================
+  // InputStream -> ByteString
+
   /**
-   * Concatenates all byte strings in the list and returns the result.
+   * Completely reads the given stream's bytes into a
+   * {@code ByteString}, blocking if necessary until all bytes are
+   * read through to the end of the stream.
+   *
+   * <b>Performance notes:</b> The returned {@code ByteString} is an
+   * immutable tree of byte arrays ("chunks") of the stream data.  The
+   * first chunk is small, with subsequent chunks each being double
+   * the size, up to 8K.  If the caller knows the precise length of
+   * the stream and wishes to avoid all unnecessary copies and
+   * allocations, consider using the two-argument version of this
+   * method, below.
+   *
+   * @param streamToDrain The source stream, which is read completely
+   *     but not closed.
+   * @return A new {@code ByteString} which is made up of chunks of
+   *     various sizes, depending on the behavior of the underlying
+   *     stream.
+   * @throws IOException IOException is thrown if there is a problem
+   *     reading the underlying stream.
+   */
+  public static ByteString readFrom(InputStream streamToDrain)
+      throws IOException {
+    return readFrom(
+        streamToDrain, MIN_READ_FROM_CHUNK_SIZE, MAX_READ_FROM_CHUNK_SIZE);
+  }
+
+  /**
+   * Completely reads the given stream's bytes into a
+   * {@code ByteString}, blocking if necessary until all bytes are
+   * read through to the end of the stream.
+   *
+   * <b>Performance notes:</b> The returned {@code ByteString} is an
+   * immutable tree of byte arrays ("chunks") of the stream data.  The
+   * chunkSize parameter sets the size of these byte arrays. In
+   * particular, if the chunkSize is precisely the same as the length
+   * of the stream, unnecessary allocations and copies will be
+   * avoided. Otherwise, the chunks will be of the given size, except
+   * for the last chunk, which will be resized (via a reallocation and
+   * copy) to contain the remainder of the stream.
+   *
+   * @param streamToDrain The source stream, which is read completely
+   *     but not closed.
+   * @param chunkSize The size of the chunks in which to read the
+   *     stream.
+   * @return A new {@code ByteString} which is made up of chunks of
+   *     the given size.
+   * @throws IOException IOException is thrown if there is a problem
+   *     reading the underlying stream.
+   */
+  public static ByteString readFrom(InputStream streamToDrain, int chunkSize)
+      throws IOException {
+    return readFrom(streamToDrain, chunkSize, chunkSize);
+  }
+
+  // Helper method that takes the chunk size range as a parameter.
+  public static ByteString readFrom(InputStream streamToDrain, int minChunkSize,
+      int maxChunkSize) throws IOException {
+    Collection<ByteString> results = new ArrayList<ByteString>();
+
+    // copy the inbound bytes into a list of chunks; the chunk size
+    // grows exponentially to support both short and long streams.
+    int chunkSize = minChunkSize;
+    while (true) {
+      ByteString chunk = readChunk(streamToDrain, chunkSize);
+      if (chunk == null) {
+        break;
+      }
+      results.add(chunk);
+      chunkSize = Math.min(chunkSize * 2, maxChunkSize);
+    }
+
+    return ByteString.copyFrom(results);
+  }
+
+  /**
+   * Blocks until a chunk of the given size can be made from the
+   * stream, or EOF is reached.  Calls read() repeatedly in case the
+   * given stream implementation doesn't completely fill the given
+   * buffer in one read() call.
+   *
+   * @return A chunk of the desired size, or else a chunk as large as
+   * was available when end of stream was reached. Returns null if the
+   * given stream had no more data in it.
+   */
+  private static ByteString readChunk(InputStream in, final int chunkSize)
+      throws IOException {
+      final byte[] buf = new byte[chunkSize];
+      int bytesRead = 0;
+      while (bytesRead < chunkSize) {
+        final int count = in.read(buf, bytesRead, chunkSize - bytesRead);
+        if (count == -1) {
+          break;
+        }
+        bytesRead += count;
+      }
+
+      if (bytesRead == 0) {
+        return null;
+      } else {
+        return ByteString.copyFrom(buf, 0, bytesRead);
+      }
+  }
+
+  // =================================================================
+  // Multiple ByteStrings -> One ByteString
+
+  /**
+   * Concatenate the given {@code ByteString} to this one. Short concatenations,
+   * of total size smaller than {@link ByteString#CONCATENATE_BY_COPY_SIZE}, are
+   * produced by copying the underlying bytes (as per Rope.java, <a
+   * href="http://www.cs.ubc.ca/local/reading/proceedings/spe91-95/spe/vol25/issue12/spe986.pdf">
+   * BAP95 </a>. In general, the concatenate involves no copying.
+   *
+   * @param other string to concatenate
+   * @return a new {@code ByteString} instance
+   */
+  public ByteString concat(ByteString other) {
+    int thisSize = size();
+    int otherSize = other.size();
+    if ((long) thisSize + otherSize >= Integer.MAX_VALUE) {
+      throw new IllegalArgumentException("ByteString would be too long: " +
+                                         thisSize + "+" + otherSize);
+    }
+
+    return RopeByteString.concatenate(this, other);
+  }
+
+  /**
+   * Concatenates all byte strings in the iterable and returns the result.
+   * This is designed to run in O(list size), not O(total bytes).
    *
    * <p>The returned {@code ByteString} is not necessarily a unique object.
    * If the list is empty, the returned object is the singleton empty
    * {@code ByteString}.  If the list has only one element, that
    * {@code ByteString} will be returned without copying.
+   *
+   * @param byteStrings strings to be concatenated
+   * @return new {@code ByteString}
    */
-  public static ByteString copyFrom(List<ByteString> list) {
-    if (list.size() == 0) {
-      return EMPTY;
-    } else if (list.size() == 1) {
-      return list.get(0);
+  public static ByteString copyFrom(Iterable<ByteString> byteStrings) {
+    Collection<ByteString> collection;
+    if (!(byteStrings instanceof Collection)) {
+      collection = new ArrayList<ByteString>();
+      for (ByteString byteString : byteStrings) {
+        collection.add(byteString);
+      }
+    } else {
+      collection = (Collection<ByteString>) byteStrings;
     }
+    ByteString result;
+    if (collection.isEmpty()) {
+      result = EMPTY;
+    } else {
+      result = balancedConcat(collection.iterator(), collection.size());
+    }
+    return result;
+  }
 
-    int size = 0;
-    for (ByteString str : list) {
-      size += str.size();
+  // Internal function used by copyFrom(Iterable<ByteString>).
+  // Create a balanced concatenation of the next "length" elements from the
+  // iterable.
+  private static ByteString balancedConcat(Iterator<ByteString> iterator,
+      int length) {
+    assert length >= 1;
+    ByteString result;
+    if (length == 1) {
+      result = iterator.next();
+    } else {
+      int halfLength = length >>> 1;
+      ByteString left = balancedConcat(iterator, halfLength);
+      ByteString right = balancedConcat(iterator, length - halfLength);
+      result = left.concat(right);
     }
-    byte[] bytes = new byte[size];
-    int pos = 0;
-    for (ByteString str : list) {
-      System.arraycopy(str.bytes, 0, bytes, pos, str.size());
-      pos += str.size();
-    }
-    return new ByteString(bytes);
+    return result;
   }
 
   // =================================================================
@@ -174,206 +447,446 @@
    *
    * @param target buffer to copy into
    * @param offset in the target buffer
+   * @throws IndexOutOfBoundsException if the offset is negative or too large
    */
-  public void copyTo(final byte[] target, final int offset) {
-    System.arraycopy(bytes, 0, target, offset, bytes.length);
+  public void copyTo(byte[] target, int offset) {
+    copyTo(target, 0, offset, size());
   }
 
   /**
    * Copies bytes into a buffer.
    *
-   * @param target buffer to copy into
+   * @param target       buffer to copy into
    * @param sourceOffset offset within these bytes
    * @param targetOffset offset within the target buffer
-   * @param size number of bytes to copy
+   * @param numberToCopy number of bytes to copy
+   * @throws IndexOutOfBoundsException if an offset or size is negative or too
+   *     large
    */
-  public void copyTo(final byte[] target, final int sourceOffset,
-                     final int targetOffset,
-      final int size) {
-    System.arraycopy(bytes, sourceOffset, target, targetOffset, size);
+  public void copyTo(byte[] target, int sourceOffset, int targetOffset,
+      int numberToCopy) {
+    if (sourceOffset < 0) {
+      throw new IndexOutOfBoundsException("Source offset < 0: " + sourceOffset);
+    }
+    if (targetOffset < 0) {
+      throw new IndexOutOfBoundsException("Target offset < 0: " + targetOffset);
+    }
+    if (numberToCopy < 0) {
+      throw new IndexOutOfBoundsException("Length < 0: " + numberToCopy);
+    }
+    if (sourceOffset + numberToCopy > size()) {
+      throw new IndexOutOfBoundsException(
+          "Source end offset < 0: " + (sourceOffset + numberToCopy));
+    }
+    if (targetOffset + numberToCopy > target.length) {
+      throw new IndexOutOfBoundsException(
+          "Target end offset < 0: " + (targetOffset + numberToCopy));
+    }
+    if (numberToCopy > 0) {
+      copyToInternal(target, sourceOffset, targetOffset, numberToCopy);
+    }
   }
 
   /**
+   * Internal (package private) implementation of
+   * @link{#copyTo(byte[],int,int,int}.
+   * It assumes that all error checking has already been performed and that 
+   * @code{numberToCopy > 0}.
+   */
+  protected abstract void copyToInternal(byte[] target, int sourceOffset,
+      int targetOffset, int numberToCopy);
+
+  /**
    * Copies bytes into a ByteBuffer.
    *
    * @param target ByteBuffer to copy into.
-   * @throws ReadOnlyBufferException if the {@code target} is read-only
-   * @throws BufferOverflowException if the {@code target}'s remaining()
-   *         space is not large enough to hold the data.
+   * @throws java.nio.ReadOnlyBufferException if the {@code target} is read-only
+   * @throws java.nio.BufferOverflowException if the {@code target}'s
+   *     remaining() space is not large enough to hold the data.
    */
-  public void copyTo(ByteBuffer target) {
-    target.put(bytes, 0, bytes.length);
-  }
+  public abstract void copyTo(ByteBuffer target);
 
   /**
    * Copies bytes to a {@code byte[]}.
+   *
+   * @return copied bytes
    */
   public byte[] toByteArray() {
-    final int size = bytes.length;
-    final byte[] copy = new byte[size];
-    System.arraycopy(bytes, 0, copy, 0, size);
-    return copy;
+    int size = size();
+    byte[] result = new byte[size];
+    copyToInternal(result, 0, 0, size);
+    return result;
   }
 
   /**
-   * Constructs a new read-only {@code java.nio.ByteBuffer} with the
-   * same backing byte array.
+   * Writes the complete contents of this byte string to
+   * the specified output stream argument.
+   *
+   * @param  out  the output stream to which to write the data.
+   * @throws IOException  if an I/O error occurs.
    */
-  public ByteBuffer asReadOnlyByteBuffer() {
-    final ByteBuffer byteBuffer = ByteBuffer.wrap(bytes);
-    return byteBuffer.asReadOnlyBuffer();
-  }
+  public abstract void writeTo(OutputStream out) throws IOException;
+
+  /**
+   * Constructs a read-only {@code java.nio.ByteBuffer} whose content
+   * is equal to the contents of this byte string.
+   * The result uses the same backing array as the byte string, if possible.
+   *
+   * @return wrapped bytes
+   */
+  public abstract ByteBuffer asReadOnlyByteBuffer();
+
+  /**
+   * Constructs a list of read-only {@code java.nio.ByteBuffer} objects
+   * such that the concatenation of their contents is equal to the contents
+   * of this byte string.  The result uses the same backing arrays as the
+   * byte string.
+   * <p>
+   * By returning a list, implementations of this method may be able to avoid
+   * copying even when there are multiple backing arrays.
+   * 
+   * @return a list of wrapped bytes
+   */
+  public abstract List<ByteBuffer> asReadOnlyByteBufferList();
 
   /**
    * Constructs a new {@code String} by decoding the bytes using the
    * specified charset.
+   *
+   * @param charsetName encode using this charset
+   * @return new string
+   * @throws UnsupportedEncodingException if charset isn't recognized
    */
-  public String toString(final String charsetName)
-      throws UnsupportedEncodingException {
-    return new String(bytes, charsetName);
-  }
+  public abstract String toString(String charsetName)
+      throws UnsupportedEncodingException;
+
+  // =================================================================
+  // UTF-8 decoding
 
   /**
    * Constructs a new {@code String} by decoding the bytes as UTF-8.
+   *
+   * @return new string using UTF-8 encoding
    */
   public String toStringUtf8() {
     try {
-      return new String(bytes, "UTF-8");
+      return toString("UTF-8");
     } catch (UnsupportedEncodingException e) {
       throw new RuntimeException("UTF-8 not supported?", e);
     }
   }
 
+  /**
+   * Tells whether this {@code ByteString} represents a well-formed UTF-8
+   * byte sequence, such that the original bytes can be converted to a
+   * String object and then round tripped back to bytes without loss.
+   *
+   * <p>More precisely, returns {@code true} whenever: <pre> {@code
+   * Arrays.equals(byteString.toByteArray(),
+   *     new String(byteString.toByteArray(), "UTF-8").getBytes("UTF-8"))
+   * }</pre>
+   *
+   * <p>This method returns {@code false} for "overlong" byte sequences,
+   * as well as for 3-byte sequences that would map to a surrogate
+   * character, in accordance with the restricted definition of UTF-8
+   * introduced in Unicode 3.1.  Note that the UTF-8 decoder included in
+   * Oracle's JDK has been modified to also reject "overlong" byte
+   * sequences, but (as of 2011) still accepts 3-byte surrogate
+   * character byte sequences.
+   *
+   * <p>See the Unicode Standard,</br>
+   * Table 3-6. <em>UTF-8 Bit Distribution</em>,</br>
+   * Table 3-7. <em>Well Formed UTF-8 Byte Sequences</em>.
+   *
+   * @return whether the bytes in this {@code ByteString} are a
+   * well-formed UTF-8 byte sequence
+   */
+  public abstract boolean isValidUtf8();
+
+  /**
+   * Tells whether the given byte sequence is a well-formed, malformed, or
+   * incomplete UTF-8 byte sequence.  This method accepts and returns a partial
+   * state result, allowing the bytes for a complete UTF-8 byte sequence to be
+   * composed from multiple {@code ByteString} segments.
+   *
+   * @param state either {@code 0} (if this is the initial decoding operation)
+   *     or the value returned from a call to a partial decoding method for the
+   *     previous bytes
+   * @param offset offset of the first byte to check
+   * @param length number of bytes to check
+   *
+   * @return {@code -1} if the partial byte sequence is definitely malformed,
+   * {@code 0} if it is well-formed (no additional input needed), or, if the
+   * byte sequence is "incomplete", i.e. apparently terminated in the middle of
+   * a character, an opaque integer "state" value containing enough information
+   * to decode the character when passed to a subsequent invocation of a
+   * partial decoding method.
+   */
+  protected abstract int partialIsValidUtf8(int state, int offset, int length);
+
   // =================================================================
   // equals() and hashCode()
 
   @Override
-  public boolean equals(final Object o) {
-    if (o == this) {
-      return true;
-    }
+  public abstract boolean equals(Object o);
 
-    if (!(o instanceof ByteString)) {
-      return false;
-    }
-
-    final ByteString other = (ByteString) o;
-    final int size = bytes.length;
-    if (size != other.bytes.length) {
-      return false;
-    }
-
-    final byte[] thisBytes = bytes;
-    final byte[] otherBytes = other.bytes;
-    for (int i = 0; i < size; i++) {
-      if (thisBytes[i] != otherBytes[i]) {
-        return false;
-      }
-    }
-
-    return true;
-  }
-
-  private volatile int hash = 0;
-
+  /**
+   * Return a non-zero hashCode depending only on the sequence of bytes
+   * in this ByteString.
+   *
+   * @return hashCode value for this object
+   */
   @Override
-  public int hashCode() {
-    int h = hash;
-
-    if (h == 0) {
-      final byte[] thisBytes = bytes;
-      final int size = bytes.length;
-
-      h = size;
-      for (int i = 0; i < size; i++) {
-        h = h * 31 + thisBytes[i];
-      }
-      if (h == 0) {
-        h = 1;
-      }
-
-      hash = h;
-    }
-
-    return h;
-  }
+  public abstract int hashCode();
 
   // =================================================================
   // Input stream
 
   /**
    * Creates an {@code InputStream} which can be used to read the bytes.
+   * <p>
+   * The {@link InputStream} returned by this method is guaranteed to be
+   * completely non-blocking.  The method {@link InputStream#available()}
+   * returns the number of bytes remaining in the stream. The methods
+   * {@link InputStream#read(byte[]), {@link InputStream#read(byte[],int,int)}
+   * and {@link InputStream#skip(long)} will read/skip as many bytes as are
+   * available.
+   * <p>
+   * The methods in the returned {@link InputStream} might <b>not</b> be
+   * thread safe.
+   *
+   * @return an input stream that returns the bytes of this byte string.
    */
-  public InputStream newInput() {
-    return new ByteArrayInputStream(bytes);
-  }
+  public abstract InputStream newInput();
 
   /**
    * Creates a {@link CodedInputStream} which can be used to read the bytes.
-   * Using this is more efficient than creating a {@link CodedInputStream}
-   * wrapping the result of {@link #newInput()}.
+   * Using this is often more efficient than creating a {@link CodedInputStream}
+   * that wraps the result of {@link #newInput()}.
+   *
+   * @return stream based on wrapped data
    */
-  public CodedInputStream newCodedInput() {
-    // We trust CodedInputStream not to modify the bytes, or to give anyone
-    // else access to them.
-    return CodedInputStream.newInstance(bytes);
-  }
+  public abstract CodedInputStream newCodedInput();
 
   // =================================================================
   // Output stream
 
   /**
-   * Creates a new {@link Output} with the given initial capacity.
+   * Creates a new {@link Output} with the given initial capacity. Call {@link
+   * Output#toByteString()} to create the {@code ByteString} instance.
+   * <p>
+   * A {@link ByteString.Output} offers the same functionality as a
+   * {@link ByteArrayOutputStream}, except that it returns a {@link ByteString}
+   * rather than a {@code byte} array.
+   *
+   * @param initialCapacity estimate of number of bytes to be written
+   * @return {@code OutputStream} for building a {@code ByteString}
    */
-  public static Output newOutput(final int initialCapacity) {
-    return new Output(new ByteArrayOutputStream(initialCapacity));
+  public static Output newOutput(int initialCapacity) {
+    return new Output(initialCapacity);
   }
 
   /**
-   * Creates a new {@link Output}.
+   * Creates a new {@link Output}. Call {@link Output#toByteString()} to create
+   * the {@code ByteString} instance.
+   * <p>
+   * A {@link ByteString.Output} offers the same functionality as a
+   * {@link ByteArrayOutputStream}, except that it returns a {@link ByteString}
+   * rather than a {@code byte array}.
+   *
+   * @return {@code OutputStream} for building a {@code ByteString}
    */
   public static Output newOutput() {
-    return newOutput(32);
+    return new Output(CONCATENATE_BY_COPY_SIZE);
   }
 
   /**
    * Outputs to a {@code ByteString} instance. Call {@link #toByteString()} to
    * create the {@code ByteString} instance.
    */
-  public static final class Output extends FilterOutputStream {
-    private final ByteArrayOutputStream bout;
+  public static final class Output extends OutputStream {
+    // Implementation note.
+    // The public methods of this class must be synchronized.  ByteStrings
+    // are guaranteed to be immutable.  Without some sort of locking, it could
+    // be possible for one thread to call toByteSring(), while another thread
+    // is still modifying the underlying byte array.
+
+    private static final byte[] EMPTY_BYTE_ARRAY = new byte[0];
+    // argument passed by user, indicating initial capacity.
+    private final int initialCapacity;
+    // ByteStrings to be concatenated to create the result
+    private final ArrayList<ByteString> flushedBuffers;
+    // Total number of bytes in the ByteStrings of flushedBuffers
+    private int flushedBuffersTotalBytes;
+    // Current buffer to which we are writing
+    private byte[] buffer;
+    // Location in buffer[] to which we write the next byte.
+    private int bufferPos;
 
     /**
-     * Constructs a new output with the given initial capacity.
+     * Creates a new ByteString output stream with the specified
+     * initial capacity.
+     *
+     * @param initialCapacity  the initial capacity of the output stream.
      */
-    private Output(final ByteArrayOutputStream bout) {
-      super(bout);
-      this.bout = bout;
+    Output(int initialCapacity) {
+      if (initialCapacity < 0) {
+        throw new IllegalArgumentException("Buffer size < 0");
+      }
+      this.initialCapacity = initialCapacity;
+      this.flushedBuffers = new ArrayList<ByteString>();
+      this.buffer = new byte[initialCapacity];
+    }
+
+    @Override
+    public synchronized void write(int b) {
+      if (bufferPos == buffer.length) {
+        flushFullBuffer(1);
+      }
+      buffer[bufferPos++] = (byte)b;
+    }
+
+    @Override
+    public synchronized void write(byte[] b, int offset, int length)  {
+      if (length <= buffer.length - bufferPos) {
+        // The bytes can fit into the current buffer.
+        System.arraycopy(b, offset, buffer, bufferPos, length);
+        bufferPos += length;
+      } else {
+        // Use up the current buffer
+        int copySize  = buffer.length - bufferPos;
+        System.arraycopy(b, offset, buffer, bufferPos, copySize);
+        offset += copySize;
+        length -= copySize;
+        // Flush the buffer, and get a new buffer at least big enough to cover
+        // what we still need to output
+        flushFullBuffer(length);
+        System.arraycopy(b, offset, buffer, 0 /* count */, length);
+        bufferPos = length;
+      }
     }
 
     /**
-     * Creates a {@code ByteString} instance from this {@code Output}.
+     * Creates a byte string. Its size is the current size of this output
+     * stream and its output has been copied to it.
+     *
+     * @return  the current contents of this output stream, as a byte string.
      */
-    public ByteString toByteString() {
-      final byte[] byteArray = bout.toByteArray();
-      return new ByteString(byteArray);
+    public synchronized ByteString toByteString() {
+      flushLastBuffer();
+      return ByteString.copyFrom(flushedBuffers);
+    }
+
+    /**
+     * Writes the complete contents of this byte array output stream to
+     * the specified output stream argument.
+     *
+     * @param out the output stream to which to write the data.
+     * @throws IOException  if an I/O error occurs.
+     */
+    public void writeTo(OutputStream out) throws IOException {
+      ByteString[] cachedFlushBuffers;
+      byte[] cachedBuffer;
+      int cachedBufferPos;
+      synchronized (this) {
+        // Copy the information we need into local variables so as to hold
+        // the lock for as short a time as possible.
+        cachedFlushBuffers =
+            flushedBuffers.toArray(new ByteString[flushedBuffers.size()]);
+        cachedBuffer = buffer;
+        cachedBufferPos = bufferPos;
+      }
+      for (ByteString byteString : cachedFlushBuffers) {
+        byteString.writeTo(out);
+      }
+
+      out.write(Arrays.copyOf(cachedBuffer, cachedBufferPos));
+    }
+
+    /**
+     * Returns the current size of the output stream.
+     *
+     * @return  the current size of the output stream
+     */
+    public synchronized int size() {
+      return flushedBuffersTotalBytes + bufferPos;
+    }
+
+    /**
+     * Resets this stream, so that all currently accumulated output in the
+     * output stream is discarded. The output stream can be used again,
+     * reusing the already allocated buffer space.
+     */
+    public synchronized void reset() {
+      flushedBuffers.clear();
+      flushedBuffersTotalBytes = 0;
+      bufferPos = 0;
+    }
+
+    @Override
+    public String toString() {
+      return String.format("<ByteString.Output@%s size=%d>",
+          Integer.toHexString(System.identityHashCode(this)), size());
+    }
+
+    /**
+     * Internal function used by writers.  The current buffer is full, and the
+     * writer needs a new buffer whose size is at least the specified minimum
+     * size.
+     */
+    private void flushFullBuffer(int minSize)  {
+      flushedBuffers.add(new LiteralByteString(buffer));
+      flushedBuffersTotalBytes += buffer.length;
+      // We want to increase our total capacity by 50%, but as a minimum,
+      // the new buffer should also at least be >= minSize and
+      // >= initial Capacity.
+      int newSize = Math.max(initialCapacity,
+          Math.max(minSize, flushedBuffersTotalBytes >>> 1));
+      buffer = new byte[newSize];
+      bufferPos = 0;
+    }
+
+    /**
+     * Internal function used by {@link #toByteString()}. The current buffer may
+     * or may not be full, but it needs to be flushed.
+     */
+    private void flushLastBuffer()  {
+      if (bufferPos < buffer.length) {
+        if (bufferPos > 0) {
+          byte[] bufferCopy = Arrays.copyOf(buffer, bufferPos);
+          flushedBuffers.add(new LiteralByteString(bufferCopy));
+        }
+        // We reuse this buffer for further writes.
+      } else {
+        // Buffer is completely full.  Huzzah.
+        flushedBuffers.add(new LiteralByteString(buffer));
+        // 99% of the time, we're not going to use this OutputStream again.
+        // We set buffer to an empty byte stream so that we're handling this
+        // case without wasting space.  In the rare case that more writes
+        // *do* occur, this empty buffer will be flushed and an appropriately
+        // sized new buffer will be created.
+        buffer = EMPTY_BYTE_ARRAY;
+      }
+      flushedBuffersTotalBytes += bufferPos;
+      bufferPos = 0;
     }
   }
 
   /**
-   * Constructs a new ByteString builder, which allows you to efficiently
-   * construct a {@code ByteString} by writing to a {@link CodedOutputStream}.
-   * Using this is much more efficient than calling {@code newOutput()} and
-   * wrapping that in a {@code CodedOutputStream}.
+   * Constructs a new {@code ByteString} builder, which allows you to
+   * efficiently construct a {@code ByteString} by writing to a {@link
+   * CodedOutputStream}. Using this is much more efficient than calling {@code
+   * newOutput()} and wrapping that in a {@code CodedOutputStream}.
    *
    * <p>This is package-private because it's a somewhat confusing interface.
    * Users can call {@link Message#toByteString()} instead of calling this
    * directly.
    *
-   * @param size The target byte size of the {@code ByteString}.  You must
-   *             write exactly this many bytes before building the result.
+   * @param size The target byte size of the {@code ByteString}.  You must write
+   *     exactly this many bytes before building the result.
+   * @return the builder
    */
-  static CodedBuilder newCodedBuilder(final int size) {
+  static CodedBuilder newCodedBuilder(int size) {
     return new CodedBuilder(size);
   }
 
@@ -382,7 +895,7 @@
     private final CodedOutputStream output;
     private final byte[] buffer;
 
-    private CodedBuilder(final int size) {
+    private CodedBuilder(int size) {
       buffer = new byte[size];
       output = CodedOutputStream.newInstance(buffer);
     }
@@ -393,11 +906,57 @@
       // We can be confident that the CodedOutputStream will not modify the
       // underlying bytes anymore because it already wrote all of them.  So,
       // no need to make a copy.
-      return new ByteString(buffer);
+      return new LiteralByteString(buffer);
     }
 
     public CodedOutputStream getCodedOutput() {
       return output;
     }
   }
+
+  // =================================================================
+  // Methods {@link RopeByteString} needs on instances, which aren't part of the
+  // public API.
+
+  /**
+   * Return the depth of the tree representing this {@code ByteString}, if any,
+   * whose root is this node. If this is a leaf node, return 0.
+   *
+   * @return tree depth or zero
+   */
+  protected abstract int getTreeDepth();
+
+  /**
+   * Return {@code true} if this ByteString is literal (a leaf node) or a
+   * flat-enough tree in the sense of {@link RopeByteString}.
+   *
+   * @return true if the tree is flat enough
+   */
+  protected abstract boolean isBalanced();
+
+  /**
+   * Return the cached hash code if available.
+   *
+   * @return value of cached hash code or 0 if not computed yet
+   */
+  protected abstract int peekCachedHashCode();
+
+  /**
+   * Compute the hash across the value bytes starting with the given hash, and
+   * return the result.  This is used to compute the hash across strings
+   * represented as a set of pieces by allowing the hash computation to be
+   * continued from piece to piece.
+   *
+   * @param h starting hash value
+   * @param offset offset into this value to start looking at data values
+   * @param length number of data values to include in the hash computation
+   * @return ending hash value
+   */
+  protected abstract int partialHash(int h, int offset, int length);
+
+  @Override
+  public String toString() {
+    return String.format("<ByteString@%s size=%d>",
+        Integer.toHexString(System.identityHashCode(this)), size());
+  }
 }
diff --git a/third_party/protobuf/java/src/main/java/com/google/protobuf/CodedInputStream.java b/third_party/protobuf/java/src/main/java/com/google/protobuf/CodedInputStream.java
index b3e0855..33417a7 100644
--- a/third_party/protobuf/java/src/main/java/com/google/protobuf/CodedInputStream.java
+++ b/third_party/protobuf/java/src/main/java/com/google/protobuf/CodedInputStream.java
@@ -243,6 +243,23 @@
     --recursionDepth;
   }
 
+  /** Read a {@code group} field value from the stream. */
+  public <T extends MessageLite> T readGroup(
+      final int fieldNumber,
+      final Parser<T> parser,
+      final ExtensionRegistryLite extensionRegistry)
+      throws IOException {
+    if (recursionDepth >= recursionLimit) {
+      throw InvalidProtocolBufferException.recursionLimitExceeded();
+    }
+    ++recursionDepth;
+    T result = parser.parsePartialFrom(this, extensionRegistry);
+    checkLastTagWas(
+      WireFormat.makeTag(fieldNumber, WireFormat.WIRETYPE_END_GROUP));
+    --recursionDepth;
+    return result;
+  }
+
   /**
    * Reads a {@code group} field value from the stream and merges it into the
    * given {@link UnknownFieldSet}.
@@ -278,6 +295,24 @@
     popLimit(oldLimit);
   }
 
+  /** Read an embedded message field value from the stream. */
+  public <T extends MessageLite> T readMessage(
+      final Parser<T> parser,
+      final ExtensionRegistryLite extensionRegistry)
+      throws IOException {
+    int length = readRawVarint32();
+    if (recursionDepth >= recursionLimit) {
+      throw InvalidProtocolBufferException.recursionLimitExceeded();
+    }
+    final int oldLimit = pushLimit(length);
+    ++recursionDepth;
+    T result = parser.parsePartialFrom(this, extensionRegistry);
+    checkLastTagWas(0);
+    --recursionDepth;
+    popLimit(oldLimit);
+    return result;
+  }
+
   /** Read a {@code bytes} field value from the stream. */
   public ByteString readBytes() throws IOException {
     final int size = readRawVarint32();
@@ -601,7 +636,7 @@
    * refreshing its buffer.  If you need to prevent reading past a certain
    * point in the underlying {@code InputStream} (e.g. because you expect it to
    * contain more data after the end of the message which you need to handle
-   * differently) then you must place a wrapper around you {@code InputStream}
+   * differently) then you must place a wrapper around your {@code InputStream}
    * which limits the amount of data that can be read from it.
    *
    * @return the old limit.
@@ -676,7 +711,7 @@
 
   /**
    * Called with {@code this.buffer} is empty to read more bytes from the
-   * input.  If {@code mustSucceed} is true, refillBuffer() gurantees that
+   * input.  If {@code mustSucceed} is true, refillBuffer() guarantees that
    * either there will be at least one byte in the buffer when it returns
    * or it will throw an exception.  If {@code mustSucceed} is false,
    * refillBuffer() returns false if no more bytes were available.
@@ -879,7 +914,7 @@
         refillBuffer(true);
       }
 
-      bufferPos = size - pos; 
+      bufferPos = size - pos;
     }
   }
 }
diff --git a/third_party/protobuf/java/src/main/java/com/google/protobuf/CodedOutputStream.java b/third_party/protobuf/java/src/main/java/com/google/protobuf/CodedOutputStream.java
index ac5f2d3..ca24638 100644
--- a/third_party/protobuf/java/src/main/java/com/google/protobuf/CodedOutputStream.java
+++ b/third_party/protobuf/java/src/main/java/com/google/protobuf/CodedOutputStream.java
@@ -30,10 +30,10 @@
 
 package com.google.protobuf;
 
-import java.io.OutputStream;
 import java.io.IOException;
-import java.io.UnsupportedEncodingException;
 import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.UnsupportedEncodingException;
 
 /**
  * Encodes and writes protocol message fields.
@@ -540,6 +540,15 @@
   }
 
   /**
+   * Compute the number of bytes that would be needed to encode an
+   * embedded message in lazy field, including tag.
+   */
+  public static int computeLazyFieldSize(final int fieldNumber,
+                                         final LazyField value) {
+    return computeTagSize(fieldNumber) + computeLazyFieldSizeNoTag(value);
+  }
+
+  /**
    * Compute the number of bytes that would be needed to encode a
    * {@code uint32} field, including tag.
    */
@@ -614,6 +623,18 @@
            computeBytesSize(WireFormat.MESSAGE_SET_MESSAGE, value);
   }
 
+  /**
+   * Compute the number of bytes that would be needed to encode an
+   * lazily parsed MessageSet extension field to the stream.  For
+   * historical reasons, the wire format differs from normal fields.
+   */
+  public static int computeLazyFieldMessageSetExtensionSize(
+      final int fieldNumber, final LazyField value) {
+    return computeTagSize(WireFormat.MESSAGE_SET_ITEM) * 2 +
+           computeUInt32Size(WireFormat.MESSAGE_SET_TYPE_ID, fieldNumber) +
+           computeLazyFieldSize(WireFormat.MESSAGE_SET_MESSAGE, value);
+  }
+  
   // -----------------------------------------------------------------
 
   /**
@@ -730,6 +751,15 @@
   }
 
   /**
+   * Compute the number of bytes that would be needed to encode an embedded
+   * message stored in lazy field.
+   */
+  public static int computeLazyFieldSizeNoTag(final LazyField value) {
+    final int size = value.getSerializedSize();
+    return computeRawVarint32Size(size) + size;
+  }
+
+  /**
    * Compute the number of bytes that would be needed to encode a
    * {@code bytes} field.
    */
diff --git a/third_party/protobuf/java/src/main/java/com/google/protobuf/Descriptors.java b/third_party/protobuf/java/src/main/java/com/google/protobuf/Descriptors.java
index 2ee8459..a491305 100644
--- a/third_party/protobuf/java/src/main/java/com/google/protobuf/Descriptors.java
+++ b/third_party/protobuf/java/src/main/java/com/google/protobuf/Descriptors.java
@@ -35,8 +35,10 @@
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 import java.io.UnsupportedEncodingException;
 
 /**
@@ -106,6 +108,11 @@
       return Collections.unmodifiableList(Arrays.asList(dependencies));
     }
 
+    /** Get a list of this file's public dependencies (public imports). */
+    public List<FileDescriptor> getPublicDependencies() {
+      return Collections.unmodifiableList(Arrays.asList(publicDependencies));
+    }
+
     /**
      * Find a message type in the file by name.  Does not find nested types.
      *
@@ -216,7 +223,7 @@
     public static FileDescriptor buildFrom(final FileDescriptorProto proto,
                                            final FileDescriptor[] dependencies)
                                     throws DescriptorValidationException {
-      // Building decsriptors involves two steps:  translating and linking.
+      // Building descriptors involves two steps:  translating and linking.
       // In the translation step (implemented by FileDescriptor's
       // constructor), we build an object tree mirroring the
       // FileDescriptorProto's tree and put all of the descriptors into the
@@ -317,12 +324,12 @@
      * {@link FileDescriptor#internalBuildGeneratedFileFrom}, the caller
      * provides a callback implementing this interface.  The callback is called
      * after the FileDescriptor has been constructed, in order to assign all
-     * the global variales defined in the generated code which point at parts
+     * the global variables defined in the generated code which point at parts
      * of the FileDescriptor.  The callback returns an ExtensionRegistry which
      * contains any extensions which might be used in the descriptor -- that
      * is, extensions of the various "Options" messages defined in
      * descriptor.proto.  The callback may also return null to indicate that
-     * no extensions are used in the decsriptor.
+     * no extensions are used in the descriptor.
      */
     public interface InternalDescriptorAssigner {
       ExtensionRegistry assignDescriptors(FileDescriptor root);
@@ -334,6 +341,7 @@
     private final ServiceDescriptor[] services;
     private final FieldDescriptor[] extensions;
     private final FileDescriptor[] dependencies;
+    private final FileDescriptor[] publicDependencies;
     private final DescriptorPool pool;
 
     private FileDescriptor(final FileDescriptorProto proto,
@@ -343,6 +351,17 @@
       this.pool = pool;
       this.proto = proto;
       this.dependencies = dependencies.clone();
+      this.publicDependencies =
+          new FileDescriptor[proto.getPublicDependencyCount()];
+      for (int i = 0; i < proto.getPublicDependencyCount(); i++) {
+        int index = proto.getPublicDependency(i);
+        if (index < 0 || index >= this.dependencies.length) {
+          throw new DescriptorValidationException(this,
+              "Invalid public dependency index.");
+        }
+        this.publicDependencies[i] =
+            this.dependencies[proto.getPublicDependency(i)];
+      }
 
       pool.addPackage(getPackage(), this);
 
@@ -390,7 +409,7 @@
      * in the original.  This method is needed for bootstrapping when a file
      * defines custom options.  The options may be defined in the file itself,
      * so we can't actually parse them until we've constructed the descriptors,
-     * but to construct the decsriptors we have to have parsed the descriptor
+     * but to construct the descriptors we have to have parsed the descriptor
      * protos.  So, we have to parse the descriptor protos a second time after
      * constructing the descriptors.
      */
@@ -641,7 +660,7 @@
                  FieldSet.FieldDescriptorLite<FieldDescriptor> {
     /**
      * Get the index of this descriptor within its parent.
-     * @see Descriptor#getIndex()
+     * @see Descriptors.Descriptor#getIndex()
      */
     public int getIndex() { return index; }
 
@@ -656,7 +675,7 @@
 
     /**
      * Get the field's fully-qualified name.
-     * @see Descriptor#getFullName()
+     * @see Descriptors.Descriptor#getFullName()
      */
     public String getFullName() { return fullName; }
 
@@ -943,7 +962,8 @@
     private void crossLink() throws DescriptorValidationException {
       if (proto.hasExtendee()) {
         final GenericDescriptor extendee =
-          file.pool.lookupSymbol(proto.getExtendee(), this);
+          file.pool.lookupSymbol(proto.getExtendee(), this,
+              DescriptorPool.SearchFilter.TYPES_ONLY);
         if (!(extendee instanceof Descriptor)) {
           throw new DescriptorValidationException(this,
               '\"' + proto.getExtendee() + "\" is not a message type.");
@@ -960,7 +980,8 @@
 
       if (proto.hasTypeName()) {
         final GenericDescriptor typeDescriptor =
-          file.pool.lookupSymbol(proto.getTypeName(), this);
+          file.pool.lookupSymbol(proto.getTypeName(), this,
+              DescriptorPool.SearchFilter.TYPES_ONLY);
 
         if (!proto.hasType()) {
           // Choose field type based on symbol.
@@ -1149,7 +1170,7 @@
       implements GenericDescriptor, Internal.EnumLiteMap<EnumValueDescriptor> {
     /**
      * Get the index of this descriptor within its parent.
-     * @see Descriptor#getIndex()
+     * @see Descriptors.Descriptor#getIndex()
      */
     public int getIndex() { return index; }
 
@@ -1161,7 +1182,7 @@
 
     /**
      * Get the type's fully-qualified name.
-     * @see Descriptor#getFullName()
+     * @see Descriptors.Descriptor#getFullName()
      */
     public String getFullName() { return fullName; }
 
@@ -1182,7 +1203,7 @@
     /**
      * Find an enum value by name.
      * @param name The unqualified name of the value (e.g. "FOO").
-     * @return the value's decsriptor, or {@code null} if not found.
+     * @return the value's descriptor, or {@code null} if not found.
      */
     public EnumValueDescriptor findValueByName(final String name) {
       final GenericDescriptor result =
@@ -1198,7 +1219,7 @@
      * Find an enum value by number.  If multiple enum values have the same
      * number, this returns the first defined value with that number.
      * @param number The value's number.
-     * @return the value's decsriptor, or {@code null} if not found.
+     * @return the value's descriptor, or {@code null} if not found.
      */
     public EnumValueDescriptor findValueByNumber(final int number) {
       return file.pool.enumValuesByNumber.get(
@@ -1261,7 +1282,7 @@
       implements GenericDescriptor, Internal.EnumLite {
     /**
      * Get the index of this descriptor within its parent.
-     * @see Descriptor#getIndex()
+     * @see Descriptors.Descriptor#getIndex()
      */
     public int getIndex() { return index; }
 
@@ -1276,7 +1297,7 @@
 
     /**
      * Get the value's fully-qualified name.
-     * @see Descriptor#getFullName()
+     * @see Descriptors.Descriptor#getFullName()
      */
     public String getFullName() { return fullName; }
 
@@ -1337,7 +1358,7 @@
 
     /**
      * Get the type's fully-qualified name.
-     * @see Descriptor#getFullName()
+     * @see Descriptors.Descriptor#getFullName()
      */
     public String getFullName() { return fullName; }
 
@@ -1355,7 +1376,7 @@
     /**
      * Find a method by name.
      * @param name The unqualified name of the method (e.g. "Foo").
-     * @return the method's decsriptor, or {@code null} if not found.
+     * @return the method's descriptor, or {@code null} if not found.
      */
     public MethodDescriptor findMethodByName(final String name) {
       final GenericDescriptor result =
@@ -1427,7 +1448,7 @@
 
     /**
      * Get the method's fully-qualified name.
-     * @see Descriptor#getFullName()
+     * @see Descriptors.Descriptor#getFullName()
      */
     public String getFullName() { return fullName; }
 
@@ -1475,7 +1496,8 @@
 
     private void crossLink() throws DescriptorValidationException {
       final GenericDescriptor input =
-        file.pool.lookupSymbol(proto.getInputType(), this);
+        file.pool.lookupSymbol(proto.getInputType(), this,
+            DescriptorPool.SearchFilter.TYPES_ONLY);
       if (!(input instanceof Descriptor)) {
         throw new DescriptorValidationException(this,
             '\"' + proto.getInputType() + "\" is not a message type.");
@@ -1483,7 +1505,8 @@
       inputType = (Descriptor)input;
 
       final GenericDescriptor output =
-        file.pool.lookupSymbol(proto.getOutputType(), this);
+        file.pool.lookupSymbol(proto.getOutputType(), this,
+            DescriptorPool.SearchFilter.TYPES_ONLY);
       if (!(output instanceof Descriptor)) {
         throw new DescriptorValidationException(this,
             '\"' + proto.getOutputType() + "\" is not a message type.");
@@ -1535,7 +1558,7 @@
     public String getProblemSymbolName() { return name; }
 
     /**
-     * Gets the the protocol message representation of the invalid descriptor.
+     * Gets the protocol message representation of the invalid descriptor.
      */
     public Message getProblemProto() { return proto; }
 
@@ -1590,14 +1613,22 @@
    * descriptors defined in a particular file.
    */
   private static final class DescriptorPool {
+    
+    /** Defines what subclass of descriptors to search in the descriptor pool. 
+     */
+    enum SearchFilter {
+      TYPES_ONLY, AGGREGATES_ONLY, ALL_SYMBOLS
+    }
+    
     DescriptorPool(final FileDescriptor[] dependencies) {
-      this.dependencies = new DescriptorPool[dependencies.length];
+      this.dependencies = new HashSet<FileDescriptor>();
 
-      for (int i = 0; i < dependencies.length; i++)  {
-        this.dependencies[i] = dependencies[i].pool;
+      for (int i = 0; i < dependencies.length; i++) {
+        this.dependencies.add(dependencies[i]);
+        importPublicDependencies(dependencies[i]);
       }
 
-      for (final FileDescriptor dependency : dependencies) {
+      for (final FileDescriptor dependency : this.dependencies) {
         try {
           addPackage(dependency.getPackage(), dependency);
         } catch (DescriptorValidationException e) {
@@ -1609,7 +1640,16 @@
       }
     }
 
-    private final DescriptorPool[] dependencies;
+    /** Find and put public dependencies of the file into dependencies set.*/
+    private void importPublicDependencies(final FileDescriptor file) {
+      for (FileDescriptor dependency : file.getPublicDependencies()) {
+        if (dependencies.add(dependency)) {
+          importPublicDependencies(dependency);
+        }
+      }
+    }
+
+    private final Set<FileDescriptor> dependencies;
 
     private final Map<String, GenericDescriptor> descriptorsByName =
       new HashMap<String, GenericDescriptor>();
@@ -1620,39 +1660,81 @@
 
     /** Find a generic descriptor by fully-qualified name. */
     GenericDescriptor findSymbol(final String fullName) {
+      return findSymbol(fullName, SearchFilter.ALL_SYMBOLS);
+    }
+    
+    /** Find a descriptor by fully-qualified name and given option to only 
+     * search valid field type descriptors. 
+     */
+    GenericDescriptor findSymbol(final String fullName,
+                                 final SearchFilter filter) {
       GenericDescriptor result = descriptorsByName.get(fullName);
       if (result != null) {
-        return result;
+        if ((filter==SearchFilter.ALL_SYMBOLS) ||
+            ((filter==SearchFilter.TYPES_ONLY) && isType(result)) ||
+            ((filter==SearchFilter.AGGREGATES_ONLY) && isAggregate(result))) {
+          return result;
+        }
       }
 
-      for (final DescriptorPool dependency : dependencies) {
-        result = dependency.descriptorsByName.get(fullName);
+      for (final FileDescriptor dependency : dependencies) {
+        result = dependency.pool.descriptorsByName.get(fullName);
         if (result != null) {
-          return result;
+          if ((filter==SearchFilter.ALL_SYMBOLS) ||
+              ((filter==SearchFilter.TYPES_ONLY) && isType(result)) ||
+              ((filter==SearchFilter.AGGREGATES_ONLY) && isAggregate(result))) {
+            return result;
+          }
         }
       }
 
       return null;
     }
 
+    /** Checks if the descriptor is a valid type for a message field. */
+    boolean isType(GenericDescriptor descriptor) {
+      return (descriptor instanceof Descriptor) || 
+        (descriptor instanceof EnumDescriptor);
+    }
+    
+    /** Checks if the descriptor is a valid namespace type. */
+    boolean isAggregate(GenericDescriptor descriptor) {
+      return (descriptor instanceof Descriptor) || 
+        (descriptor instanceof EnumDescriptor) || 
+        (descriptor instanceof PackageDescriptor) || 
+        (descriptor instanceof ServiceDescriptor);
+    }
+       
     /**
-     * Look up a descriptor by name, relative to some other descriptor.
+     * Look up a type descriptor by name, relative to some other descriptor.
      * The name may be fully-qualified (with a leading '.'),
      * partially-qualified, or unqualified.  C++-like name lookup semantics
      * are used to search for the matching descriptor.
      */
     GenericDescriptor lookupSymbol(final String name,
-                                   final GenericDescriptor relativeTo)
+                                   final GenericDescriptor relativeTo,
+                                   final DescriptorPool.SearchFilter filter)
                             throws DescriptorValidationException {
       // TODO(kenton):  This could be optimized in a number of ways.
 
       GenericDescriptor result;
       if (name.startsWith(".")) {
         // Fully-qualified name.
-        result = findSymbol(name.substring(1));
+        result = findSymbol(name.substring(1), filter);
       } else {
         // If "name" is a compound identifier, we want to search for the
         // first component of it, then search within it for the rest.
+        // If name is something like "Foo.Bar.baz", and symbols named "Foo" are
+        // defined in multiple parent scopes, we only want to find "Bar.baz" in
+        // the innermost one.  E.g., the following should produce an error:
+        //   message Bar { message Baz {} }
+        //   message Foo {
+        //     message Bar {
+        //     }
+        //     optional Bar.Baz baz = 1;
+        //   }
+        // So, we look for just "Foo" first, then look for "Bar.baz" within it
+        // if found.
         final int firstPartLength = name.indexOf('.');
         final String firstPart;
         if (firstPartLength == -1) {
@@ -1670,14 +1752,15 @@
           // Chop off the last component of the scope.
           final int dotpos = scopeToTry.lastIndexOf(".");
           if (dotpos == -1) {
-            result = findSymbol(name);
+            result = findSymbol(name, filter);
             break;
           } else {
             scopeToTry.setLength(dotpos + 1);
 
-            // Append firstPart and try to find.
+            // Append firstPart and try to find
             scopeToTry.append(firstPart);
-            result = findSymbol(scopeToTry.toString());
+            result = findSymbol(scopeToTry.toString(), 
+                DescriptorPool.SearchFilter.AGGREGATES_ONLY);
 
             if (result != null) {
               if (firstPartLength != -1) {
@@ -1686,7 +1769,7 @@
                 // searching parent scopes.
                 scopeToTry.setLength(dotpos + 1);
                 scopeToTry.append(name);
-                result = findSymbol(scopeToTry.toString());
+                result = findSymbol(scopeToTry.toString(), filter);
               }
               break;
             }
@@ -1817,7 +1900,7 @@
 
     /**
      * Adds a field to the fieldsByNumber table.  Throws an exception if a
-     * field with hte same containing type and number already exists.
+     * field with the same containing type and number already exists.
      */
     void addFieldByNumber(final FieldDescriptor field)
                    throws DescriptorValidationException {
diff --git a/third_party/protobuf/java/src/main/java/com/google/protobuf/DynamicMessage.java b/third_party/protobuf/java/src/main/java/com/google/protobuf/DynamicMessage.java
index c106b66..c0c9fc9 100644
--- a/third_party/protobuf/java/src/main/java/com/google/protobuf/DynamicMessage.java
+++ b/third_party/protobuf/java/src/main/java/com/google/protobuf/DynamicMessage.java
@@ -35,6 +35,7 @@
 
 import java.io.InputStream;
 import java.io.IOException;
+import java.util.Collections;
 import java.util.Map;
 
 /**
@@ -160,7 +161,9 @@
     verifyContainingType(field);
     Object result = fields.getField(field);
     if (result == null) {
-      if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
+      if (field.isRepeated()) {
+        result = Collections.emptyList();
+      } else if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
         result = getDefaultInstance(field.getMessageType());
       } else {
         result = field.getDefaultValue();
@@ -198,10 +201,12 @@
     return fields.isInitialized();
   }
 
+  @Override
   public boolean isInitialized() {
     return isInitialized(type, fields);
   }
 
+  @Override
   public void writeTo(CodedOutputStream output) throws IOException {
     if (type.getOptions().getMessageSetWireFormat()) {
       fields.writeMessageSetTo(output);
@@ -212,6 +217,7 @@
     }
   }
 
+  @Override
   public int getSerializedSize() {
     int size = memoizedSize;
     if (size != -1) return size;
@@ -236,6 +242,26 @@
     return newBuilderForType().mergeFrom(this);
   }
 
+  public Parser<DynamicMessage> getParserForType() {
+    return new AbstractParser<DynamicMessage>() {
+      public DynamicMessage parsePartialFrom(
+          CodedInputStream input,
+          ExtensionRegistryLite extensionRegistry)
+          throws InvalidProtocolBufferException {
+        Builder builder = newBuilder(type);
+        try {
+          builder.mergeFrom(input, extensionRegistry);
+        } catch (InvalidProtocolBufferException e) {
+          throw e.setUnfinishedMessage(builder.buildPartial());
+        } catch (IOException e) {
+          throw new InvalidProtocolBufferException(e.getMessage())
+              .setUnfinishedMessage(builder.buildPartial());
+        }
+        return builder.buildPartial();
+      }
+    };
+  }
+
   /** Verifies that the field is a field of this message. */
   private void verifyContainingType(FieldDescriptor field) {
     if (field.getContainingType() != type) {
@@ -264,14 +290,18 @@
     // ---------------------------------------------------------------
     // Implementation of Message.Builder interface.
 
+    @Override
     public Builder clear() {
-      if (fields == null) {
-        throw new IllegalStateException("Cannot call clear() after build().");
+      if (fields.isImmutable()) {
+        fields = FieldSet.newFieldSet();
+      } else {
+        fields.clear();
       }
-      fields.clear();
+      unknownFields = UnknownFieldSet.getDefaultInstance();
       return this;
     }
 
+    @Override
     public Builder mergeFrom(Message other) {
       if (other instanceof DynamicMessage) {
         // This should be somewhat faster than calling super.mergeFrom().
@@ -280,6 +310,7 @@
           throw new IllegalArgumentException(
             "mergeFrom(Message) can only merge messages of the same type.");
         }
+        ensureIsMutable();
         fields.mergeFrom(otherDynamicMessage.fields);
         mergeUnknownFields(otherDynamicMessage.unknownFields);
         return this;
@@ -289,8 +320,7 @@
     }
 
     public DynamicMessage build() {
-      // If fields == null, we'll throw an appropriate exception later.
-      if (fields != null && !isInitialized()) {
+      if (!isInitialized()) {
         throw newUninitializedMessageException(
           new DynamicMessage(type, fields, unknownFields));
       }
@@ -312,21 +342,17 @@
     }
 
     public DynamicMessage buildPartial() {
-      if (fields == null) {
-        throw new IllegalStateException(
-            "build() has already been called on this Builder.");
-      }
       fields.makeImmutable();
       DynamicMessage result =
         new DynamicMessage(type, fields, unknownFields);
-      fields = null;
-      unknownFields = null;
       return result;
     }
 
+    @Override
     public Builder clone() {
       Builder result = new Builder(type);
       result.fields.mergeFrom(fields);
+      result.mergeUnknownFields(unknownFields);
       return result;
     }
 
@@ -377,12 +403,14 @@
 
     public Builder setField(FieldDescriptor field, Object value) {
       verifyContainingType(field);
+      ensureIsMutable();
       fields.setField(field, value);
       return this;
     }
 
     public Builder clearField(FieldDescriptor field) {
       verifyContainingType(field);
+      ensureIsMutable();
       fields.clearField(field);
       return this;
     }
@@ -400,12 +428,14 @@
     public Builder setRepeatedField(FieldDescriptor field,
                                     int index, Object value) {
       verifyContainingType(field);
+      ensureIsMutable();
       fields.setRepeatedField(field, index, value);
       return this;
     }
 
     public Builder addRepeatedField(FieldDescriptor field, Object value) {
       verifyContainingType(field);
+      ensureIsMutable();
       fields.addRepeatedField(field, value);
       return this;
     }
@@ -419,6 +449,7 @@
       return this;
     }
 
+    @Override
     public Builder mergeUnknownFields(UnknownFieldSet unknownFields) {
       this.unknownFields =
         UnknownFieldSet.newBuilder(this.unknownFields)
@@ -434,5 +465,18 @@
           "FieldDescriptor does not match message type.");
       }
     }
+
+    private void ensureIsMutable() {
+      if (fields.isImmutable()) {
+        fields = fields.clone();
+      }
+    }
+
+    @Override
+    public com.google.protobuf.Message.Builder getFieldBuilder(FieldDescriptor field) {
+      // TODO(xiangl): need implementation for dynamic message
+      throw new UnsupportedOperationException(
+        "getFieldBuilder() called on a dynamic message type.");
+    }
   }
 }
diff --git a/third_party/protobuf/java/src/main/java/com/google/protobuf/ExtensionRegistryLite.java b/third_party/protobuf/java/src/main/java/com/google/protobuf/ExtensionRegistryLite.java
index d5288dd..1e1289d 100644
--- a/third_party/protobuf/java/src/main/java/com/google/protobuf/ExtensionRegistryLite.java
+++ b/third_party/protobuf/java/src/main/java/com/google/protobuf/ExtensionRegistryLite.java
@@ -43,7 +43,7 @@
  * make sense to mix the two, since if you have any regular types in your
  * program, you then require the full runtime and lose all the benefits of
  * the lite runtime, so you might as well make all your types be regular types.
- * However, in some cases (e.g. when depending on multiple third-patry libraries
+ * However, in some cases (e.g. when depending on multiple third-party libraries
  * where one uses lite types and one uses regular), you may find yourself
  * wanting to mix the two.  In this case things get more complicated.
  * <p>
@@ -71,6 +71,22 @@
  * @author kenton@google.com Kenton Varda
  */
 public class ExtensionRegistryLite {
+
+  // Set true to enable lazy parsing feature for MessageSet.
+  //
+  // TODO(xiangl): Now we use a global flag to control whether enable lazy
+  // parsing feature for MessageSet, which may be too crude for some
+  // applications. Need to support this feature on smaller granularity.
+  private static volatile boolean eagerlyParseMessageSets = false;
+
+  public static boolean isEagerlyParseMessageSets() {
+    return eagerlyParseMessageSets;
+  }
+
+  public static void setEagerlyParseMessageSets(boolean isEagerlyParse) {
+    eagerlyParseMessageSets = isEagerlyParse;
+  }
+
   /** Construct a new, empty instance. */
   public static ExtensionRegistryLite newInstance() {
     return new ExtensionRegistryLite();
diff --git a/third_party/protobuf/java/src/main/java/com/google/protobuf/FieldSet.java b/third_party/protobuf/java/src/main/java/com/google/protobuf/FieldSet.java
index a85dbaa..2663694 100644
--- a/third_party/protobuf/java/src/main/java/com/google/protobuf/FieldSet.java
+++ b/third_party/protobuf/java/src/main/java/com/google/protobuf/FieldSet.java
@@ -30,12 +30,14 @@
 
 package com.google.protobuf;
 
+import com.google.protobuf.LazyField.LazyIterator;
+
+import java.io.IOException;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
-import java.io.IOException;
 
 /**
  * A class which represents an arbitrary set of fields of some message type.
@@ -68,6 +70,7 @@
 
   private final SmallSortedMap<FieldDescriptorType, Object> fields;
   private boolean isImmutable;
+  private boolean hasLazyField = false;
 
   /** Construct a new FieldSet. */
   private FieldSet() {
@@ -95,7 +98,7 @@
       FieldSet<T> emptySet() {
     return DEFAULT_INSTANCE;
   }
-  @SuppressWarnings("unchecked")
+  @SuppressWarnings("rawtypes")
   private static final FieldSet DEFAULT_INSTANCE = new FieldSet(true);
 
   /** Make this FieldSet immutable from this point forward. */
@@ -109,7 +112,7 @@
   }
 
   /**
-   * Retuns whether the FieldSet is immutable. This is true if it is the
+   * Returns whether the FieldSet is immutable. This is true if it is the
    * {@link #emptySet} or if {@link #makeImmutable} were called.
    *
    * @return whether the FieldSet is immutable.
@@ -139,6 +142,7 @@
       FieldDescriptorType descriptor = entry.getKey();
       clone.setField(descriptor, entry.getValue());
     }
+    clone.hasLazyField = hasLazyField;
     return clone;
   }
 
@@ -147,21 +151,52 @@
   /** See {@link Message.Builder#clear()}. */
   public void clear() {
     fields.clear();
+    hasLazyField = false;
   }
 
   /**
    * Get a simple map containing all the fields.
    */
   public Map<FieldDescriptorType, Object> getAllFields() {
+    if (hasLazyField) {
+      SmallSortedMap<FieldDescriptorType, Object> result =
+          SmallSortedMap.newFieldMap(16);
+      for (int i = 0; i < fields.getNumArrayEntries(); i++) {
+        cloneFieldEntry(result, fields.getArrayEntryAt(i));
+      }
+      for (Map.Entry<FieldDescriptorType, Object> entry :
+          fields.getOverflowEntries()) {
+        cloneFieldEntry(result, entry);
+      }
+      if (fields.isImmutable()) {
+        result.makeImmutable();
+      }
+      return result;
+    }
     return fields.isImmutable() ? fields : Collections.unmodifiableMap(fields);
   }
 
+  private void cloneFieldEntry(Map<FieldDescriptorType, Object> map,
+      Map.Entry<FieldDescriptorType, Object> entry) {
+    FieldDescriptorType key = entry.getKey();
+    Object value = entry.getValue();
+    if (value instanceof LazyField) {
+      map.put(key, ((LazyField) value).getValue());
+    } else {
+      map.put(key, value);
+    }
+  }
+
   /**
    * Get an iterator to the field map. This iterator should not be leaked out
-   * of the protobuf library as it is not protected from mutation when
-   * fields is not immutable.
+   * of the protobuf library as it is not protected from mutation when fields
+   * is not immutable.
    */
   public Iterator<Map.Entry<FieldDescriptorType, Object>> iterator() {
+    if (hasLazyField) {
+      return new LazyIterator<FieldDescriptorType>(
+          fields.entrySet().iterator());
+    }
     return fields.entrySet().iterator();
   }
 
@@ -185,14 +220,18 @@
    * to the caller to fetch the field's default value.
    */
   public Object getField(final FieldDescriptorType descriptor) {
-    return fields.get(descriptor);
+    Object o = fields.get(descriptor);
+    if (o instanceof LazyField) {
+      return ((LazyField) o).getValue();
+    }
+    return o;
   }
 
   /**
    * Useful for implementing
    * {@link Message.Builder#setField(Descriptors.FieldDescriptor,Object)}.
    */
-  @SuppressWarnings("unchecked")
+  @SuppressWarnings({"unchecked", "rawtypes"})
   public void setField(final FieldDescriptorType descriptor,
                        Object value) {
     if (descriptor.isRepeated()) {
@@ -204,7 +243,7 @@
       // Wrap the contents in a new list so that the caller cannot change
       // the list's contents after setting it.
       final List newList = new ArrayList();
-      newList.addAll((List)value);
+      newList.addAll((List) value);
       for (final Object element : newList) {
         verifyType(descriptor.getLiteType(), element);
       }
@@ -213,6 +252,9 @@
       verifyType(descriptor.getLiteType(), value);
     }
 
+    if (value instanceof LazyField) {
+      hasLazyField = true;
+    }
     fields.put(descriptor, value);
   }
 
@@ -222,6 +264,9 @@
    */
   public void clearField(final FieldDescriptorType descriptor) {
     fields.remove(descriptor);
+    if (fields.isEmpty()) {
+      hasLazyField = false;
+    }
   }
 
   /**
@@ -234,7 +279,7 @@
         "getRepeatedField() can only be called on repeated fields.");
     }
 
-    final Object value = fields.get(descriptor);
+    final Object value = getField(descriptor);
     if (value == null) {
       return 0;
     } else {
@@ -253,7 +298,7 @@
         "getRepeatedField() can only be called on repeated fields.");
     }
 
-    final Object value = fields.get(descriptor);
+    final Object value = getField(descriptor);
 
     if (value == null) {
       throw new IndexOutOfBoundsException();
@@ -275,13 +320,13 @@
         "getRepeatedField() can only be called on repeated fields.");
     }
 
-    final Object list = fields.get(descriptor);
+    final Object list = getField(descriptor);
     if (list == null) {
       throw new IndexOutOfBoundsException();
     }
 
     verifyType(descriptor.getLiteType(), value);
-    ((List) list).set(index, value);
+    ((List<Object>) list).set(index, value);
   }
 
   /**
@@ -298,13 +343,13 @@
 
     verifyType(descriptor.getLiteType(), value);
 
-    final Object existingValue = fields.get(descriptor);
-    List list;
+    final Object existingValue = getField(descriptor);
+    List<Object> list;
     if (existingValue == null) {
-      list = new ArrayList();
+      list = new ArrayList<Object>();
       fields.put(descriptor, list);
     } else {
-      list = (List) existingValue;
+      list = (List<Object>) existingValue;
     }
 
     list.add(value);
@@ -338,7 +383,8 @@
         break;
       case MESSAGE:
         // TODO(kenton):  Caller must do type checking here, I guess.
-        isValid = value instanceof MessageLite;
+        isValid =
+            (value instanceof MessageLite) || (value instanceof LazyField);
         break;
     }
 
@@ -392,8 +438,16 @@
           }
         }
       } else {
-        if (!((MessageLite) entry.getValue()).isInitialized()) {
-          return false;
+        Object value = entry.getValue();
+        if (value instanceof MessageLite) {
+          if (!((MessageLite) value).isInitialized()) {
+            return false;
+          }
+        } else if (value instanceof LazyField) {
+          return true;
+        } else {
+          throw new IllegalArgumentException(
+              "Wrong object type used with protocol message reflection.");
         }
       }
     }
@@ -416,7 +470,8 @@
   }
 
   /**
-   * Like {@link #mergeFrom(Message)}, but merges from another {@link FieldSet}.
+   * Like {@link Message.Builder#mergeFrom(Message)}, but merges from another 
+   * {@link FieldSet}.
    */
   public void mergeFrom(final FieldSet<FieldDescriptorType> other) {
     for (int i = 0; i < other.fields.getNumArrayEntries(); i++) {
@@ -428,14 +483,17 @@
     }
   }
 
-  @SuppressWarnings("unchecked")
+  @SuppressWarnings({"unchecked", "rawtypes"})
   private void mergeFromField(
       final Map.Entry<FieldDescriptorType, Object> entry) {
     final FieldDescriptorType descriptor = entry.getKey();
-    final Object otherValue = entry.getValue();
+    Object otherValue = entry.getValue();
+    if (otherValue instanceof LazyField) {
+      otherValue = ((LazyField) otherValue).getValue();
+    }
 
     if (descriptor.isRepeated()) {
-      Object value = fields.get(descriptor);
+      Object value = getField(descriptor);
       if (value == null) {
         // Our list is empty, but we still need to make a defensive copy of
         // the other list since we don't know if the other FieldSet is still
@@ -446,7 +504,7 @@
         ((List) value).addAll((List) otherValue);
       }
     } else if (descriptor.getLiteJavaType() == WireFormat.JavaType.MESSAGE) {
-      Object value = fields.get(descriptor);
+      Object value = getField(descriptor);
       if (value == null) {
         fields.put(descriptor, otherValue);
       } else {
@@ -457,7 +515,6 @@
                 ((MessageLite) value).toBuilder(), (MessageLite) otherValue)
             .build());
       }
-
     } else {
       fields.put(descriptor, otherValue);
     }
@@ -646,7 +703,11 @@
         }
       }
     } else {
-      writeElement(output, type, number, value);
+      if (value instanceof LazyField) {
+        writeElement(output, type, number, ((LazyField) value).getValue());
+      } else {
+        writeElement(output, type, number, value);
+      }
     }
   }
 
@@ -686,12 +747,18 @@
   private int getMessageSetSerializedSize(
       final Map.Entry<FieldDescriptorType, Object> entry) {
     final FieldDescriptorType descriptor = entry.getKey();
-    if (descriptor.getLiteJavaType() == WireFormat.JavaType.MESSAGE &&
-        !descriptor.isRepeated() && !descriptor.isPacked()) {
-      return CodedOutputStream.computeMessageSetExtensionSize(
-          entry.getKey().getNumber(), (MessageLite) entry.getValue());
+    Object value = entry.getValue();
+    if (descriptor.getLiteJavaType() == WireFormat.JavaType.MESSAGE
+        && !descriptor.isRepeated() && !descriptor.isPacked()) {
+      if (value instanceof LazyField) {
+        return CodedOutputStream.computeLazyFieldMessageSetExtensionSize(
+            entry.getKey().getNumber(), (LazyField) value);
+      } else {
+        return CodedOutputStream.computeMessageSetExtensionSize(
+            entry.getKey().getNumber(), (MessageLite) value);
+      }
     } else {
-      return computeFieldSize(descriptor, entry.getValue());
+      return computeFieldSize(descriptor, value);
     }
   }
 
@@ -741,7 +808,6 @@
       case BOOL    : return CodedOutputStream.computeBoolSizeNoTag    ((Boolean    )value);
       case STRING  : return CodedOutputStream.computeStringSizeNoTag  ((String     )value);
       case GROUP   : return CodedOutputStream.computeGroupSizeNoTag   ((MessageLite)value);
-      case MESSAGE : return CodedOutputStream.computeMessageSizeNoTag ((MessageLite)value);
       case BYTES   : return CodedOutputStream.computeBytesSizeNoTag   ((ByteString )value);
       case UINT32  : return CodedOutputStream.computeUInt32SizeNoTag  ((Integer    )value);
       case SFIXED32: return CodedOutputStream.computeSFixed32SizeNoTag((Integer    )value);
@@ -749,6 +815,13 @@
       case SINT32  : return CodedOutputStream.computeSInt32SizeNoTag  ((Integer    )value);
       case SINT64  : return CodedOutputStream.computeSInt64SizeNoTag  ((Long       )value);
 
+      case MESSAGE:
+        if (value instanceof LazyField) {
+          return CodedOutputStream.computeLazyFieldSizeNoTag((LazyField) value);
+        } else {
+          return CodedOutputStream.computeMessageSizeNoTag((MessageLite) value);
+        }
+
       case ENUM:
         return CodedOutputStream.computeEnumSizeNoTag(
             ((Internal.EnumLite) value).getNumber());
diff --git a/third_party/protobuf/java/src/main/java/com/google/protobuf/GeneratedMessage.java b/third_party/protobuf/java/src/main/java/com/google/protobuf/GeneratedMessage.java
index b5eaded..0c15ca8 100644
--- a/third_party/protobuf/java/src/main/java/com/google/protobuf/GeneratedMessage.java
+++ b/third_party/protobuf/java/src/main/java/com/google/protobuf/GeneratedMessage.java
@@ -58,8 +58,6 @@
     implements Serializable {
   private static final long serialVersionUID = 1L;
 
-  private final UnknownFieldSet unknownFields;
-
   /**
    * For testing. Allows a test to disable the optimization that avoids using
    * field builders for nested messages until they are requested. By disabling
@@ -68,11 +66,14 @@
   protected static boolean alwaysUseFieldBuilders = false;
 
   protected GeneratedMessage() {
-    this.unknownFields = UnknownFieldSet.getDefaultInstance();
   }
 
   protected GeneratedMessage(Builder<?> builder) {
-    this.unknownFields = builder.getUnknownFields();
+  }
+
+  public Parser<? extends Message> getParserForType() {
+    throw new UnsupportedOperationException(
+        "This is supposed to be overridden by subclasses.");
   }
 
  /**
@@ -175,8 +176,28 @@
   }
 
   //@Override (Java 1.6 override semantics, but we must support 1.5)
-  public final UnknownFieldSet getUnknownFields() {
-    return unknownFields;
+  public UnknownFieldSet getUnknownFields() {
+    throw new UnsupportedOperationException(
+        "This is supposed to be overridden by subclasses.");
+  }
+
+  /**
+   * Called by subclasses to parse an unknown field.
+   * @return {@code true} unless the tag is an end-group tag.
+   */
+  protected boolean parseUnknownField(
+      CodedInputStream input,
+      UnknownFieldSet.Builder unknownFields,
+      ExtensionRegistryLite extensionRegistry,
+      int tag) throws IOException {
+    return unknownFields.mergeFieldFrom(tag, input);
+  }
+
+  /**
+   * Used by parsing constructors in generated classes.
+   */
+  protected void makeExtensionsImmutable() {
+    // Noop for messages without extensions.
   }
 
   protected abstract Message.Builder newBuilderForType(BuilderParent parent);
@@ -319,6 +340,11 @@
     }
 
     //@Override (Java 1.6 override semantics, but we must support 1.5)
+    public Message.Builder getFieldBuilder(final FieldDescriptor field) {
+      return internalGetFieldAccessorTable().getField(field).getBuilder(this);
+    }
+
+    //@Override (Java 1.6 override semantics, but we must support 1.5)
     public boolean hasField(final FieldDescriptor field) {
       return internalGetFieldAccessorTable().getField(field).has(this);
     }
@@ -626,6 +652,25 @@
       return super.isInitialized() && extensionsAreInitialized();
     }
 
+    @Override
+    protected boolean parseUnknownField(
+        CodedInputStream input,
+        UnknownFieldSet.Builder unknownFields,
+        ExtensionRegistryLite extensionRegistry,
+        int tag) throws IOException {
+      return AbstractMessage.Builder.mergeFieldFrom(
+        input, unknownFields, extensionRegistry, getDescriptorForType(),
+        null, extensions, tag);
+    }
+
+    /**
+     * Used by parsing constructors in generated classes.
+     */
+    @Override
+    protected void makeExtensionsImmutable() {
+      extensions.makeImmutable();
+    }
+
     /**
      * Used by subclasses to serialize extensions.  Extension ranges may be
      * interleaved with field numbers, but we must write them in canonical
@@ -655,9 +700,21 @@
           if (messageSetWireFormat && descriptor.getLiteJavaType() ==
                   WireFormat.JavaType.MESSAGE &&
               !descriptor.isRepeated()) {
-            output.writeMessageSetExtension(descriptor.getNumber(),
-                                            (Message) next.getValue());
+            if (next instanceof LazyField.LazyEntry<?>) {
+              output.writeRawMessageSetExtension(descriptor.getNumber(),
+                  ((LazyField.LazyEntry<?>) next).getField().toByteString());
+            } else {
+              output.writeMessageSetExtension(descriptor.getNumber(),
+                                              (Message) next.getValue());
+            }
           } else {
+            // TODO(xiangl): Taken care of following code, it may cause
+            // problem when we use LazyField for normal fields/extensions.
+            // Due to the optional field can be duplicated at the end of
+            // serialized bytes, which will make the serialized size change
+            // after lazy field parsed. So when we use LazyField globally,
+            // we need to change the following write method to write cached
+            // bytes directly rather than write the parsed message.
             FieldSet.writeField(descriptor, next.getValue(), output);
           }
           if (iter.hasNext()) {
@@ -974,7 +1031,8 @@
         final ExtensionRegistryLite extensionRegistry,
         final int tag) throws IOException {
       return AbstractMessage.Builder.mergeFieldFrom(
-        input, unknownFields, extensionRegistry, this, tag);
+        input, unknownFields, extensionRegistry, getDescriptorForType(),
+        this, null, tag);
     }
 
     // ---------------------------------------------------------------
@@ -1405,39 +1463,72 @@
         final String[] camelCaseNames,
         final Class<? extends GeneratedMessage> messageClass,
         final Class<? extends Builder> builderClass) {
-      this.descriptor = descriptor;
-      fields = new FieldAccessor[descriptor.getFields().size()];
+      this(descriptor, camelCaseNames);
+      ensureFieldAccessorsInitialized(messageClass, builderClass);
+    }
 
-      for (int i = 0; i < fields.length; i++) {
-        final FieldDescriptor field = descriptor.getFields().get(i);
-        if (field.isRepeated()) {
-          if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
-            fields[i] = new RepeatedMessageFieldAccessor(
-              field, camelCaseNames[i], messageClass, builderClass);
-          } else if (field.getJavaType() == FieldDescriptor.JavaType.ENUM) {
-            fields[i] = new RepeatedEnumFieldAccessor(
-              field, camelCaseNames[i], messageClass, builderClass);
+    /**
+     * Construct a FieldAccessorTable for a particular message class without
+     * initializing FieldAccessors.
+     */
+    public FieldAccessorTable(
+        final Descriptor descriptor,
+        final String[] camelCaseNames) {
+      this.descriptor = descriptor;
+      this.camelCaseNames = camelCaseNames;
+      fields = new FieldAccessor[descriptor.getFields().size()];
+      initialized = false;
+    }
+
+    /**
+     * Ensures the field accessors are initialized. This method is thread-safe.
+     *
+     * @param messageClass   The message type.
+     * @param builderClass   The builder type.
+     * @return this
+     */
+    public FieldAccessorTable ensureFieldAccessorsInitialized(
+        Class<? extends GeneratedMessage> messageClass,
+        Class<? extends Builder> builderClass) {
+      if (initialized) { return this; }
+      synchronized (this) {
+        if (initialized) { return this; }
+        for (int i = 0; i < fields.length; i++) {
+          FieldDescriptor field = descriptor.getFields().get(i);
+          if (field.isRepeated()) {
+            if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
+              fields[i] = new RepeatedMessageFieldAccessor(
+                  field, camelCaseNames[i], messageClass, builderClass);
+            } else if (field.getJavaType() == FieldDescriptor.JavaType.ENUM) {
+              fields[i] = new RepeatedEnumFieldAccessor(
+                  field, camelCaseNames[i], messageClass, builderClass);
+            } else {
+              fields[i] = new RepeatedFieldAccessor(
+                  field, camelCaseNames[i], messageClass, builderClass);
+            }
           } else {
-            fields[i] = new RepeatedFieldAccessor(
-              field, camelCaseNames[i], messageClass, builderClass);
-          }
-        } else {
-          if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
-            fields[i] = new SingularMessageFieldAccessor(
-              field, camelCaseNames[i], messageClass, builderClass);
-          } else if (field.getJavaType() == FieldDescriptor.JavaType.ENUM) {
-            fields[i] = new SingularEnumFieldAccessor(
-              field, camelCaseNames[i], messageClass, builderClass);
-          } else {
-            fields[i] = new SingularFieldAccessor(
-              field, camelCaseNames[i], messageClass, builderClass);
+            if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
+              fields[i] = new SingularMessageFieldAccessor(
+                  field, camelCaseNames[i], messageClass, builderClass);
+            } else if (field.getJavaType() == FieldDescriptor.JavaType.ENUM) {
+              fields[i] = new SingularEnumFieldAccessor(
+                  field, camelCaseNames[i], messageClass, builderClass);
+            } else {
+              fields[i] = new SingularFieldAccessor(
+                  field, camelCaseNames[i], messageClass, builderClass);
+            }
           }
         }
+        initialized = true;
+        camelCaseNames = null;
+        return this;
       }
     }
 
     private final Descriptor descriptor;
     private final FieldAccessor[] fields;
+    private String[] camelCaseNames;
+    private volatile boolean initialized;
 
     /** Get the FieldAccessor for a particular field. */
     private FieldAccessor getField(final FieldDescriptor field) {
@@ -1472,6 +1563,7 @@
       int getRepeatedCount(GeneratedMessage.Builder builder);
       void clear(Builder builder);
       Message.Builder newBuilder();
+      Message.Builder getBuilder(GeneratedMessage.Builder builder);
     }
 
     // ---------------------------------------------------------------
@@ -1551,6 +1643,10 @@
         throw new UnsupportedOperationException(
           "newBuilderForField() called on a non-Message type.");
       }
+      public Message.Builder getBuilder(GeneratedMessage.Builder builder) {
+        throw new UnsupportedOperationException(
+          "getFieldBuilder() called on a non-Message type.");
+      }
     }
 
     private static class RepeatedFieldAccessor implements FieldAccessor {
@@ -1573,8 +1669,6 @@
                                    "get" + camelCaseName + "List");
         getMethodBuilder = getMethodOrDie(builderClass,
                                    "get" + camelCaseName + "List");
-
-
         getRepeatedMethod =
             getMethodOrDie(messageClass, "get" + camelCaseName, Integer.TYPE);
         getRepeatedMethodBuilder =
@@ -1625,11 +1719,11 @@
       }
       public boolean has(final GeneratedMessage message) {
         throw new UnsupportedOperationException(
-          "hasField() called on a singular field.");
+          "hasField() called on a repeated field.");
       }
       public boolean has(GeneratedMessage.Builder builder) {
         throw new UnsupportedOperationException(
-          "hasField() called on a singular field.");
+          "hasField() called on a repeated field.");
       }
       public int getRepeatedCount(final GeneratedMessage message) {
         return (Integer) invokeOrDie(getCountMethod, message);
@@ -1644,6 +1738,10 @@
         throw new UnsupportedOperationException(
           "newBuilderForField() called on a non-Message type.");
       }
+      public Message.Builder getBuilder(GeneratedMessage.Builder builder) {
+        throw new UnsupportedOperationException(
+          "getFieldBuilder() called on a non-Message type.");
+      }
     }
 
     // ---------------------------------------------------------------
@@ -1753,9 +1851,12 @@
         super(descriptor, camelCaseName, messageClass, builderClass);
 
         newBuilderMethod = getMethodOrDie(type, "newBuilder");
+        getBuilderMethodBuilder =
+            getMethodOrDie(builderClass, "get" + camelCaseName + "Builder");
       }
 
       private final Method newBuilderMethod;
+      private final Method getBuilderMethodBuilder;
 
       private Object coerceType(final Object value) {
         if (type.isInstance(value)) {
@@ -1766,7 +1867,7 @@
           // DynamicMessage -- we should accept it.  In this case we can make
           // a copy of the message.
           return ((Message.Builder) invokeOrDie(newBuilderMethod, null))
-                  .mergeFrom((Message) value).build();
+                  .mergeFrom((Message) value).buildPartial();
         }
       }
 
@@ -1778,6 +1879,10 @@
       public Message.Builder newBuilder() {
         return (Message.Builder) invokeOrDie(newBuilderMethod, null);
       }
+      @Override
+      public Message.Builder getBuilder(GeneratedMessage.Builder builder) {
+        return (Message.Builder) invokeOrDie(getBuilderMethodBuilder, builder);
+      }
     }
 
     private static final class RepeatedMessageFieldAccessor
@@ -1825,7 +1930,7 @@
   /**
    * Replaces this object in the output stream with a serialized form.
    * Part of Java's serialization magic.  Generated sub-classes must override
-   * this method by calling <code>return super.writeReplace();</code>
+   * this method by calling {@code return super.writeReplace();}
    * @return a SerializedForm of this message
    */
   protected Object writeReplace() throws ObjectStreamException {
diff --git a/third_party/protobuf/java/src/main/java/com/google/protobuf/GeneratedMessageLite.java b/third_party/protobuf/java/src/main/java/com/google/protobuf/GeneratedMessageLite.java
index 1813e9b..437e341 100644
--- a/third_party/protobuf/java/src/main/java/com/google/protobuf/GeneratedMessageLite.java
+++ b/third_party/protobuf/java/src/main/java/com/google/protobuf/GeneratedMessageLite.java
@@ -55,6 +55,29 @@
   protected GeneratedMessageLite(Builder builder) {
   }
 
+  public Parser<? extends MessageLite> getParserForType() {
+    throw new UnsupportedOperationException(
+        "This is supposed to be overridden by subclasses.");
+  }
+
+  /**
+   * Called by subclasses to parse an unknown field.
+   * @return {@code true} unless the tag is an end-group tag.
+   */
+  protected boolean parseUnknownField(
+      CodedInputStream input,
+      ExtensionRegistryLite extensionRegistry,
+      int tag) throws IOException {
+    return input.skipField(tag);
+  }
+
+  /**
+   * Used by parsing constructors in generated classes.
+   */
+  protected void makeExtensionsImmutable() {
+    // Noop for messages without extensions.
+  }
+
   @SuppressWarnings("unchecked")
   public abstract static class Builder<MessageType extends GeneratedMessageLite,
                                        BuilderType extends Builder>
@@ -86,9 +109,9 @@
      * @return {@code true} unless the tag is an end-group tag.
      */
     protected boolean parseUnknownField(
-        final CodedInputStream input,
-        final ExtensionRegistryLite extensionRegistry,
-        final int tag) throws IOException {
+        CodedInputStream input,
+        ExtensionRegistryLite extensionRegistry,
+        int tag) throws IOException {
       return input.skipField(tag);
     }
   }
@@ -194,6 +217,31 @@
     }
 
     /**
+     * Called by subclasses to parse an unknown field or an extension.
+     * @return {@code true} unless the tag is an end-group tag.
+     */
+    @Override
+    protected boolean parseUnknownField(
+        CodedInputStream input,
+        ExtensionRegistryLite extensionRegistry,
+        int tag) throws IOException {
+      return GeneratedMessageLite.parseUnknownField(
+          extensions,
+          getDefaultInstanceForType(),
+          input,
+          extensionRegistry,
+          tag);
+    }
+
+    /**
+     * Used by parsing constructors in generated classes.
+     */
+    @Override
+    protected void makeExtensionsImmutable() {
+      extensions.makeImmutable();
+    }
+
+    /**
      * Used by subclasses to serialize extensions.  Extension ranges may be
      * interleaved with field numbers, but we must write them in canonical
      * (sorted by field number) order.  ExtensionWriter helps us write
@@ -400,115 +448,16 @@
      */
     @Override
     protected boolean parseUnknownField(
-        final CodedInputStream input,
-        final ExtensionRegistryLite extensionRegistry,
-        final int tag) throws IOException {
-      final int wireType = WireFormat.getTagWireType(tag);
-      final int fieldNumber = WireFormat.getTagFieldNumber(tag);
-
-      final GeneratedExtension<MessageType, ?> extension =
-        extensionRegistry.findLiteExtensionByNumber(
-            getDefaultInstanceForType(), fieldNumber);
-
-      boolean unknown = false;
-      boolean packed = false;
-      if (extension == null) {
-        unknown = true;  // Unknown field.
-      } else if (wireType == FieldSet.getWireFormatForFieldType(
-                   extension.descriptor.getLiteType(),
-                   false  /* isPacked */)) {
-        packed = false;  // Normal, unpacked value.
-      } else if (extension.descriptor.isRepeated &&
-                 extension.descriptor.type.isPackable() &&
-                 wireType == FieldSet.getWireFormatForFieldType(
-                   extension.descriptor.getLiteType(),
-                   true  /* isPacked */)) {
-        packed = true;  // Packed value.
-      } else {
-        unknown = true;  // Wrong wire type.
-      }
-
-      if (unknown) {  // Unknown field or wrong wire type.  Skip.
-        return input.skipField(tag);
-      }
-
-      if (packed) {
-        final int length = input.readRawVarint32();
-        final int limit = input.pushLimit(length);
-        if (extension.descriptor.getLiteType() == WireFormat.FieldType.ENUM) {
-          while (input.getBytesUntilLimit() > 0) {
-            final int rawValue = input.readEnum();
-            final Object value =
-                extension.descriptor.getEnumType().findValueByNumber(rawValue);
-            if (value == null) {
-              // If the number isn't recognized as a valid value for this
-              // enum, drop it (don't even add it to unknownFields).
-              return true;
-            }
-            ensureExtensionsIsMutable();
-            extensions.addRepeatedField(extension.descriptor, value);
-          }
-        } else {
-          while (input.getBytesUntilLimit() > 0) {
-            final Object value =
-              FieldSet.readPrimitiveField(input,
-                                          extension.descriptor.getLiteType());
-            ensureExtensionsIsMutable();
-            extensions.addRepeatedField(extension.descriptor, value);
-          }
-        }
-        input.popLimit(limit);
-      } else {
-        final Object value;
-        switch (extension.descriptor.getLiteJavaType()) {
-          case MESSAGE: {
-            MessageLite.Builder subBuilder = null;
-            if (!extension.descriptor.isRepeated()) {
-              MessageLite existingValue =
-                  (MessageLite) extensions.getField(extension.descriptor);
-              if (existingValue != null) {
-                subBuilder = existingValue.toBuilder();
-              }
-            }
-            if (subBuilder == null) {
-              subBuilder = extension.messageDefaultInstance.newBuilderForType();
-            }
-            if (extension.descriptor.getLiteType() ==
-                WireFormat.FieldType.GROUP) {
-              input.readGroup(extension.getNumber(),
-                              subBuilder, extensionRegistry);
-            } else {
-              input.readMessage(subBuilder, extensionRegistry);
-            }
-            value = subBuilder.build();
-            break;
-          }
-          case ENUM:
-            final int rawValue = input.readEnum();
-            value = extension.descriptor.getEnumType()
-                             .findValueByNumber(rawValue);
-            // If the number isn't recognized as a valid value for this enum,
-            // drop it.
-            if (value == null) {
-              return true;
-            }
-            break;
-          default:
-            value = FieldSet.readPrimitiveField(input,
-                extension.descriptor.getLiteType());
-            break;
-        }
-
-        if (extension.descriptor.isRepeated()) {
-          ensureExtensionsIsMutable();
-          extensions.addRepeatedField(extension.descriptor, value);
-        } else {
-          ensureExtensionsIsMutable();
-          extensions.setField(extension.descriptor, value);
-        }
-      }
-
-      return true;
+        CodedInputStream input,
+        ExtensionRegistryLite extensionRegistry,
+        int tag) throws IOException {
+      ensureExtensionsIsMutable();
+      return GeneratedMessageLite.parseUnknownField(
+          extensions,
+          getDefaultInstanceForType(),
+          input,
+          extensionRegistry,
+          tag);
     }
 
     protected final void mergeExtensionFields(final MessageType other) {
@@ -519,6 +468,123 @@
 
   // -----------------------------------------------------------------
 
+  /**
+   * Parse an unknown field or an extension.
+   * @return {@code true} unless the tag is an end-group tag.
+   */
+  private static <MessageType extends MessageLite>
+      boolean parseUnknownField(
+          FieldSet<ExtensionDescriptor> extensions,
+          MessageType defaultInstance,
+          CodedInputStream input,
+          ExtensionRegistryLite extensionRegistry,
+          int tag) throws IOException {
+    int wireType = WireFormat.getTagWireType(tag);
+    int fieldNumber = WireFormat.getTagFieldNumber(tag);
+
+    GeneratedExtension<MessageType, ?> extension =
+      extensionRegistry.findLiteExtensionByNumber(
+          defaultInstance, fieldNumber);
+
+    boolean unknown = false;
+    boolean packed = false;
+    if (extension == null) {
+      unknown = true;  // Unknown field.
+    } else if (wireType == FieldSet.getWireFormatForFieldType(
+                 extension.descriptor.getLiteType(),
+                 false  /* isPacked */)) {
+      packed = false;  // Normal, unpacked value.
+    } else if (extension.descriptor.isRepeated &&
+               extension.descriptor.type.isPackable() &&
+               wireType == FieldSet.getWireFormatForFieldType(
+                 extension.descriptor.getLiteType(),
+                 true  /* isPacked */)) {
+      packed = true;  // Packed value.
+    } else {
+      unknown = true;  // Wrong wire type.
+    }
+
+    if (unknown) {  // Unknown field or wrong wire type.  Skip.
+      return input.skipField(tag);
+    }
+
+    if (packed) {
+      int length = input.readRawVarint32();
+      int limit = input.pushLimit(length);
+      if (extension.descriptor.getLiteType() == WireFormat.FieldType.ENUM) {
+        while (input.getBytesUntilLimit() > 0) {
+          int rawValue = input.readEnum();
+          Object value =
+              extension.descriptor.getEnumType().findValueByNumber(rawValue);
+          if (value == null) {
+            // If the number isn't recognized as a valid value for this
+            // enum, drop it (don't even add it to unknownFields).
+            return true;
+          }
+          extensions.addRepeatedField(extension.descriptor, value);
+        }
+      } else {
+        while (input.getBytesUntilLimit() > 0) {
+          Object value =
+            FieldSet.readPrimitiveField(input,
+                                        extension.descriptor.getLiteType());
+          extensions.addRepeatedField(extension.descriptor, value);
+        }
+      }
+      input.popLimit(limit);
+    } else {
+      Object value;
+      switch (extension.descriptor.getLiteJavaType()) {
+        case MESSAGE: {
+          MessageLite.Builder subBuilder = null;
+          if (!extension.descriptor.isRepeated()) {
+            MessageLite existingValue =
+                (MessageLite) extensions.getField(extension.descriptor);
+            if (existingValue != null) {
+              subBuilder = existingValue.toBuilder();
+            }
+          }
+          if (subBuilder == null) {
+            subBuilder = extension.messageDefaultInstance.newBuilderForType();
+          }
+          if (extension.descriptor.getLiteType() ==
+              WireFormat.FieldType.GROUP) {
+            input.readGroup(extension.getNumber(),
+                            subBuilder, extensionRegistry);
+          } else {
+            input.readMessage(subBuilder, extensionRegistry);
+          }
+          value = subBuilder.build();
+          break;
+        }
+        case ENUM:
+          int rawValue = input.readEnum();
+          value = extension.descriptor.getEnumType()
+                           .findValueByNumber(rawValue);
+          // If the number isn't recognized as a valid value for this enum,
+          // drop it.
+          if (value == null) {
+            return true;
+          }
+          break;
+        default:
+          value = FieldSet.readPrimitiveField(input,
+              extension.descriptor.getLiteType());
+          break;
+      }
+
+      if (extension.descriptor.isRepeated()) {
+        extensions.addRepeatedField(extension.descriptor, value);
+      } else {
+        extensions.setField(extension.descriptor, value);
+      }
+    }
+
+    return true;
+  }
+
+  // -----------------------------------------------------------------
+
   /** For use by generated code only. */
   public static <ContainingType extends MessageLite, Type>
       GeneratedExtension<ContainingType, Type>
@@ -722,7 +788,7 @@
   /**
    * Replaces this object in the output stream with a serialized form.
    * Part of Java's serialization magic.  Generated sub-classes must override
-   * this method by calling <code>return super.writeReplace();</code>
+   * this method by calling {@code return super.writeReplace();}
    * @return a SerializedForm of this message
    */
   protected Object writeReplace() throws ObjectStreamException {
diff --git a/third_party/protobuf/java/src/main/java/com/google/protobuf/Internal.java b/third_party/protobuf/java/src/main/java/com/google/protobuf/Internal.java
index 05eab57..81af258 100644
--- a/third_party/protobuf/java/src/main/java/com/google/protobuf/Internal.java
+++ b/third_party/protobuf/java/src/main/java/com/google/protobuf/Internal.java
@@ -103,85 +103,32 @@
    * Helper called by generated code to determine if a byte array is a valid
    * UTF-8 encoded string such that the original bytes can be converted to
    * a String object and then back to a byte array round tripping the bytes
-   * without loss.
-   * <p>
-   * This is inspired by UTF_8.java in sun.nio.cs.
+   * without loss.  More precisely, returns {@code true} whenever:
+   * <pre>   {@code
+   * Arrays.equals(byteString.toByteArray(),
+   *     new String(byteString.toByteArray(), "UTF-8").getBytes("UTF-8"))
+   * }</pre>
+   *
+   * <p>This method rejects "overlong" byte sequences, as well as
+   * 3-byte sequences that would map to a surrogate character, in
+   * accordance with the restricted definition of UTF-8 introduced in
+   * Unicode 3.1.  Note that the UTF-8 decoder included in Oracle's
+   * JDK has been modified to also reject "overlong" byte sequences,
+   * but currently (2011) still accepts 3-byte surrogate character
+   * byte sequences.
+   *
+   * <p>See the Unicode Standard,</br>
+   * Table 3-6. <em>UTF-8 Bit Distribution</em>,</br>
+   * Table 3-7. <em>Well Formed UTF-8 Byte Sequences</em>.
+   *
+   * <p>As of 2011-02, this method simply returns the result of {@link
+   * ByteString#isValidUtf8()}.  Calling that method directly is preferred.
    *
    * @param byteString the string to check
    * @return whether the byte array is round trippable
    */
   public static boolean isValidUtf8(ByteString byteString) {
-    int index = 0;
-    int size = byteString.size();
-    // To avoid the masking, we could change this to use bytes;
-    // Then X > 0xC2 gets turned into X < -0xC2; X < 0x80
-    // gets turned into X >= 0, etc.
-
-    while (index < size) {
-      int byte1 = byteString.byteAt(index++) & 0xFF;
-      if (byte1 < 0x80) {
-        // fast loop for single bytes
-        continue;
-
-        // we know from this point on that we have 2-4 byte forms
-      } else if (byte1 < 0xC2 || byte1 > 0xF4) {
-        // catch illegal first bytes: < C2 or > F4
-        return false;
-      }
-      if (index >= size) {
-        // fail if we run out of bytes
-        return false;
-      }
-      int byte2 = byteString.byteAt(index++) & 0xFF;
-      if (byte2 < 0x80 || byte2 > 0xBF) {
-        // general trail-byte test
-        return false;
-      }
-      if (byte1 <= 0xDF) {
-        // two-byte form; general trail-byte test is sufficient
-        continue;
-      }
-
-      // we know from this point on that we have 3 or 4 byte forms
-      if (index >= size) {
-        // fail if we run out of bytes
-        return false;
-      }
-      int byte3 = byteString.byteAt(index++) & 0xFF;
-      if (byte3 < 0x80 || byte3 > 0xBF) {
-        // general trail-byte test
-        return false;
-      }
-      if (byte1 <= 0xEF) {
-        // three-byte form. Vastly more frequent than four-byte forms
-        // The following has an extra test, but not worth restructuring
-        if (byte1 == 0xE0 && byte2 < 0xA0 ||
-            byte1 == 0xED && byte2 > 0x9F) {
-          // check special cases of byte2
-          return false;
-        }
-
-      } else {
-        // four-byte form
-
-        if (index >= size) {
-          // fail if we run out of bytes
-          return false;
-        }
-        int byte4 = byteString.byteAt(index++) & 0xFF;
-        if (byte4 < 0x80 || byte4 > 0xBF) {
-          // general trail-byte test
-          return false;
-        }
-        // The following has an extra test, but not worth restructuring
-        if (byte1 == 0xF0 && byte2 < 0x90 ||
-            byte1 == 0xF4 && byte2 > 0x8F) {
-          // check special cases of byte2
-          return false;
-        }
-      }
-    }
-    return true;
+    return byteString.isValidUtf8();
   }
 
   /**
diff --git a/third_party/protobuf/java/src/main/java/com/google/protobuf/InvalidProtocolBufferException.java b/third_party/protobuf/java/src/main/java/com/google/protobuf/InvalidProtocolBufferException.java
index 90f7ffb..72d7ff7 100644
--- a/third_party/protobuf/java/src/main/java/com/google/protobuf/InvalidProtocolBufferException.java
+++ b/third_party/protobuf/java/src/main/java/com/google/protobuf/InvalidProtocolBufferException.java
@@ -40,11 +40,32 @@
  */
 public class InvalidProtocolBufferException extends IOException {
   private static final long serialVersionUID = -1616151763072450476L;
+  private MessageLite unfinishedMessage = null;
 
   public InvalidProtocolBufferException(final String description) {
     super(description);
   }
 
+  /**
+   * Attaches an unfinished message to the exception to support best-effort
+   * parsing in {@code Parser} interface.
+   *
+   * @return this
+   */
+  public InvalidProtocolBufferException setUnfinishedMessage(
+      MessageLite unfinishedMessage) {
+    this.unfinishedMessage = unfinishedMessage;
+    return this;
+  }
+
+  /**
+   * Returns the unfinished message attached to the exception, or null if
+   * no message is attached.
+   */
+  public MessageLite getUnfinishedMessage() {
+    return unfinishedMessage;
+  }
+
   static InvalidProtocolBufferException truncatedMessage() {
     return new InvalidProtocolBufferException(
       "While parsing a protocol message, the input ended unexpectedly " +
diff --git a/third_party/protobuf/java/src/main/java/com/google/protobuf/LazyField.java b/third_party/protobuf/java/src/main/java/com/google/protobuf/LazyField.java
new file mode 100644
index 0000000..df9425e
--- /dev/null
+++ b/third_party/protobuf/java/src/main/java/com/google/protobuf/LazyField.java
@@ -0,0 +1,216 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 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.
+
+package com.google.protobuf;
+
+import java.io.IOException;
+import java.util.Iterator;
+import java.util.Map.Entry;
+
+/**
+ * LazyField encapsulates the logic of lazily parsing message fields. It stores
+ * the message in a ByteString initially and then parse it on-demand.
+ *
+ * LazyField is thread-compatible e.g. concurrent read are safe, however,
+ * synchronizations are needed under read/write situations.
+ *
+ * Now LazyField is only used to lazily load MessageSet.
+ * TODO(xiangl): Use LazyField to lazily load all messages.
+ *
+ * @author xiangl@google.com (Xiang Li)
+ */
+class LazyField {
+
+  final private MessageLite defaultInstance;
+  final private ExtensionRegistryLite extensionRegistry;
+
+  // Mutable because it is initialized lazily.
+  private ByteString bytes;
+  private volatile MessageLite value;
+  private volatile boolean isDirty = false;
+
+  public LazyField(MessageLite defaultInstance,
+      ExtensionRegistryLite extensionRegistry, ByteString bytes) {
+    this.defaultInstance = defaultInstance;
+    this.extensionRegistry = extensionRegistry;
+    this.bytes = bytes;
+  }
+
+  public MessageLite getValue() {
+    ensureInitialized();
+    return value;
+  }
+
+  /**
+   * LazyField is not thread-safe for write access. Synchronizations are needed
+   * under read/write situations.
+   */
+  public MessageLite setValue(MessageLite value) {
+    MessageLite originalValue = this.value;
+    this.value = value;
+    bytes = null;
+    isDirty = true;
+    return originalValue;
+  }
+
+  /**
+   * Due to the optional field can be duplicated at the end of serialized
+   * bytes, which will make the serialized size changed after LazyField
+   * parsed. Be careful when using this method.
+   */
+  public int getSerializedSize() {
+    if (isDirty) {
+      return value.getSerializedSize();
+    }
+    return bytes.size();
+  }
+
+  public ByteString toByteString() {
+    if (!isDirty) {
+      return bytes;
+    }
+    synchronized (this) {
+      if (!isDirty) {
+        return bytes;
+      }
+      bytes = value.toByteString();
+      isDirty = false;
+      return bytes;
+    }
+  }
+
+  @Override
+  public int hashCode() {
+    ensureInitialized();
+    return value.hashCode();
+  }
+
+  @Override
+  public boolean equals(Object obj) {
+    ensureInitialized();
+    return value.equals(obj);
+  }
+
+  @Override
+  public String toString() {
+    ensureInitialized();
+    return value.toString();
+  }
+
+  private void ensureInitialized() {
+    if (value != null) {
+      return;
+    }
+    synchronized (this) {
+      if (value != null) {
+        return;
+      }
+      try {
+        if (bytes != null) {
+          value = defaultInstance.getParserForType()
+              .parseFrom(bytes, extensionRegistry);
+        }
+      } catch (IOException e) {
+        // TODO(xiangl): Refactory the API to support the exception thrown from
+        // lazily load messages.
+      }
+    }
+  }
+
+  // ====================================================
+
+  /**
+   * LazyEntry and LazyIterator are used to encapsulate the LazyField, when
+   * users iterate all fields from FieldSet.
+   */
+  static class LazyEntry<K> implements Entry<K, Object> {
+    private Entry<K, LazyField> entry;
+
+    private LazyEntry(Entry<K, LazyField> entry) {
+      this.entry = entry;
+    }
+
+    @Override
+    public K getKey() {
+      return entry.getKey();
+    }
+
+    @Override
+    public Object getValue() {
+      LazyField field = entry.getValue();
+      if (field == null) {
+        return null;
+      }
+      return field.getValue();
+    }
+
+    public LazyField getField() {
+      return entry.getValue();
+    }
+
+    @Override
+    public Object setValue(Object value) {
+      if (!(value instanceof MessageLite)) {
+        throw new IllegalArgumentException(
+            "LazyField now only used for MessageSet, "
+            + "and the value of MessageSet must be an instance of MessageLite");
+      }
+      return entry.getValue().setValue((MessageLite) value);
+    }
+  }
+
+  static class LazyIterator<K> implements Iterator<Entry<K, Object>> {
+    private Iterator<Entry<K, Object>> iterator;
+
+    public LazyIterator(Iterator<Entry<K, Object>> iterator) {
+      this.iterator = iterator;
+    }
+
+    @Override
+    public boolean hasNext() {
+      return iterator.hasNext();
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public Entry<K, Object> next() {
+      Entry<K, ?> entry = iterator.next();
+      if (entry.getValue() instanceof LazyField) {
+        return new LazyEntry<K>((Entry<K, LazyField>) entry);
+      }
+      return (Entry<K, Object>) entry;
+    }
+
+    @Override
+    public void remove() {
+      iterator.remove();
+    }
+  }
+}
diff --git a/third_party/protobuf/java/src/main/java/com/google/protobuf/LazyStringArrayList.java b/third_party/protobuf/java/src/main/java/com/google/protobuf/LazyStringArrayList.java
index 1683a64..75c6a4b 100644
--- a/third_party/protobuf/java/src/main/java/com/google/protobuf/LazyStringArrayList.java
+++ b/third_party/protobuf/java/src/main/java/com/google/protobuf/LazyStringArrayList.java
@@ -33,8 +33,9 @@
 import java.util.List;
 import java.util.AbstractList;
 import java.util.ArrayList;
-import java.util.RandomAccess;
 import java.util.Collection;
+import java.util.Collections;
+import java.util.RandomAccess;
 
 /**
  * An implementation of {@link LazyStringList} that wraps an ArrayList. Each
@@ -72,6 +73,11 @@
     list = new ArrayList<Object>();
   }
 
+  public LazyStringArrayList(LazyStringList from) {
+    list = new ArrayList<Object>(from.size());
+    addAll(from);
+  }
+
   public LazyStringArrayList(List<String> from) {
     list = new ArrayList<Object>(from);
   }
@@ -84,7 +90,7 @@
     } else {
       ByteString bs = (ByteString) o;
       String s = bs.toStringUtf8();
-      if (Internal.isValidUtf8(bs)) {
+      if (bs.isValidUtf8()) {
         list.set(index, s);
       }
       return s;
@@ -109,8 +115,21 @@
   }
 
   @Override
+  public boolean addAll(Collection<? extends String> c) {
+    // The default implementation of AbstractCollection.addAll(Collection)
+    // delegates to add(Object). This implementation instead delegates to
+    // addAll(int, Collection), which makes a special case for Collections
+    // which are instances of LazyStringList.
+    return addAll(size(), c);
+  }
+
+  @Override
   public boolean addAll(int index, Collection<? extends String> c) {
-    boolean ret = list.addAll(index, c);
+    // When copying from another LazyStringList, directly copy the underlying
+    // elements rather than forcing each element to be decoded to a String.
+    Collection<?> collection = c instanceof LazyStringList
+        ? ((LazyStringList) c).getUnderlyingElements() : c;
+    boolean ret = list.addAll(index, collection);
     modCount++;
     return ret;
   }
@@ -152,4 +171,9 @@
       return ((ByteString) o).toStringUtf8();
     }
   }
+
+  @Override
+  public List<?> getUnderlyingElements() {
+    return Collections.unmodifiableList(list);
+  }
 }
diff --git a/third_party/protobuf/java/src/main/java/com/google/protobuf/LazyStringList.java b/third_party/protobuf/java/src/main/java/com/google/protobuf/LazyStringList.java
index 97139ca..630932f 100644
--- a/third_party/protobuf/java/src/main/java/com/google/protobuf/LazyStringList.java
+++ b/third_party/protobuf/java/src/main/java/com/google/protobuf/LazyStringList.java
@@ -33,7 +33,7 @@
 import java.util.List;
 
 /**
- * An interface extending List&lt;String&gt; that also provides access to the
+ * An interface extending {@code List<String>} that also provides access to the
  * items of the list as UTF8-encoded ByteString objects. This is used by the
  * protocol buffer implementation to support lazily converting bytes parsed
  * over the wire to String objects until needed and also increases the
@@ -41,9 +41,9 @@
  * ByteString is already cached.
  * <p>
  * This only adds additional methods that are required for the use in the
- * protocol buffer code in order to be able successfuly round trip byte arrays
+ * protocol buffer code in order to be able successfully round trip byte arrays
  * through parsing and serialization without conversion to strings. It's not
- * attempting to support the functionality of say List&ltByteString&gt, hence
+ * attempting to support the functionality of say {@code List<ByteString>}, hence
  * why only these two very specific methods are added.
  *
  * @author jonp@google.com (Jon Perlow)
@@ -56,7 +56,7 @@
    * @param index index of the element to return
    * @return the element at the specified position in this list
    * @throws IndexOutOfBoundsException if the index is out of range
-   *         (<tt>index &lt; 0 || index &gt;= size()</tt>)
+   *         ({@code index < 0 || index >= size()})
    */
   ByteString getByteString(int index);
 
@@ -69,4 +69,13 @@
    *         is not supported by this list
    */
   void add(ByteString element);
+
+  /**
+   * Returns an unmodifiable List of the underlying elements, each of
+   * which is either a {@code String} or its equivalent UTF-8 encoded
+   * {@code ByteString}. It is an error for the caller to modify the returned
+   * List, and attempting to do so will result in an
+   * {@link UnsupportedOperationException}.
+   */
+  List<?> getUnderlyingElements();
 }
diff --git a/third_party/protobuf/java/src/main/java/com/google/protobuf/LiteralByteString.java b/third_party/protobuf/java/src/main/java/com/google/protobuf/LiteralByteString.java
new file mode 100644
index 0000000..93c53dc
--- /dev/null
+++ b/third_party/protobuf/java/src/main/java/com/google/protobuf/LiteralByteString.java
@@ -0,0 +1,349 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 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.
+
+package com.google.protobuf;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.UnsupportedEncodingException;
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.NoSuchElementException;
+
+/**
+ * This class implements a {@link com.google.protobuf.ByteString} backed by a
+ * single array of bytes, contiguous in memory. It supports substring by
+ * pointing to only a sub-range of the underlying byte array, meaning that a
+ * substring will reference the full byte-array of the string it's made from,
+ * exactly as with {@link String}.
+ *
+ * @author carlanton@google.com (Carl Haverl)
+ */
+class LiteralByteString extends ByteString {
+
+  protected final byte[] bytes;
+
+  /**
+   * Creates a {@code LiteralByteString} backed by the given array, without
+   * copying.
+   *
+   * @param bytes array to wrap
+   */
+  LiteralByteString(byte[] bytes) {
+    this.bytes = bytes;
+  }
+
+  @Override
+  public byte byteAt(int index) {
+    // Unlike most methods in this class, this one is a direct implementation
+    // ignoring the potential offset because we need to do range-checking in the
+    // substring case anyway.
+    return bytes[index];
+  }
+
+  @Override
+  public int size() {
+    return bytes.length;
+  }
+
+  // =================================================================
+  // ByteString -> substring
+
+  @Override
+  public ByteString substring(int beginIndex, int endIndex) {
+    if (beginIndex < 0) {
+      throw new IndexOutOfBoundsException(
+          "Beginning index: " + beginIndex + " < 0");
+    }
+    if (endIndex > size()) {
+      throw new IndexOutOfBoundsException("End index: " + endIndex + " > " +
+          size());
+    }
+    int substringLength = endIndex - beginIndex;
+    if (substringLength < 0) {
+      throw new IndexOutOfBoundsException(
+          "Beginning index larger than ending index: " + beginIndex + ", "
+              + endIndex);
+    }
+
+    ByteString result;
+    if (substringLength == 0) {
+      result = ByteString.EMPTY;
+    } else {
+      result = new BoundedByteString(bytes, getOffsetIntoBytes() + beginIndex,
+          substringLength);
+    }
+    return result;
+  }
+
+  // =================================================================
+  // ByteString -> byte[]
+
+  @Override
+  protected void copyToInternal(byte[] target, int sourceOffset, 
+      int targetOffset, int numberToCopy) {
+    // Optimized form, not for subclasses, since we don't call
+    // getOffsetIntoBytes() or check the 'numberToCopy' parameter.
+    System.arraycopy(bytes, sourceOffset, target, targetOffset, numberToCopy);
+  }
+
+  @Override
+  public void copyTo(ByteBuffer target) {
+    target.put(bytes, getOffsetIntoBytes(), size());  // Copies bytes
+  }
+
+  @Override
+  public ByteBuffer asReadOnlyByteBuffer() {
+    ByteBuffer byteBuffer =
+        ByteBuffer.wrap(bytes, getOffsetIntoBytes(), size());
+    return byteBuffer.asReadOnlyBuffer();
+  }
+
+  @Override
+  public List<ByteBuffer> asReadOnlyByteBufferList() {
+    // Return the ByteBuffer generated by asReadOnlyByteBuffer() as a singleton
+    List<ByteBuffer> result = new ArrayList<ByteBuffer>(1);
+    result.add(asReadOnlyByteBuffer());
+    return result;
+ }
+
+ @Override
+  public void writeTo(OutputStream outputStream) throws IOException {
+    outputStream.write(toByteArray());
+  }
+
+  @Override
+  public String toString(String charsetName)
+      throws UnsupportedEncodingException {
+    return new String(bytes, getOffsetIntoBytes(), size(), charsetName);
+  }
+
+  // =================================================================
+  // UTF-8 decoding
+
+  @Override
+  public boolean isValidUtf8() {
+    int offset = getOffsetIntoBytes();
+    return Utf8.isValidUtf8(bytes, offset, offset + size());
+  }
+
+  @Override
+  protected int partialIsValidUtf8(int state, int offset, int length) {
+    int index = getOffsetIntoBytes() + offset;
+    return Utf8.partialIsValidUtf8(state, bytes, index, index + length);
+  }
+
+  // =================================================================
+  // equals() and hashCode()
+
+  @Override
+  public boolean equals(Object other) {
+    if (other == this) {
+      return true;
+    }
+    if (!(other instanceof ByteString)) {
+      return false;
+    }
+
+    if (size() != ((ByteString) other).size()) {
+      return false;
+    }
+    if (size() == 0) {
+      return true;
+    }
+
+    if (other instanceof LiteralByteString) {
+      return equalsRange((LiteralByteString) other, 0, size());
+    } else if (other instanceof RopeByteString) {
+      return other.equals(this);
+    } else {
+      throw new IllegalArgumentException(
+          "Has a new type of ByteString been created? Found "
+              + other.getClass());
+    }
+  }
+
+  /**
+   * Check equality of the substring of given length of this object starting at
+   * zero with another {@code LiteralByteString} substring starting at offset.
+   *
+   * @param other  what to compare a substring in
+   * @param offset offset into other
+   * @param length number of bytes to compare
+   * @return true for equality of substrings, else false.
+   */
+  boolean equalsRange(LiteralByteString other, int offset, int length) {
+    if (length > other.size()) {
+      throw new IllegalArgumentException(
+          "Length too large: " + length + size());
+    }
+    if (offset + length > other.size()) {
+      throw new IllegalArgumentException(
+          "Ran off end of other: " + offset + ", " + length + ", " +
+              other.size());
+    }
+
+    byte[] thisBytes = bytes;
+    byte[] otherBytes = other.bytes;
+    int thisLimit = getOffsetIntoBytes() + length;
+    for (int thisIndex = getOffsetIntoBytes(), otherIndex =
+        other.getOffsetIntoBytes() + offset;
+        (thisIndex < thisLimit); ++thisIndex, ++otherIndex) {
+      if (thisBytes[thisIndex] != otherBytes[otherIndex]) {
+        return false;
+      }
+    }
+    return true;
+  }
+
+  /**
+   * Cached hash value.  Intentionally accessed via a data race, which
+   * is safe because of the Java Memory Model's "no out-of-thin-air values"
+   * guarantees for ints.
+   */
+  private int hash = 0;
+
+  /**
+   * Compute the hashCode using the traditional algorithm from {@link
+   * ByteString}.
+   *
+   * @return hashCode value
+   */
+  @Override
+  public int hashCode() {
+    int h = hash;
+
+    if (h == 0) {
+      int size = size();
+      h = partialHash(size, 0, size);
+      if (h == 0) {
+        h = 1;
+      }
+      hash = h;
+    }
+    return h;
+  }
+
+  @Override
+  protected int peekCachedHashCode() {
+    return hash;
+  }
+
+  @Override
+  protected int partialHash(int h, int offset, int length) {
+    byte[] thisBytes = bytes;
+    for (int i = getOffsetIntoBytes() + offset, limit = i + length; i < limit;
+        i++) {
+      h = h * 31 + thisBytes[i];
+    }
+    return h;
+  }
+
+  // =================================================================
+  // Input stream
+
+  @Override
+  public InputStream newInput() {
+    return new ByteArrayInputStream(bytes, getOffsetIntoBytes(),
+        size());  // No copy
+  }
+
+  @Override
+  public CodedInputStream newCodedInput() {
+    // We trust CodedInputStream not to modify the bytes, or to give anyone
+    // else access to them.
+    return CodedInputStream
+        .newInstance(bytes, getOffsetIntoBytes(), size());  // No copy
+  }
+
+  // =================================================================
+  // ByteIterator
+
+  @Override
+  public ByteIterator iterator() {
+    return new LiteralByteIterator();
+  }
+
+  private class LiteralByteIterator implements ByteIterator {
+    private int position;
+    private final int limit;
+
+    private LiteralByteIterator() {
+      position = 0;
+      limit = size();
+    }
+
+    public boolean hasNext() {
+      return (position < limit);
+    }
+
+    public Byte next() {
+      // Boxing calls Byte.valueOf(byte), which does not instantiate.
+      return nextByte();
+    }
+
+    public byte nextByte() {
+      try {
+        return bytes[position++];
+      } catch (ArrayIndexOutOfBoundsException e) {
+        throw new NoSuchElementException(e.getMessage());
+      }
+    }
+
+    public void remove() {
+      throw new UnsupportedOperationException();
+    }
+  }
+
+  // =================================================================
+  // Internal methods
+
+  @Override
+  protected int getTreeDepth() {
+    return 0;
+  }
+
+  @Override
+  protected boolean isBalanced() {
+    return true;
+  }
+
+  /**
+   * Offset into {@code bytes[]} to use, non-zero for substrings.
+   *
+   * @return always 0 for this class
+   */
+  protected int getOffsetIntoBytes() {
+    return 0;
+  }
+}
diff --git a/third_party/protobuf/java/src/main/java/com/google/protobuf/Message.java b/third_party/protobuf/java/src/main/java/com/google/protobuf/Message.java
index 67c4148..2b88141 100644
--- a/third_party/protobuf/java/src/main/java/com/google/protobuf/Message.java
+++ b/third_party/protobuf/java/src/main/java/com/google/protobuf/Message.java
@@ -50,25 +50,28 @@
  */
 public interface Message extends MessageLite, MessageOrBuilder {
 
+  // (From MessageLite, re-declared here only for return type covariance.)
+  Parser<? extends Message> getParserForType();
+
   // -----------------------------------------------------------------
   // Comparison and hashing
 
   /**
    * Compares the specified object with this message for equality.  Returns
-   * <tt>true</tt> if the given object is a message of the same type (as
+   * {@code true} if the given object is a message of the same type (as
    * defined by {@code getDescriptorForType()}) and has identical values for
    * all of its fields.  Subclasses must implement this; inheriting
    * {@code Object.equals()} is incorrect.
    *
    * @param other object to be compared for equality with this message
-   * @return <tt>true</tt> if the specified object is equal to this message
+   * @return {@code true} if the specified object is equal to this message
    */
   @Override
   boolean equals(Object other);
 
   /**
    * Returns the hash code value for this message.  The hash code of a message
-   * should mix the message's type (object identity of the decsriptor) with its
+   * should mix the message's type (object identity of the descriptor) with its
    * contents (known and unknown field values).  Subclasses must implement this;
    * inheriting {@code Object.hashCode()} is incorrect.
    *
@@ -83,7 +86,8 @@
 
   /**
    * Converts the message to a string in protocol buffer text format. This is
-   * just a trivial wrapper around {@link TextFormat#printToString(Message)}.
+   * just a trivial wrapper around {@link
+   * TextFormat#printToString(MessageOrBuilder)}.
    */
   @Override
   String toString();
@@ -145,6 +149,24 @@
     Builder newBuilderForField(Descriptors.FieldDescriptor field);
 
     /**
+     * Get a nested builder instance for the given field.
+     * <p>
+     * Normally, we hold a reference to the immutable message object for the
+     * message type field. Some implementations(the generated message builders),
+     * however, can also hold a reference to the builder object (a nested
+     * builder) for the field.
+     * <p>
+     * If the field is already backed up by a nested builder, the nested builder
+     * will be returned. Otherwise, a new field builder will be created and
+     * returned. The original message field (if exist) will be merged into the
+     * field builder, which will then be nested into its parent builder.
+     * <p>
+     * NOTE: implementations that do not support nested builders will throw
+     * <code>UnsupportedException</code>.
+     */
+    Builder getFieldBuilder(Descriptors.FieldDescriptor field);
+
+    /**
      * Sets a field to the given value.  The value must be of the correct type
      * for this field, i.e. the same type that
      * {@link Message#getField(Descriptors.FieldDescriptor)} would return.
diff --git a/third_party/protobuf/java/src/main/java/com/google/protobuf/MessageLite.java b/third_party/protobuf/java/src/main/java/com/google/protobuf/MessageLite.java
index 31b8256..e5b9a47 100644
--- a/third_party/protobuf/java/src/main/java/com/google/protobuf/MessageLite.java
+++ b/third_party/protobuf/java/src/main/java/com/google/protobuf/MessageLite.java
@@ -79,6 +79,12 @@
    */
   int getSerializedSize();
 
+
+  /**
+   * Gets the parser for a message of the same type as this message.
+   */
+  Parser<? extends MessageLite> getParserForType();
+
   // -----------------------------------------------------------------
   // Convenience methods.
 
@@ -144,11 +150,8 @@
     Builder clear();
 
     /**
-     * Construct the final message.  Once this is called, the Builder is no
-     * longer valid, and calling any other method will result in undefined
-     * behavior and may throw a NullPointerException.  If you need to continue
-     * working with the builder after calling {@code build()}, {@code clone()}
-     * it first.
+     * Constructs the message based on the state of the Builder. Subsequent
+     * changes to the Builder will not affect the returned message.
      * @throws UninitializedMessageException The message is missing one or more
      *         required fields (i.e. {@link #isInitialized()} returns false).
      *         Use {@link #buildPartial()} to bypass this check.
@@ -158,11 +161,7 @@
     /**
      * Like {@link #build()}, but does not throw an exception if the message
      * is missing required fields.  Instead, a partial message is returned.
-     * Once this is called, the Builder is no longer valid, and calling any
-     * will result in undefined behavior and may throw a NullPointerException.
-     *
-     * If you need to continue working with the builder after calling
-     * {@code buildPartial()}, {@code clone()} it first.
+     * Subsequent changes to the Builder will not affect the returned message.
      */
     MessageLite buildPartial();
 
@@ -174,7 +173,7 @@
 
     /**
      * Parses a message of this type from the input and merges it with this
-     * message, as if using {@link Builder#mergeFrom(MessageLite)}.
+     * message.
      *
      * <p>Warning:  This does not verify that all required fields are present in
      * the input message.  If you call {@link #build()} without setting all
@@ -184,11 +183,6 @@
      * <ul>
      *   <li>Call {@link #isInitialized()} to verify that all required fields
      *       are set before building.
-     *   <li>Parse the message separately using one of the static
-     *       {@code parseFrom} methods, then use {@link #mergeFrom(MessageLite)}
-     *       to merge it with this one.  {@code parseFrom} will throw an
-     *       {@link InvalidProtocolBufferException} (an {@code IOException})
-     *       if some required fields are missing.
      *   <li>Use {@code buildPartial()} to build, which ignores missing
      *       required fields.
      * </ul>
@@ -225,7 +219,7 @@
     /**
      * Parse {@code data} as a message of this type and merge it with the
      * message being built.  This is just a small wrapper around
-     * {@link #mergeFrom(CodedInputStream,ExtensionRegistry)}.
+     * {@link #mergeFrom(CodedInputStream,ExtensionRegistryLite)}.
      *
      * @return this
      */
@@ -255,7 +249,7 @@
     /**
      * Parse {@code data} as a message of this type and merge it with the
      * message being built.  This is just a small wrapper around
-     * {@link #mergeFrom(CodedInputStream,ExtensionRegistry)}.
+     * {@link #mergeFrom(CodedInputStream,ExtensionRegistryLite)}.
      *
      * @return this
      */
@@ -266,7 +260,7 @@
     /**
      * Parse {@code data} as a message of this type and merge it with the
      * message being built.  This is just a small wrapper around
-     * {@link #mergeFrom(CodedInputStream,ExtensionRegistry)}.
+     * {@link #mergeFrom(CodedInputStream,ExtensionRegistryLite)}.
      *
      * @return this
      */
@@ -293,7 +287,7 @@
     /**
      * Parse a message of this type from {@code input} and merge it with the
      * message being built.  This is just a small wrapper around
-     * {@link #mergeFrom(CodedInputStream,ExtensionRegistry)}.
+     * {@link #mergeFrom(CodedInputStream,ExtensionRegistryLite)}.
      *
      * @return this
      */
@@ -308,9 +302,9 @@
      * {@link MessageLite#writeDelimitedTo(OutputStream)} to write messages in
      * this format.
      *
-     * @returns True if successful, or false if the stream is at EOF when the
-     *          method starts.  Any other error (including reaching EOF during
-     *          parsing) will cause an exception to be thrown.
+     * @return True if successful, or false if the stream is at EOF when the
+     *         method starts.  Any other error (including reaching EOF during
+     *         parsing) will cause an exception to be thrown.
      */
     boolean mergeDelimitedFrom(InputStream input)
                                throws IOException;
diff --git a/third_party/protobuf/java/src/main/java/com/google/protobuf/MessageLiteOrBuilder.java b/third_party/protobuf/java/src/main/java/com/google/protobuf/MessageLiteOrBuilder.java
index 7cc72e9..05b2b16 100644
--- a/third_party/protobuf/java/src/main/java/com/google/protobuf/MessageLiteOrBuilder.java
+++ b/third_party/protobuf/java/src/main/java/com/google/protobuf/MessageLiteOrBuilder.java
@@ -52,6 +52,8 @@
   /**
    * Returns true if all required fields in the message and all embedded
    * messages are set, false otherwise.
+   *
+   * <p>See also: {@link MessageOrBuilder#getInitializationErrorString()}
    */
   boolean isInitialized();
 
diff --git a/third_party/protobuf/java/src/main/java/com/google/protobuf/MessageOrBuilder.java b/third_party/protobuf/java/src/main/java/com/google/protobuf/MessageOrBuilder.java
index 0132e7c..bf62d45 100644
--- a/third_party/protobuf/java/src/main/java/com/google/protobuf/MessageOrBuilder.java
+++ b/third_party/protobuf/java/src/main/java/com/google/protobuf/MessageOrBuilder.java
@@ -30,6 +30,7 @@
 
 package com.google.protobuf;
 
+import java.util.List;
 import java.util.Map;
 
 /**
@@ -45,6 +46,24 @@
   Message getDefaultInstanceForType();
 
   /**
+   * Returns a list of field paths (e.g. "foo.bar.baz") of required fields
+   * which are not set in this message.  You should call
+   * {@link MessageLiteOrBuilder#isInitialized()} first to check if there
+   * are any missing fields, as that method is likely to be much faster
+   * than this one even when the message is fully-initialized.
+   */
+  List<String> findInitializationErrors();
+
+  /**
+   * Returns a comma-delimited list of required fields which are not set
+   * in this message object.  You should call
+   * {@link MessageLiteOrBuilder#isInitialized()} first to check if there
+   * are any missing fields, as that method is likely to be much faster
+   * than this one even when the message is fully-initialized.
+   */
+  String getInitializationErrorString();
+
+  /**
    * Get the message's type's descriptor.  This differs from the
    * {@code getDescriptor()} method of generated message classes in that
    * this method is an abstract method of the {@code Message} interface
@@ -80,7 +99,7 @@
   /**
    * Obtains the value of the given field, or the default value if it is
    * not set.  For primitive fields, the boxed primitive value is returned.
-   * For enum fields, the EnumValueDescriptor for the value is returend. For
+   * For enum fields, the EnumValueDescriptor for the value is returned. For
    * embedded message fields, the sub-message is returned.  For repeated
    * fields, a java.util.List is returned.
    */
@@ -98,7 +117,7 @@
   /**
    * Gets an element of a repeated field.  For primitive fields, the boxed
    * primitive value is returned.  For enum fields, the EnumValueDescriptor
-   * for the value is returend. For embedded message fields, the sub-message
+   * for the value is returned. For embedded message fields, the sub-message
    * is returned.
    * @throws IllegalArgumentException The field is not a repeated field, or
    *           {@code field.getContainingType() != getDescriptorForType()}.
diff --git a/third_party/protobuf/java/src/main/java/com/google/protobuf/Parser.java b/third_party/protobuf/java/src/main/java/com/google/protobuf/Parser.java
new file mode 100644
index 0000000..7d8e821
--- /dev/null
+++ b/third_party/protobuf/java/src/main/java/com/google/protobuf/Parser.java
@@ -0,0 +1,259 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 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.
+
+package com.google.protobuf;
+
+import java.io.InputStream;
+
+/**
+ * Abstract interface for parsing Protocol Messages.
+ *
+ * @author liujisi@google.com (Pherl Liu)
+ */
+public interface Parser<MessageType> {
+  /**
+   * Parses a message of {@code MessageType} from the input.
+   *
+   * <p>Note:  The caller should call
+   * {@link CodedInputStream#checkLastTagWas(int)} after calling this to
+   * verify that the last tag seen was the appropriate end-group tag,
+   * or zero for EOF.
+   */
+  public MessageType parseFrom(CodedInputStream input)
+      throws InvalidProtocolBufferException;
+
+  /**
+   * Like {@link #parseFrom(CodedInputStream)}, but also parses extensions.
+   * The extensions that you want to be able to parse must be registered in
+   * {@code extensionRegistry}. Extensions not in the registry will be treated
+   * as unknown fields.
+   */
+  public MessageType parseFrom(CodedInputStream input,
+                               ExtensionRegistryLite extensionRegistry)
+      throws InvalidProtocolBufferException;
+
+  /**
+   * Like {@link #parseFrom(CodedInputStream)}, but does not throw an
+   * exception if the message is missing required fields. Instead, a partial
+   * message is returned.
+   */
+  public MessageType parsePartialFrom(CodedInputStream input)
+      throws InvalidProtocolBufferException;
+
+  /**
+   * Like {@link #parseFrom(CodedInputStream input, ExtensionRegistryLite)},
+   * but does not throw an exception if the message is missing required fields.
+   * Instead, a partial message is returned.
+   */
+  public MessageType parsePartialFrom(CodedInputStream input,
+                                      ExtensionRegistryLite extensionRegistry)
+      throws InvalidProtocolBufferException;
+
+  // ---------------------------------------------------------------
+  // Convenience methods.
+
+  /**
+   * Parses {@code data} as a message of {@code MessageType}.
+   * This is just a small wrapper around {@link #parseFrom(CodedInputStream)}.
+   */
+  public MessageType parseFrom(ByteString data)
+      throws InvalidProtocolBufferException;
+
+  /**
+   * Parses {@code data} as a message of {@code MessageType}.
+   * This is just a small wrapper around
+   * {@link #parseFrom(CodedInputStream, ExtensionRegistryLite)}.
+   */
+  public MessageType parseFrom(ByteString data,
+                               ExtensionRegistryLite extensionRegistry)
+      throws InvalidProtocolBufferException;
+
+  /**
+   * Like {@link #parseFrom(ByteString)}, but does not throw an
+   * exception if the message is missing required fields. Instead, a partial
+   * message is returned.
+   */
+  public MessageType parsePartialFrom(ByteString data)
+      throws InvalidProtocolBufferException;
+
+  /**
+   * Like {@link #parseFrom(ByteString, ExtensionRegistryLite)},
+   * but does not throw an exception if the message is missing required fields.
+   * Instead, a partial message is returned.
+   */
+  public MessageType parsePartialFrom(ByteString data,
+                                      ExtensionRegistryLite extensionRegistry)
+      throws InvalidProtocolBufferException;
+
+  /**
+   * Parses {@code data} as a message of {@code MessageType}.
+   * This is just a small wrapper around {@link #parseFrom(CodedInputStream)}.
+   */
+  public MessageType parseFrom(byte[] data, int off, int len)
+      throws InvalidProtocolBufferException;
+
+  /**
+   * Parses {@code data} as a message of {@code MessageType}.
+   * This is just a small wrapper around
+   * {@link #parseFrom(CodedInputStream, ExtensionRegistryLite)}.
+   */
+  public MessageType parseFrom(byte[] data, int off, int len,
+                               ExtensionRegistryLite extensionRegistry)
+      throws InvalidProtocolBufferException;
+
+  /**
+   * Parses {@code data} as a message of {@code MessageType}.
+   * This is just a small wrapper around {@link #parseFrom(CodedInputStream)}.
+   */
+  public MessageType parseFrom(byte[] data)
+      throws InvalidProtocolBufferException;
+
+  /**
+   * Parses {@code data} as a message of {@code MessageType}.
+   * This is just a small wrapper around
+   * {@link #parseFrom(CodedInputStream, ExtensionRegistryLite)}.
+   */
+  public MessageType parseFrom(byte[] data,
+                               ExtensionRegistryLite extensionRegistry)
+      throws InvalidProtocolBufferException;
+
+  /**
+   * Like {@link #parseFrom(byte[], int, int)}, but does not throw an
+   * exception if the message is missing required fields. Instead, a partial
+   * message is returned.
+   */
+  public MessageType parsePartialFrom(byte[] data, int off, int len)
+      throws InvalidProtocolBufferException;
+
+  /**
+   * Like {@link #parseFrom(ByteString, ExtensionRegistryLite)},
+   * but does not throw an exception if the message is missing required fields.
+   * Instead, a partial message is returned.
+   */
+  public MessageType parsePartialFrom(byte[] data, int off, int len,
+                                      ExtensionRegistryLite extensionRegistry)
+      throws InvalidProtocolBufferException;
+
+  /**
+   * Like {@link #parseFrom(byte[])}, but does not throw an
+   * exception if the message is missing required fields. Instead, a partial
+   * message is returned.
+   */
+  public MessageType parsePartialFrom(byte[] data)
+      throws InvalidProtocolBufferException;
+
+  /**
+   * Like {@link #parseFrom(byte[], ExtensionRegistryLite)},
+   * but does not throw an exception if the message is missing required fields.
+   * Instead, a partial message is returned.
+   */
+  public MessageType parsePartialFrom(byte[] data,
+                                      ExtensionRegistryLite extensionRegistry)
+      throws InvalidProtocolBufferException;
+
+  /**
+   * Parse a message of {@code MessageType} from {@code input}.
+   * This is just a small wrapper around {@link #parseFrom(CodedInputStream)}.
+   * Note that this method always reads the <i>entire</i> input (unless it
+   * throws an exception).  If you want it to stop earlier, you will need to
+   * wrap your input in some wrapper stream that limits reading.  Or, use
+   * {@link MessageLite#writeDelimitedTo(java.io.OutputStream)} to write your
+   * message and {@link #parseDelimitedFrom(InputStream)} to read it.
+   * <p>
+   * Despite usually reading the entire input, this does not close the stream.
+   */
+  public MessageType parseFrom(InputStream input)
+      throws InvalidProtocolBufferException;
+
+  /**
+   * Parses a message of {@code MessageType} from {@code input}.
+   * This is just a small wrapper around
+   * {@link #parseFrom(CodedInputStream, ExtensionRegistryLite)}.
+   */
+  public MessageType parseFrom(InputStream input,
+                               ExtensionRegistryLite extensionRegistry)
+      throws InvalidProtocolBufferException;
+
+  /**
+   * Like {@link #parseFrom(InputStream)}, but does not throw an
+   * exception if the message is missing required fields. Instead, a partial
+   * message is returned.
+   */
+  public MessageType parsePartialFrom(InputStream input)
+      throws InvalidProtocolBufferException;
+
+  /**
+   * Like {@link #parseFrom(InputStream, ExtensionRegistryLite)},
+   * but does not throw an exception if the message is missing required fields.
+   * Instead, a partial message is returned.
+   */
+  public MessageType parsePartialFrom(InputStream input,
+                                      ExtensionRegistryLite extensionRegistry)
+      throws InvalidProtocolBufferException;
+
+  /**
+   * Like {@link #parseFrom(InputStream)}, but does not read util EOF.
+   * Instead, the size of message (encoded as a varint) is read first,
+   * then the message data. Use
+   * {@link MessageLite#writeDelimitedTo(java.io.OutputStream)} to write
+   * messages in this format.
+   *
+   * @return True if successful, or false if the stream is at EOF when the
+   *         method starts. Any other error (including reaching EOF during
+   *         parsing) will cause an exception to be thrown.
+   */
+  public MessageType parseDelimitedFrom(InputStream input)
+      throws InvalidProtocolBufferException;
+
+  /**
+   * Like {@link #parseDelimitedFrom(InputStream)} but supporting extensions.
+   */
+  public MessageType parseDelimitedFrom(InputStream input,
+                                        ExtensionRegistryLite extensionRegistry)
+      throws InvalidProtocolBufferException;
+
+  /**
+   * Like {@link #parseDelimitedFrom(InputStream)}, but does not throw an
+   * exception if the message is missing required fields. Instead, a partial
+   * message is returned.
+   */
+  public MessageType parsePartialDelimitedFrom(InputStream input)
+      throws InvalidProtocolBufferException;
+
+  /**
+   * Like {@link #parseDelimitedFrom(InputStream, ExtensionRegistryLite)},
+   * but does not throw an exception if the message is missing required fields.
+   * Instead, a partial message is returned.
+   */
+  public MessageType parsePartialDelimitedFrom(
+      InputStream input,
+      ExtensionRegistryLite extensionRegistry)
+      throws InvalidProtocolBufferException;
+}
diff --git a/third_party/protobuf/java/src/main/java/com/google/protobuf/RepeatedFieldBuilder.java b/third_party/protobuf/java/src/main/java/com/google/protobuf/RepeatedFieldBuilder.java
index 0024f79..65d9270 100644
--- a/third_party/protobuf/java/src/main/java/com/google/protobuf/RepeatedFieldBuilder.java
+++ b/third_party/protobuf/java/src/main/java/com/google/protobuf/RepeatedFieldBuilder.java
@@ -37,22 +37,22 @@
 import java.util.List;
 
 /**
- * <code>RepeatedFieldBuilder</code> implements a structure that a protocol
+ * {@code RepeatedFieldBuilder} implements a structure that a protocol
  * message uses to hold a repeated field of other protocol messages. It supports
  * the classical use case of adding immutable {@link Message}'s to the
  * repeated field and is highly optimized around this (no extra memory
  * allocations and sharing of immutable arrays).
  * <br>
  * It also supports the additional use case of adding a {@link Message.Builder}
- * to the repeated field and deferring conversion of that <code>Builder</code>
- * to an immutable <code>Message</code>. In this way, it's possible to maintain
- * a tree of <code>Builder</code>'s that acts as a fully read/write data
+ * to the repeated field and deferring conversion of that {@code Builder}
+ * to an immutable {@code Message}. In this way, it's possible to maintain
+ * a tree of {@code Builder}'s that acts as a fully read/write data
  * structure.
  * <br>
  * Logically, one can think of a tree of builders as converting the entire tree
  * to messages when build is called on the root or when any method is called
  * that desires a Message instead of a Builder. In terms of the implementation,
- * the <code>SingleFieldBuilder</code> and <code>RepeatedFieldBuilder</code>
+ * the {@code SingleFieldBuilder} and {@code RepeatedFieldBuilder}
  * classes cache messages that were created so that messages only need to be
  * created when some change occured in its builder or a builder for one of its
  * descendants.
@@ -192,7 +192,7 @@
 
   /**
    * Get the message at the specified index. If the message is currently stored
-   * as a <code>Builder</code>, it is converted to a <code>Message</code> by
+   * as a {@code Builder}, it is converted to a {@code Message} by
    * calling {@link Message.Builder#buildPartial} on it.
    *
    * @param index the index of the message to get
@@ -204,7 +204,7 @@
 
   /**
    * Get the message at the specified index. If the message is currently stored
-   * as a <code>Builder</code>, it is converted to a <code>Message</code> by
+   * as a {@code Builder}, it is converted to a {@code Message} by
    * calling {@link Message.Builder#buildPartial} on it.
    *
    * @param index the index of the message to get
diff --git a/third_party/protobuf/java/src/main/java/com/google/protobuf/RopeByteString.java b/third_party/protobuf/java/src/main/java/com/google/protobuf/RopeByteString.java
new file mode 100644
index 0000000..8d44d11
--- /dev/null
+++ b/third_party/protobuf/java/src/main/java/com/google/protobuf/RopeByteString.java
@@ -0,0 +1,945 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 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.
+
+package com.google.protobuf;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.UnsupportedEncodingException;
+import java.io.ByteArrayInputStream;
+import java.nio.ByteBuffer;
+import java.util.ArrayDeque;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Deque;
+import java.util.Iterator;
+import java.util.List;
+import java.util.NoSuchElementException;
+
+/**
+ * Class to represent {@code ByteStrings} formed by concatenation of other
+ * ByteStrings, without copying the data in the pieces. The concatenation is
+ * represented as a tree whose leaf nodes are each a {@link LiteralByteString}.
+ *
+ * <p>Most of the operation here is inspired by the now-famous paper <a
+ * href="http://www.cs.ubc.ca/local/reading/proceedings/spe91-95/spe/vol25/issue12/spe986.pdf">
+ * BAP95 </a> Ropes: an Alternative to Strings hans-j. boehm, russ atkinson and
+ * michael plass
+ *
+ * <p>The algorithms described in the paper have been implemented for character
+ * strings in {@link com.google.common.string.Rope} and in the c++ class {@code
+ * cord.cc}.
+ *
+ * <p>Fundamentally the Rope algorithm represents the collection of pieces as a
+ * binary tree. BAP95 uses a Fibonacci bound relating depth to a minimum
+ * sequence length, sequences that are too short relative to their depth cause a
+ * tree rebalance.  More precisely, a tree of depth d is "balanced" in the
+ * terminology of BAP95 if its length is at least F(d+2), where F(n) is the
+ * n-the Fibonacci number. Thus for depths 0, 1, 2, 3, 4, 5,... we have minimum
+ * lengths 1, 2, 3, 5, 8, 13,...
+ *
+ * @author carlanton@google.com (Carl Haverl)
+ */
+class RopeByteString extends ByteString {
+
+  /**
+   * BAP95. Let Fn be the nth Fibonacci number. A {@link RopeByteString} of
+   * depth n is "balanced", i.e flat enough, if its length is at least Fn+2,
+   * e.g. a "balanced" {@link RopeByteString} of depth 1 must have length at
+   * least 2, of depth 4 must have length >= 8, etc.
+   *
+   * <p>There's nothing special about using the Fibonacci numbers for this, but
+   * they are a reasonable sequence for encapsulating the idea that we are OK
+   * with longer strings being encoded in deeper binary trees.
+   *
+   * <p>For 32-bit integers, this array has length 46.
+   */
+  private static final int[] minLengthByDepth;
+
+  static {
+    // Dynamically generate the list of Fibonacci numbers the first time this
+    // class is accessed.
+    List<Integer> numbers = new ArrayList<Integer>();
+
+    // we skip the first Fibonacci number (1).  So instead of: 1 1 2 3 5 8 ...
+    // we have: 1 2 3 5 8 ...
+    int f1 = 1;
+    int f2 = 1;
+
+    // get all the values until we roll over.
+    while (f2 > 0) {
+      numbers.add(f2);
+      int temp = f1 + f2;
+      f1 = f2;
+      f2 = temp;
+    }
+
+    // we include this here so that we can index this array to [x + 1] in the
+    // loops below.
+    numbers.add(Integer.MAX_VALUE);
+    minLengthByDepth = new int[numbers.size()];
+    for (int i = 0; i < minLengthByDepth.length; i++) {
+      // unbox all the values
+      minLengthByDepth[i] = numbers.get(i);
+    }
+  }
+
+  private final int totalLength;
+  private final ByteString left;
+  private final ByteString right;
+  private final int leftLength;
+  private final int treeDepth;
+
+  /**
+   * Create a new RopeByteString, which can be thought of as a new tree node, by
+   * recording references to the two given strings.
+   *
+   * @param left  string on the left of this node, should have {@code size() >
+   *              0}
+   * @param right string on the right of this node, should have {@code size() >
+   *              0}
+   */
+  private RopeByteString(ByteString left, ByteString right) {
+    this.left = left;
+    this.right = right;
+    leftLength = left.size();
+    totalLength = leftLength + right.size();
+    treeDepth = Math.max(left.getTreeDepth(), right.getTreeDepth()) + 1;
+  }
+
+  /**
+   * Concatenate the given strings while performing various optimizations to
+   * slow the growth rate of tree depth and tree node count. The result is
+   * either a {@link LiteralByteString} or a {@link RopeByteString}
+   * depending on which optimizations, if any, were applied.
+   *
+   * <p>Small pieces of length less than {@link
+   * ByteString#CONCATENATE_BY_COPY_SIZE} may be copied by value here, as in
+   * BAP95.  Large pieces are referenced without copy.
+   *
+   * @param left  string on the left
+   * @param right string on the right
+   * @return concatenation representing the same sequence as the given strings
+   */
+  static ByteString concatenate(ByteString left, ByteString right) {
+    ByteString result;
+    RopeByteString leftRope =
+        (left instanceof RopeByteString) ? (RopeByteString) left : null;
+    if (right.size() == 0) {
+      result = left;
+    } else if (left.size() == 0) {
+      result = right;
+    } else {
+      int newLength = left.size() + right.size();
+      if (newLength < ByteString.CONCATENATE_BY_COPY_SIZE) {
+        // Optimization from BAP95: For short (leaves in paper, but just short
+        // here) total length, do a copy of data to a new leaf.
+        result = concatenateBytes(left, right);
+      } else if (leftRope != null
+          && leftRope.right.size() + right.size() < CONCATENATE_BY_COPY_SIZE) {
+        // Optimization from BAP95: As an optimization of the case where the
+        // ByteString is constructed by repeated concatenate, recognize the case
+        // where a short string is concatenated to a left-hand node whose
+        // right-hand branch is short.  In the paper this applies to leaves, but
+        // we just look at the length here. This has the advantage of shedding
+        // references to unneeded data when substrings have been taken.
+        //
+        // When we recognize this case, we do a copy of the data and create a
+        // new parent node so that the depth of the result is the same as the
+        // given left tree.
+        ByteString newRight = concatenateBytes(leftRope.right, right);
+        result = new RopeByteString(leftRope.left, newRight);
+      } else if (leftRope != null
+          && leftRope.left.getTreeDepth() > leftRope.right.getTreeDepth()
+          && leftRope.getTreeDepth() > right.getTreeDepth()) {
+        // Typically for concatenate-built strings the left-side is deeper than
+        // the right.  This is our final attempt to concatenate without
+        // increasing the tree depth.  We'll redo the the node on the RHS.  This
+        // is yet another optimization for building the string by repeatedly
+        // concatenating on the right.
+        ByteString newRight = new RopeByteString(leftRope.right, right);
+        result = new RopeByteString(leftRope.left, newRight);
+      } else {
+        // Fine, we'll add a node and increase the tree depth--unless we
+        // rebalance ;^)
+        int newDepth = Math.max(left.getTreeDepth(), right.getTreeDepth()) + 1;
+        if (newLength >= minLengthByDepth[newDepth]) {
+          // The tree is shallow enough, so don't rebalance
+          result = new RopeByteString(left, right);
+        } else {
+          result = new Balancer().balance(left, right);
+        }
+      }
+    }
+    return result;
+  }
+
+  /**
+   * Concatenates two strings by copying data values. This is called in a few
+   * cases in order to reduce the growth of the number of tree nodes.
+   *
+   * @param left  string on the left
+   * @param right string on the right
+   * @return string formed by copying data bytes
+   */
+  private static LiteralByteString concatenateBytes(ByteString left,
+      ByteString right) {
+    int leftSize = left.size();
+    int rightSize = right.size();
+    byte[] bytes = new byte[leftSize + rightSize];
+    left.copyTo(bytes, 0, 0, leftSize);
+    right.copyTo(bytes, 0, leftSize, rightSize);
+    return new LiteralByteString(bytes);  // Constructor wraps bytes
+  }
+
+  /**
+   * Create a new RopeByteString for testing only while bypassing all the
+   * defenses of {@link #concatenate(ByteString, ByteString)}. This allows
+   * testing trees of specific structure. We are also able to insert empty
+   * leaves, though these are dis-allowed, so that we can make sure the
+   * implementation can withstand their presence.
+   *
+   * @param left  string on the left of this node
+   * @param right string on the right of this node
+   * @return an unsafe instance for testing only
+   */
+  static RopeByteString newInstanceForTest(ByteString left, ByteString right) {
+    return new RopeByteString(left, right);
+  }
+
+  /**
+   * Gets the byte at the given index.
+   * Throws {@link ArrayIndexOutOfBoundsException} for backwards-compatibility
+   * reasons although it would more properly be {@link
+   * IndexOutOfBoundsException}.
+   *
+   * @param index index of byte
+   * @return the value
+   * @throws ArrayIndexOutOfBoundsException {@code index} is < 0 or >= size
+   */
+  @Override
+  public byte byteAt(int index) {
+    if (index < 0) {
+      throw new ArrayIndexOutOfBoundsException("Index < 0: " + index);
+    }
+    if (index > totalLength) {
+      throw new ArrayIndexOutOfBoundsException(
+          "Index > length: " + index + ", " + totalLength);
+    }
+
+    byte result;
+    // Find the relevant piece by recursive descent
+    if (index < leftLength) {
+      result = left.byteAt(index);
+    } else {
+      result = right.byteAt(index - leftLength);
+    }
+    return result;
+  }
+
+  @Override
+  public int size() {
+    return totalLength;
+  }
+
+  // =================================================================
+  // Pieces
+
+  @Override
+  protected int getTreeDepth() {
+    return treeDepth;
+  }
+
+  /**
+   * Determines if the tree is balanced according to BAP95, which means the tree
+   * is flat-enough with respect to the bounds. Note that this definition of
+   * balanced is one where sub-trees of balanced trees are not necessarily
+   * balanced.
+   *
+   * @return true if the tree is balanced
+   */
+  @Override
+  protected boolean isBalanced() {
+    return totalLength >= minLengthByDepth[treeDepth];
+  }
+
+  /**
+   * Takes a substring of this one. This involves recursive descent along the
+   * left and right edges of the substring, and referencing any wholly contained
+   * segments in between. Any leaf nodes entirely uninvolved in the substring
+   * will not be referenced by the substring.
+   *
+   * <p>Substrings of {@code length < 2} should result in at most a single
+   * recursive call chain, terminating at a leaf node. Thus the result will be a
+   * {@link LiteralByteString}. {@link #RopeByteString(ByteString,
+   * ByteString)}.
+   *
+   * @param beginIndex start at this index
+   * @param endIndex   the last character is the one before this index
+   * @return substring leaf node or tree
+   */
+  @Override
+  public ByteString substring(int beginIndex, int endIndex) {
+    if (beginIndex < 0) {
+      throw new IndexOutOfBoundsException(
+          "Beginning index: " + beginIndex + " < 0");
+    }
+    if (endIndex > totalLength) {
+      throw new IndexOutOfBoundsException(
+          "End index: " + endIndex + " > " + totalLength);
+    }
+    int substringLength = endIndex - beginIndex;
+    if (substringLength < 0) {
+      throw new IndexOutOfBoundsException(
+          "Beginning index larger than ending index: " + beginIndex + ", "
+              + endIndex);
+    }
+
+    ByteString result;
+    if (substringLength == 0) {
+      // Empty substring
+      result = ByteString.EMPTY;
+    } else if (substringLength == totalLength) {
+      // The whole string
+      result = this;
+    } else {
+      // Proper substring
+      if (endIndex <= leftLength) {
+        // Substring on the left
+        result = left.substring(beginIndex, endIndex);
+      } else if (beginIndex >= leftLength) {
+        // Substring on the right
+        result = right
+            .substring(beginIndex - leftLength, endIndex - leftLength);
+      } else {
+        // Split substring
+        ByteString leftSub = left.substring(beginIndex);
+        ByteString rightSub = right.substring(0, endIndex - leftLength);
+        // Intentionally not rebalancing, since in many cases these two
+        // substrings will already be less deep than the top-level
+        // RopeByteString we're taking a substring of.
+        result = new RopeByteString(leftSub, rightSub);
+      }
+    }
+    return result;
+  }
+
+  // =================================================================
+  // ByteString -> byte[]
+
+  @Override
+  protected void copyToInternal(byte[] target, int sourceOffset,
+      int targetOffset, int numberToCopy) {
+   if (sourceOffset + numberToCopy <= leftLength) {
+      left.copyToInternal(target, sourceOffset, targetOffset, numberToCopy);
+    } else if (sourceOffset >= leftLength) {
+      right.copyToInternal(target, sourceOffset - leftLength, targetOffset,
+          numberToCopy);
+    } else {
+      int leftLength = this.leftLength - sourceOffset;
+      left.copyToInternal(target, sourceOffset, targetOffset, leftLength);
+      right.copyToInternal(target, 0, targetOffset + leftLength,
+          numberToCopy - leftLength);
+    }
+  }
+
+  @Override
+  public void copyTo(ByteBuffer target) {
+    left.copyTo(target);
+    right.copyTo(target);
+  }
+
+  @Override
+  public ByteBuffer asReadOnlyByteBuffer() {
+    ByteBuffer byteBuffer = ByteBuffer.wrap(toByteArray());
+    return byteBuffer.asReadOnlyBuffer();
+  }
+
+  @Override
+  public List<ByteBuffer> asReadOnlyByteBufferList() {
+    // Walk through the list of LiteralByteString's that make up this
+    // rope, and add each one as a read-only ByteBuffer.
+    List<ByteBuffer> result = new ArrayList<ByteBuffer>();
+    PieceIterator pieces = new PieceIterator(this);
+    while (pieces.hasNext()) {
+      LiteralByteString byteString = pieces.next();
+      result.add(byteString.asReadOnlyByteBuffer());
+    }
+    return result;
+  }
+
+  @Override
+  public void writeTo(OutputStream outputStream) throws IOException {
+    left.writeTo(outputStream);
+    right.writeTo(outputStream);
+  }
+
+  @Override
+  public String toString(String charsetName)
+      throws UnsupportedEncodingException {
+    return new String(toByteArray(), charsetName);
+  }
+
+  // =================================================================
+  // UTF-8 decoding
+
+  @Override
+  public boolean isValidUtf8() {
+    int leftPartial = left.partialIsValidUtf8(Utf8.COMPLETE, 0, leftLength);
+    int state = right.partialIsValidUtf8(leftPartial, 0, right.size());
+    return state == Utf8.COMPLETE;
+  }
+
+  @Override
+  protected int partialIsValidUtf8(int state, int offset, int length) {
+    int toIndex = offset + length;
+    if (toIndex <= leftLength) {
+      return left.partialIsValidUtf8(state, offset, length);
+    } else if (offset >= leftLength) {
+      return right.partialIsValidUtf8(state, offset - leftLength, length);
+    } else {
+      int leftLength = this.leftLength - offset;
+      int leftPartial = left.partialIsValidUtf8(state, offset, leftLength);
+      return right.partialIsValidUtf8(leftPartial, 0, length - leftLength);
+    }
+  }
+
+  // =================================================================
+  // equals() and hashCode()
+
+  @Override
+  public boolean equals(Object other) {
+    if (other == this) {
+      return true;
+    }
+    if (!(other instanceof ByteString)) {
+      return false;
+    }
+
+    ByteString otherByteString = (ByteString) other;
+    if (totalLength != otherByteString.size()) {
+      return false;
+    }
+    if (totalLength == 0) {
+      return true;
+    }
+
+    // You don't really want to be calling equals on long strings, but since
+    // we cache the hashCode, we effectively cache inequality. We use the cached
+    // hashCode if it's already computed.  It's arguable we should compute the
+    // hashCode here, and if we're going to be testing a bunch of byteStrings,
+    // it might even make sense.
+    if (hash != 0) {
+      int cachedOtherHash = otherByteString.peekCachedHashCode();
+      if (cachedOtherHash != 0 && hash != cachedOtherHash) {
+        return false;
+      }
+    }
+
+    return equalsFragments(otherByteString);
+  }
+
+  /**
+   * Determines if this string is equal to another of the same length by
+   * iterating over the leaf nodes. On each step of the iteration, the
+   * overlapping segments of the leaves are compared.
+   *
+   * @param other string of the same length as this one
+   * @return true if the values of this string equals the value of the given
+   *         one
+   */
+  private boolean equalsFragments(ByteString other) {
+    int thisOffset = 0;
+    Iterator<LiteralByteString> thisIter = new PieceIterator(this);
+    LiteralByteString thisString = thisIter.next();
+
+    int thatOffset = 0;
+    Iterator<LiteralByteString> thatIter = new PieceIterator(other);
+    LiteralByteString thatString = thatIter.next();
+
+    int pos = 0;
+    while (true) {
+      int thisRemaining = thisString.size() - thisOffset;
+      int thatRemaining = thatString.size() - thatOffset;
+      int bytesToCompare = Math.min(thisRemaining, thatRemaining);
+
+      // At least one of the offsets will be zero
+      boolean stillEqual = (thisOffset == 0)
+          ? thisString.equalsRange(thatString, thatOffset, bytesToCompare)
+          : thatString.equalsRange(thisString, thisOffset, bytesToCompare);
+      if (!stillEqual) {
+        return false;
+      }
+
+      pos += bytesToCompare;
+      if (pos >= totalLength) {
+        if (pos == totalLength) {
+          return true;
+        }
+        throw new IllegalStateException();
+      }
+      // We always get to the end of at least one of the pieces
+      if (bytesToCompare == thisRemaining) { // If reached end of this
+        thisOffset = 0;
+        thisString = thisIter.next();
+      } else {
+        thisOffset += bytesToCompare;
+      }
+      if (bytesToCompare == thatRemaining) { // If reached end of that
+        thatOffset = 0;
+        thatString = thatIter.next();
+      } else {
+        thatOffset += bytesToCompare;
+      }
+    }
+  }
+
+  /**
+   * Cached hash value.  Intentionally accessed via a data race, which is safe
+   * because of the Java Memory Model's "no out-of-thin-air values" guarantees
+   * for ints.
+   */
+  private int hash = 0;
+
+  @Override
+  public int hashCode() {
+    int h = hash;
+
+    if (h == 0) {
+      h = totalLength;
+      h = partialHash(h, 0, totalLength);
+      if (h == 0) {
+        h = 1;
+      }
+      hash = h;
+    }
+    return h;
+  }
+
+  @Override
+  protected int peekCachedHashCode() {
+    return hash;
+  }
+
+  @Override
+  protected int partialHash(int h, int offset, int length) {
+    int toIndex = offset + length;
+    if (toIndex <= leftLength) {
+      return left.partialHash(h, offset, length);
+    } else if (offset >= leftLength) {
+      return right.partialHash(h, offset - leftLength, length);
+    } else {
+      int leftLength = this.leftLength - offset;
+      int leftPartial = left.partialHash(h, offset, leftLength);
+      return right.partialHash(leftPartial, 0, length - leftLength);
+    }
+  }
+
+  // =================================================================
+  // Input stream
+
+  @Override
+  public CodedInputStream newCodedInput() {
+    return CodedInputStream.newInstance(new RopeInputStream());
+  }
+
+  @Override
+  public InputStream newInput() {
+    return new RopeInputStream();
+  }
+
+  /**
+   * This class implements the balancing algorithm of BAP95. In the paper the
+   * authors use an array to keep track of pieces, while here we use a stack.
+   * The tree is balanced by traversing subtrees in left to right order, and the
+   * stack always contains the part of the string we've traversed so far.
+   *
+   * <p>One surprising aspect of the algorithm is the result of balancing is not
+   * necessarily balanced, though it is nearly balanced.  For details, see
+   * BAP95.
+   */
+  private static class Balancer {
+    // Stack containing the part of the string, starting from the left, that
+    // we've already traversed.  The final string should be the equivalent of
+    // concatenating the strings on the stack from bottom to top.
+    private final Deque<ByteString> prefixesStack =
+        new ArrayDeque<ByteString>(minLengthByDepth.length);
+
+    private ByteString balance(ByteString left, ByteString right) {
+      doBalance(left);
+      doBalance(right);
+
+      // Sweep stack to gather the result
+      ByteString partialString = prefixesStack.pop();
+      while (!prefixesStack.isEmpty()) {
+        ByteString newLeft = prefixesStack.pop();
+        partialString = new RopeByteString(newLeft, partialString);
+      }
+      // We should end up with a RopeByteString since at a minimum we will
+      // create one from concatenating left and right
+      return partialString;
+    }
+
+    private void doBalance(ByteString root) {
+      // BAP95: Insert balanced subtrees whole. This means the result might not
+      // be balanced, leading to repeated rebalancings on concatenate. However,
+      // these rebalancings are shallow due to ignoring balanced subtrees, and
+      // relatively few calls to insert() result.
+      if (root.isBalanced()) {
+        insert(root);
+      } else if (root instanceof RopeByteString) {
+        RopeByteString rbs = (RopeByteString) root;
+        doBalance(rbs.left);
+        doBalance(rbs.right);
+      } else {
+        throw new IllegalArgumentException(
+            "Has a new type of ByteString been created? Found " +
+                root.getClass());
+      }
+    }
+
+    /**
+     * Push a string on the balance stack (BAP95).  BAP95 uses an array and
+     * calls the elements in the array 'bins'.  We instead use a stack, so the
+     * 'bins' of lengths are represented by differences between the elements of
+     * minLengthByDepth.
+     *
+     * <p>If the length bin for our string, and all shorter length bins, are
+     * empty, we just push it on the stack.  Otherwise, we need to start
+     * concatenating, putting the given string in the "middle" and continuing
+     * until we land in an empty length bin that matches the length of our
+     * concatenation.
+     *
+     * @param byteString string to place on the balance stack
+     */
+    private void insert(ByteString byteString) {
+      int depthBin = getDepthBinForLength(byteString.size());
+      int binEnd = minLengthByDepth[depthBin + 1];
+
+      // BAP95: Concatenate all trees occupying bins representing the length of
+      // our new piece or of shorter pieces, to the extent that is possible.
+      // The goal is to clear the bin which our piece belongs in, but that may
+      // not be entirely possible if there aren't enough longer bins occupied.
+      if (prefixesStack.isEmpty() || prefixesStack.peek().size() >= binEnd) {
+        prefixesStack.push(byteString);
+      } else {
+        int binStart = minLengthByDepth[depthBin];
+
+        // Concatenate the subtrees of shorter length
+        ByteString newTree = prefixesStack.pop();
+        while (!prefixesStack.isEmpty()
+            && prefixesStack.peek().size() < binStart) {
+          ByteString left = prefixesStack.pop();
+          newTree = new RopeByteString(left, newTree);
+        }
+
+        // Concatenate the given string
+        newTree = new RopeByteString(newTree, byteString);
+
+        // Continue concatenating until we land in an empty bin
+        while (!prefixesStack.isEmpty()) {
+          depthBin = getDepthBinForLength(newTree.size());
+          binEnd = minLengthByDepth[depthBin + 1];
+          if (prefixesStack.peek().size() < binEnd) {
+            ByteString left = prefixesStack.pop();
+            newTree = new RopeByteString(left, newTree);
+          } else {
+            break;
+          }
+        }
+        prefixesStack.push(newTree);
+      }
+    }
+
+    private int getDepthBinForLength(int length) {
+      int depth = Arrays.binarySearch(minLengthByDepth, length);
+      if (depth < 0) {
+        // It wasn't an exact match, so convert to the index of the containing
+        // fragment, which is one less even than the insertion point.
+        int insertionPoint = -(depth + 1);
+        depth = insertionPoint - 1;
+      }
+
+      return depth;
+    }
+  }
+
+  /**
+   * This class is a continuable tree traversal, which keeps the state
+   * information which would exist on the stack in a recursive traversal instead
+   * on a stack of "Bread Crumbs". The maximum depth of the stack in this
+   * iterator is the same as the depth of the tree being traversed.
+   *
+   * <p>This iterator is used to implement
+   * {@link RopeByteString#equalsFragments(ByteString)}.
+   */
+  private static class PieceIterator implements Iterator<LiteralByteString> {
+
+    private final Deque<RopeByteString> breadCrumbs =
+        new ArrayDeque<RopeByteString>(minLengthByDepth.length);
+    private LiteralByteString next;
+
+    private PieceIterator(ByteString root) {
+      next = getLeafByLeft(root);
+    }
+
+    private LiteralByteString getLeafByLeft(ByteString root) {
+      ByteString pos = root;
+      while (pos instanceof RopeByteString) {
+        RopeByteString rbs = (RopeByteString) pos;
+        breadCrumbs.push(rbs);
+        pos = rbs.left;
+      }
+      return (LiteralByteString) pos;
+    }
+
+    private LiteralByteString getNextNonEmptyLeaf() {
+      while (true) {
+        // Almost always, we go through this loop exactly once.  However, if
+        // we discover an empty string in the rope, we toss it and try again.
+        if (breadCrumbs.isEmpty()) {
+          return null;
+        } else {
+          LiteralByteString result = getLeafByLeft(breadCrumbs.pop().right);
+          if (!result.isEmpty()) {
+            return result;
+          }
+        }
+      }
+    }
+
+    public boolean hasNext() {
+      return next != null;
+    }
+
+    /**
+     * Returns the next item and advances one {@code LiteralByteString}.
+     *
+     * @return next non-empty LiteralByteString or {@code null}
+     */
+    public LiteralByteString next() {
+      if (next == null) {
+        throw new NoSuchElementException();
+      }
+      LiteralByteString result = next;
+      next = getNextNonEmptyLeaf();
+      return result;
+    }
+
+    public void remove() {
+      throw new UnsupportedOperationException();
+    }
+  }
+
+  // =================================================================
+  // ByteIterator
+
+  @Override
+  public ByteIterator iterator() {
+    return new RopeByteIterator();
+  }
+
+  private class RopeByteIterator implements ByteString.ByteIterator {
+
+    private final PieceIterator pieces;
+    private ByteIterator bytes;
+    int bytesRemaining;
+
+    private RopeByteIterator() {
+      pieces = new PieceIterator(RopeByteString.this);
+      bytes = pieces.next().iterator();
+      bytesRemaining = size();
+    }
+
+    public boolean hasNext() {
+      return (bytesRemaining > 0);
+    }
+
+    public Byte next() {
+      return nextByte(); // Does not instantiate a Byte
+    }
+
+    public byte nextByte() {
+      if (!bytes.hasNext()) {
+        bytes = pieces.next().iterator();
+      }
+      --bytesRemaining;
+      return bytes.nextByte();
+    }
+
+    public void remove() {
+      throw new UnsupportedOperationException();
+    }
+  }
+
+  /**
+   * This class is the {@link RopeByteString} equivalent for
+   * {@link ByteArrayInputStream}.
+   */
+  private class RopeInputStream extends InputStream {
+    // Iterates through the pieces of the rope
+    private PieceIterator pieceIterator;
+    // The current piece
+    private LiteralByteString currentPiece;
+    // The size of the current piece
+    private int currentPieceSize;
+    // The index of the next byte to read in the current piece
+    private int currentPieceIndex;
+    // The offset of the start of the current piece in the rope byte string
+    private int currentPieceOffsetInRope;
+    // Offset in the buffer at which user called mark();
+    private int mark;
+
+    public RopeInputStream() {
+      initialize();
+    }
+
+    @Override
+    public int read(byte b[], int offset, int length)  {
+      if (b == null) {
+        throw new NullPointerException();
+      } else if (offset < 0 || length < 0 || length > b.length - offset) {
+        throw new IndexOutOfBoundsException();
+      }
+      return readSkipInternal(b, offset, length);
+    }
+
+    @Override
+    public long skip(long length) {
+      if (length < 0) {
+        throw new IndexOutOfBoundsException();
+      } else if (length > Integer.MAX_VALUE) {
+        length = Integer.MAX_VALUE;
+      }
+      return readSkipInternal(null, 0, (int) length);
+    }
+
+    /**
+     * Internal implementation of read and skip.  If b != null, then read the
+     * next {@code length} bytes into the buffer {@code b} at
+     * offset {@code offset}.  If b == null, then skip the next {@code length)
+     * bytes.
+     * <p>
+     * This method assumes that all error checking has already happened.
+     * <p>
+     * Returns the actual number of bytes read or skipped.
+     */
+    private int readSkipInternal(byte b[], int offset, int length)  {
+      int bytesRemaining = length;
+      while (bytesRemaining > 0) {
+        advanceIfCurrentPieceFullyRead();
+        if (currentPiece == null) {
+          if (bytesRemaining == length) {
+             // We didn't manage to read anything
+             return -1;
+           }
+          break;
+        } else {
+          // Copy the bytes from this piece.
+          int currentPieceRemaining = currentPieceSize - currentPieceIndex;
+          int count = Math.min(currentPieceRemaining, bytesRemaining);
+          if (b != null) {
+            currentPiece.copyTo(b, currentPieceIndex, offset, count);
+            offset += count;
+          }
+          currentPieceIndex += count;
+          bytesRemaining -= count;
+        }
+      }
+       // Return the number of bytes read.
+      return length - bytesRemaining;
+    }
+
+    @Override
+    public int read() throws IOException {
+      advanceIfCurrentPieceFullyRead();
+      if (currentPiece == null) {
+        return -1;
+      } else {
+        return currentPiece.byteAt(currentPieceIndex++) & 0xFF;
+      }
+    }
+
+    @Override
+    public int available() throws IOException {
+      int bytesRead = currentPieceOffsetInRope + currentPieceIndex;
+      return RopeByteString.this.size() - bytesRead;
+    }
+
+    @Override
+    public boolean markSupported() {
+      return true;
+    }
+
+    @Override
+    public void mark(int readAheadLimit) {
+      // Set the mark to our position in the byte string
+      mark = currentPieceOffsetInRope + currentPieceIndex;
+    }
+
+    @Override
+    public synchronized void reset() {
+      // Just reinitialize and skip the specified number of bytes.
+      initialize();
+      readSkipInternal(null, 0, mark);
+    }
+
+    /** Common initialization code used by both the constructor and reset() */
+    private void initialize() {
+      pieceIterator = new PieceIterator(RopeByteString.this);
+      currentPiece = pieceIterator.next();
+      currentPieceSize = currentPiece.size();
+      currentPieceIndex = 0;
+      currentPieceOffsetInRope = 0;
+    }
+
+    /**
+     * Skips to the next piece if we have read all the data in the current
+     * piece.  Sets currentPiece to null if we have reached the end of the
+     * input.
+     */
+    private void advanceIfCurrentPieceFullyRead() {
+      if (currentPiece != null && currentPieceIndex == currentPieceSize) {
+        // Generally, we can only go through this loop at most once, since
+        // empty strings can't end up in a rope.  But better to test.
+        currentPieceOffsetInRope += currentPieceSize;
+        currentPieceIndex = 0;
+        if (pieceIterator.hasNext()) {
+          currentPiece = pieceIterator.next();
+          currentPieceSize = currentPiece.size();
+        } else {
+          currentPiece = null;
+          currentPieceSize = 0;
+        }
+      }
+    }
+  }
+}
diff --git a/third_party/protobuf/java/src/main/java/com/google/protobuf/SingleFieldBuilder.java b/third_party/protobuf/java/src/main/java/com/google/protobuf/SingleFieldBuilder.java
index d4475f6..4bfc9f3 100644
--- a/third_party/protobuf/java/src/main/java/com/google/protobuf/SingleFieldBuilder.java
+++ b/third_party/protobuf/java/src/main/java/com/google/protobuf/SingleFieldBuilder.java
@@ -31,21 +31,21 @@
 package com.google.protobuf;
 
 /**
- * <code>SingleFieldBuilder</code> implements a structure that a protocol
+ * {@code SingleFieldBuilder} implements a structure that a protocol
  * message uses to hold a single field of another protocol message. It supports
  * the classical use case of setting an immutable {@link Message} as the value
  * of the field and is highly optimized around this.
  * <br>
  * It also supports the additional use case of setting a {@link Message.Builder}
- * as the field and deferring conversion of that <code>Builder</code>
- * to an immutable <code>Message</code>. In this way, it's possible to maintain
- * a tree of <code>Builder</code>'s that acts as a fully read/write data
+ * as the field and deferring conversion of that {@code Builder}
+ * to an immutable {@code Message}. In this way, it's possible to maintain
+ * a tree of {@code Builder}'s that acts as a fully read/write data
  * structure.
  * <br>
  * Logically, one can think of a tree of builders as converting the entire tree
  * to messages when build is called on the root or when any method is called
  * that desires a Message instead of a Builder. In terms of the implementation,
- * the <code>SingleFieldBuilder</code> and <code>RepeatedFieldBuilder</code>
+ * the {@code SingleFieldBuilder} and {@code RepeatedFieldBuilder}
  * classes cache messages that were created so that messages only need to be
  * created when some change occured in its builder or a builder for one of its
  * descendants.
@@ -99,7 +99,7 @@
 
   /**
    * Get the message for the field. If the message is currently stored
-   * as a <code>Builder</code>, it is converted to a <code>Message</code> by
+   * as a {@code Builder}, it is converted to a {@code Message} by
    * calling {@link Message.Builder#buildPartial} on it. If no message has
    * been set, returns the default instance of the message.
    *
diff --git a/third_party/protobuf/java/src/main/java/com/google/protobuf/SmallSortedMap.java b/third_party/protobuf/java/src/main/java/com/google/protobuf/SmallSortedMap.java
index 1cf270f..c6cad6a 100644
--- a/third_party/protobuf/java/src/main/java/com/google/protobuf/SmallSortedMap.java
+++ b/third_party/protobuf/java/src/main/java/com/google/protobuf/SmallSortedMap.java
@@ -51,14 +51,14 @@
  * remaining entries are stored in an overflow map. Iteration over the entries
  * in the map should be done as follows:
  *
- * <pre>
- * for (int i = 0; i &lt; fieldMap.getNumArrayEntries(); i++) {
+ * <pre>   {@code
+ * for (int i = 0; i < fieldMap.getNumArrayEntries(); i++) {
  *   process(fieldMap.getArrayEntryAt(i));
  * }
- * for (Map.Entry&lt;K, V&gt; entry : fieldMap.getOverflowEntries()) {
+ * for (Map.Entry<K, V> entry : fieldMap.getOverflowEntries()) {
  *   process(entry);
  * }
- * </pre>
+ * }</pre>
  *
  * The resulting iteration is in order of ascending field tag number. The
  * object returned by {@link #entrySet()} adheres to the same contract but is
@@ -394,7 +394,7 @@
 
   /**
    * Entry implementation that implements Comparable in order to support
-   * binary search witin the entry array. Also checks mutability in
+   * binary search within the entry array. Also checks mutability in
    * {@link #setValue()}.
    */
   private class Entry implements Map.Entry<K, V>, Comparable<Entry> {
diff --git a/third_party/protobuf/java/src/main/java/com/google/protobuf/TextFormat.java b/third_party/protobuf/java/src/main/java/com/google/protobuf/TextFormat.java
index d5fbdab..ed46289 100644
--- a/third_party/protobuf/java/src/main/java/com/google/protobuf/TextFormat.java
+++ b/third_party/protobuf/java/src/main/java/com/google/protobuf/TextFormat.java
@@ -55,15 +55,18 @@
 public final class TextFormat {
   private TextFormat() {}
 
-  private static final Printer DEFAULT_PRINTER = new Printer(false);
-  private static final Printer SINGLE_LINE_PRINTER = new Printer(true);
+  private static final Printer DEFAULT_PRINTER = new Printer();
+  private static final Printer SINGLE_LINE_PRINTER =
+      (new Printer()).setSingleLineMode(true);
+  private static final Printer UNICODE_PRINTER =
+      (new Printer()).setEscapeNonAscii(false);
 
   /**
    * Outputs a textual representation of the Protocol Message supplied into
    * the parameter output. (This representation is the new version of the
    * classic "ProtocolPrinter" output from the original Protocol Buffer system)
    */
-  public static void print(final Message message, final Appendable output)
+  public static void print(final MessageOrBuilder message, final Appendable output)
                            throws IOException {
     DEFAULT_PRINTER.print(message, new TextGenerator(output));
   }
@@ -79,7 +82,7 @@
    * Generates a human readable form of this message, useful for debugging and
    * other purposes, with no newline characters.
    */
-  public static String shortDebugString(final Message message) {
+  public static String shortDebugString(final MessageOrBuilder message) {
     try {
       final StringBuilder sb = new StringBuilder();
       SINGLE_LINE_PRINTER.print(message, new TextGenerator(sb));
@@ -109,7 +112,7 @@
    * Like {@code print()}, but writes directly to a {@code String} and
    * returns it.
    */
-  public static String printToString(final Message message) {
+  public static String printToString(final MessageOrBuilder message) {
     try {
       final StringBuilder text = new StringBuilder();
       print(message, text);
@@ -133,6 +136,34 @@
     }
   }
 
+  /**
+   * Same as {@code printToString()}, except that non-ASCII characters
+   * in string type fields are not escaped in backslash+octals.
+   */
+  public static String printToUnicodeString(final MessageOrBuilder message) {
+    try {
+      final StringBuilder text = new StringBuilder();
+      UNICODE_PRINTER.print(message, new TextGenerator(text));
+      return text.toString();
+    } catch (IOException e) {
+      throw new IllegalStateException(e);
+    }
+  }
+
+  /**
+   * Same as {@code printToString()}, except that non-ASCII characters
+   * in string type fields are not escaped in backslash+octals.
+   */
+  public static String printToUnicodeString(final UnknownFieldSet fields) {
+    try {
+      final StringBuilder text = new StringBuilder();
+      UNICODE_PRINTER.printUnknownFields(fields, new TextGenerator(text));
+      return text.toString();
+    } catch (IOException e) {
+      throw new IllegalStateException(e);
+    }
+  }
+
   public static void printField(final FieldDescriptor field,
                                 final Object value,
                                 final Appendable output)
@@ -216,13 +247,26 @@
   /** Helper class for converting protobufs to text. */
   private static final class Printer {
     /** Whether to omit newlines from the output. */
-    final boolean singleLineMode;
+    boolean singleLineMode = false;
 
-    private Printer(final boolean singleLineMode) {
+    /** Whether to escape non ASCII characters with backslash and octal. */
+    boolean escapeNonAscii = true;
+
+    private Printer() {}
+
+    /** Setter of singleLineMode */
+    private Printer setSingleLineMode(boolean singleLineMode) {
       this.singleLineMode = singleLineMode;
+      return this;
     }
 
-    private void print(final Message message, final TextGenerator generator)
+    /** Setter of escapeNonAscii */
+    private Printer setEscapeNonAscii(boolean escapeNonAscii) {
+      this.escapeNonAscii = escapeNonAscii;
+      return this;
+    }
+
+    private void print(final MessageOrBuilder message, final TextGenerator generator)
         throws IOException {
       for (Map.Entry<FieldDescriptor, Object> field
           : message.getAllFields().entrySet()) {
@@ -339,7 +383,9 @@
 
         case STRING:
           generator.print("\"");
-          generator.print(escapeText((String) value));
+          generator.print(escapeNonAscii ?
+              escapeText((String) value) :
+              (String) value);
           generator.print("\"");
           break;
 
@@ -541,7 +587,7 @@
     private int previousLine = 0;
     private int previousColumn = 0;
 
-    // We use possesive quantifiers (*+ and ++) because otherwise the Java
+    // We use possessive quantifiers (*+ and ++) because otherwise the Java
     // regex matcher has stack overflows on large inputs.
     private static final Pattern WHITESPACE =
       Pattern.compile("(\\s|(#.*$))++", Pattern.MULTILINE);
@@ -864,7 +910,7 @@
     public ParseException parseException(final String description) {
       // Note:  People generally prefer one-based line and column numbers.
       return new ParseException(
-        (line + 1) + ":" + (column + 1) + ": " + description);
+        line + 1, column + 1, description);
     }
 
     /**
@@ -875,7 +921,7 @@
         final String description) {
       // Note:  People generally prefer one-based line and column numbers.
       return new ParseException(
-        (previousLine + 1) + ":" + (previousColumn + 1) + ": " + description);
+        previousLine + 1, previousColumn + 1, description);
     }
 
     /**
@@ -900,8 +946,45 @@
   public static class ParseException extends IOException {
     private static final long serialVersionUID = 3196188060225107702L;
 
+    private final int line;
+    private final int column;
+
+    /** Create a new instance, with -1 as the line and column numbers. */
     public ParseException(final String message) {
-      super(message);
+      this(-1, -1, message);
+    }
+
+    /**
+     * Create a new instance
+     *
+     * @param line the line number where the parse error occurred,
+     * using 1-offset.
+     * @param column the column number where the parser error occurred,
+     * using 1-offset.
+     */
+    public ParseException(final int line, final int column,
+        final String message) {
+      super(Integer.toString(line) + ":" + column + ": " + message);
+      this.line = line;
+      this.column = column;
+    }
+
+    /**
+     * Return the line where the parse exception occurred, or -1 when
+     * none is provided. The value is specified as 1-offset, so the first
+     * line is line 1.
+     */
+    public int getLine() {
+      return line;
+    }
+
+    /**
+     * Return the column where the parse exception occurred, or -1 when
+     * none is provided. The value is specified as 1-offset, so the first
+     * line is line 1.
+     */
+    public int getColumn() {
+      return column;
     }
   }
 
@@ -1073,7 +1156,7 @@
         mergeField(tokenizer, extensionRegistry, subBuilder);
       }
 
-      value = subBuilder.build();
+      value = subBuilder.buildPartial();
 
     } else {
       tokenizer.consume(":");
@@ -1212,7 +1295,7 @@
    */
   static ByteString unescapeBytes(final CharSequence charString)
       throws InvalidEscapeSequenceException {
-    // First convert the Java characater sequence to UTF-8 bytes.
+    // First convert the Java character sequence to UTF-8 bytes.
     ByteString input = ByteString.copyFromUtf8(charString.toString());
     // Then unescape certain byte sequences introduced by ASCII '\\'.  The valid
     // escapes can all be expressed with ASCII characters, so it is safe to
@@ -1349,7 +1432,7 @@
   /**
    * Parse a 32-bit signed integer from the text.  Unlike the Java standard
    * {@code Integer.parseInt()}, this function recognizes the prefixes "0x"
-   * and "0" to signify hexidecimal and octal numbers, respectively.
+   * and "0" to signify hexadecimal and octal numbers, respectively.
    */
   static int parseInt32(final String text) throws NumberFormatException {
     return (int) parseInteger(text, true, false);
@@ -1358,7 +1441,7 @@
   /**
    * Parse a 32-bit unsigned integer from the text.  Unlike the Java standard
    * {@code Integer.parseInt()}, this function recognizes the prefixes "0x"
-   * and "0" to signify hexidecimal and octal numbers, respectively.  The
+   * and "0" to signify hexadecimal and octal numbers, respectively.  The
    * result is coerced to a (signed) {@code int} when returned since Java has
    * no unsigned integer type.
    */
@@ -1369,7 +1452,7 @@
   /**
    * Parse a 64-bit signed integer from the text.  Unlike the Java standard
    * {@code Integer.parseInt()}, this function recognizes the prefixes "0x"
-   * and "0" to signify hexidecimal and octal numbers, respectively.
+   * and "0" to signify hexadecimal and octal numbers, respectively.
    */
   static long parseInt64(final String text) throws NumberFormatException {
     return parseInteger(text, true, true);
@@ -1378,7 +1461,7 @@
   /**
    * Parse a 64-bit unsigned integer from the text.  Unlike the Java standard
    * {@code Integer.parseInt()}, this function recognizes the prefixes "0x"
-   * and "0" to signify hexidecimal and octal numbers, respectively.  The
+   * and "0" to signify hexadecimal and octal numbers, respectively.  The
    * result is coerced to a (signed) {@code long} when returned since Java has
    * no unsigned long type.
    */
diff --git a/third_party/protobuf/java/src/main/java/com/google/protobuf/UnknownFieldSet.java b/third_party/protobuf/java/src/main/java/com/google/protobuf/UnknownFieldSet.java
index 26a15d0..45e2e6e 100644
--- a/third_party/protobuf/java/src/main/java/com/google/protobuf/UnknownFieldSet.java
+++ b/third_party/protobuf/java/src/main/java/com/google/protobuf/UnknownFieldSet.java
@@ -46,7 +46,7 @@
  * {@code UnknownFieldSet} is used to keep track of fields which were seen when
  * parsing a protocol message but whose field numbers or types are unrecognized.
  * This most frequently occurs when new fields are added to a message type
- * and then messages containing those feilds are read by old software that was
+ * and then messages containing those fields are read by old software that was
  * compiled before the new types were added.
  *
  * <p>Every {@link Message} contains an {@code UnknownFieldSet} (and every
@@ -468,7 +468,7 @@
     /**
      * Parse a single field from {@code input} and merge it into this set.
      * @param tag The field's tag number, which was already parsed.
-     * @return {@code false} if the tag is an engroup tag.
+     * @return {@code false} if the tag is an end group tag.
      */
     public boolean mergeFieldFrom(final int tag, final CodedInputStream input)
                                   throws IOException {
@@ -950,4 +950,29 @@
       }
     }
   }
+
+  /**
+   * Parser to implement MessageLite interface.
+   */
+  public static final class Parser extends AbstractParser<UnknownFieldSet> {
+    public UnknownFieldSet parsePartialFrom(
+        CodedInputStream input, ExtensionRegistryLite extensionRegistry)
+        throws InvalidProtocolBufferException {
+      Builder builder = newBuilder();
+      try {
+        builder.mergeFrom(input);
+      } catch (InvalidProtocolBufferException e) {
+        throw e.setUnfinishedMessage(builder.buildPartial());
+      } catch (IOException e) {
+        throw new InvalidProtocolBufferException(e.getMessage())
+            .setUnfinishedMessage(builder.buildPartial());
+      }
+      return builder.buildPartial();
+    }
+  }
+
+  private static final Parser PARSER = new Parser();
+  public final Parser getParserForType() {
+    return PARSER;
+  }
 }
diff --git a/third_party/protobuf/java/src/main/java/com/google/protobuf/UnmodifiableLazyStringList.java b/third_party/protobuf/java/src/main/java/com/google/protobuf/UnmodifiableLazyStringList.java
index 83e5c79..f80f096 100644
--- a/third_party/protobuf/java/src/main/java/com/google/protobuf/UnmodifiableLazyStringList.java
+++ b/third_party/protobuf/java/src/main/java/com/google/protobuf/UnmodifiableLazyStringList.java
@@ -32,6 +32,7 @@
 
 import java.util.AbstractList;
 import java.util.RandomAccess;
+import java.util.List;
 import java.util.ListIterator;
 import java.util.Iterator;
 
@@ -143,4 +144,10 @@
       }
     };
   }
+
+  @Override
+  public List<?> getUnderlyingElements() {
+    // The returned value is already unmodifiable.
+    return list.getUnderlyingElements();
+  }
 }
diff --git a/third_party/protobuf/java/src/main/java/com/google/protobuf/Utf8.java b/third_party/protobuf/java/src/main/java/com/google/protobuf/Utf8.java
new file mode 100644
index 0000000..388f7fc
--- /dev/null
+++ b/third_party/protobuf/java/src/main/java/com/google/protobuf/Utf8.java
@@ -0,0 +1,349 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 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.
+
+package com.google.protobuf;
+
+/**
+ * A set of low-level, high-performance static utility methods related
+ * to the UTF-8 character encoding.  This class has no dependencies
+ * outside of the core JDK libraries.
+ *
+ * <p>There are several variants of UTF-8.  The one implemented by
+ * this class is the restricted definition of UTF-8 introduced in
+ * Unicode 3.1, which mandates the rejection of "overlong" byte
+ * sequences as well as rejection of 3-byte surrogate codepoint byte
+ * sequences.  Note that the UTF-8 decoder included in Oracle's JDK
+ * has been modified to also reject "overlong" byte sequences, but (as
+ * of 2011) still accepts 3-byte surrogate codepoint byte sequences.
+ *
+ * <p>The byte sequences considered valid by this class are exactly
+ * those that can be roundtrip converted to Strings and back to bytes
+ * using the UTF-8 charset, without loss: <pre> {@code
+ * Arrays.equals(bytes, new String(bytes, "UTF-8").getBytes("UTF-8"))
+ * }</pre>
+ *
+ * <p>See the Unicode Standard,</br>
+ * Table 3-6. <em>UTF-8 Bit Distribution</em>,</br>
+ * Table 3-7. <em>Well Formed UTF-8 Byte Sequences</em>.
+ *
+ * <p>This class supports decoding of partial byte sequences, so that the
+ * bytes in a complete UTF-8 byte sequences can be stored in multiple
+ * segments.  Methods typically return {@link #MALFORMED} if the partial
+ * byte sequence is definitely not well-formed, {@link #COMPLETE} if it is
+ * well-formed in the absence of additional input, or if the byte sequence
+ * apparently terminated in the middle of a character, an opaque integer
+ * "state" value containing enough information to decode the character when
+ * passed to a subsequent invocation of a partial decoding method.
+ *
+ * @author martinrb@google.com (Martin Buchholz)
+ */
+final class Utf8 {
+  private Utf8() {}
+
+  /**
+   * State value indicating that the byte sequence is well-formed and
+   * complete (no further bytes are needed to complete a character).
+   */
+  public static final int COMPLETE = 0;
+
+  /**
+   * State value indicating that the byte sequence is definitely not
+   * well-formed.
+   */
+  public static final int MALFORMED = -1;
+
+  // Other state values include the partial bytes of the incomplete
+  // character to be decoded in the simplest way: we pack the bytes
+  // into the state int in little-endian order.  For example:
+  //
+  // int state = byte1 ^ (byte2 << 8) ^ (byte3 << 16);
+  //
+  // Such a state is unpacked thus (note the ~ operation for byte2 to
+  // undo byte1's sign-extension bits):
+  //
+  // int byte1 = (byte) state;
+  // int byte2 = (byte) ~(state >> 8);
+  // int byte3 = (byte) (state >> 16);
+  //
+  // We cannot store a zero byte in the state because it would be
+  // indistinguishable from the absence of a byte.  But we don't need
+  // to, because partial bytes must always be negative.  When building
+  // a state, we ensure that byte1 is negative and subsequent bytes
+  // are valid trailing bytes.
+
+  /**
+   * Returns {@code true} if the given byte array is a well-formed
+   * UTF-8 byte sequence.
+   *
+   * <p>This is a convenience method, equivalent to a call to {@code
+   * isValidUtf8(bytes, 0, bytes.length)}.
+   */
+  public static boolean isValidUtf8(byte[] bytes) {
+    return isValidUtf8(bytes, 0, bytes.length);
+  }
+
+  /**
+   * Returns {@code true} if the given byte array slice is a
+   * well-formed UTF-8 byte sequence.  The range of bytes to be
+   * checked extends from index {@code index}, inclusive, to {@code
+   * limit}, exclusive.
+   *
+   * <p>This is a convenience method, equivalent to {@code
+   * partialIsValidUtf8(bytes, index, limit) == Utf8.COMPLETE}.
+   */
+  public static boolean isValidUtf8(byte[] bytes, int index, int limit) {
+    return partialIsValidUtf8(bytes, index, limit) == COMPLETE;
+  }
+
+  /**
+   * Tells whether the given byte array slice is a well-formed,
+   * malformed, or incomplete UTF-8 byte sequence.  The range of bytes
+   * to be checked extends from index {@code index}, inclusive, to
+   * {@code limit}, exclusive.
+   *
+   * @param state either {@link Utf8#COMPLETE} (if this is the initial decoding
+   * operation) or the value returned from a call to a partial decoding method
+   * for the previous bytes
+   *
+   * @return {@link #MALFORMED} if the partial byte sequence is
+   * definitely not well-formed, {@link #COMPLETE} if it is well-formed
+   * (no additional input needed), or if the byte sequence is
+   * "incomplete", i.e. apparently terminated in the middle of a character,
+   * an opaque integer "state" value containing enough information to
+   * decode the character when passed to a subsequent invocation of a
+   * partial decoding method.
+   */
+  public static int partialIsValidUtf8(
+      int state, byte[] bytes, int index, int limit) {
+    if (state != COMPLETE) {
+      // The previous decoding operation was incomplete (or malformed).
+      // We look for a well-formed sequence consisting of bytes from
+      // the previous decoding operation (stored in state) together
+      // with bytes from the array slice.
+      //
+      // We expect such "straddler characters" to be rare.
+
+      if (index >= limit) {  // No bytes? No progress.
+        return state;
+      }
+      int byte1 = (byte) state;
+      // byte1 is never ASCII.
+      if (byte1 < (byte) 0xE0) {
+        // two-byte form
+
+        // Simultaneously checks for illegal trailing-byte in
+        // leading position and overlong 2-byte form.
+        if (byte1 < (byte) 0xC2 ||
+            // byte2 trailing-byte test
+            bytes[index++] > (byte) 0xBF) {
+          return MALFORMED;
+        }
+      } else if (byte1 < (byte) 0xF0) {
+        // three-byte form
+
+        // Get byte2 from saved state or array
+        int byte2 = (byte) ~(state >> 8);
+        if (byte2 == 0) {
+          byte2 = bytes[index++];
+          if (index >= limit) {
+            return incompleteStateFor(byte1, byte2);
+          }
+        }
+        if (byte2 > (byte) 0xBF ||
+            // overlong? 5 most significant bits must not all be zero
+            (byte1 == (byte) 0xE0 && byte2 < (byte) 0xA0) ||
+            // illegal surrogate codepoint?
+            (byte1 == (byte) 0xED && byte2 >= (byte) 0xA0) ||
+            // byte3 trailing-byte test
+            bytes[index++] > (byte) 0xBF) {
+          return MALFORMED;
+        }
+      } else {
+        // four-byte form
+
+        // Get byte2 and byte3 from saved state or array
+        int byte2 = (byte) ~(state >> 8);
+        int byte3 = 0;
+        if (byte2 == 0) {
+          byte2 = bytes[index++];
+          if (index >= limit) {
+            return incompleteStateFor(byte1, byte2);
+          }
+        } else {
+          byte3 = (byte) (state >> 16);
+        }
+        if (byte3 == 0) {
+          byte3 = bytes[index++];
+          if (index >= limit) {
+            return incompleteStateFor(byte1, byte2, byte3);
+          }
+        }
+
+        // If we were called with state == MALFORMED, then byte1 is 0xFF,
+        // which never occurs in well-formed UTF-8, and so we will return
+        // MALFORMED again below.
+
+        if (byte2 > (byte) 0xBF ||
+            // Check that 1 <= plane <= 16.  Tricky optimized form of:
+            // if (byte1 > (byte) 0xF4 ||
+            //     byte1 == (byte) 0xF0 && byte2 < (byte) 0x90 ||
+            //     byte1 == (byte) 0xF4 && byte2 > (byte) 0x8F)
+            (((byte1 << 28) + (byte2 - (byte) 0x90)) >> 30) != 0 ||
+            // byte3 trailing-byte test
+            byte3 > (byte) 0xBF ||
+            // byte4 trailing-byte test
+             bytes[index++] > (byte) 0xBF) {
+          return MALFORMED;
+        }
+      }
+    }
+
+    return partialIsValidUtf8(bytes, index, limit);
+  }
+
+  /**
+   * Tells whether the given byte array slice is a well-formed,
+   * malformed, or incomplete UTF-8 byte sequence.  The range of bytes
+   * to be checked extends from index {@code index}, inclusive, to
+   * {@code limit}, exclusive.
+   *
+   * <p>This is a convenience method, equivalent to a call to {@code
+   * partialIsValidUtf8(Utf8.COMPLETE, bytes, index, limit)}.
+   *
+   * @return {@link #MALFORMED} if the partial byte sequence is
+   * definitely not well-formed, {@link #COMPLETE} if it is well-formed
+   * (no additional input needed), or if the byte sequence is
+   * "incomplete", i.e. apparently terminated in the middle of a character,
+   * an opaque integer "state" value containing enough information to
+   * decode the character when passed to a subsequent invocation of a
+   * partial decoding method.
+   */
+  public static int partialIsValidUtf8(
+      byte[] bytes, int index, int limit) {
+    // Optimize for 100% ASCII.
+    // Hotspot loves small simple top-level loops like this.
+    while (index < limit && bytes[index] >= 0) {
+      index++;
+    }
+
+    return (index >= limit) ? COMPLETE :
+        partialIsValidUtf8NonAscii(bytes, index, limit);
+  }
+
+  private static int partialIsValidUtf8NonAscii(
+      byte[] bytes, int index, int limit) {
+    for (;;) {
+      int byte1, byte2;
+
+      // Optimize for interior runs of ASCII bytes.
+      do {
+        if (index >= limit) {
+          return COMPLETE;
+        }
+      } while ((byte1 = bytes[index++]) >= 0);
+
+      if (byte1 < (byte) 0xE0) {
+        // two-byte form
+
+        if (index >= limit) {
+          return byte1;
+        }
+
+        // Simultaneously checks for illegal trailing-byte in
+        // leading position and overlong 2-byte form.
+        if (byte1 < (byte) 0xC2 ||
+            bytes[index++] > (byte) 0xBF) {
+          return MALFORMED;
+        }
+      } else if (byte1 < (byte) 0xF0) {
+        // three-byte form
+
+        if (index >= limit - 1) { // incomplete sequence
+          return incompleteStateFor(bytes, index, limit);
+        }
+        if ((byte2 = bytes[index++]) > (byte) 0xBF ||
+            // overlong? 5 most significant bits must not all be zero
+            (byte1 == (byte) 0xE0 && byte2 < (byte) 0xA0) ||
+            // check for illegal surrogate codepoints
+            (byte1 == (byte) 0xED && byte2 >= (byte) 0xA0) ||
+            // byte3 trailing-byte test
+            bytes[index++] > (byte) 0xBF) {
+          return MALFORMED;
+        }
+      } else {
+        // four-byte form
+
+        if (index >= limit - 2) {  // incomplete sequence
+          return incompleteStateFor(bytes, index, limit);
+        }
+        if ((byte2 = bytes[index++]) > (byte) 0xBF ||
+            // Check that 1 <= plane <= 16.  Tricky optimized form of:
+            // if (byte1 > (byte) 0xF4 ||
+            //     byte1 == (byte) 0xF0 && byte2 < (byte) 0x90 ||
+            //     byte1 == (byte) 0xF4 && byte2 > (byte) 0x8F)
+            (((byte1 << 28) + (byte2 - (byte) 0x90)) >> 30) != 0 ||
+            // byte3 trailing-byte test
+            bytes[index++] > (byte) 0xBF ||
+            // byte4 trailing-byte test
+            bytes[index++] > (byte) 0xBF) {
+          return MALFORMED;
+        }
+      }
+    }
+  }
+
+  private static int incompleteStateFor(int byte1) {
+    return (byte1 > (byte) 0xF4) ?
+        MALFORMED : byte1;
+  }
+
+  private static int incompleteStateFor(int byte1, int byte2) {
+    return (byte1 > (byte) 0xF4 ||
+            byte2 > (byte) 0xBF) ?
+        MALFORMED : byte1 ^ (byte2 << 8);
+  }
+
+  private static int incompleteStateFor(int byte1, int byte2, int byte3) {
+    return (byte1 > (byte) 0xF4 ||
+            byte2 > (byte) 0xBF ||
+            byte3 > (byte) 0xBF) ?
+        MALFORMED : byte1 ^ (byte2 << 8) ^ (byte3 << 16);
+  }
+
+  private static int incompleteStateFor(byte[] bytes, int index, int limit) {
+    int byte1 = bytes[index - 1];
+    switch (limit - index) {
+      case 0: return incompleteStateFor(byte1);
+      case 1: return incompleteStateFor(byte1, bytes[index]);
+      case 2: return incompleteStateFor(byte1, bytes[index], bytes[index + 1]);
+      default: throw new AssertionError();
+    }
+  }
+}
diff --git a/third_party/protobuf/java/src/main/java/com/google/protobuf/WireFormat.java b/third_party/protobuf/java/src/main/java/com/google/protobuf/WireFormat.java
index a30f2a3..dd2d631 100644
--- a/third_party/protobuf/java/src/main/java/com/google/protobuf/WireFormat.java
+++ b/third_party/protobuf/java/src/main/java/com/google/protobuf/WireFormat.java
@@ -146,7 +146,7 @@
     public boolean isPackable() { return true; }
   }
 
-  // Field numbers for feilds in MessageSet wire format.
+  // Field numbers for fields in MessageSet wire format.
   static final int MESSAGE_SET_ITEM    = 1;
   static final int MESSAGE_SET_TYPE_ID = 2;
   static final int MESSAGE_SET_MESSAGE = 3;
diff --git a/third_party/protobuf/java/src/test/java/com/google/protobuf/AbstractMessageTest.java b/third_party/protobuf/java/src/test/java/com/google/protobuf/AbstractMessageTest.java
index d53ce8d..3d05cb7 100644
--- a/third_party/protobuf/java/src/test/java/com/google/protobuf/AbstractMessageTest.java
+++ b/third_party/protobuf/java/src/test/java/com/google/protobuf/AbstractMessageTest.java
@@ -30,6 +30,7 @@
 
 package com.google.protobuf;
 
+import com.google.protobuf.Descriptors.FieldDescriptor;
 import protobuf_unittest.UnittestOptimizeFor.TestOptimizedForSize;
 import protobuf_unittest.UnittestProto;
 import protobuf_unittest.UnittestProto.ForeignMessage;
@@ -167,6 +168,13 @@
         wrappedBuilder.setUnknownFields(unknownFields);
         return this;
       }
+      @Override
+      public Message.Builder getFieldBuilder(FieldDescriptor field) {
+        return wrappedBuilder.getFieldBuilder(field);
+      }
+    }
+    public Parser<? extends Message> getParserForType() {
+      return wrappedMessage.getParserForType();
     }
   }
 
@@ -220,6 +228,34 @@
     TestUtil.assertAllFieldsSet((TestAllTypes) message.wrappedMessage);
   }
 
+  public void testParsingUninitialized() throws Exception {
+    TestRequiredForeign.Builder builder = TestRequiredForeign.newBuilder();
+    builder.getOptionalMessageBuilder().setDummy2(10);
+    ByteString bytes = builder.buildPartial().toByteString();
+    Message.Builder abstractMessageBuilder =
+        new AbstractMessageWrapper.Builder(TestRequiredForeign.newBuilder());
+    // mergeFrom() should not throw initialization error.
+    abstractMessageBuilder.mergeFrom(bytes).buildPartial();
+    try {
+      abstractMessageBuilder.mergeFrom(bytes).build();
+      fail();
+    } catch (UninitializedMessageException ex) {
+      // pass
+    }
+
+    // test DynamicMessage directly.
+    Message.Builder dynamicMessageBuilder = DynamicMessage.newBuilder(
+        TestRequiredForeign.getDescriptor());
+    // mergeFrom() should not throw initialization error.
+    dynamicMessageBuilder.mergeFrom(bytes).buildPartial();
+    try {
+      dynamicMessageBuilder.mergeFrom(bytes).build();
+      fail();
+    } catch (UninitializedMessageException ex) {
+      // pass
+    }
+  }
+
   public void testPackedSerialization() throws Exception {
     Message abstractMessage =
         new AbstractMessageWrapper(TestUtil.getPackedSet());
@@ -298,12 +334,16 @@
       new AbstractMessageWrapper.Builder(builder);
 
     assertFalse(abstractBuilder.isInitialized());
+    assertEquals("a, b, c", abstractBuilder.getInitializationErrorString());
     builder.setA(1);
     assertFalse(abstractBuilder.isInitialized());
+    assertEquals("b, c", abstractBuilder.getInitializationErrorString());
     builder.setB(1);
     assertFalse(abstractBuilder.isInitialized());
+    assertEquals("c", abstractBuilder.getInitializationErrorString());
     builder.setC(1);
     assertTrue(abstractBuilder.isInitialized());
+    assertEquals("", abstractBuilder.getInitializationErrorString());
   }
 
   public void testForeignIsInitialized() throws Exception {
@@ -312,18 +352,27 @@
       new AbstractMessageWrapper.Builder(builder);
 
     assertTrue(abstractBuilder.isInitialized());
+    assertEquals("", abstractBuilder.getInitializationErrorString());
 
     builder.setOptionalMessage(TEST_REQUIRED_UNINITIALIZED);
     assertFalse(abstractBuilder.isInitialized());
+    assertEquals(
+        "optional_message.a, optional_message.b, optional_message.c",
+        abstractBuilder.getInitializationErrorString());
 
     builder.setOptionalMessage(TEST_REQUIRED_INITIALIZED);
     assertTrue(abstractBuilder.isInitialized());
+    assertEquals("", abstractBuilder.getInitializationErrorString());
 
     builder.addRepeatedMessage(TEST_REQUIRED_UNINITIALIZED);
     assertFalse(abstractBuilder.isInitialized());
+    assertEquals(
+        "repeated_message[0].a, repeated_message[0].b, repeated_message[0].c",
+        abstractBuilder.getInitializationErrorString());
 
     builder.setRepeatedMessage(0, TEST_REQUIRED_INITIALIZED);
     assertTrue(abstractBuilder.isInitialized());
+    assertEquals("", abstractBuilder.getInitializationErrorString());
   }
 
   // -----------------------------------------------------------------
@@ -421,7 +470,7 @@
 
 
   /**
-   * Asserts that the given proto has symetric equals and hashCode methods.
+   * Asserts that the given proto has symmetric equals and hashCode methods.
    */
   private void checkEqualsIsConsistent(Message message) {
     // Object should be equal to itself.
diff --git a/third_party/protobuf/java/src/test/java/com/google/protobuf/BoundedByteStringTest.java b/third_party/protobuf/java/src/test/java/com/google/protobuf/BoundedByteStringTest.java
new file mode 100644
index 0000000..20fa2df
--- /dev/null
+++ b/third_party/protobuf/java/src/test/java/com/google/protobuf/BoundedByteStringTest.java
@@ -0,0 +1,68 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 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.
+
+package com.google.protobuf;
+
+import java.io.UnsupportedEncodingException;
+
+/**
+ * This class tests {@link BoundedByteString}, which extends {@link LiteralByteString},
+ * by inheriting the tests from {@link LiteralByteStringTest}.  The only method which
+ * is strange enough that it needs to be overridden here is {@link #testToString()}.
+ *
+ * @author carlanton@google.com (Carl Haverl)
+ */
+public class BoundedByteStringTest extends LiteralByteStringTest {
+
+  @Override
+  protected void setUp() throws Exception {
+    classUnderTest = "BoundedByteString";
+    byte[] sourceBytes = ByteStringTest.getTestBytes(2341, 11337766L);
+    int from = 100;
+    int to = sourceBytes.length - 100;
+    stringUnderTest = ByteString.copyFrom(sourceBytes).substring(from, to);
+    referenceBytes = new byte[to - from];
+    System.arraycopy(sourceBytes, from, referenceBytes, 0, to - from);
+    expectedHashCode = 727575887;
+  }
+
+  @Override
+  public void testToString() throws UnsupportedEncodingException {
+    String testString = "I love unicode \u1234\u5678 characters";
+    LiteralByteString unicode = new LiteralByteString(testString.getBytes(UTF_8));
+    ByteString chopped = unicode.substring(2, unicode.size() - 6);
+    assertEquals(classUnderTest + ".substring() must have the expected type",
+        classUnderTest, getActualClassName(chopped));
+
+    String roundTripString = chopped.toString(UTF_8);
+    assertEquals(classUnderTest + " unicode bytes must match",
+        testString.substring(2, testString.length() - 6), roundTripString);
+  }
+}
diff --git a/third_party/protobuf/java/src/test/java/com/google/protobuf/ByteStringTest.java b/third_party/protobuf/java/src/test/java/com/google/protobuf/ByteStringTest.java
new file mode 100644
index 0000000..7a1d682
--- /dev/null
+++ b/third_party/protobuf/java/src/test/java/com/google/protobuf/ByteStringTest.java
@@ -0,0 +1,692 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 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.
+
+package com.google.protobuf;
+
+import com.google.protobuf.ByteString.Output;
+
+import junit.framework.TestCase;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.UnsupportedEncodingException;
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.List;
+import java.util.NoSuchElementException;
+import java.util.Random;
+
+/**
+ * Test methods with implementations in {@link ByteString}, plus do some top-level "integration"
+ * tests.
+ *
+ * @author carlanton@google.com (Carl Haverl)
+ */
+public class ByteStringTest extends TestCase {
+
+  private static final String UTF_16 = "UTF-16";
+
+  static byte[] getTestBytes(int size, long seed) {
+    Random random = new Random(seed);
+    byte[] result = new byte[size];
+    random.nextBytes(result);
+    return result;
+  }
+
+  private byte[] getTestBytes(int size) {
+    return getTestBytes(size, 445566L);
+  }
+
+  private byte[] getTestBytes() {
+    return getTestBytes(1000);
+  }
+
+  // Compare the entire left array with a subset of the right array.
+  private boolean isArrayRange(byte[] left, byte[] right, int rightOffset, int length) {
+    boolean stillEqual = (left.length == length);
+    for (int i = 0; (stillEqual && i < length); ++i) {
+      stillEqual = (left[i] == right[rightOffset + i]);
+    }
+    return stillEqual;
+  }
+
+  // Returns true only if the given two arrays have identical contents.
+  private boolean isArray(byte[] left, byte[] right) {
+    return left.length == right.length && isArrayRange(left, right, 0, left.length);
+  }
+
+  public void testSubstring_BeginIndex() {
+    byte[] bytes = getTestBytes();
+    ByteString substring = ByteString.copyFrom(bytes).substring(500);
+    assertTrue("substring must contain the tail of the string",
+        isArrayRange(substring.toByteArray(), bytes, 500, bytes.length - 500));
+  }
+
+  public void testCopyFrom_BytesOffsetSize() {
+    byte[] bytes = getTestBytes();
+    ByteString byteString = ByteString.copyFrom(bytes, 500, 200);
+    assertTrue("copyFrom sub-range must contain the expected bytes",
+        isArrayRange(byteString.toByteArray(), bytes, 500, 200));
+  }
+
+  public void testCopyFrom_Bytes() {
+    byte[] bytes = getTestBytes();
+    ByteString byteString = ByteString.copyFrom(bytes);
+    assertTrue("copyFrom must contain the expected bytes",
+        isArray(byteString.toByteArray(), bytes));
+  }
+
+  public void testCopyFrom_ByteBufferSize() {
+    byte[] bytes = getTestBytes();
+    ByteBuffer byteBuffer = ByteBuffer.allocate(bytes.length);
+    byteBuffer.put(bytes);
+    byteBuffer.position(500);
+    ByteString byteString = ByteString.copyFrom(byteBuffer, 200);
+    assertTrue("copyFrom byteBuffer sub-range must contain the expected bytes",
+        isArrayRange(byteString.toByteArray(), bytes, 500, 200));
+  }
+
+  public void testCopyFrom_ByteBuffer() {
+    byte[] bytes = getTestBytes();
+    ByteBuffer byteBuffer = ByteBuffer.allocate(bytes.length);
+    byteBuffer.put(bytes);
+    byteBuffer.position(500);
+    ByteString byteString = ByteString.copyFrom(byteBuffer);
+    assertTrue("copyFrom byteBuffer sub-range must contain the expected bytes",
+        isArrayRange(byteString.toByteArray(), bytes, 500, bytes.length - 500));
+  }
+
+  public void testCopyFrom_StringEncoding() throws UnsupportedEncodingException {
+    String testString = "I love unicode \u1234\u5678 characters";
+    ByteString byteString = ByteString.copyFrom(testString, UTF_16);
+    byte[] testBytes = testString.getBytes(UTF_16);
+    assertTrue("copyFrom string must respect the charset",
+        isArrayRange(byteString.toByteArray(), testBytes, 0, testBytes.length));
+  }
+
+  public void testCopyFrom_Utf8() throws UnsupportedEncodingException {
+    String testString = "I love unicode \u1234\u5678 characters";
+    ByteString byteString = ByteString.copyFromUtf8(testString);
+    byte[] testBytes = testString.getBytes("UTF-8");
+    assertTrue("copyFromUtf8 string must respect the charset",
+        isArrayRange(byteString.toByteArray(), testBytes, 0, testBytes.length));
+  }
+
+  public void testCopyFrom_Iterable() {
+    byte[] testBytes = getTestBytes(77777, 113344L);
+    final List<ByteString> pieces = makeConcretePieces(testBytes);
+    // Call copyFrom() on a Collection
+    ByteString byteString = ByteString.copyFrom(pieces);
+    assertTrue("copyFrom a List must contain the expected bytes",
+        isArrayRange(byteString.toByteArray(), testBytes, 0, testBytes.length));
+    // Call copyFrom on an iteration that's not a collection
+    ByteString byteStringAlt = ByteString.copyFrom(new Iterable<ByteString>() {
+      public Iterator<ByteString> iterator() {
+        return pieces.iterator();
+      }
+    });
+    assertEquals("copyFrom from an Iteration must contain the expected bytes",
+        byteString, byteStringAlt);
+  }
+
+  public void testCopyTo_TargetOffset() {
+    byte[] bytes = getTestBytes();
+    ByteString byteString = ByteString.copyFrom(bytes);
+    byte[] target = new byte[bytes.length + 1000];
+    byteString.copyTo(target, 400);
+    assertTrue("copyFrom byteBuffer sub-range must contain the expected bytes",
+        isArrayRange(bytes, target, 400, bytes.length));
+  }
+
+  public void testReadFrom_emptyStream() throws IOException {
+    ByteString byteString =
+        ByteString.readFrom(new ByteArrayInputStream(new byte[0]));
+    assertSame("reading an empty stream must result in the EMPTY constant "
+        + "byte string", ByteString.EMPTY, byteString);
+  }
+
+  public void testReadFrom_smallStream() throws IOException {
+    assertReadFrom(getTestBytes(10));
+  }
+
+  public void testReadFrom_mutating() throws IOException {
+    byte[] capturedArray = null;
+    EvilInputStream eis = new EvilInputStream();
+    ByteString byteString = ByteString.readFrom(eis);
+
+    capturedArray = eis.capturedArray;
+    byte[] originalValue = byteString.toByteArray();
+    for (int x = 0; x < capturedArray.length; ++x) {
+      capturedArray[x] = (byte) 0;
+    }
+
+    byte[] newValue = byteString.toByteArray();
+    assertTrue("copyFrom byteBuffer must not grant access to underlying array",
+        Arrays.equals(originalValue, newValue));
+  }
+
+  // Tests sizes that are near the rope copy-out threshold.
+  public void testReadFrom_mediumStream() throws IOException {
+    assertReadFrom(getTestBytes(ByteString.CONCATENATE_BY_COPY_SIZE - 1));
+    assertReadFrom(getTestBytes(ByteString.CONCATENATE_BY_COPY_SIZE));
+    assertReadFrom(getTestBytes(ByteString.CONCATENATE_BY_COPY_SIZE + 1));
+    assertReadFrom(getTestBytes(200));
+  }
+
+  // Tests sizes that are over multi-segment rope threshold.
+  public void testReadFrom_largeStream() throws IOException {
+    assertReadFrom(getTestBytes(0x100));
+    assertReadFrom(getTestBytes(0x101));
+    assertReadFrom(getTestBytes(0x110));
+    assertReadFrom(getTestBytes(0x1000));
+    assertReadFrom(getTestBytes(0x1001));
+    assertReadFrom(getTestBytes(0x1010));
+    assertReadFrom(getTestBytes(0x10000));
+    assertReadFrom(getTestBytes(0x10001));
+    assertReadFrom(getTestBytes(0x10010));
+  }
+
+  // Tests sizes that are near the read buffer size.
+  public void testReadFrom_byteBoundaries() throws IOException {
+    final int min = ByteString.MIN_READ_FROM_CHUNK_SIZE;
+    final int max = ByteString.MAX_READ_FROM_CHUNK_SIZE;
+
+    assertReadFrom(getTestBytes(min - 1));
+    assertReadFrom(getTestBytes(min));
+    assertReadFrom(getTestBytes(min + 1));
+
+    assertReadFrom(getTestBytes(min * 2 - 1));
+    assertReadFrom(getTestBytes(min * 2));
+    assertReadFrom(getTestBytes(min * 2 + 1));
+
+    assertReadFrom(getTestBytes(min * 4 - 1));
+    assertReadFrom(getTestBytes(min * 4));
+    assertReadFrom(getTestBytes(min * 4 + 1));
+
+    assertReadFrom(getTestBytes(min * 8 - 1));
+    assertReadFrom(getTestBytes(min * 8));
+    assertReadFrom(getTestBytes(min * 8 + 1));
+
+    assertReadFrom(getTestBytes(max - 1));
+    assertReadFrom(getTestBytes(max));
+    assertReadFrom(getTestBytes(max + 1));
+
+    assertReadFrom(getTestBytes(max * 2 - 1));
+    assertReadFrom(getTestBytes(max * 2));
+    assertReadFrom(getTestBytes(max * 2 + 1));
+  }
+
+  // Tests that IOExceptions propagate through ByteString.readFrom().
+  public void testReadFrom_IOExceptions() {
+    try {
+      ByteString.readFrom(new FailStream());
+      fail("readFrom must throw the underlying IOException");
+
+    } catch (IOException e) {
+      assertEquals("readFrom must throw the expected exception",
+                   "synthetic failure", e.getMessage());
+    }
+  }
+
+  // Tests that ByteString.readFrom works with streams that don't
+  // always fill their buffers.
+  public void testReadFrom_reluctantStream() throws IOException {
+    final byte[] data = getTestBytes(0x1000);
+
+    ByteString byteString = ByteString.readFrom(new ReluctantStream(data));
+    assertTrue("readFrom byte stream must contain the expected bytes",
+        isArray(byteString.toByteArray(), data));
+
+    // Same test as above, but with some specific chunk sizes.
+    assertReadFromReluctantStream(data, 100);
+    assertReadFromReluctantStream(data, 248);
+    assertReadFromReluctantStream(data, 249);
+    assertReadFromReluctantStream(data, 250);
+    assertReadFromReluctantStream(data, 251);
+    assertReadFromReluctantStream(data, 0x1000);
+    assertReadFromReluctantStream(data, 0x1001);
+  }
+
+  // Fails unless ByteString.readFrom reads the bytes correctly from a
+  // reluctant stream with the given chunkSize parameter.
+  private void assertReadFromReluctantStream(byte[] bytes, int chunkSize)
+      throws IOException {
+    ByteString b = ByteString.readFrom(new ReluctantStream(bytes), chunkSize);
+    assertTrue("readFrom byte stream must contain the expected bytes",
+        isArray(b.toByteArray(), bytes));
+  }
+
+  // Tests that ByteString.readFrom works with streams that implement
+  // available().
+  public void testReadFrom_available() throws IOException {
+    final byte[] data = getTestBytes(0x1001);
+
+    ByteString byteString = ByteString.readFrom(new AvailableStream(data));
+    assertTrue("readFrom byte stream must contain the expected bytes",
+        isArray(byteString.toByteArray(), data));
+  }
+
+  // Fails unless ByteString.readFrom reads the bytes correctly.
+  private void assertReadFrom(byte[] bytes) throws IOException {
+    ByteString byteString =
+        ByteString.readFrom(new ByteArrayInputStream(bytes));
+    assertTrue("readFrom byte stream must contain the expected bytes",
+        isArray(byteString.toByteArray(), bytes));
+  }
+
+  // A stream that fails when read.
+  private static final class FailStream extends InputStream {
+    @Override public int read() throws IOException {
+      throw new IOException("synthetic failure");
+    }
+  }
+
+  // A stream that simulates blocking by only producing 250 characters
+  // per call to read(byte[]).
+  private static class ReluctantStream extends InputStream {
+    protected final byte[] data;
+    protected int pos = 0;
+
+    public ReluctantStream(byte[] data) {
+      this.data = data;
+    }
+
+    @Override public int read() {
+      if (pos == data.length) {
+        return -1;
+      } else {
+        return data[pos++];
+      }
+    }
+
+    @Override public int read(byte[] buf) {
+      return read(buf, 0, buf.length);
+    }
+
+    @Override public int read(byte[] buf, int offset, int size) {
+      if (pos == data.length) {
+        return -1;
+      }
+      int count = Math.min(Math.min(size, data.length - pos), 250);
+      System.arraycopy(data, pos, buf, offset, count);
+      pos += count;
+      return count;
+    }
+  }
+
+  // Same as above, but also implements available().
+  private static final class AvailableStream extends ReluctantStream {
+    public AvailableStream(byte[] data) {
+      super(data);
+    }
+
+    @Override public int available() {
+      return Math.min(250, data.length - pos);
+    }
+  }
+
+  // A stream which exposes the byte array passed into read(byte[], int, int).
+  private static class EvilInputStream extends InputStream {
+    public byte[] capturedArray = null;
+
+    @Override
+    public int read(byte[] buf, int off, int len) {
+      if (capturedArray != null) {
+        return -1;
+      } else {
+        capturedArray = buf;
+        for (int x = 0; x < len; ++x) {
+          buf[x] = (byte) x;
+        }
+        return len;
+      }
+    }
+
+    @Override
+    public int read() {
+      // Purposefully do nothing.
+      return -1;
+    }
+  }
+  
+  // A stream which exposes the byte array passed into write(byte[], int, int).
+  private static class EvilOutputStream extends OutputStream {
+    public byte[] capturedArray = null;
+
+    @Override
+    public void write(byte[] buf, int off, int len) {
+      if (capturedArray == null) {
+        capturedArray = buf;
+      }
+    }
+
+    @Override
+    public void write(int ignored) {
+      // Purposefully do nothing.
+    }
+  }
+
+  public void testToStringUtf8() throws UnsupportedEncodingException {
+    String testString = "I love unicode \u1234\u5678 characters";
+    byte[] testBytes = testString.getBytes("UTF-8");
+    ByteString byteString = ByteString.copyFrom(testBytes);
+    assertEquals("copyToStringUtf8 must respect the charset",
+        testString, byteString.toStringUtf8());
+  }
+
+  public void testNewOutput_InitialCapacity() throws IOException {
+    byte[] bytes = getTestBytes();
+    ByteString.Output output = ByteString.newOutput(bytes.length + 100);
+    output.write(bytes);
+    ByteString byteString = output.toByteString();
+    assertTrue(
+        "String built from newOutput(int) must contain the expected bytes",
+        isArrayRange(bytes, byteString.toByteArray(), 0, bytes.length));
+  }
+
+  // Test newOutput() using a variety of buffer sizes and a variety of (fixed)
+  // write sizes
+  public void testNewOutput_ArrayWrite() throws IOException {
+    byte[] bytes = getTestBytes();
+    int length = bytes.length;
+    int[] bufferSizes = {128, 256, length / 2, length - 1, length, length + 1,
+                         2 * length, 3 * length};
+    int[] writeSizes = {1, 4, 5, 7, 23, bytes.length};
+
+    for (int bufferSize : bufferSizes) {
+      for (int writeSize : writeSizes) {
+        // Test writing the entire output writeSize bytes at a time.
+        ByteString.Output output = ByteString.newOutput(bufferSize);
+        for (int i = 0; i < length; i += writeSize) {
+          output.write(bytes, i, Math.min(writeSize, length - i));
+        }
+        ByteString byteString = output.toByteString();
+        assertTrue("String built from newOutput() must contain the expected bytes",
+            isArrayRange(bytes, byteString.toByteArray(), 0, bytes.length));
+      }
+    }
+  }
+
+  // Test newOutput() using a variety of buffer sizes, but writing all the
+  // characters using write(byte);
+  public void testNewOutput_WriteChar() throws IOException {
+    byte[] bytes = getTestBytes();
+    int length = bytes.length;
+    int[] bufferSizes = {0, 1, 128, 256, length / 2,
+                         length - 1, length, length + 1,
+                         2 * length, 3 * length};
+    for (int bufferSize : bufferSizes) {
+      ByteString.Output output = ByteString.newOutput(bufferSize);
+      for (byte byteValue : bytes) {
+        output.write(byteValue);
+      }
+      ByteString byteString = output.toByteString();
+      assertTrue("String built from newOutput() must contain the expected bytes",
+          isArrayRange(bytes, byteString.toByteArray(), 0, bytes.length));
+    }
+  }
+
+  // Test newOutput() in which we write the bytes using a variety of methods
+  // and sizes, and in which we repeatedly call toByteString() in the middle.
+  public void testNewOutput_Mixed() throws IOException {
+    Random rng = new Random(1);
+    byte[] bytes = getTestBytes();
+    int length = bytes.length;
+    int[] bufferSizes = {0, 1, 128, 256, length / 2,
+                         length - 1, length, length + 1,
+                         2 * length, 3 * length};
+
+    for (int bufferSize : bufferSizes) {
+      // Test writing the entire output using a mixture of write sizes and
+      // methods;
+      ByteString.Output output = ByteString.newOutput(bufferSize);
+      int position = 0;
+      while (position < bytes.length) {
+        if (rng.nextBoolean()) {
+          int count = 1 + rng.nextInt(bytes.length - position);
+          output.write(bytes, position, count);
+          position += count;
+        } else {
+          output.write(bytes[position]);
+          position++;
+        }
+        assertEquals("size() returns the right value", position, output.size());
+        assertTrue("newOutput() substring must have correct bytes",
+            isArrayRange(output.toByteString().toByteArray(),
+                bytes, 0, position));
+      }
+      ByteString byteString = output.toByteString();
+      assertTrue("String built from newOutput() must contain the expected bytes",
+          isArrayRange(bytes, byteString.toByteArray(), 0, bytes.length));
+    }
+  }
+  
+  public void testNewOutputEmpty() throws IOException {
+    // Make sure newOutput() correctly builds empty byte strings
+    ByteString byteString = ByteString.newOutput().toByteString();
+    assertEquals(ByteString.EMPTY, byteString);
+  }
+  
+  public void testNewOutput_Mutating() throws IOException {
+    Output os = ByteString.newOutput(5);
+    os.write(new byte[] {1, 2, 3, 4, 5});
+    EvilOutputStream eos = new EvilOutputStream();
+    os.writeTo(eos);
+    byte[] capturedArray = eos.capturedArray;
+    ByteString byteString = os.toByteString();
+    byte[] oldValue = byteString.toByteArray();
+    Arrays.fill(capturedArray, (byte) 0);
+    byte[] newValue = byteString.toByteArray();
+    assertTrue("Output must not provide access to the underlying byte array",
+        Arrays.equals(oldValue, newValue));
+  }
+
+  public void testNewCodedBuilder() throws IOException {
+    byte[] bytes = getTestBytes();
+    ByteString.CodedBuilder builder = ByteString.newCodedBuilder(bytes.length);
+    builder.getCodedOutput().writeRawBytes(bytes);
+    ByteString byteString = builder.build();
+    assertTrue("String built from newCodedBuilder() must contain the expected bytes",
+        isArrayRange(bytes, byteString.toByteArray(), 0, bytes.length));
+  }
+
+  public void testSubstringParity() {
+    byte[] bigBytes = getTestBytes(2048 * 1024, 113344L);
+    int start = 512 * 1024 - 3333;
+    int end   = 512 * 1024 + 7777;
+    ByteString concreteSubstring = ByteString.copyFrom(bigBytes).substring(start, end);
+    boolean ok = true;
+    for (int i = start; ok && i < end; ++i) {
+      ok = (bigBytes[i] == concreteSubstring.byteAt(i - start));
+    }
+    assertTrue("Concrete substring didn't capture the right bytes", ok);
+
+    ByteString literalString = ByteString.copyFrom(bigBytes, start, end - start);
+    assertTrue("Substring must be equal to literal string",
+        concreteSubstring.equals(literalString));
+    assertEquals("Substring must have same hashcode as literal string",
+        literalString.hashCode(), concreteSubstring.hashCode());
+  }
+
+  public void testCompositeSubstring() {
+    byte[] referenceBytes = getTestBytes(77748, 113344L);
+
+    List<ByteString> pieces = makeConcretePieces(referenceBytes);
+    ByteString listString = ByteString.copyFrom(pieces);
+
+    int from = 1000;
+    int to = 40000;
+    ByteString compositeSubstring = listString.substring(from, to);
+    byte[] substringBytes = compositeSubstring.toByteArray();
+    boolean stillEqual = true;
+    for (int i = 0; stillEqual && i < to - from; ++i) {
+      stillEqual = referenceBytes[from + i] == substringBytes[i];
+    }
+    assertTrue("Substring must return correct bytes", stillEqual);
+
+    stillEqual = true;
+    for (int i = 0; stillEqual && i < to - from; ++i) {
+      stillEqual = referenceBytes[from + i] == compositeSubstring.byteAt(i);
+    }
+    assertTrue("Substring must support byteAt() correctly", stillEqual);
+
+    ByteString literalSubstring = ByteString.copyFrom(referenceBytes, from, to - from);
+    assertTrue("Composite substring must equal a literal substring over the same bytes",
+        compositeSubstring.equals(literalSubstring));
+    assertTrue("Literal substring must equal a composite substring over the same bytes",
+        literalSubstring.equals(compositeSubstring));
+
+    assertEquals("We must get the same hashcodes for composite and literal substrings",
+        literalSubstring.hashCode(), compositeSubstring.hashCode());
+
+    assertFalse("We can't be equal to a proper substring",
+        compositeSubstring.equals(literalSubstring.substring(0, literalSubstring.size() - 1)));
+  }
+
+  public void testCopyFromList() {
+    byte[] referenceBytes = getTestBytes(77748, 113344L);
+    ByteString literalString = ByteString.copyFrom(referenceBytes);
+
+    List<ByteString> pieces = makeConcretePieces(referenceBytes);
+    ByteString listString = ByteString.copyFrom(pieces);
+
+    assertTrue("Composite string must be equal to literal string",
+        listString.equals(literalString));
+    assertEquals("Composite string must have same hashcode as literal string",
+        literalString.hashCode(), listString.hashCode());
+  }
+
+  public void testConcat() {
+    byte[] referenceBytes = getTestBytes(77748, 113344L);
+    ByteString literalString = ByteString.copyFrom(referenceBytes);
+
+    List<ByteString> pieces = makeConcretePieces(referenceBytes);
+
+    Iterator<ByteString> iter = pieces.iterator();
+    ByteString concatenatedString = iter.next();
+    while (iter.hasNext()) {
+      concatenatedString = concatenatedString.concat(iter.next());
+    }
+
+    assertTrue("Concatenated string must be equal to literal string",
+        concatenatedString.equals(literalString));
+    assertEquals("Concatenated string must have same hashcode as literal string",
+        literalString.hashCode(), concatenatedString.hashCode());
+  }
+
+  /**
+   * Test the Rope implementation can deal with Empty nodes, even though we
+   * guard against them. See also {@link LiteralByteStringTest#testConcat_empty()}.
+   */
+  public void testConcat_empty() {
+    byte[] referenceBytes = getTestBytes(7748, 113344L);
+    ByteString literalString = ByteString.copyFrom(referenceBytes);
+
+    ByteString duo = RopeByteString.newInstanceForTest(literalString, literalString);
+    ByteString temp = RopeByteString.newInstanceForTest(
+        RopeByteString.newInstanceForTest(literalString, ByteString.EMPTY),
+        RopeByteString.newInstanceForTest(ByteString.EMPTY, literalString));
+    ByteString quintet = RopeByteString.newInstanceForTest(temp, ByteString.EMPTY);
+
+    assertTrue("String with concatenated nulls must equal simple concatenate",
+        duo.equals(quintet));
+    assertEquals("String with concatenated nulls have same hashcode as simple concatenate",
+        duo.hashCode(), quintet.hashCode());
+
+    ByteString.ByteIterator duoIter = duo.iterator();
+    ByteString.ByteIterator quintetIter = quintet.iterator();
+    boolean stillEqual = true;
+    while (stillEqual && quintetIter.hasNext()) {
+      stillEqual = (duoIter.nextByte() == quintetIter.nextByte());
+    }
+    assertTrue("We must get the same characters by iterating", stillEqual);
+    assertFalse("Iterator must be exhausted", duoIter.hasNext());
+    try {
+      duoIter.nextByte();
+      fail("Should have thrown an exception.");
+    } catch (NoSuchElementException e) {
+      // This is success
+    }
+    try {
+      quintetIter.nextByte();
+      fail("Should have thrown an exception.");
+    } catch (NoSuchElementException e) {
+      // This is success
+    }
+
+    // Test that even if we force empty strings in as rope leaves in this
+    // configuration, we always get a (possibly Bounded) LiteralByteString
+    // for a length 1 substring.
+    //
+    // It is possible, using the testing factory method to create deeply nested
+    // trees of empty leaves, to make a string that will fail this test.
+    for (int i = 1; i < duo.size(); ++i) {
+      assertTrue("Substrings of size() < 2 must not be RopeByteStrings",
+          duo.substring(i - 1, i) instanceof LiteralByteString);
+    }
+    for (int i = 1; i < quintet.size(); ++i) {
+      assertTrue("Substrings of size() < 2 must not be RopeByteStrings",
+          quintet.substring(i - 1, i) instanceof LiteralByteString);
+    }
+  }
+
+  public void testStartsWith() {
+    byte[] bytes = getTestBytes(1000, 1234L);
+    ByteString string = ByteString.copyFrom(bytes);
+    ByteString prefix = ByteString.copyFrom(bytes, 0, 500);
+    ByteString suffix = ByteString.copyFrom(bytes, 400, 600);
+    assertTrue(string.startsWith(ByteString.EMPTY));
+    assertTrue(string.startsWith(string));
+    assertTrue(string.startsWith(prefix));
+    assertFalse(string.startsWith(suffix));
+    assertFalse(prefix.startsWith(suffix));
+    assertFalse(suffix.startsWith(prefix));
+    assertFalse(ByteString.EMPTY.startsWith(prefix));
+    assertTrue(ByteString.EMPTY.startsWith(ByteString.EMPTY));
+  }
+
+  static List<ByteString> makeConcretePieces(byte[] referenceBytes) {
+    List<ByteString> pieces = new ArrayList<ByteString>();
+    // Starting length should be small enough that we'll do some concatenating by
+    // copying if we just concatenate all these pieces together.
+    for (int start = 0, length = 16; start < referenceBytes.length; start += length) {
+      length = (length << 1) - 1;
+      if (start + length > referenceBytes.length) {
+        length = referenceBytes.length - start;
+      }
+      pieces.add(ByteString.copyFrom(referenceBytes, start, length));
+    }
+    return pieces;
+  }
+}
diff --git a/third_party/protobuf/java/src/test/java/com/google/protobuf/CodedOutputStreamTest.java b/third_party/protobuf/java/src/test/java/com/google/protobuf/CodedOutputStreamTest.java
index 74476e3..8625502 100644
--- a/third_party/protobuf/java/src/test/java/com/google/protobuf/CodedOutputStreamTest.java
+++ b/third_party/protobuf/java/src/test/java/com/google/protobuf/CodedOutputStreamTest.java
@@ -30,8 +30,10 @@
 
 package com.google.protobuf;
 
+import protobuf_unittest.UnittestProto.SparseEnumMessage;
 import protobuf_unittest.UnittestProto.TestAllTypes;
 import protobuf_unittest.UnittestProto.TestPackedTypes;
+import protobuf_unittest.UnittestProto.TestSparseEnum;
 
 import junit.framework.TestCase;
 
@@ -302,17 +304,14 @@
   }
 
   /** Test writing a message containing a negative enum value. This used to
-   * fail because the size was not properly computed as a sign-extended varint. */
+   * fail because the size was not properly computed as a sign-extended varint.
+   */
   public void testWriteMessageWithNegativeEnumValue() throws Exception {
-    protobuf_unittest.UnittestProto.SparseEnumMessage message =
-        protobuf_unittest.UnittestProto.SparseEnumMessage.newBuilder()
-        .setSparseEnum(protobuf_unittest.UnittestProto.TestSparseEnum.SPARSE_E)
-        .build();
+    SparseEnumMessage message = SparseEnumMessage.newBuilder()
+        .setSparseEnum(TestSparseEnum.SPARSE_E) .build();
     assertTrue(message.getSparseEnum().getNumber() < 0);
     byte[] rawBytes = message.toByteArray();
-    protobuf_unittest.UnittestProto.SparseEnumMessage message2 =
-        protobuf_unittest.UnittestProto.SparseEnumMessage.parseFrom(rawBytes);
-    assertEquals(protobuf_unittest.UnittestProto.TestSparseEnum.SPARSE_E,
-                 message2.getSparseEnum());
+    SparseEnumMessage message2 = SparseEnumMessage.parseFrom(rawBytes);
+    assertEquals(TestSparseEnum.SPARSE_E, message2.getSparseEnum());
   }
 }
diff --git a/third_party/protobuf/java/src/test/java/com/google/protobuf/DescriptorsTest.java b/third_party/protobuf/java/src/test/java/com/google/protobuf/DescriptorsTest.java
index 65d06e3..9c31091 100644
--- a/third_party/protobuf/java/src/test/java/com/google/protobuf/DescriptorsTest.java
+++ b/third_party/protobuf/java/src/test/java/com/google/protobuf/DescriptorsTest.java
@@ -31,6 +31,8 @@
 package com.google.protobuf;
 
 import com.google.protobuf.DescriptorProtos.DescriptorProto;
+import com.google.protobuf.DescriptorProtos.EnumDescriptorProto;
+import com.google.protobuf.DescriptorProtos.EnumValueDescriptorProto;
 import com.google.protobuf.DescriptorProtos.FieldDescriptorProto;
 import com.google.protobuf.DescriptorProtos.FileDescriptorProto;
 import com.google.protobuf.Descriptors.DescriptorValidationException;
@@ -60,6 +62,7 @@
 
 import java.util.Arrays;
 import java.util.Collections;
+import java.util.List;
 
 /**
  * Unit test for {@link Descriptors}.
@@ -426,7 +429,7 @@
         UnittestEnormousDescriptor.getDescriptor()
           .toProto().getSerializedSize() > 65536);
   }
-  
+
   /**
    * Tests that the DescriptorValidationException works as intended.
    */
@@ -445,7 +448,7 @@
         .build())
       .build();
     try {
-      Descriptors.FileDescriptor.buildFrom(fileDescriptorProto, 
+      Descriptors.FileDescriptor.buildFrom(fileDescriptorProto,
           new FileDescriptor[0]);
       fail("DescriptorValidationException expected");
     } catch (DescriptorValidationException e) {
@@ -457,4 +460,189 @@
       assertTrue(e.getCause().getMessage().indexOf("invalid") != -1);
     }
   }
+
+  /**
+   * Tests the translate/crosslink for an example where a message field's name
+   * and type name are the same.
+   */
+  public void testDescriptorComplexCrosslink() throws Exception {
+    FileDescriptorProto fileDescriptorProto = FileDescriptorProto.newBuilder()
+      .setName("foo.proto")
+      .addMessageType(DescriptorProto.newBuilder()
+        .setName("Foo")
+        .addField(FieldDescriptorProto.newBuilder()
+          .setLabel(FieldDescriptorProto.Label.LABEL_OPTIONAL)
+          .setType(FieldDescriptorProto.Type.TYPE_INT32)
+          .setName("foo")
+          .setNumber(1)
+          .build())
+        .build())
+      .addMessageType(DescriptorProto.newBuilder()
+        .setName("Bar")
+        .addField(FieldDescriptorProto.newBuilder()
+          .setLabel(FieldDescriptorProto.Label.LABEL_OPTIONAL)
+          .setTypeName("Foo")
+          .setName("Foo")
+          .setNumber(1)
+          .build())
+        .build())
+      .build();
+    // translate and crosslink
+    FileDescriptor file =
+      Descriptors.FileDescriptor.buildFrom(fileDescriptorProto, 
+          new FileDescriptor[0]);
+    // verify resulting descriptors
+    assertNotNull(file);
+    List<Descriptor> msglist = file.getMessageTypes();
+    assertNotNull(msglist);
+    assertTrue(msglist.size() == 2);
+    boolean barFound = false;
+    for (Descriptor desc : msglist) {
+      if (desc.getName().equals("Bar")) {
+        barFound = true;
+        assertNotNull(desc.getFields());
+        List<FieldDescriptor> fieldlist = desc.getFields();
+        assertNotNull(fieldlist);
+        assertTrue(fieldlist.size() == 1);
+        assertTrue(fieldlist.get(0).getType() == FieldDescriptor.Type.MESSAGE);
+        assertTrue(fieldlist.get(0).getMessageType().getName().equals("Foo"));
+      }
+    }
+    assertTrue(barFound);
+  }
+  
+  public void testInvalidPublicDependency() throws Exception {
+    FileDescriptorProto fooProto = FileDescriptorProto.newBuilder()
+        .setName("foo.proto") .build();
+    FileDescriptorProto barProto = FileDescriptorProto.newBuilder()
+        .setName("boo.proto")
+        .addDependency("foo.proto")
+        .addPublicDependency(1)  // Error, should be 0.
+        .build();
+    FileDescriptor fooFile = Descriptors.FileDescriptor.buildFrom(fooProto,
+        new FileDescriptor[0]);
+    try {
+      Descriptors.FileDescriptor.buildFrom(barProto,
+          new FileDescriptor[] {fooFile});
+      fail("DescriptorValidationException expected");
+    } catch (DescriptorValidationException e) {
+      assertTrue(
+          e.getMessage().indexOf("Invalid public dependency index.") != -1);
+    }
+  }
+
+  public void testHiddenDependency() throws Exception {
+    FileDescriptorProto barProto = FileDescriptorProto.newBuilder()
+        .setName("bar.proto")
+        .addMessageType(DescriptorProto.newBuilder().setName("Bar"))
+        .build();
+    FileDescriptorProto forwardProto = FileDescriptorProto.newBuilder()
+        .setName("forward.proto")
+        .addDependency("bar.proto")
+        .build();
+    FileDescriptorProto fooProto = FileDescriptorProto.newBuilder()
+        .setName("foo.proto")
+        .addDependency("forward.proto")
+        .addMessageType(DescriptorProto.newBuilder()
+            .setName("Foo")
+            .addField(FieldDescriptorProto.newBuilder()
+                .setLabel(FieldDescriptorProto.Label.LABEL_OPTIONAL)
+                .setTypeName("Bar")
+                .setName("bar")
+                .setNumber(1)))
+        .build();
+    FileDescriptor barFile = Descriptors.FileDescriptor.buildFrom(
+        barProto, new FileDescriptor[0]);
+    FileDescriptor forwardFile = Descriptors.FileDescriptor.buildFrom(
+        forwardProto, new FileDescriptor[] {barFile});
+
+    try {
+      Descriptors.FileDescriptor.buildFrom(
+          fooProto, new FileDescriptor[] {forwardFile});
+      fail("DescriptorValidationException expected");
+    } catch (DescriptorValidationException e) {
+      assertTrue(e.getMessage().indexOf("Bar") != -1);
+      assertTrue(e.getMessage().indexOf("is not defined") != -1);
+    }
+  }
+
+  public void testPublicDependency() throws Exception {
+    FileDescriptorProto barProto = FileDescriptorProto.newBuilder()
+        .setName("bar.proto")
+        .addMessageType(DescriptorProto.newBuilder().setName("Bar"))
+        .build();
+    FileDescriptorProto forwardProto = FileDescriptorProto.newBuilder()
+        .setName("forward.proto")
+        .addDependency("bar.proto")
+        .addPublicDependency(0)
+        .build();
+    FileDescriptorProto fooProto = FileDescriptorProto.newBuilder()
+        .setName("foo.proto")
+        .addDependency("forward.proto")
+        .addMessageType(DescriptorProto.newBuilder()
+            .setName("Foo")
+            .addField(FieldDescriptorProto.newBuilder()
+                .setLabel(FieldDescriptorProto.Label.LABEL_OPTIONAL)
+                .setTypeName("Bar")
+                .setName("bar")
+                .setNumber(1)))
+        .build();
+    FileDescriptor barFile = Descriptors.FileDescriptor.buildFrom(
+        barProto, new FileDescriptor[0]);
+    FileDescriptor forwardFile = Descriptors.FileDescriptor.buildFrom(
+        forwardProto, new FileDescriptor[]{barFile});
+    Descriptors.FileDescriptor.buildFrom(
+        fooProto, new FileDescriptor[] {forwardFile});
+  }
+  
+  /**
+   * Tests the translate/crosslink for an example with a more complex namespace
+   * referencing.
+   */
+  public void testComplexNamespacePublicDependency() throws Exception {
+    FileDescriptorProto fooProto = FileDescriptorProto.newBuilder()
+        .setName("bar.proto")
+        .setPackage("a.b.c.d.bar.shared")
+        .addEnumType(EnumDescriptorProto.newBuilder()
+            .setName("MyEnum")
+            .addValue(EnumValueDescriptorProto.newBuilder()
+                .setName("BLAH")
+                .setNumber(1)))
+        .build();
+    FileDescriptorProto barProto = FileDescriptorProto.newBuilder()
+        .setName("foo.proto")
+        .addDependency("bar.proto")
+        .setPackage("a.b.c.d.foo.shared")
+        .addMessageType(DescriptorProto.newBuilder()
+            .setName("MyMessage")
+            .addField(FieldDescriptorProto.newBuilder()
+                .setLabel(FieldDescriptorProto.Label.LABEL_REPEATED)
+                .setTypeName("bar.shared.MyEnum")
+                .setName("MyField")
+                .setNumber(1)))
+        .build();
+    // translate and crosslink
+    FileDescriptor fooFile = Descriptors.FileDescriptor.buildFrom(
+        fooProto, new FileDescriptor[0]);
+    FileDescriptor barFile = Descriptors.FileDescriptor.buildFrom(
+        barProto, new FileDescriptor[]{fooFile});
+    // verify resulting descriptors
+    assertNotNull(barFile);
+    List<Descriptor> msglist = barFile.getMessageTypes();
+    assertNotNull(msglist);
+    assertTrue(msglist.size() == 1);
+    Descriptor desc = msglist.get(0);
+    if (desc.getName().equals("MyMessage")) {
+      assertNotNull(desc.getFields());
+      List<FieldDescriptor> fieldlist = desc.getFields();
+      assertNotNull(fieldlist);
+      assertTrue(fieldlist.size() == 1);
+      FieldDescriptor field = fieldlist.get(0);
+      assertTrue(field.getType() == FieldDescriptor.Type.ENUM);
+      assertTrue(field.getEnumType().getName().equals("MyEnum"));
+      assertTrue(field.getEnumType().getFile().getName().equals("bar.proto"));
+      assertTrue(field.getEnumType().getFile().getPackage().equals(
+          "a.b.c.d.bar.shared"));
+    }   
+  }
 }
diff --git a/third_party/protobuf/java/src/test/java/com/google/protobuf/DynamicMessageTest.java b/third_party/protobuf/java/src/test/java/com/google/protobuf/DynamicMessageTest.java
index aabccda..990e8ca 100644
--- a/third_party/protobuf/java/src/test/java/com/google/protobuf/DynamicMessageTest.java
+++ b/third_party/protobuf/java/src/test/java/com/google/protobuf/DynamicMessageTest.java
@@ -30,8 +30,9 @@
 
 package com.google.protobuf;
 
-import protobuf_unittest.UnittestProto.TestAllTypes;
 import protobuf_unittest.UnittestProto.TestAllExtensions;
+import protobuf_unittest.UnittestProto.TestAllTypes;
+import protobuf_unittest.UnittestProto.TestEmptyMessage;
 import protobuf_unittest.UnittestProto.TestPackedTypes;
 
 import junit.framework.TestCase;
@@ -61,28 +62,44 @@
     reflectionTester.assertAllFieldsSetViaReflection(message);
   }
 
-  public void testDoubleBuildError() throws Exception {
+  public void testSettersAfterBuild() throws Exception {
     Message.Builder builder =
       DynamicMessage.newBuilder(TestAllTypes.getDescriptor());
+    Message firstMessage = builder.build();
+    // double build()
     builder.build();
-    try {
-      builder.build();
-      fail("Should have thrown exception.");
-    } catch (IllegalStateException e) {
-      // Success.
-    }
+    // clear() after build()
+    builder.clear();
+    // setters after build()
+    reflectionTester.setAllFieldsViaReflection(builder);
+    Message message = builder.build();
+    reflectionTester.assertAllFieldsSetViaReflection(message);
+    // repeated setters after build()
+    reflectionTester.modifyRepeatedFieldsViaReflection(builder);
+    message = builder.build();
+    reflectionTester.assertRepeatedFieldsModifiedViaReflection(message);
+    // firstMessage shouldn't have been modified.
+    reflectionTester.assertClearViaReflection(firstMessage);
   }
 
-  public void testClearAfterBuildError() throws Exception {
+  public void testUnknownFields() throws Exception {
     Message.Builder builder =
-      DynamicMessage.newBuilder(TestAllTypes.getDescriptor());
-    builder.build();
-    try {
-      builder.clear();
-      fail("Should have thrown exception.");
-    } catch (IllegalStateException e) {
-      // Success.
-    }
+        DynamicMessage.newBuilder(TestEmptyMessage.getDescriptor());
+    builder.setUnknownFields(UnknownFieldSet.newBuilder()
+        .addField(1, UnknownFieldSet.Field.newBuilder().addVarint(1).build())
+        .addField(2, UnknownFieldSet.Field.newBuilder().addFixed32(1).build())
+        .build());
+    Message message = builder.build();
+    assertEquals(2, message.getUnknownFields().asMap().size());
+    // clone() with unknown fields
+    Message.Builder newBuilder = builder.clone();
+    assertEquals(2, newBuilder.getUnknownFields().asMap().size());
+    // clear() with unknown fields
+    newBuilder.clear();
+    assertTrue(newBuilder.getUnknownFields().asMap().isEmpty());
+    // serialize/parse with unknown fields
+    newBuilder.mergeFrom(message.toByteString());
+    assertEquals(2, newBuilder.getUnknownFields().asMap().size());
   }
 
   public void testDynamicMessageSettersRejectNull() throws Exception {
@@ -167,6 +184,23 @@
     Message message2 =
       DynamicMessage.parseFrom(TestAllTypes.getDescriptor(), rawBytes);
     reflectionTester.assertAllFieldsSetViaReflection(message2);
+
+    // Test Parser interface.
+    Message message3 = message2.getParserForType().parseFrom(rawBytes);
+    reflectionTester.assertAllFieldsSetViaReflection(message3);
+  }
+
+  public void testDynamicMessageExtensionParsing() throws Exception {
+    ByteString rawBytes = TestUtil.getAllExtensionsSet().toByteString();
+    Message message = DynamicMessage.parseFrom(
+        TestAllExtensions.getDescriptor(), rawBytes,
+        TestUtil.getExtensionRegistry());
+    extensionsReflectionTester.assertAllFieldsSetViaReflection(message);
+
+    // Test Parser interface.
+    Message message2 = message.getParserForType().parseFrom(
+        rawBytes, TestUtil.getExtensionRegistry());
+    extensionsReflectionTester.assertAllFieldsSetViaReflection(message2);
   }
 
   public void testDynamicMessagePackedSerialization() throws Exception {
@@ -194,6 +228,10 @@
     Message message2 =
       DynamicMessage.parseFrom(TestPackedTypes.getDescriptor(), rawBytes);
     packedReflectionTester.assertPackedFieldsSetViaReflection(message2);
+
+    // Test Parser interface.
+    Message message3 = message2.getParserForType().parseFrom(rawBytes);
+    packedReflectionTester.assertPackedFieldsSetViaReflection(message3);
   }
 
   public void testDynamicMessageCopy() throws Exception {
diff --git a/third_party/protobuf/java/src/test/java/com/google/protobuf/GeneratedMessageTest.java b/third_party/protobuf/java/src/test/java/com/google/protobuf/GeneratedMessageTest.java
index acb2235..bf9db75 100644
--- a/third_party/protobuf/java/src/test/java/com/google/protobuf/GeneratedMessageTest.java
+++ b/third_party/protobuf/java/src/test/java/com/google/protobuf/GeneratedMessageTest.java
@@ -30,6 +30,8 @@
 
 package com.google.protobuf;
 
+import com.google.protobuf.Descriptors.Descriptor;
+import com.google.protobuf.Descriptors.FieldDescriptor;
 import com.google.protobuf.UnittestLite.TestAllExtensionsLite;
 import com.google.protobuf.test.UnittestImport;
 import protobuf_unittest.EnumWithNoOuter;
@@ -53,6 +55,7 @@
 import protobuf_unittest.UnittestProto.ForeignMessageOrBuilder;
 import protobuf_unittest.UnittestProto.TestAllExtensions;
 import protobuf_unittest.UnittestProto.TestAllTypes;
+import protobuf_unittest.UnittestProto.TestAllTypes.NestedMessage;
 import protobuf_unittest.UnittestProto.TestAllTypesOrBuilder;
 import protobuf_unittest.UnittestProto.TestExtremeDefaultValues;
 import protobuf_unittest.UnittestProto.TestPackedTypes;
@@ -180,6 +183,33 @@
     assertIsUnmodifiable(value.getRepeatedFloatList());
   }
 
+  public void testParsedMessagesAreImmutable() throws Exception {
+    TestAllTypes value = TestAllTypes.PARSER.parseFrom(
+        TestUtil.getAllSet().toByteString());
+    assertIsUnmodifiable(value.getRepeatedInt32List());
+    assertIsUnmodifiable(value.getRepeatedInt64List());
+    assertIsUnmodifiable(value.getRepeatedUint32List());
+    assertIsUnmodifiable(value.getRepeatedUint64List());
+    assertIsUnmodifiable(value.getRepeatedSint32List());
+    assertIsUnmodifiable(value.getRepeatedSint64List());
+    assertIsUnmodifiable(value.getRepeatedFixed32List());
+    assertIsUnmodifiable(value.getRepeatedFixed64List());
+    assertIsUnmodifiable(value.getRepeatedSfixed32List());
+    assertIsUnmodifiable(value.getRepeatedSfixed64List());
+    assertIsUnmodifiable(value.getRepeatedFloatList());
+    assertIsUnmodifiable(value.getRepeatedDoubleList());
+    assertIsUnmodifiable(value.getRepeatedBoolList());
+    assertIsUnmodifiable(value.getRepeatedStringList());
+    assertIsUnmodifiable(value.getRepeatedBytesList());
+    assertIsUnmodifiable(value.getRepeatedGroupList());
+    assertIsUnmodifiable(value.getRepeatedNestedMessageList());
+    assertIsUnmodifiable(value.getRepeatedForeignMessageList());
+    assertIsUnmodifiable(value.getRepeatedImportMessageList());
+    assertIsUnmodifiable(value.getRepeatedNestedEnumList());
+    assertIsUnmodifiable(value.getRepeatedForeignEnumList());
+    assertIsUnmodifiable(value.getRepeatedImportEnumList());
+  }
+
   private void assertIsUnmodifiable(List<?> list) {
     if (list == Collections.emptyList()) {
       // OKAY -- Need to check this b/c EmptyList allows you to call clear.
@@ -881,7 +911,7 @@
     builder.setOptionalNestedMessage(nestedMessage1);
     assertEquals(3, mockParent.getInvalidationCount());
 
-    // primitive repated
+    // primitive repeated
     builder.buildPartial();
     builder.addRepeatedInt32(2);
     builder.addRepeatedInt32(3);
@@ -977,4 +1007,140 @@
     assertSame(b1, messageOrBuilderList.get(1));
     assertSame(m2, messageOrBuilderList.get(2));
   }
+
+  public void testGetFieldBuilder() {
+    Descriptor descriptor = TestAllTypes.getDescriptor();
+
+    FieldDescriptor fieldDescriptor =
+        descriptor.findFieldByName("optional_nested_message");
+    FieldDescriptor foreignFieldDescriptor =
+        descriptor.findFieldByName("optional_foreign_message");
+    FieldDescriptor importFieldDescriptor =
+        descriptor.findFieldByName("optional_import_message");
+
+    // Mutate the message with new field builder
+    // Mutate nested message
+    TestAllTypes.Builder builder1 = TestAllTypes.newBuilder();
+    Message.Builder fieldBuilder1 = builder1.newBuilderForField(fieldDescriptor)
+        .mergeFrom((Message) builder1.getField(fieldDescriptor));
+    FieldDescriptor subFieldDescriptor1 =
+        fieldBuilder1.getDescriptorForType().findFieldByName("bb");
+    fieldBuilder1.setField(subFieldDescriptor1, 1);
+    builder1.setField(fieldDescriptor, fieldBuilder1.build());
+
+    // Mutate foreign message
+    Message.Builder foreignFieldBuilder1 = builder1.newBuilderForField(
+        foreignFieldDescriptor)
+        .mergeFrom((Message) builder1.getField(foreignFieldDescriptor));
+    FieldDescriptor subForeignFieldDescriptor1 =
+        foreignFieldBuilder1.getDescriptorForType().findFieldByName("c");
+    foreignFieldBuilder1.setField(subForeignFieldDescriptor1, 2);
+    builder1.setField(foreignFieldDescriptor, foreignFieldBuilder1.build());
+
+    // Mutate import message
+    Message.Builder importFieldBuilder1 = builder1.newBuilderForField(
+        importFieldDescriptor)
+        .mergeFrom((Message) builder1.getField(importFieldDescriptor));
+    FieldDescriptor subImportFieldDescriptor1 =
+        importFieldBuilder1.getDescriptorForType().findFieldByName("d");
+    importFieldBuilder1.setField(subImportFieldDescriptor1, 3);
+    builder1.setField(importFieldDescriptor, importFieldBuilder1.build());
+
+    Message newMessage1 = builder1.build();
+
+    // Mutate the message with existing field builder
+    // Mutate nested message
+    TestAllTypes.Builder builder2 = TestAllTypes.newBuilder();
+    Message.Builder fieldBuilder2 = builder2.getFieldBuilder(fieldDescriptor);
+    FieldDescriptor subFieldDescriptor2 =
+        fieldBuilder2.getDescriptorForType().findFieldByName("bb");
+    fieldBuilder2.setField(subFieldDescriptor2, 1);
+    builder2.setField(fieldDescriptor, fieldBuilder2.build());
+
+    // Mutate foreign message
+    Message.Builder foreignFieldBuilder2 = builder2.newBuilderForField(
+        foreignFieldDescriptor)
+        .mergeFrom((Message) builder2.getField(foreignFieldDescriptor));
+    FieldDescriptor subForeignFieldDescriptor2 =
+        foreignFieldBuilder2.getDescriptorForType().findFieldByName("c");
+    foreignFieldBuilder2.setField(subForeignFieldDescriptor2, 2);
+    builder2.setField(foreignFieldDescriptor, foreignFieldBuilder2.build());
+
+    // Mutate import message
+    Message.Builder importFieldBuilder2 = builder2.newBuilderForField(
+        importFieldDescriptor)
+        .mergeFrom((Message) builder2.getField(importFieldDescriptor));
+    FieldDescriptor subImportFieldDescriptor2 =
+        importFieldBuilder2.getDescriptorForType().findFieldByName("d");
+    importFieldBuilder2.setField(subImportFieldDescriptor2, 3);
+    builder2.setField(importFieldDescriptor, importFieldBuilder2.build());
+
+    Message newMessage2 = builder2.build();
+
+    // These two messages should be equal.
+    assertEquals(newMessage1, newMessage2);
+  }
+
+  public void testGetFieldBuilderWithInitializedValue() {
+    Descriptor descriptor = TestAllTypes.getDescriptor();
+    FieldDescriptor fieldDescriptor =
+        descriptor.findFieldByName("optional_nested_message");
+
+    // Before setting field, builder is initialized by default value. 
+    TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+    NestedMessage.Builder fieldBuilder =
+        (NestedMessage.Builder) builder.getFieldBuilder(fieldDescriptor);
+    assertEquals(0, fieldBuilder.getBb());
+
+    // Setting field value with new field builder instance.
+    builder = TestAllTypes.newBuilder();
+    NestedMessage.Builder newFieldBuilder =
+        builder.getOptionalNestedMessageBuilder();
+    newFieldBuilder.setBb(2);
+    // Then get the field builder instance by getFieldBuilder().
+    fieldBuilder =
+        (NestedMessage.Builder) builder.getFieldBuilder(fieldDescriptor);
+    // It should contain new value.
+    assertEquals(2, fieldBuilder.getBb());
+    // These two builder should be equal.
+    assertSame(fieldBuilder, newFieldBuilder);
+  }
+
+  public void testGetFieldBuilderNotSupportedException() {
+    Descriptor descriptor = TestAllTypes.getDescriptor();
+    TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+    try {
+      builder.getFieldBuilder(descriptor.findFieldByName("optional_int32"));
+      fail("Exception was not thrown");
+    } catch (UnsupportedOperationException e) {
+      // We expect this exception.
+    }
+    try {
+      builder.getFieldBuilder(
+          descriptor.findFieldByName("optional_nested_enum"));
+      fail("Exception was not thrown");
+    } catch (UnsupportedOperationException e) {
+      // We expect this exception.
+    }
+    try {
+      builder.getFieldBuilder(descriptor.findFieldByName("repeated_int32"));
+      fail("Exception was not thrown");
+    } catch (UnsupportedOperationException e) {
+      // We expect this exception.
+    }
+    try {
+      builder.getFieldBuilder(
+          descriptor.findFieldByName("repeated_nested_enum"));
+      fail("Exception was not thrown");
+    } catch (UnsupportedOperationException e) {
+      // We expect this exception.
+    }
+    try {
+      builder.getFieldBuilder(
+          descriptor.findFieldByName("repeated_nested_message"));
+      fail("Exception was not thrown");
+    } catch (UnsupportedOperationException e) {
+      // We expect this exception.
+    }
+  }
 }
diff --git a/third_party/protobuf/java/src/test/java/com/google/protobuf/IsValidUtf8Test.java b/third_party/protobuf/java/src/test/java/com/google/protobuf/IsValidUtf8Test.java
new file mode 100644
index 0000000..b204b60
--- /dev/null
+++ b/third_party/protobuf/java/src/test/java/com/google/protobuf/IsValidUtf8Test.java
@@ -0,0 +1,180 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 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.
+
+package com.google.protobuf;
+
+import com.google.protobuf.IsValidUtf8TestUtil.Shard;
+
+import junit.framework.TestCase;
+
+import java.io.UnsupportedEncodingException;
+
+/**
+ * Tests cases for {@link ByteString#isValidUtf8()}. This includes three
+ * brute force tests that actually test every permutation of one byte, two byte,
+ * and three byte sequences to ensure that the method produces the right result
+ * for every possible byte encoding where "right" means it's consistent with
+ * java's UTF-8 string encoding/decoding such that the method returns true for
+ * any sequence that will round trip when converted to a String and then back to
+ * bytes and will return false for any sequence that will not round trip.
+ * See also {@link IsValidUtf8FourByteTest}. It also includes some
+ * other more targeted tests.
+ *
+ * @author jonp@google.com (Jon Perlow)
+ * @author martinrb@google.com (Martin Buchholz)
+ */
+public class IsValidUtf8Test extends TestCase {
+
+  /**
+   * Tests that round tripping of all two byte permutations work.
+   */
+  public void testIsValidUtf8_1Byte() throws UnsupportedEncodingException {
+    IsValidUtf8TestUtil.testBytes(1,
+        IsValidUtf8TestUtil.EXPECTED_ONE_BYTE_ROUNDTRIPPABLE_COUNT);
+  }
+
+  /**
+   * Tests that round tripping of all two byte permutations work.
+   */
+  public void testIsValidUtf8_2Bytes() throws UnsupportedEncodingException {
+    IsValidUtf8TestUtil.testBytes(2,
+        IsValidUtf8TestUtil.EXPECTED_TWO_BYTE_ROUNDTRIPPABLE_COUNT);
+  }
+
+  /**
+   * Tests that round tripping of all three byte permutations work.
+   */
+  public void testIsValidUtf8_3Bytes() throws UnsupportedEncodingException {
+    IsValidUtf8TestUtil.testBytes(3,
+        IsValidUtf8TestUtil.EXPECTED_THREE_BYTE_ROUNDTRIPPABLE_COUNT);
+  }
+
+  /**
+   * Tests that round tripping of a sample of four byte permutations work.
+   * All permutations are prohibitively expensive to test for automated runs;
+   * {@link IsValidUtf8FourByteTest} is used for full coverage. This method
+   * tests specific four-byte cases.
+   */
+  public void testIsValidUtf8_4BytesSamples()
+      throws UnsupportedEncodingException {
+    // Valid 4 byte.
+    assertValidUtf8(0xF0, 0xA4, 0xAD, 0xA2);
+
+    // Bad trailing bytes
+    assertInvalidUtf8(0xF0, 0xA4, 0xAD, 0x7F);
+    assertInvalidUtf8(0xF0, 0xA4, 0xAD, 0xC0);
+
+    // Special cases for byte2
+    assertInvalidUtf8(0xF0, 0x8F, 0xAD, 0xA2);
+    assertInvalidUtf8(0xF4, 0x90, 0xAD, 0xA2);
+  }
+
+  /**
+   * Tests some hard-coded test cases.
+   */
+  public void testSomeSequences() {
+    // Empty
+    assertTrue(asBytes("").isValidUtf8());
+
+    // One-byte characters, including control characters
+    assertTrue(asBytes("\u0000abc\u007f").isValidUtf8());
+
+    // Two-byte characters
+    assertTrue(asBytes("\u00a2\u00a2").isValidUtf8());
+
+    // Three-byte characters
+    assertTrue(asBytes("\u020ac\u020ac").isValidUtf8());
+
+    // Four-byte characters
+    assertTrue(asBytes("\u024B62\u024B62").isValidUtf8());
+
+    // Mixed string
+    assertTrue(
+        asBytes("a\u020ac\u00a2b\\u024B62u020acc\u00a2de\u024B62")
+        .isValidUtf8());
+
+    // Not a valid string
+    assertInvalidUtf8(-1, 0, -1, 0);
+  }
+
+  private byte[] toByteArray(int... bytes) {
+    byte[] realBytes = new byte[bytes.length];
+    for (int i = 0; i < bytes.length; i++) {
+      realBytes[i] = (byte) bytes[i];
+    }
+    return realBytes;
+  }
+
+  private ByteString toByteString(int... bytes) {
+    return ByteString.copyFrom(toByteArray(bytes));
+  }
+
+  private void assertValidUtf8(int[] bytes, boolean not) {
+    byte[] realBytes = toByteArray(bytes);
+    assertTrue(not ^ Utf8.isValidUtf8(realBytes));
+    assertTrue(not ^ Utf8.isValidUtf8(realBytes, 0, bytes.length));
+    ByteString lit = ByteString.copyFrom(realBytes);
+    ByteString sub = lit.substring(0, bytes.length);
+    assertTrue(not ^ lit.isValidUtf8());
+    assertTrue(not ^ sub.isValidUtf8());
+    ByteString[] ropes = {
+      RopeByteString.newInstanceForTest(ByteString.EMPTY, lit),
+      RopeByteString.newInstanceForTest(ByteString.EMPTY, sub),
+      RopeByteString.newInstanceForTest(lit, ByteString.EMPTY),
+      RopeByteString.newInstanceForTest(sub, ByteString.EMPTY),
+      RopeByteString.newInstanceForTest(sub, lit)
+    };
+    for (ByteString rope : ropes) {
+      assertTrue(not ^ rope.isValidUtf8());
+    }
+  }
+
+  private void assertValidUtf8(int... bytes) {
+    assertValidUtf8(bytes, false);
+  }
+
+  private void assertInvalidUtf8(int... bytes) {
+    assertValidUtf8(bytes, true);
+  }
+
+  private static ByteString asBytes(String s) {
+    return ByteString.copyFromUtf8(s);
+  }
+
+  public void testShardsHaveExpectedRoundTrippables() {
+    // A sanity check.
+    int actual = 0;
+    for (Shard shard : IsValidUtf8TestUtil.FOUR_BYTE_SHARDS) {
+      actual += shard.expected;
+    }
+    assertEquals(IsValidUtf8TestUtil.EXPECTED_FOUR_BYTE_ROUNDTRIPPABLE_COUNT,
+        actual);
+  }
+}
diff --git a/third_party/protobuf/java/src/test/java/com/google/protobuf/IsValidUtf8TestUtil.java b/third_party/protobuf/java/src/test/java/com/google/protobuf/IsValidUtf8TestUtil.java
new file mode 100644
index 0000000..4cb3d5b
--- /dev/null
+++ b/third_party/protobuf/java/src/test/java/com/google/protobuf/IsValidUtf8TestUtil.java
@@ -0,0 +1,421 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 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.
+
+package com.google.protobuf;
+
+import static junit.framework.Assert.*;
+
+import java.io.UnsupportedEncodingException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Random;
+import java.util.logging.Logger;
+import java.nio.charset.CharsetDecoder;
+import java.nio.charset.Charset;
+import java.nio.charset.CodingErrorAction;
+import java.nio.charset.CharsetEncoder;
+import java.nio.charset.CoderResult;
+import java.nio.ByteBuffer;
+import java.nio.CharBuffer;
+
+/**
+ * Shared testing code for {@link IsValidUtf8Test} and
+ * {@link IsValidUtf8FourByteTest}.
+ *
+ * @author jonp@google.com (Jon Perlow)
+ * @author martinrb@google.com (Martin Buchholz)
+ */
+class IsValidUtf8TestUtil {
+  private static Logger logger = Logger.getLogger(
+      IsValidUtf8TestUtil.class.getName());
+
+  // 128 - [chars 0x0000 to 0x007f]
+  static long ONE_BYTE_ROUNDTRIPPABLE_CHARACTERS = 0x007f - 0x0000 + 1;
+
+  // 128
+  static long EXPECTED_ONE_BYTE_ROUNDTRIPPABLE_COUNT =
+      ONE_BYTE_ROUNDTRIPPABLE_CHARACTERS;
+
+  // 1920 [chars 0x0080 to 0x07FF]
+  static long TWO_BYTE_ROUNDTRIPPABLE_CHARACTERS = 0x07FF - 0x0080 + 1;
+
+  // 18,304
+  static long EXPECTED_TWO_BYTE_ROUNDTRIPPABLE_COUNT =
+      // Both bytes are one byte characters
+      (long) Math.pow(EXPECTED_ONE_BYTE_ROUNDTRIPPABLE_COUNT, 2) +
+      // The possible number of two byte characters
+      TWO_BYTE_ROUNDTRIPPABLE_CHARACTERS;
+
+  // 2048
+  static long THREE_BYTE_SURROGATES = 2 * 1024;
+
+  // 61,440 [chars 0x0800 to 0xFFFF, minus surrogates]
+  static long THREE_BYTE_ROUNDTRIPPABLE_CHARACTERS =
+      0xFFFF - 0x0800 + 1 - THREE_BYTE_SURROGATES;
+
+  // 2,650,112
+  static long EXPECTED_THREE_BYTE_ROUNDTRIPPABLE_COUNT =
+      // All one byte characters
+      (long) Math.pow(EXPECTED_ONE_BYTE_ROUNDTRIPPABLE_COUNT, 3) +
+      // One two byte character and a one byte character
+      2 * TWO_BYTE_ROUNDTRIPPABLE_CHARACTERS *
+          ONE_BYTE_ROUNDTRIPPABLE_CHARACTERS +
+       // Three byte characters
+      THREE_BYTE_ROUNDTRIPPABLE_CHARACTERS;
+
+  // 1,048,576 [chars 0x10000L to 0x10FFFF]
+  static long FOUR_BYTE_ROUNDTRIPPABLE_CHARACTERS = 0x10FFFF - 0x10000L + 1;
+
+  // 289,571,839
+  static long EXPECTED_FOUR_BYTE_ROUNDTRIPPABLE_COUNT =
+      // All one byte characters
+      (long) Math.pow(EXPECTED_ONE_BYTE_ROUNDTRIPPABLE_COUNT, 4) +
+      // One and three byte characters
+      2 * THREE_BYTE_ROUNDTRIPPABLE_CHARACTERS *
+          ONE_BYTE_ROUNDTRIPPABLE_CHARACTERS +
+      // Two two byte characters
+      TWO_BYTE_ROUNDTRIPPABLE_CHARACTERS * TWO_BYTE_ROUNDTRIPPABLE_CHARACTERS +
+      // Permutations of one and two byte characters
+      3 * TWO_BYTE_ROUNDTRIPPABLE_CHARACTERS *
+          ONE_BYTE_ROUNDTRIPPABLE_CHARACTERS *
+          ONE_BYTE_ROUNDTRIPPABLE_CHARACTERS +
+      // Four byte characters
+      FOUR_BYTE_ROUNDTRIPPABLE_CHARACTERS;
+
+  static class Shard {
+    final long index;
+    final long start;
+    final long lim;
+    final long expected;
+
+
+    public Shard(long index, long start, long lim, long expected) {
+      assertTrue(start < lim);
+      this.index = index;
+      this.start = start;
+      this.lim = lim;
+      this.expected = expected;
+    }
+  }
+
+  static final long[] FOUR_BYTE_SHARDS_EXPECTED_ROUNTRIPPABLES =
+      generateFourByteShardsExpectedRunnables();
+
+  private static long[] generateFourByteShardsExpectedRunnables() {
+    long[] expected = new long[128];
+
+    // 0-63 are all 5300224
+    for (int i = 0; i <= 63; i++) {
+      expected[i] = 5300224;
+    }
+
+    // 97-111 are all 2342912
+    for (int i = 97; i <= 111; i++) {
+     expected[i] = 2342912;
+    }
+
+    // 113-117 are all 1048576
+    for (int i = 113; i <= 117; i++) {
+      expected[i] = 1048576;
+    }
+
+    // One offs
+    expected[112] = 786432;
+    expected[118] = 786432;
+    expected[119] = 1048576;
+    expected[120] = 458752;
+    expected[121] = 524288;
+    expected[122] = 65536;
+
+    // Anything not assigned was the default 0.
+    return expected;
+  }
+
+  static final List<Shard> FOUR_BYTE_SHARDS = generateFourByteShards(
+      128, FOUR_BYTE_SHARDS_EXPECTED_ROUNTRIPPABLES);
+
+
+  private static List<Shard> generateFourByteShards(
+      int numShards, long[] expected) {
+    assertEquals(numShards, expected.length);
+    List<Shard> shards = new ArrayList<Shard>(numShards);
+    long LIM = 1L << 32;
+    long increment = LIM / numShards;
+    assertTrue(LIM % numShards == 0);
+    for (int i = 0; i < numShards; i++) {
+      shards.add(new Shard(i,
+          increment * i,
+          increment * (i + 1),
+          expected[i]));
+    }
+    return shards;
+  }
+
+  /**
+   * Helper to run the loop to test all the permutations for the number of bytes
+   * specified.
+   *
+   * @param numBytes the number of bytes in the byte array
+   * @param expectedCount the expected number of roundtrippable permutations
+   */
+  static void testBytes(int numBytes, long expectedCount)
+      throws UnsupportedEncodingException {
+    testBytes(numBytes, expectedCount, 0, -1);
+  }
+
+  /**
+   * Helper to run the loop to test all the permutations for the number of bytes
+   * specified. This overload is useful for debugging to get the loop to start
+   * at a certain character.
+   *
+   * @param numBytes the number of bytes in the byte array
+   * @param expectedCount the expected number of roundtrippable permutations
+   * @param start the starting bytes encoded as a long as big-endian
+   * @param lim the limit of bytes to process encoded as a long as big-endian,
+   *     or -1 to mean the max limit for numBytes
+   */
+  static void testBytes(int numBytes, long expectedCount, long start, long lim)
+      throws UnsupportedEncodingException {
+    Random rnd = new Random();
+    byte[] bytes = new byte[numBytes];
+
+    if (lim == -1) {
+      lim = 1L << (numBytes * 8);
+    }
+    long count = 0;
+    long countRoundTripped = 0;
+    for (long byteChar = start; byteChar < lim; byteChar++) {
+      long tmpByteChar = byteChar;
+      for (int i = 0; i < numBytes; i++) {
+        bytes[bytes.length - i - 1] = (byte) tmpByteChar;
+        tmpByteChar = tmpByteChar >> 8;
+      }
+      ByteString bs = ByteString.copyFrom(bytes);
+      boolean isRoundTrippable = bs.isValidUtf8();
+      String s = new String(bytes, "UTF-8");
+      byte[] bytesReencoded = s.getBytes("UTF-8");
+      boolean bytesEqual = Arrays.equals(bytes, bytesReencoded);
+
+      if (bytesEqual != isRoundTrippable) {
+        outputFailure(byteChar, bytes, bytesReencoded);
+      }
+
+      // Check agreement with static Utf8 methods.
+      assertEquals(isRoundTrippable, Utf8.isValidUtf8(bytes));
+      assertEquals(isRoundTrippable, Utf8.isValidUtf8(bytes, 0, numBytes));
+
+      // Test partial sequences.
+      // Partition numBytes into three segments (not necessarily non-empty).
+      int i = rnd.nextInt(numBytes);
+      int j = rnd.nextInt(numBytes);
+      if (j < i) {
+        int tmp = i; i = j; j = tmp;
+      }
+      int state1 = Utf8.partialIsValidUtf8(Utf8.COMPLETE, bytes, 0, i);
+      int state2 = Utf8.partialIsValidUtf8(state1, bytes, i, j);
+      int state3 = Utf8.partialIsValidUtf8(state2, bytes, j, numBytes);
+      if (isRoundTrippable != (state3 == Utf8.COMPLETE)) {
+        System.out.printf("state=%04x %04x %04x i=%d j=%d%n",
+                          state1, state2, state3, i, j);
+        outputFailure(byteChar, bytes, bytesReencoded);
+      }
+      assertEquals(isRoundTrippable, (state3 == Utf8.COMPLETE));
+
+      // Test ropes built out of small partial sequences
+      ByteString rope = RopeByteString.newInstanceForTest(
+          bs.substring(0, i),
+          RopeByteString.newInstanceForTest(
+              bs.substring(i, j),
+              bs.substring(j, numBytes)));
+      assertSame(RopeByteString.class, rope.getClass());
+
+      ByteString[] byteStrings = { bs, bs.substring(0, numBytes), rope };
+      for (ByteString x : byteStrings) {
+        assertEquals(isRoundTrippable,
+                     x.isValidUtf8());
+        assertEquals(state3,
+                     x.partialIsValidUtf8(Utf8.COMPLETE, 0, numBytes));
+
+        assertEquals(state1,
+                     x.partialIsValidUtf8(Utf8.COMPLETE, 0, i));
+        assertEquals(state1,
+                     x.substring(0, i).partialIsValidUtf8(Utf8.COMPLETE, 0, i));
+        assertEquals(state2,
+                     x.partialIsValidUtf8(state1, i, j - i));
+        assertEquals(state2,
+                     x.substring(i, j).partialIsValidUtf8(state1, 0, j - i));
+        assertEquals(state3,
+                     x.partialIsValidUtf8(state2, j, numBytes - j));
+        assertEquals(state3,
+                     x.substring(j, numBytes)
+                     .partialIsValidUtf8(state2, 0, numBytes - j));
+      }
+
+      // ByteString reduplication should not affect its UTF-8 validity.
+      ByteString ropeADope =
+          RopeByteString.newInstanceForTest(bs, bs.substring(0, numBytes));
+      assertEquals(isRoundTrippable, ropeADope.isValidUtf8());
+
+      if (isRoundTrippable) {
+        countRoundTripped++;
+      }
+      count++;
+      if (byteChar != 0 && byteChar % 1000000L == 0) {
+        logger.info("Processed " + (byteChar / 1000000L) +
+            " million characters");
+      }
+    }
+    logger.info("Round tripped " + countRoundTripped + " of " + count);
+    assertEquals(expectedCount, countRoundTripped);
+  }
+
+  /**
+   * Variation of {@link #testBytes} that does less allocation using the
+   * low-level encoders/decoders directly. Checked in because it's useful for
+   * debugging when trying to process bytes faster, but since it doesn't use the
+   * actual String class, it's possible for incompatibilities to develop
+   * (although unlikely).
+   *
+   * @param numBytes the number of bytes in the byte array
+   * @param expectedCount the expected number of roundtrippable permutations
+   * @param start the starting bytes encoded as a long as big-endian
+   * @param lim the limit of bytes to process encoded as a long as big-endian,
+   *     or -1 to mean the max limit for numBytes
+   */
+  void testBytesUsingByteBuffers(
+      int numBytes, long expectedCount, long start, long lim)
+      throws UnsupportedEncodingException {
+    CharsetDecoder decoder = Charset.forName("UTF-8").newDecoder()
+        .onMalformedInput(CodingErrorAction.REPLACE)
+        .onUnmappableCharacter(CodingErrorAction.REPLACE);
+    CharsetEncoder encoder = Charset.forName("UTF-8").newEncoder()
+        .onMalformedInput(CodingErrorAction.REPLACE)
+        .onUnmappableCharacter(CodingErrorAction.REPLACE);
+    byte[] bytes = new byte[numBytes];
+    int maxChars = (int) (decoder.maxCharsPerByte() * numBytes) + 1;
+    char[] charsDecoded =
+        new char[(int) (decoder.maxCharsPerByte() * numBytes) + 1];
+    int maxBytes = (int) (encoder.maxBytesPerChar() * maxChars) + 1;
+    byte[] bytesReencoded = new byte[maxBytes];
+
+    ByteBuffer bb = ByteBuffer.wrap(bytes);
+    CharBuffer cb = CharBuffer.wrap(charsDecoded);
+    ByteBuffer bbReencoded = ByteBuffer.wrap(bytesReencoded);
+    if (lim == -1) {
+      lim = 1L << (numBytes * 8);
+    }
+    long count = 0;
+    long countRoundTripped = 0;
+    for (long byteChar = start; byteChar < lim; byteChar++) {
+      bb.rewind();
+      bb.limit(bytes.length);
+      cb.rewind();
+      cb.limit(charsDecoded.length);
+      bbReencoded.rewind();
+      bbReencoded.limit(bytesReencoded.length);
+      encoder.reset();
+      decoder.reset();
+      long tmpByteChar = byteChar;
+      for (int i = 0; i < bytes.length; i++) {
+        bytes[bytes.length - i - 1] = (byte) tmpByteChar;
+        tmpByteChar = tmpByteChar >> 8;
+      }
+      boolean isRoundTrippable = ByteString.copyFrom(bytes).isValidUtf8();
+      CoderResult result = decoder.decode(bb, cb, true);
+      assertFalse(result.isError());
+      result = decoder.flush(cb);
+      assertFalse(result.isError());
+
+      int charLen = cb.position();
+      cb.rewind();
+      cb.limit(charLen);
+      result = encoder.encode(cb, bbReencoded, true);
+      assertFalse(result.isError());
+      result = encoder.flush(bbReencoded);
+      assertFalse(result.isError());
+
+      boolean bytesEqual = true;
+      int bytesLen = bbReencoded.position();
+      if (bytesLen != numBytes) {
+        bytesEqual = false;
+      } else {
+        for (int i = 0; i < numBytes; i++) {
+          if (bytes[i] != bytesReencoded[i]) {
+            bytesEqual = false;
+            break;
+          }
+        }
+      }
+      if (bytesEqual != isRoundTrippable) {
+        outputFailure(byteChar, bytes, bytesReencoded, bytesLen);
+      }
+
+      count++;
+      if (isRoundTrippable) {
+        countRoundTripped++;
+      }
+      if (byteChar != 0 && byteChar % 1000000 == 0) {
+        logger.info("Processed " + (byteChar / 1000000) +
+            " million characters");
+      }
+    }
+    logger.info("Round tripped " + countRoundTripped + " of " + count);
+    assertEquals(expectedCount, countRoundTripped);
+  }
+
+  private static void outputFailure(long byteChar, byte[] bytes, byte[] after) {
+    outputFailure(byteChar, bytes, after, after.length);
+  }
+
+  private static void outputFailure(long byteChar, byte[] bytes, byte[] after,
+      int len) {
+    fail("Failure: (" + Long.toHexString(byteChar) + ") " +
+        toHexString(bytes) + " => " + toHexString(after, len));
+  }
+
+  private static String toHexString(byte[] b) {
+    return toHexString(b, b.length);
+  }
+
+  private static String toHexString(byte[] b, int len) {
+    StringBuilder s = new StringBuilder();
+    s.append("\"");
+    for (int i = 0; i < len; i++) {
+      if (i > 0) {
+        s.append(" ");
+      }
+      s.append(String.format("%02x", b[i] & 0xFF));
+    }
+    s.append("\"");
+    return s.toString();
+  }
+
+}
diff --git a/third_party/protobuf/java/src/test/java/com/google/protobuf/LazyStringArrayListTest.java b/third_party/protobuf/java/src/test/java/com/google/protobuf/LazyStringArrayListTest.java
index 4dcdc74..d500595 100644
--- a/third_party/protobuf/java/src/test/java/com/google/protobuf/LazyStringArrayListTest.java
+++ b/third_party/protobuf/java/src/test/java/com/google/protobuf/LazyStringArrayListTest.java
@@ -32,6 +32,9 @@
 
 import junit.framework.TestCase;
 
+import java.util.ArrayList;
+import java.util.List;
+
 /**
  * Tests for {@link LazyStringArrayList}.
  *
@@ -115,4 +118,45 @@
     assertSame(aPrimeByteString, list.getByteString(0));
     assertSame(bPrimeByteString, list.getByteString(1));
   }
+
+  public void testCopyConstructorCopiesByReference() {
+    LazyStringArrayList list1 = new LazyStringArrayList();
+    list1.add(STRING_A);
+    list1.add(BYTE_STRING_B);
+    list1.add(BYTE_STRING_C);
+
+    LazyStringArrayList list2 = new LazyStringArrayList(list1);
+    assertEquals(3, list2.size());
+    assertSame(STRING_A, list2.get(0));
+    assertSame(BYTE_STRING_B, list2.getByteString(1));
+    assertSame(BYTE_STRING_C, list2.getByteString(2));
+  }
+
+  public void testListCopyConstructor() {
+    List<String> list1 = new ArrayList<String>();
+    list1.add(STRING_A);
+    list1.add(STRING_B);
+    list1.add(STRING_C);
+
+    LazyStringArrayList list2 = new LazyStringArrayList(list1);
+    assertEquals(3, list2.size());
+    assertSame(STRING_A, list2.get(0));
+    assertSame(STRING_B, list2.get(1));
+    assertSame(STRING_C, list2.get(2));
+  }
+
+  public void testAddAllCopiesByReferenceIfPossible() {
+    LazyStringArrayList list1 = new LazyStringArrayList();
+    list1.add(STRING_A);
+    list1.add(BYTE_STRING_B);
+    list1.add(BYTE_STRING_C);
+
+    LazyStringArrayList list2 = new LazyStringArrayList();
+    list2.addAll(list1);
+
+    assertEquals(3, list2.size());
+    assertSame(STRING_A, list2.get(0));
+    assertSame(BYTE_STRING_B, list2.getByteString(1));
+    assertSame(BYTE_STRING_C, list2.getByteString(2));
+  }
 }
diff --git a/third_party/protobuf/java/src/test/java/com/google/protobuf/LazyStringEndToEndTest.java b/third_party/protobuf/java/src/test/java/com/google/protobuf/LazyStringEndToEndTest.java
index e6870b5..fe9599e 100644
--- a/third_party/protobuf/java/src/test/java/com/google/protobuf/LazyStringEndToEndTest.java
+++ b/third_party/protobuf/java/src/test/java/com/google/protobuf/LazyStringEndToEndTest.java
@@ -50,6 +50,19 @@
           114, 4, -1, 0, -1, 0, -30, 2, 4, -1,
           0, -1, 0, -30, 2, 4, -1, 0, -1, 0, });
 
+  private ByteString encodedTestAllTypes;
+
+  @Override
+  protected void setUp() throws Exception {
+    super.setUp();
+    this.encodedTestAllTypes = UnittestProto.TestAllTypes.newBuilder()
+        .setOptionalString("foo")
+        .addRepeatedString("bar")
+        .addRepeatedString("baz")
+        .build()
+        .toByteString();
+  }
+
   /**
    * Tests that an invalid UTF8 string will roundtrip through a parse
    * and serialization.
@@ -112,4 +125,19 @@
     assertSame(bPrime, proto.getRepeatedString(0));
     assertSame(cPrime, proto.getRepeatedString(1));
   }
+
+  public void testNoStringCachingIfOnlyBytesAccessed() throws Exception {
+    UnittestProto.TestAllTypes proto =
+        UnittestProto.TestAllTypes.parseFrom(encodedTestAllTypes);
+    ByteString optional = proto.getOptionalStringBytes();
+    assertSame(optional, proto.getOptionalStringBytes());
+    assertSame(optional, proto.toBuilder().getOptionalStringBytes());
+
+    ByteString repeated0 = proto.getRepeatedStringBytes(0);
+    ByteString repeated1 = proto.getRepeatedStringBytes(1);
+    assertSame(repeated0, proto.getRepeatedStringBytes(0));
+    assertSame(repeated1, proto.getRepeatedStringBytes(1));
+    assertSame(repeated0, proto.toBuilder().getRepeatedStringBytes(0));
+    assertSame(repeated1, proto.toBuilder().getRepeatedStringBytes(1));
+  }
 }
diff --git a/third_party/protobuf/java/src/test/java/com/google/protobuf/LiteralByteStringTest.java b/third_party/protobuf/java/src/test/java/com/google/protobuf/LiteralByteStringTest.java
new file mode 100644
index 0000000..deee1ee
--- /dev/null
+++ b/third_party/protobuf/java/src/test/java/com/google/protobuf/LiteralByteStringTest.java
@@ -0,0 +1,396 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 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.
+
+package com.google.protobuf;
+
+import junit.framework.TestCase;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.UnsupportedEncodingException;
+import java.nio.ByteBuffer;
+import java.util.Arrays;
+import java.util.List;
+import java.util.NoSuchElementException;
+
+/**
+ * Test {@link LiteralByteString} by setting up a reference string in {@link #setUp()}.
+ * This class is designed to be extended for testing extensions of {@link LiteralByteString}
+ * such as {@link BoundedByteString}, see {@link BoundedByteStringTest}.
+ *
+ * @author carlanton@google.com (Carl Haverl)
+ */
+public class LiteralByteStringTest extends TestCase {
+  protected static final String UTF_8 = "UTF-8";
+
+  protected String classUnderTest;
+  protected byte[] referenceBytes;
+  protected ByteString stringUnderTest;
+  protected int expectedHashCode;
+
+  @Override
+  protected void setUp() throws Exception {
+    classUnderTest = "LiteralByteString";
+    referenceBytes = ByteStringTest.getTestBytes(1234, 11337766L);
+    stringUnderTest = ByteString.copyFrom(referenceBytes);
+    expectedHashCode = 331161852;
+  }
+
+  public void testExpectedType() {
+    String actualClassName = getActualClassName(stringUnderTest);
+    assertEquals(classUnderTest + " should match type exactly", classUnderTest, actualClassName);
+  }
+
+  protected String getActualClassName(Object object) {
+    String actualClassName = object.getClass().getName();
+    actualClassName = actualClassName.substring(actualClassName.lastIndexOf('.') + 1);
+    return actualClassName;
+  }
+
+  public void testByteAt() {
+    boolean stillEqual = true;
+    for (int i = 0; stillEqual && i < referenceBytes.length; ++i) {
+      stillEqual = (referenceBytes[i] == stringUnderTest.byteAt(i));
+    }
+    assertTrue(classUnderTest + " must capture the right bytes", stillEqual);
+  }
+
+  public void testByteIterator() {
+    boolean stillEqual = true;
+    ByteString.ByteIterator iter = stringUnderTest.iterator();
+    for (int i = 0; stillEqual && i < referenceBytes.length; ++i) {
+      stillEqual = (iter.hasNext() && referenceBytes[i] == iter.nextByte());
+    }
+    assertTrue(classUnderTest + " must capture the right bytes", stillEqual);
+    assertFalse(classUnderTest + " must have exhausted the itertor", iter.hasNext());
+
+    try {
+      iter.nextByte();
+      fail("Should have thrown an exception.");
+    } catch (NoSuchElementException e) {
+      // This is success
+    }
+  }
+
+  public void testByteIterable() {
+    boolean stillEqual = true;
+    int j = 0;
+    for (byte quantum : stringUnderTest) {
+      stillEqual = (referenceBytes[j] == quantum);
+      ++j;
+    }
+    assertTrue(classUnderTest + " must capture the right bytes as Bytes", stillEqual);
+    assertEquals(classUnderTest + " iterable character count", referenceBytes.length, j);
+  }
+
+  public void testSize() {
+    assertEquals(classUnderTest + " must have the expected size", referenceBytes.length,
+        stringUnderTest.size());
+  }
+
+  public void testGetTreeDepth() {
+    assertEquals(classUnderTest + " must have depth 0", 0, stringUnderTest.getTreeDepth());
+  }
+
+  public void testIsBalanced() {
+    assertTrue(classUnderTest + " is technically balanced", stringUnderTest.isBalanced());
+  }
+
+  public void testCopyTo_ByteArrayOffsetLength() {
+    int destinationOffset = 50;
+    int length = 100;
+    byte[] destination = new byte[destinationOffset + length];
+    int sourceOffset = 213;
+    stringUnderTest.copyTo(destination, sourceOffset, destinationOffset, length);
+    boolean stillEqual = true;
+    for (int i = 0; stillEqual && i < length; ++i) {
+      stillEqual = referenceBytes[i + sourceOffset] == destination[i + destinationOffset];
+    }
+    assertTrue(classUnderTest + ".copyTo(4 arg) must give the expected bytes", stillEqual);
+  }
+
+  public void testCopyTo_ByteArrayOffsetLengthErrors() {
+    int destinationOffset = 50;
+    int length = 100;
+    byte[] destination = new byte[destinationOffset + length];
+
+    try {
+      // Copy one too many bytes
+      stringUnderTest.copyTo(destination, stringUnderTest.size() + 1 - length,
+          destinationOffset, length);
+      fail("Should have thrown an exception when copying too many bytes of a "
+          + classUnderTest);
+    } catch (IndexOutOfBoundsException expected) {
+      // This is success
+    }
+
+    try {
+      // Copy with illegal negative sourceOffset
+      stringUnderTest.copyTo(destination, -1, destinationOffset, length);
+      fail("Should have thrown an exception when given a negative sourceOffset in "
+          + classUnderTest);
+    } catch (IndexOutOfBoundsException expected) {
+      // This is success
+    }
+
+    try {
+      // Copy with illegal negative destinationOffset
+      stringUnderTest.copyTo(destination, 0, -1, length);
+      fail("Should have thrown an exception when given a negative destinationOffset in "
+          + classUnderTest);
+    } catch (IndexOutOfBoundsException expected) {
+      // This is success
+    }
+
+    try {
+      // Copy with illegal negative size
+      stringUnderTest.copyTo(destination, 0, 0, -1);
+      fail("Should have thrown an exception when given a negative size in "
+          + classUnderTest);
+    } catch (IndexOutOfBoundsException expected) {
+      // This is success
+    }
+
+    try {
+      // Copy with illegal too-large sourceOffset
+      stringUnderTest.copyTo(destination, 2 * stringUnderTest.size(), 0, length);
+      fail("Should have thrown an exception when the destinationOffset is too large in "
+          + classUnderTest);
+    } catch (IndexOutOfBoundsException expected) {
+      // This is success
+    }
+
+    try {
+      // Copy with illegal too-large destinationOffset
+      stringUnderTest.copyTo(destination, 0, 2 * destination.length, length);
+      fail("Should have thrown an exception when the destinationOffset is too large in "
+          + classUnderTest);
+    } catch (IndexOutOfBoundsException expected) {
+      // This is success
+    }
+  }
+
+  public void testCopyTo_ByteBuffer() {
+    ByteBuffer myBuffer = ByteBuffer.allocate(referenceBytes.length);
+    stringUnderTest.copyTo(myBuffer);
+    assertTrue(classUnderTest + ".copyTo(ByteBuffer) must give back the same bytes",
+        Arrays.equals(referenceBytes, myBuffer.array()));
+  }
+
+  public void testAsReadOnlyByteBuffer() {
+    ByteBuffer byteBuffer = stringUnderTest.asReadOnlyByteBuffer();
+    byte[] roundTripBytes = new byte[referenceBytes.length];
+    assertTrue(byteBuffer.remaining() == referenceBytes.length);
+    assertTrue(byteBuffer.isReadOnly());
+    byteBuffer.get(roundTripBytes);
+    assertTrue(classUnderTest + ".asReadOnlyByteBuffer() must give back the same bytes",
+        Arrays.equals(referenceBytes, roundTripBytes));
+  }
+
+  public void testAsReadOnlyByteBufferList() {
+    List<ByteBuffer> byteBuffers = stringUnderTest.asReadOnlyByteBufferList();
+    int bytesSeen = 0;
+    byte[] roundTripBytes = new byte[referenceBytes.length];
+    for (ByteBuffer byteBuffer : byteBuffers) {
+      int thisLength = byteBuffer.remaining();
+      assertTrue(byteBuffer.isReadOnly());
+      assertTrue(bytesSeen + thisLength <= referenceBytes.length);
+      byteBuffer.get(roundTripBytes, bytesSeen, thisLength);
+      bytesSeen += thisLength;
+    }
+    assertTrue(bytesSeen == referenceBytes.length);
+    assertTrue(classUnderTest + ".asReadOnlyByteBufferTest() must give back the same bytes",
+        Arrays.equals(referenceBytes, roundTripBytes));
+  }
+
+  public void testToByteArray() {
+    byte[] roundTripBytes = stringUnderTest.toByteArray();
+    assertTrue(classUnderTest + ".toByteArray() must give back the same bytes",
+        Arrays.equals(referenceBytes, roundTripBytes));
+  }
+
+  public void testWriteTo() throws IOException {
+    ByteArrayOutputStream bos = new ByteArrayOutputStream();
+    stringUnderTest.writeTo(bos);
+    byte[] roundTripBytes = bos.toByteArray();
+    assertTrue(classUnderTest + ".writeTo() must give back the same bytes",
+        Arrays.equals(referenceBytes, roundTripBytes));
+  }
+  
+  public void testWriteTo_mutating() throws IOException {
+    OutputStream os = new OutputStream() {
+      @Override
+      public void write(byte[] b, int off, int len) {
+        for (int x = 0; x < len; ++x) {
+          b[off + x] = (byte) 0;
+        }
+      }
+
+      @Override
+      public void write(int b) {
+        // Purposefully left blank.
+      }
+    };
+
+    stringUnderTest.writeTo(os);
+    byte[] newBytes = stringUnderTest.toByteArray();
+    assertTrue(classUnderTest + ".writeTo() must not grant access to underlying array",
+        Arrays.equals(referenceBytes, newBytes));
+  }
+
+  public void testNewOutput() throws IOException {
+    ByteArrayOutputStream bos = new ByteArrayOutputStream();
+    ByteString.Output output = ByteString.newOutput();
+    stringUnderTest.writeTo(output);
+    assertEquals("Output Size returns correct result",
+        output.size(), stringUnderTest.size());
+    output.writeTo(bos);
+    assertTrue("Output.writeTo() must give back the same bytes",
+        Arrays.equals(referenceBytes, bos.toByteArray()));
+
+    // write the output stream to itself! This should cause it to double
+    output.writeTo(output);
+    assertEquals("Writing an output stream to itself is successful",
+        stringUnderTest.concat(stringUnderTest), output.toByteString());
+
+    output.reset();
+    assertEquals("Output.reset() resets the output", 0, output.size());
+    assertEquals("Output.reset() resets the output",
+        ByteString.EMPTY, output.toByteString());
+    
+  }
+
+  public void testToString() throws UnsupportedEncodingException {
+    String testString = "I love unicode \u1234\u5678 characters";
+    LiteralByteString unicode = new LiteralByteString(testString.getBytes(UTF_8));
+    String roundTripString = unicode.toString(UTF_8);
+    assertEquals(classUnderTest + " unicode must match", testString, roundTripString);
+  }
+
+  public void testEquals() {
+    assertEquals(classUnderTest + " must not equal null", false, stringUnderTest.equals(null));
+    assertEquals(classUnderTest + " must equal self", stringUnderTest, stringUnderTest);
+    assertFalse(classUnderTest + " must not equal the empty string",
+        stringUnderTest.equals(ByteString.EMPTY));
+    assertEquals(classUnderTest + " empty strings must be equal",
+        new LiteralByteString(new byte[]{}), stringUnderTest.substring(55, 55));
+    assertEquals(classUnderTest + " must equal another string with the same value",
+        stringUnderTest, new LiteralByteString(referenceBytes));
+
+    byte[] mungedBytes = new byte[referenceBytes.length];
+    System.arraycopy(referenceBytes, 0, mungedBytes, 0, referenceBytes.length);
+    mungedBytes[mungedBytes.length - 5] ^= 0xFF;
+    assertFalse(classUnderTest + " must not equal every string with the same length",
+        stringUnderTest.equals(new LiteralByteString(mungedBytes)));
+  }
+
+  public void testHashCode() {
+    int hash = stringUnderTest.hashCode();
+    assertEquals(classUnderTest + " must have expected hashCode", expectedHashCode, hash);
+  }
+
+  public void testPeekCachedHashCode() {
+    assertEquals(classUnderTest + ".peekCachedHashCode() should return zero at first", 0,
+        stringUnderTest.peekCachedHashCode());
+    stringUnderTest.hashCode();
+    assertEquals(classUnderTest + ".peekCachedHashCode should return zero at first",
+        expectedHashCode, stringUnderTest.peekCachedHashCode());
+  }
+
+  public void testPartialHash() {
+    // partialHash() is more strenuously tested elsewhere by testing hashes of substrings.
+    // This test would fail if the expected hash were 1.  It's not.
+    int hash = stringUnderTest.partialHash(stringUnderTest.size(), 0, stringUnderTest.size());
+    assertEquals(classUnderTest + ".partialHash() must yield expected hashCode",
+        expectedHashCode, hash);
+  }
+
+  public void testNewInput() throws IOException {
+    InputStream input = stringUnderTest.newInput();
+    assertEquals("InputStream.available() returns correct value",
+        stringUnderTest.size(), input.available());
+    boolean stillEqual = true;
+    for (byte referenceByte : referenceBytes) {
+      int expectedInt = (referenceByte & 0xFF);
+      stillEqual = (expectedInt == input.read());
+    }
+    assertEquals("InputStream.available() returns correct value",
+        0, input.available());
+    assertTrue(classUnderTest + " must give the same bytes from the InputStream", stillEqual);
+    assertEquals(classUnderTest + " InputStream must now be exhausted", -1, input.read());
+  }
+
+  public void testNewInput_skip() throws IOException {
+    InputStream input = stringUnderTest.newInput();
+    int stringSize = stringUnderTest.size();
+    int nearEndIndex = stringSize * 2 / 3;
+    long skipped1 = input.skip(nearEndIndex);
+    assertEquals("InputStream.skip()", skipped1, nearEndIndex);
+    assertEquals("InputStream.available()",
+        stringSize - skipped1, input.available());
+    assertTrue("InputStream.mark() is available", input.markSupported());
+    input.mark(0);
+    assertEquals("InputStream.skip(), read()",
+        stringUnderTest.byteAt(nearEndIndex) & 0xFF, input.read());
+    assertEquals("InputStream.available()",
+                 stringSize - skipped1 - 1, input.available());
+    long skipped2 = input.skip(stringSize);
+    assertEquals("InputStream.skip() incomplete",
+        skipped2, stringSize - skipped1 - 1);
+    assertEquals("InputStream.skip(), no more input", 0, input.available());
+    assertEquals("InputStream.skip(), no more input", -1, input.read());
+    input.reset();
+    assertEquals("InputStream.reset() succeded",
+                 stringSize - skipped1, input.available());
+    assertEquals("InputStream.reset(), read()",
+        stringUnderTest.byteAt(nearEndIndex) & 0xFF, input.read());
+  }
+
+  public void testNewCodedInput() throws IOException {
+    CodedInputStream cis = stringUnderTest.newCodedInput();
+    byte[] roundTripBytes = cis.readRawBytes(referenceBytes.length);
+    assertTrue(classUnderTest + " must give the same bytes back from the CodedInputStream",
+        Arrays.equals(referenceBytes, roundTripBytes));
+    assertTrue(classUnderTest + " CodedInputStream must now be exhausted", cis.isAtEnd());
+  }
+
+  /**
+   * Make sure we keep things simple when concatenating with empty. See also
+   * {@link ByteStringTest#testConcat_empty()}.
+   */
+  public void testConcat_empty() {
+    assertSame(classUnderTest + " concatenated with empty must give " + classUnderTest,
+        stringUnderTest.concat(ByteString.EMPTY), stringUnderTest);
+    assertSame("empty concatenated with " + classUnderTest + " must give " + classUnderTest,
+        ByteString.EMPTY.concat(stringUnderTest), stringUnderTest);
+  }
+}
diff --git a/third_party/protobuf/java/src/test/java/com/google/protobuf/MessageTest.java b/third_party/protobuf/java/src/test/java/com/google/protobuf/MessageTest.java
index c2f47eb..747fed7 100644
--- a/third_party/protobuf/java/src/test/java/com/google/protobuf/MessageTest.java
+++ b/third_party/protobuf/java/src/test/java/com/google/protobuf/MessageTest.java
@@ -38,6 +38,8 @@
 
 import junit.framework.TestCase;
 
+import java.util.List;
+
 /**
  * Misc. unit tests for message operations that apply to both generated
  * and dynamic messages.
@@ -310,4 +312,42 @@
       assertEquals("Message missing required fields: a, b, c", e.getMessage());
     }
   }
+  
+  /** Test reading unset repeated message from DynamicMessage. */
+  public void testDynamicRepeatedMessageNull() throws Exception {
+    Descriptors.Descriptor descriptor = TestRequired.getDescriptor();
+    DynamicMessage result =
+      DynamicMessage.newBuilder(TestAllTypes.getDescriptor())
+        .mergeFrom(DynamicMessage.newBuilder(MERGE_SOURCE).build())
+        .build();
+
+    assertTrue(result.getField(result.getDescriptorForType()
+        .findFieldByName("repeated_foreign_message")) instanceof List<?>);
+    assertEquals(result.getRepeatedFieldCount(result.getDescriptorForType()
+        .findFieldByName("repeated_foreign_message")), 0);
+  }
+  
+  /** Test reading repeated message from DynamicMessage. */
+  public void testDynamicRepeatedMessageNotNull() throws Exception {
+
+    TestAllTypes REPEATED_NESTED =
+      TestAllTypes.newBuilder()
+        .setOptionalInt32(1)
+        .setOptionalString("foo")
+        .setOptionalForeignMessage(ForeignMessage.getDefaultInstance())
+        .addRepeatedString("bar")
+        .addRepeatedForeignMessage(ForeignMessage.getDefaultInstance())
+        .addRepeatedForeignMessage(ForeignMessage.getDefaultInstance())
+        .build();
+    Descriptors.Descriptor descriptor = TestRequired.getDescriptor();
+    DynamicMessage result =
+      DynamicMessage.newBuilder(TestAllTypes.getDescriptor())
+        .mergeFrom(DynamicMessage.newBuilder(REPEATED_NESTED).build())
+        .build();
+
+    assertTrue(result.getField(result.getDescriptorForType()
+        .findFieldByName("repeated_foreign_message")) instanceof List<?>);
+    assertEquals(result.getRepeatedFieldCount(result.getDescriptorForType()
+        .findFieldByName("repeated_foreign_message")), 2);
+  }
 }
diff --git a/third_party/protobuf/java/src/test/java/com/google/protobuf/ParserTest.java b/third_party/protobuf/java/src/test/java/com/google/protobuf/ParserTest.java
new file mode 100644
index 0000000..396902c
--- /dev/null
+++ b/third_party/protobuf/java/src/test/java/com/google/protobuf/ParserTest.java
@@ -0,0 +1,375 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 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.
+
+package com.google.protobuf;
+
+import com.google.protobuf.UnittestLite.TestAllTypesLite;
+import com.google.protobuf.UnittestLite.TestPackedExtensionsLite;
+import com.google.protobuf.UnittestLite.TestParsingMergeLite;
+import com.google.protobuf.UnittestLite;
+import protobuf_unittest.UnittestOptimizeFor.TestOptimizedForSize;
+import protobuf_unittest.UnittestOptimizeFor.TestRequiredOptimizedForSize;
+import protobuf_unittest.UnittestOptimizeFor;
+import protobuf_unittest.UnittestProto.ForeignMessage;
+import protobuf_unittest.UnittestProto.TestAllTypes;
+import protobuf_unittest.UnittestProto.TestEmptyMessage;
+import protobuf_unittest.UnittestProto.TestRequired;
+import protobuf_unittest.UnittestProto.TestParsingMerge;
+import protobuf_unittest.UnittestProto;
+
+import junit.framework.TestCase;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+/**
+ * Unit test for {@link Parser}.
+ *
+ * @author liujisi@google.com (Pherl Liu)
+ */
+public class ParserTest extends TestCase {
+  public void testGeneratedMessageParserSingleton() throws Exception {
+    for (int i = 0; i < 10; i++) {
+      assertEquals(TestAllTypes.PARSER,
+                   TestUtil.getAllSet().getParserForType());
+    }
+  }
+
+  private void assertRoundTripEquals(MessageLite message,
+                                     ExtensionRegistryLite registry)
+      throws Exception {
+    final byte[] data = message.toByteArray();
+    final int offset = 20;
+    final int length = data.length;
+    final int padding = 30;
+    Parser<? extends MessageLite> parser = message.getParserForType();
+    assertMessageEquals(message, parser.parseFrom(data, registry));
+    assertMessageEquals(message, parser.parseFrom(
+        generatePaddingArray(data, offset, padding),
+        offset, length, registry));
+    assertMessageEquals(message, parser.parseFrom(
+        message.toByteString(), registry));
+    assertMessageEquals(message, parser.parseFrom(
+        new ByteArrayInputStream(data), registry));
+    assertMessageEquals(message, parser.parseFrom(
+        CodedInputStream.newInstance(data), registry));
+  }
+
+  private void assertRoundTripEquals(MessageLite message) throws Exception {
+    final byte[] data = message.toByteArray();
+    final int offset = 20;
+    final int length = data.length;
+    final int padding = 30;
+    Parser<? extends MessageLite> parser = message.getParserForType();
+    assertMessageEquals(message, parser.parseFrom(data));
+    assertMessageEquals(message, parser.parseFrom(
+        generatePaddingArray(data, offset, padding),
+        offset, length));
+    assertMessageEquals(message, parser.parseFrom(message.toByteString()));
+    assertMessageEquals(message, parser.parseFrom(
+        new ByteArrayInputStream(data)));
+    assertMessageEquals(message, parser.parseFrom(
+        CodedInputStream.newInstance(data)));
+  }
+
+  private void assertMessageEquals(MessageLite expected, MessageLite actual)
+      throws Exception {
+    if (expected instanceof Message) {
+      assertEquals(expected, actual);
+    } else {
+      assertEquals(expected.toByteString(), actual.toByteString());
+    }
+  }
+
+  private byte[] generatePaddingArray(byte[] data, int offset, int padding) {
+    byte[] result = new byte[offset + data.length + padding];
+    System.arraycopy(data, 0, result, offset, data.length);
+    return result;
+  }
+
+  public void testNormalMessage() throws Exception {
+    assertRoundTripEquals(TestUtil.getAllSet());
+  }
+
+  public void testParsePartial() throws Exception {
+    Parser<TestRequired> parser = TestRequired.PARSER;
+    final String errorString =
+        "Should throw exceptions when the parsed message isn't initialized.";
+
+    // TestRequired.b and TestRequired.c are not set.
+    TestRequired partialMessage = TestRequired.newBuilder()
+        .setA(1).buildPartial();
+
+    // parsePartialFrom should pass.
+    byte[] data = partialMessage.toByteArray();
+    assertEquals(partialMessage, parser.parsePartialFrom(data));
+    assertEquals(partialMessage, parser.parsePartialFrom(
+        partialMessage.toByteString()));
+    assertEquals(partialMessage, parser.parsePartialFrom(
+        new ByteArrayInputStream(data)));
+    assertEquals(partialMessage, parser.parsePartialFrom(
+        CodedInputStream.newInstance(data)));
+
+    // parseFrom(ByteArray)
+    try {
+      parser.parseFrom(partialMessage.toByteArray());
+      fail(errorString);
+    } catch (InvalidProtocolBufferException e) {
+      // pass.
+    }
+
+    // parseFrom(ByteString)
+    try {
+      parser.parseFrom(partialMessage.toByteString());
+      fail(errorString);
+    } catch (InvalidProtocolBufferException e) {
+      // pass.
+    }
+
+    // parseFrom(InputStream)
+    try {
+      parser.parseFrom(new ByteArrayInputStream(partialMessage.toByteArray()));
+      fail(errorString);
+    } catch (IOException e) {
+      // pass.
+    }
+
+    // parseFrom(CodedInputStream)
+    try {
+      parser.parseFrom(CodedInputStream.newInstance(
+          partialMessage.toByteArray()));
+      fail(errorString);
+    } catch (IOException e) {
+      // pass.
+    }
+  }
+
+  public void testParseExtensions() throws Exception {
+    assertRoundTripEquals(TestUtil.getAllExtensionsSet(),
+                          TestUtil.getExtensionRegistry());
+    assertRoundTripEquals(TestUtil.getAllLiteExtensionsSet(),
+                          TestUtil.getExtensionRegistryLite());
+  }
+
+  public void testParsePacked() throws Exception {
+    assertRoundTripEquals(TestUtil.getPackedSet());
+    assertRoundTripEquals(TestUtil.getPackedExtensionsSet(),
+                          TestUtil.getExtensionRegistry());
+    assertRoundTripEquals(TestUtil.getLitePackedExtensionsSet(),
+                          TestUtil.getExtensionRegistryLite());
+  }
+
+  public void testParseDelimitedTo() throws Exception {
+    // Write normal Message.
+    TestAllTypes normalMessage = TestUtil.getAllSet();
+    ByteArrayOutputStream output = new ByteArrayOutputStream();
+    normalMessage.writeDelimitedTo(output);
+
+    // Write MessageLite with packed extension fields.
+    TestPackedExtensionsLite packedMessage =
+        TestUtil.getLitePackedExtensionsSet();
+    packedMessage.writeDelimitedTo(output);
+
+    InputStream input = new ByteArrayInputStream(output.toByteArray());
+    assertMessageEquals(
+        normalMessage,
+        normalMessage.getParserForType().parseDelimitedFrom(input));
+    assertMessageEquals(
+        packedMessage,
+        packedMessage.getParserForType().parseDelimitedFrom(
+            input, TestUtil.getExtensionRegistryLite()));
+  }
+
+  public void testParseUnknownFields() throws Exception {
+    // All fields will be treated as unknown fields in emptyMessage.
+    TestEmptyMessage emptyMessage = TestEmptyMessage.PARSER.parseFrom(
+        TestUtil.getAllSet().toByteString());
+    assertEquals(
+        TestUtil.getAllSet().toByteString(),
+        emptyMessage.toByteString());
+  }
+
+  public void testOptimizeForSize() throws Exception {
+    TestOptimizedForSize.Builder builder = TestOptimizedForSize.newBuilder();
+    builder.setI(12).setMsg(ForeignMessage.newBuilder().setC(34).build());
+    builder.setExtension(TestOptimizedForSize.testExtension, 56);
+    builder.setExtension(TestOptimizedForSize.testExtension2,
+        TestRequiredOptimizedForSize.newBuilder().setX(78).build());
+
+    TestOptimizedForSize message = builder.build();
+    ExtensionRegistry registry = ExtensionRegistry.newInstance();
+    UnittestOptimizeFor.registerAllExtensions(registry);
+
+    assertRoundTripEquals(message, registry);
+  }
+
+  /** Helper method for {@link #testParsingMerge()}.*/
+  private void assertMessageMerged(TestAllTypes allTypes)
+      throws Exception {
+    assertEquals(3, allTypes.getOptionalInt32());
+    assertEquals(2, allTypes.getOptionalInt64());
+    assertEquals("hello", allTypes.getOptionalString());
+  }
+
+  /** Helper method for {@link #testParsingMergeLite()}.*/
+  private void assertMessageMerged(TestAllTypesLite allTypes)
+      throws Exception {
+    assertEquals(3, allTypes.getOptionalInt32());
+    assertEquals(2, allTypes.getOptionalInt64());
+    assertEquals("hello", allTypes.getOptionalString());
+  }
+
+  public void testParsingMerge() throws Exception {
+    // Build messages.
+    TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+    TestAllTypes msg1 = builder.setOptionalInt32(1).build();
+    builder.clear();
+    TestAllTypes msg2 = builder.setOptionalInt64(2).build();
+    builder.clear();
+    TestAllTypes msg3 = builder.setOptionalInt32(3)
+        .setOptionalString("hello").build();
+
+    // Build groups.
+    TestParsingMerge.RepeatedFieldsGenerator.Group1 optionalG1 =
+        TestParsingMerge.RepeatedFieldsGenerator.Group1.newBuilder()
+        .setField1(msg1).build();
+    TestParsingMerge.RepeatedFieldsGenerator.Group1 optionalG2 =
+        TestParsingMerge.RepeatedFieldsGenerator.Group1.newBuilder()
+        .setField1(msg2).build();
+    TestParsingMerge.RepeatedFieldsGenerator.Group1 optionalG3 =
+        TestParsingMerge.RepeatedFieldsGenerator.Group1.newBuilder()
+        .setField1(msg3).build();
+    TestParsingMerge.RepeatedFieldsGenerator.Group2 repeatedG1 =
+        TestParsingMerge.RepeatedFieldsGenerator.Group2.newBuilder()
+        .setField1(msg1).build();
+    TestParsingMerge.RepeatedFieldsGenerator.Group2 repeatedG2 =
+        TestParsingMerge.RepeatedFieldsGenerator.Group2.newBuilder()
+        .setField1(msg2).build();
+    TestParsingMerge.RepeatedFieldsGenerator.Group2 repeatedG3 =
+        TestParsingMerge.RepeatedFieldsGenerator.Group2.newBuilder()
+        .setField1(msg3).build();
+
+    // Assign and serialize RepeatedFieldsGenerator.
+    ByteString data = TestParsingMerge.RepeatedFieldsGenerator.newBuilder()
+        .addField1(msg1).addField1(msg2).addField1(msg3)
+        .addField2(msg1).addField2(msg2).addField2(msg3)
+        .addField3(msg1).addField3(msg2).addField3(msg3)
+        .addGroup1(optionalG1).addGroup1(optionalG2).addGroup1(optionalG3)
+        .addGroup2(repeatedG1).addGroup2(repeatedG2).addGroup2(repeatedG3)
+        .addExt1(msg1).addExt1(msg2).addExt1(msg3)
+        .addExt2(msg1).addExt2(msg2).addExt2(msg3)
+        .build().toByteString();
+
+    // Parse TestParsingMerge.
+    ExtensionRegistry registry = ExtensionRegistry.newInstance();
+    UnittestProto.registerAllExtensions(registry);
+    TestParsingMerge parsingMerge =
+        TestParsingMerge.PARSER.parseFrom(data, registry);
+
+    // Required and optional fields should be merged.
+    assertMessageMerged(parsingMerge.getRequiredAllTypes());
+    assertMessageMerged(parsingMerge.getOptionalAllTypes());
+    assertMessageMerged(
+        parsingMerge.getOptionalGroup().getOptionalGroupAllTypes());
+    assertMessageMerged(parsingMerge.getExtension(
+        TestParsingMerge.optionalExt));
+
+    // Repeated fields should not be merged.
+    assertEquals(3, parsingMerge.getRepeatedAllTypesCount());
+    assertEquals(3, parsingMerge.getRepeatedGroupCount());
+    assertEquals(3, parsingMerge.getExtensionCount(
+        TestParsingMerge.repeatedExt));
+  }
+
+  public void testParsingMergeLite() throws Exception {
+    // Build messages.
+    TestAllTypesLite.Builder builder =
+        TestAllTypesLite.newBuilder();
+    TestAllTypesLite msg1 = builder.setOptionalInt32(1).build();
+    builder.clear();
+    TestAllTypesLite msg2 = builder.setOptionalInt64(2).build();
+    builder.clear();
+    TestAllTypesLite msg3 = builder.setOptionalInt32(3)
+        .setOptionalString("hello").build();
+
+    // Build groups.
+    TestParsingMergeLite.RepeatedFieldsGenerator.Group1 optionalG1 =
+        TestParsingMergeLite.RepeatedFieldsGenerator.Group1.newBuilder()
+        .setField1(msg1).build();
+    TestParsingMergeLite.RepeatedFieldsGenerator.Group1 optionalG2 =
+        TestParsingMergeLite.RepeatedFieldsGenerator.Group1.newBuilder()
+        .setField1(msg2).build();
+    TestParsingMergeLite.RepeatedFieldsGenerator.Group1 optionalG3 =
+        TestParsingMergeLite.RepeatedFieldsGenerator.Group1.newBuilder()
+        .setField1(msg3).build();
+    TestParsingMergeLite.RepeatedFieldsGenerator.Group2 repeatedG1 =
+        TestParsingMergeLite.RepeatedFieldsGenerator.Group2.newBuilder()
+        .setField1(msg1).build();
+    TestParsingMergeLite.RepeatedFieldsGenerator.Group2 repeatedG2 =
+        TestParsingMergeLite.RepeatedFieldsGenerator.Group2.newBuilder()
+        .setField1(msg2).build();
+    TestParsingMergeLite.RepeatedFieldsGenerator.Group2 repeatedG3 =
+        TestParsingMergeLite.RepeatedFieldsGenerator.Group2.newBuilder()
+        .setField1(msg3).build();
+
+    // Assign and serialize RepeatedFieldsGenerator.
+    ByteString data = TestParsingMergeLite.RepeatedFieldsGenerator.newBuilder()
+        .addField1(msg1).addField1(msg2).addField1(msg3)
+        .addField2(msg1).addField2(msg2).addField2(msg3)
+        .addField3(msg1).addField3(msg2).addField3(msg3)
+        .addGroup1(optionalG1).addGroup1(optionalG2).addGroup1(optionalG3)
+        .addGroup2(repeatedG1).addGroup2(repeatedG2).addGroup2(repeatedG3)
+        .addExt1(msg1).addExt1(msg2).addExt1(msg3)
+        .addExt2(msg1).addExt2(msg2).addExt2(msg3)
+        .build().toByteString();
+
+    // Parse TestParsingMergeLite.
+    ExtensionRegistry registry = ExtensionRegistry.newInstance();
+    UnittestLite.registerAllExtensions(registry);
+    TestParsingMergeLite parsingMerge =
+        TestParsingMergeLite.PARSER.parseFrom(data, registry);
+
+    // Required and optional fields should be merged.
+    assertMessageMerged(parsingMerge.getRequiredAllTypes());
+    assertMessageMerged(parsingMerge.getOptionalAllTypes());
+    assertMessageMerged(
+        parsingMerge.getOptionalGroup().getOptionalGroupAllTypes());
+    assertMessageMerged(parsingMerge.getExtension(
+        TestParsingMergeLite.optionalExt));
+
+    // Repeated fields should not be merged.
+    assertEquals(3, parsingMerge.getRepeatedAllTypesCount());
+    assertEquals(3, parsingMerge.getRepeatedGroupCount());
+    assertEquals(3, parsingMerge.getExtensionCount(
+        TestParsingMergeLite.repeatedExt));
+  }
+}
diff --git a/third_party/protobuf/java/src/test/java/com/google/protobuf/RopeByteStringSubstringTest.java b/third_party/protobuf/java/src/test/java/com/google/protobuf/RopeByteStringSubstringTest.java
new file mode 100644
index 0000000..06707a2
--- /dev/null
+++ b/third_party/protobuf/java/src/test/java/com/google/protobuf/RopeByteStringSubstringTest.java
@@ -0,0 +1,97 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 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.
+
+package com.google.protobuf;
+
+import java.io.UnsupportedEncodingException;
+import java.util.Iterator;
+
+/**
+ * This class tests {@link RopeByteString#substring(int, int)} by inheriting the tests from
+ * {@link LiteralByteStringTest}.  Only a couple of methods are overridden.  
+ *
+ * @author carlanton@google.com (Carl Haverl)
+ */
+public class RopeByteStringSubstringTest extends LiteralByteStringTest {
+
+  @Override
+  protected void setUp() throws Exception {
+    classUnderTest = "RopeByteString";
+    byte[] sourceBytes = ByteStringTest.getTestBytes(22341, 22337766L);
+    Iterator<ByteString> iter = ByteStringTest.makeConcretePieces(sourceBytes).iterator();
+    ByteString sourceString = iter.next();
+    while (iter.hasNext()) {
+      sourceString = sourceString.concat(iter.next());
+    }
+
+    int from = 1130;
+    int to = sourceBytes.length - 5555;
+    stringUnderTest = sourceString.substring(from, to);
+    referenceBytes = new byte[to - from];
+    System.arraycopy(sourceBytes, from, referenceBytes, 0, to - from);
+    expectedHashCode = -1259260680;
+  }
+
+  @Override
+  public void testGetTreeDepth() {
+    assertEquals(classUnderTest + " must have the expected tree depth",
+        3, stringUnderTest.getTreeDepth());
+  }
+
+  @Override
+  public void testToString() throws UnsupportedEncodingException {
+    String sourceString = "I love unicode \u1234\u5678 characters";
+    ByteString sourceByteString = ByteString.copyFromUtf8(sourceString);
+    int copies = 250;
+
+    // By building the RopeByteString by concatenating, this is actually a fairly strenuous test.
+    StringBuilder builder = new StringBuilder(copies * sourceString.length());
+    ByteString unicode = ByteString.EMPTY;
+    for (int i = 0; i < copies; ++i) {
+      builder.append(sourceString);
+      unicode = RopeByteString.concatenate(unicode, sourceByteString);
+    }
+    String testString = builder.toString();
+
+    // Do the substring part
+    testString = testString.substring(2, testString.length() - 6);
+    unicode = unicode.substring(2, unicode.size() - 6);
+
+    assertEquals(classUnderTest + " from string must have the expected type",
+        classUnderTest, getActualClassName(unicode));
+    String roundTripString = unicode.toString(UTF_8);
+    assertEquals(classUnderTest + " unicode bytes must match",
+        testString, roundTripString);
+    ByteString flatString = ByteString.copyFromUtf8(testString);
+    assertEquals(classUnderTest + " string must equal the flat string", flatString, unicode);
+    assertEquals(classUnderTest + " string must must have same hashCode as the flat string",
+        flatString.hashCode(), unicode.hashCode());
+  }
+}
diff --git a/third_party/protobuf/java/src/test/java/com/google/protobuf/RopeByteStringTest.java b/third_party/protobuf/java/src/test/java/com/google/protobuf/RopeByteStringTest.java
new file mode 100644
index 0000000..15f660d
--- /dev/null
+++ b/third_party/protobuf/java/src/test/java/com/google/protobuf/RopeByteStringTest.java
@@ -0,0 +1,115 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 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.
+
+package com.google.protobuf;
+
+import java.io.UnsupportedEncodingException;
+import java.util.Arrays;
+import java.util.Iterator;
+
+/**
+ * This class tests {@link RopeByteString} by inheriting the tests from
+ * {@link LiteralByteStringTest}.  Only a couple of methods are overridden.
+ * 
+ * <p>A full test of the result of {@link RopeByteString#substring(int, int)} is found in the
+ * separate class {@link RopeByteStringSubstringTest}.
+ *
+ * @author carlanton@google.com (Carl Haverl)
+ */
+public class RopeByteStringTest extends LiteralByteStringTest {
+
+  @Override
+  protected void setUp() throws Exception {
+    classUnderTest = "RopeByteString";
+    referenceBytes = ByteStringTest.getTestBytes(22341, 22337766L);
+    Iterator<ByteString> iter = ByteStringTest.makeConcretePieces(referenceBytes).iterator();
+    stringUnderTest = iter.next();
+    while (iter.hasNext()) {
+      stringUnderTest = stringUnderTest.concat(iter.next());
+    }
+    expectedHashCode = -1214197238;
+  }
+
+  @Override
+  public void testGetTreeDepth() {
+    assertEquals(classUnderTest + " must have the expected tree depth",
+        4, stringUnderTest.getTreeDepth());
+  }
+
+  public void testBalance() {
+    int numberOfPieces = 10000;
+    int pieceSize = 64;
+    byte[] testBytes = ByteStringTest.getTestBytes(numberOfPieces * pieceSize, 113377L);
+
+    // Build up a big ByteString from smaller pieces to force a rebalance
+    ByteString concatenated = ByteString.EMPTY;
+    for (int i = 0; i < numberOfPieces; ++i) {
+      concatenated = concatenated.concat(ByteString.copyFrom(testBytes, i * pieceSize, pieceSize));
+    }
+
+    assertEquals(classUnderTest + " from string must have the expected type",
+        classUnderTest, getActualClassName(concatenated));
+    assertTrue(classUnderTest + " underlying bytes must match after balancing",
+        Arrays.equals(testBytes, concatenated.toByteArray()));
+    ByteString testString = ByteString.copyFrom(testBytes);
+    assertTrue(classUnderTest + " balanced string must equal flat string",
+        concatenated.equals(testString));
+    assertTrue(classUnderTest + " flat string must equal balanced string",
+        testString.equals(concatenated));
+    assertEquals(classUnderTest + " balanced string must have same hash code as flat string",
+        testString.hashCode(), concatenated.hashCode());
+  }
+
+  @Override
+  public void testToString() throws UnsupportedEncodingException {
+    String sourceString = "I love unicode \u1234\u5678 characters";
+    ByteString sourceByteString = ByteString.copyFromUtf8(sourceString);
+    int copies = 250;
+
+    // By building the RopeByteString by concatenating, this is actually a fairly strenuous test.
+    StringBuilder builder = new StringBuilder(copies * sourceString.length());
+    ByteString unicode = ByteString.EMPTY;
+    for (int i = 0; i < copies; ++i) {
+      builder.append(sourceString);
+      unicode = RopeByteString.concatenate(unicode, sourceByteString);
+    }
+    String testString = builder.toString();
+
+    assertEquals(classUnderTest + " from string must have the expected type",
+        classUnderTest, getActualClassName(unicode));
+    String roundTripString = unicode.toString(UTF_8);
+    assertEquals(classUnderTest + " unicode bytes must match",
+        testString, roundTripString);
+    ByteString flatString = ByteString.copyFromUtf8(testString);
+    assertEquals(classUnderTest + " string must equal the flat string", flatString, unicode);
+    assertEquals(classUnderTest + " string must must have same hashCode as the flat string",
+        flatString.hashCode(), unicode.hashCode());
+  }
+}
diff --git a/third_party/protobuf/java/src/test/java/com/google/protobuf/TestBadIdentifiers.java b/third_party/protobuf/java/src/test/java/com/google/protobuf/TestBadIdentifiers.java
index 6feec4e..382acf0 100644
--- a/third_party/protobuf/java/src/test/java/com/google/protobuf/TestBadIdentifiers.java
+++ b/third_party/protobuf/java/src/test/java/com/google/protobuf/TestBadIdentifiers.java
@@ -35,7 +35,7 @@
 /**
  * Tests that proto2 api generation doesn't cause compile errors when
  * compiling protocol buffers that have names that would otherwise conflict
- * if not fully qualified (like @Deprecated and @Override). 
+ * if not fully qualified (like @Deprecated and @Override).
  *
  * @author jonp@google.com (Jon Perlow)
  */
@@ -45,5 +45,19 @@
     // If this compiles, it means the generation was correct.
     TestBadIdentifiersProto.Deprecated.newBuilder();
     TestBadIdentifiersProto.Override.newBuilder();
-  } 
+  }
+
+  public void testGetDescriptor() {
+    Descriptors.FileDescriptor fileDescriptor =
+        TestBadIdentifiersProto.getDescriptor();
+    String descriptorField = TestBadIdentifiersProto.Descriptor
+        .getDefaultInstance().getDescriptor();
+    Descriptors.Descriptor protoDescriptor = TestBadIdentifiersProto.Descriptor
+        .getDefaultInstance().getDescriptorForType();
+    String nestedDescriptorField = TestBadIdentifiersProto.Descriptor
+        .NestedDescriptor.getDefaultInstance().getDescriptor();
+    Descriptors.Descriptor nestedProtoDescriptor = TestBadIdentifiersProto
+        .Descriptor.NestedDescriptor.getDefaultInstance()
+        .getDescriptorForType();
+  }
 }
diff --git a/third_party/protobuf/java/src/test/java/com/google/protobuf/TestUtil.java b/third_party/protobuf/java/src/test/java/com/google/protobuf/TestUtil.java
index 9109f41..76f5c60 100644
--- a/third_party/protobuf/java/src/test/java/com/google/protobuf/TestUtil.java
+++ b/third_party/protobuf/java/src/test/java/com/google/protobuf/TestUtil.java
@@ -72,14 +72,16 @@
 import static protobuf_unittest.UnittestProto.optionalStringExtension;
 import static protobuf_unittest.UnittestProto.optionalBytesExtension;
 import static protobuf_unittest.UnittestProto.optionalGroupExtension;
-import static protobuf_unittest.UnittestProto.optionalNestedMessageExtension;
+import static protobuf_unittest.UnittestProto.optionalCordExtension;
+import static protobuf_unittest.UnittestProto.optionalForeignEnumExtension;
 import static protobuf_unittest.UnittestProto.optionalForeignMessageExtension;
+import static protobuf_unittest.UnittestProto.optionalImportEnumExtension;
 import static protobuf_unittest.UnittestProto.optionalImportMessageExtension;
 import static protobuf_unittest.UnittestProto.optionalNestedEnumExtension;
-import static protobuf_unittest.UnittestProto.optionalForeignEnumExtension;
-import static protobuf_unittest.UnittestProto.optionalImportEnumExtension;
+import static protobuf_unittest.UnittestProto.optionalNestedMessageExtension;
+import static protobuf_unittest.UnittestProto.optionalPublicImportMessageExtension;
+import static protobuf_unittest.UnittestProto.optionalLazyMessageExtension;
 import static protobuf_unittest.UnittestProto.optionalStringPieceExtension;
-import static protobuf_unittest.UnittestProto.optionalCordExtension;
 
 import static protobuf_unittest.UnittestProto.repeatedInt32Extension;
 import static protobuf_unittest.UnittestProto.repeatedInt64Extension;
@@ -100,6 +102,7 @@
 import static protobuf_unittest.UnittestProto.repeatedNestedMessageExtension;
 import static protobuf_unittest.UnittestProto.repeatedForeignMessageExtension;
 import static protobuf_unittest.UnittestProto.repeatedImportMessageExtension;
+import static protobuf_unittest.UnittestProto.repeatedLazyMessageExtension;
 import static protobuf_unittest.UnittestProto.repeatedNestedEnumExtension;
 import static protobuf_unittest.UnittestProto.repeatedForeignEnumExtension;
 import static protobuf_unittest.UnittestProto.repeatedImportEnumExtension;
@@ -162,11 +165,13 @@
 import static com.google.protobuf.UnittestLite.optionalBytesExtensionLite;
 import static com.google.protobuf.UnittestLite.optionalGroupExtensionLite;
 import static com.google.protobuf.UnittestLite.optionalNestedMessageExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalForeignEnumExtensionLite;
 import static com.google.protobuf.UnittestLite.optionalForeignMessageExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalImportEnumExtensionLite;
 import static com.google.protobuf.UnittestLite.optionalImportMessageExtensionLite;
 import static com.google.protobuf.UnittestLite.optionalNestedEnumExtensionLite;
-import static com.google.protobuf.UnittestLite.optionalForeignEnumExtensionLite;
-import static com.google.protobuf.UnittestLite.optionalImportEnumExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalPublicImportMessageExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalLazyMessageExtensionLite;
 import static com.google.protobuf.UnittestLite.optionalStringPieceExtensionLite;
 import static com.google.protobuf.UnittestLite.optionalCordExtensionLite;
 
@@ -189,6 +194,7 @@
 import static com.google.protobuf.UnittestLite.repeatedNestedMessageExtensionLite;
 import static com.google.protobuf.UnittestLite.repeatedForeignMessageExtensionLite;
 import static com.google.protobuf.UnittestLite.repeatedImportMessageExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedLazyMessageExtensionLite;
 import static com.google.protobuf.UnittestLite.repeatedNestedEnumExtensionLite;
 import static com.google.protobuf.UnittestLite.repeatedForeignEnumExtensionLite;
 import static com.google.protobuf.UnittestLite.repeatedImportEnumExtensionLite;
@@ -222,8 +228,9 @@
 import protobuf_unittest.UnittestProto.TestUnpackedTypes;
 import protobuf_unittest.UnittestProto.ForeignMessage;
 import protobuf_unittest.UnittestProto.ForeignEnum;
-import com.google.protobuf.test.UnittestImport.ImportMessage;
 import com.google.protobuf.test.UnittestImport.ImportEnum;
+import com.google.protobuf.test.UnittestImport.ImportMessage;
+import com.google.protobuf.test.UnittestImportPublic.PublicImportMessage;
 
 import com.google.protobuf.UnittestLite.TestAllTypesLite;
 import com.google.protobuf.UnittestLite.TestAllExtensionsLite;
@@ -231,8 +238,9 @@
 import com.google.protobuf.UnittestLite.TestPackedExtensionsLite;
 import com.google.protobuf.UnittestLite.ForeignMessageLite;
 import com.google.protobuf.UnittestLite.ForeignEnumLite;
-import com.google.protobuf.UnittestImportLite.ImportMessageLite;
 import com.google.protobuf.UnittestImportLite.ImportEnumLite;
+import com.google.protobuf.UnittestImportLite.ImportMessageLite;
+import com.google.protobuf.UnittestImportPublicLite.PublicImportMessageLite;
 
 import junit.framework.Assert;
 
@@ -242,7 +250,7 @@
 
 /**
  * Contains methods for setting all fields of {@code TestAllTypes} to
- * some vaules as well as checking that all the fields are set to those values.
+ * some values as well as checking that all the fields are set to those values.
  * These are useful for testing various protocol message features, e.g.
  * set all fields of a message, serialize it, parse it, and check that all
  * fields are set.
@@ -275,6 +283,16 @@
   }
 
   /**
+   * Get a {@code TestAllTypes.Builder} with all fields set as they would be by
+   * {@link #setAllFields(TestAllTypes.Builder)}.
+   */
+  public static TestAllTypes.Builder getAllSetBuilder() {
+    TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+    setAllFields(builder);
+    return builder;
+  }
+
+  /**
    * Get a {@code TestAllExtensions} with all fields set as they would be by
    * {@link #setAllExtensions(TestAllExtensions.Builder)}.
    */
@@ -344,6 +362,10 @@
       ForeignMessage.newBuilder().setC(119).build());
     message.setOptionalImportMessage(
       ImportMessage.newBuilder().setD(120).build());
+    message.setOptionalPublicImportMessage(
+      PublicImportMessage.newBuilder().setE(126).build());
+    message.setOptionalLazyMessage(
+      TestAllTypes.NestedMessage.newBuilder().setBb(127).build());
 
     message.setOptionalNestedEnum (TestAllTypes.NestedEnum.BAZ);
     message.setOptionalForeignEnum(ForeignEnum.FOREIGN_BAZ);
@@ -378,6 +400,8 @@
       ForeignMessage.newBuilder().setC(219).build());
     message.addRepeatedImportMessage(
       ImportMessage.newBuilder().setD(220).build());
+    message.addRepeatedLazyMessage(
+      TestAllTypes.NestedMessage.newBuilder().setBb(227).build());
 
     message.addRepeatedNestedEnum (TestAllTypes.NestedEnum.BAR);
     message.addRepeatedForeignEnum(ForeignEnum.FOREIGN_BAR);
@@ -411,6 +435,8 @@
       ForeignMessage.newBuilder().setC(319).build());
     message.addRepeatedImportMessage(
       ImportMessage.newBuilder().setD(320).build());
+    message.addRepeatedLazyMessage(
+      TestAllTypes.NestedMessage.newBuilder().setBb(327).build());
 
     message.addRepeatedNestedEnum (TestAllTypes.NestedEnum.BAZ);
     message.addRepeatedForeignEnum(ForeignEnum.FOREIGN_BAZ);
@@ -476,6 +502,8 @@
       ForeignMessage.newBuilder().setC(519).build());
     message.setRepeatedImportMessage(1,
       ImportMessage.newBuilder().setD(520).build());
+    message.setRepeatedLazyMessage(1,
+      TestAllTypes.NestedMessage.newBuilder().setBb(527).build());
 
     message.setRepeatedNestedEnum (1, TestAllTypes.NestedEnum.FOO);
     message.setRepeatedForeignEnum(1, ForeignEnum.FOREIGN_FOO);
@@ -541,10 +569,12 @@
     Assert.assertEquals("115", message.getOptionalString  ());
     Assert.assertEquals(toBytes("116"), message.getOptionalBytes());
 
-    Assert.assertEquals(117, message.getOptionalGroup         ().getA());
-    Assert.assertEquals(118, message.getOptionalNestedMessage ().getBb());
-    Assert.assertEquals(119, message.getOptionalForeignMessage().getC());
-    Assert.assertEquals(120, message.getOptionalImportMessage ().getD());
+    Assert.assertEquals(117, message.getOptionalGroup              ().getA());
+    Assert.assertEquals(118, message.getOptionalNestedMessage      ().getBb());
+    Assert.assertEquals(119, message.getOptionalForeignMessage     ().getC());
+    Assert.assertEquals(120, message.getOptionalImportMessage      ().getD());
+    Assert.assertEquals(126, message.getOptionalPublicImportMessage().getE());
+    Assert.assertEquals(127, message.getOptionalLazyMessage        ().getBb());
 
     Assert.assertEquals(TestAllTypes.NestedEnum.BAZ, message.getOptionalNestedEnum());
     Assert.assertEquals(ForeignEnum.FOREIGN_BAZ, message.getOptionalForeignEnum());
@@ -575,6 +605,7 @@
     Assert.assertEquals(2, message.getRepeatedNestedMessageCount ());
     Assert.assertEquals(2, message.getRepeatedForeignMessageCount());
     Assert.assertEquals(2, message.getRepeatedImportMessageCount ());
+    Assert.assertEquals(2, message.getRepeatedLazyMessageCount   ());
     Assert.assertEquals(2, message.getRepeatedNestedEnumCount    ());
     Assert.assertEquals(2, message.getRepeatedForeignEnumCount   ());
     Assert.assertEquals(2, message.getRepeatedImportEnumCount    ());
@@ -602,6 +633,7 @@
     Assert.assertEquals(218, message.getRepeatedNestedMessage (0).getBb());
     Assert.assertEquals(219, message.getRepeatedForeignMessage(0).getC());
     Assert.assertEquals(220, message.getRepeatedImportMessage (0).getD());
+    Assert.assertEquals(227, message.getRepeatedLazyMessage   (0).getBb());
 
     Assert.assertEquals(TestAllTypes.NestedEnum.BAR, message.getRepeatedNestedEnum (0));
     Assert.assertEquals(ForeignEnum.FOREIGN_BAR, message.getRepeatedForeignEnum(0));
@@ -630,6 +662,7 @@
     Assert.assertEquals(318, message.getRepeatedNestedMessage (1).getBb());
     Assert.assertEquals(319, message.getRepeatedForeignMessage(1).getC());
     Assert.assertEquals(320, message.getRepeatedImportMessage (1).getD());
+    Assert.assertEquals(327, message.getRepeatedLazyMessage   (1).getBb());
 
     Assert.assertEquals(TestAllTypes.NestedEnum.BAZ, message.getRepeatedNestedEnum (1));
     Assert.assertEquals(ForeignEnum.FOREIGN_BAZ, message.getRepeatedForeignEnum(1));
@@ -741,15 +774,19 @@
     Assert.assertEquals(ByteString.EMPTY, message.getOptionalBytes());
 
     // Embedded messages should also be clear.
-    Assert.assertFalse(message.getOptionalGroup         ().hasA());
-    Assert.assertFalse(message.getOptionalNestedMessage ().hasBb());
-    Assert.assertFalse(message.getOptionalForeignMessage().hasC());
-    Assert.assertFalse(message.getOptionalImportMessage ().hasD());
+    Assert.assertFalse(message.getOptionalGroup              ().hasA());
+    Assert.assertFalse(message.getOptionalNestedMessage      ().hasBb());
+    Assert.assertFalse(message.getOptionalForeignMessage     ().hasC());
+    Assert.assertFalse(message.getOptionalImportMessage      ().hasD());
+    Assert.assertFalse(message.getOptionalPublicImportMessage().hasE());
+    Assert.assertFalse(message.getOptionalLazyMessage        ().hasBb());
 
-    Assert.assertEquals(0, message.getOptionalGroup         ().getA());
-    Assert.assertEquals(0, message.getOptionalNestedMessage ().getBb());
-    Assert.assertEquals(0, message.getOptionalForeignMessage().getC());
-    Assert.assertEquals(0, message.getOptionalImportMessage ().getD());
+    Assert.assertEquals(0, message.getOptionalGroup              ().getA());
+    Assert.assertEquals(0, message.getOptionalNestedMessage      ().getBb());
+    Assert.assertEquals(0, message.getOptionalForeignMessage     ().getC());
+    Assert.assertEquals(0, message.getOptionalImportMessage      ().getD());
+    Assert.assertEquals(0, message.getOptionalPublicImportMessage().getE());
+    Assert.assertEquals(0, message.getOptionalLazyMessage        ().getBb());
 
     // Enums without defaults are set to the first value in the enum.
     Assert.assertEquals(TestAllTypes.NestedEnum.FOO, message.getOptionalNestedEnum ());
@@ -780,6 +817,7 @@
     Assert.assertEquals(0, message.getRepeatedNestedMessageCount ());
     Assert.assertEquals(0, message.getRepeatedForeignMessageCount());
     Assert.assertEquals(0, message.getRepeatedImportMessageCount ());
+    Assert.assertEquals(0, message.getRepeatedLazyMessageCount   ());
     Assert.assertEquals(0, message.getRepeatedNestedEnumCount    ());
     Assert.assertEquals(0, message.getRepeatedForeignEnumCount   ());
     Assert.assertEquals(0, message.getRepeatedImportEnumCount    ());
@@ -868,6 +906,7 @@
     Assert.assertEquals(2, message.getRepeatedNestedMessageCount ());
     Assert.assertEquals(2, message.getRepeatedForeignMessageCount());
     Assert.assertEquals(2, message.getRepeatedImportMessageCount ());
+    Assert.assertEquals(2, message.getRepeatedLazyMessageCount   ());
     Assert.assertEquals(2, message.getRepeatedNestedEnumCount    ());
     Assert.assertEquals(2, message.getRepeatedForeignEnumCount   ());
     Assert.assertEquals(2, message.getRepeatedImportEnumCount    ());
@@ -895,6 +934,7 @@
     Assert.assertEquals(218, message.getRepeatedNestedMessage (0).getBb());
     Assert.assertEquals(219, message.getRepeatedForeignMessage(0).getC());
     Assert.assertEquals(220, message.getRepeatedImportMessage (0).getD());
+    Assert.assertEquals(227, message.getRepeatedLazyMessage   (0).getBb());
 
     Assert.assertEquals(TestAllTypes.NestedEnum.BAR, message.getRepeatedNestedEnum (0));
     Assert.assertEquals(ForeignEnum.FOREIGN_BAR, message.getRepeatedForeignEnum(0));
@@ -924,6 +964,7 @@
     Assert.assertEquals(518, message.getRepeatedNestedMessage (1).getBb());
     Assert.assertEquals(519, message.getRepeatedForeignMessage(1).getC());
     Assert.assertEquals(520, message.getRepeatedImportMessage (1).getD());
+    Assert.assertEquals(527, message.getRepeatedLazyMessage   (1).getBb());
 
     Assert.assertEquals(TestAllTypes.NestedEnum.FOO, message.getRepeatedNestedEnum (1));
     Assert.assertEquals(ForeignEnum.FOREIGN_FOO, message.getRepeatedForeignEnum(1));
@@ -1210,6 +1251,10 @@
       ForeignMessage.newBuilder().setC(119).build());
     message.setExtension(optionalImportMessageExtension,
       ImportMessage.newBuilder().setD(120).build());
+    message.setExtension(optionalPublicImportMessageExtension,
+      PublicImportMessage.newBuilder().setE(126).build());
+    message.setExtension(optionalLazyMessageExtension,
+      TestAllTypes.NestedMessage.newBuilder().setBb(127).build());
 
     message.setExtension(optionalNestedEnumExtension, TestAllTypes.NestedEnum.BAZ);
     message.setExtension(optionalForeignEnumExtension, ForeignEnum.FOREIGN_BAZ);
@@ -1244,6 +1289,8 @@
       ForeignMessage.newBuilder().setC(219).build());
     message.addExtension(repeatedImportMessageExtension,
       ImportMessage.newBuilder().setD(220).build());
+    message.addExtension(repeatedLazyMessageExtension,
+      TestAllTypes.NestedMessage.newBuilder().setBb(227).build());
 
     message.addExtension(repeatedNestedEnumExtension, TestAllTypes.NestedEnum.BAR);
     message.addExtension(repeatedForeignEnumExtension, ForeignEnum.FOREIGN_BAR);
@@ -1277,6 +1324,8 @@
       ForeignMessage.newBuilder().setC(319).build());
     message.addExtension(repeatedImportMessageExtension,
       ImportMessage.newBuilder().setD(320).build());
+    message.addExtension(repeatedLazyMessageExtension,
+      TestAllTypes.NestedMessage.newBuilder().setBb(327).build());
 
     message.addExtension(repeatedNestedEnumExtension, TestAllTypes.NestedEnum.BAZ);
     message.addExtension(repeatedForeignEnumExtension, ForeignEnum.FOREIGN_BAZ);
@@ -1343,6 +1392,8 @@
       ForeignMessage.newBuilder().setC(519).build());
     message.setExtension(repeatedImportMessageExtension, 1,
       ImportMessage.newBuilder().setD(520).build());
+    message.setExtension(repeatedLazyMessageExtension, 1,
+      TestAllTypes.NestedMessage.newBuilder().setBb(527).build());
 
     message.setExtension(repeatedNestedEnumExtension , 1, TestAllTypes.NestedEnum.FOO);
     message.setExtension(repeatedForeignEnumExtension, 1, ForeignEnum.FOREIGN_FOO);
@@ -1409,10 +1460,12 @@
     assertEqualsExactType("115", message.getExtension(optionalStringExtension  ));
     assertEqualsExactType(toBytes("116"), message.getExtension(optionalBytesExtension));
 
-    assertEqualsExactType(117, message.getExtension(optionalGroupExtension         ).getA());
-    assertEqualsExactType(118, message.getExtension(optionalNestedMessageExtension ).getBb());
-    assertEqualsExactType(119, message.getExtension(optionalForeignMessageExtension).getC());
-    assertEqualsExactType(120, message.getExtension(optionalImportMessageExtension ).getD());
+    assertEqualsExactType(117, message.getExtension(optionalGroupExtension              ).getA());
+    assertEqualsExactType(118, message.getExtension(optionalNestedMessageExtension      ).getBb());
+    assertEqualsExactType(119, message.getExtension(optionalForeignMessageExtension     ).getC());
+    assertEqualsExactType(120, message.getExtension(optionalImportMessageExtension      ).getD());
+    assertEqualsExactType(126, message.getExtension(optionalPublicImportMessageExtension).getE());
+    assertEqualsExactType(127, message.getExtension(optionalLazyMessageExtension        ).getBb());
 
     assertEqualsExactType(TestAllTypes.NestedEnum.BAZ,
       message.getExtension(optionalNestedEnumExtension));
@@ -1446,6 +1499,7 @@
     Assert.assertEquals(2, message.getExtensionCount(repeatedNestedMessageExtension ));
     Assert.assertEquals(2, message.getExtensionCount(repeatedForeignMessageExtension));
     Assert.assertEquals(2, message.getExtensionCount(repeatedImportMessageExtension ));
+    Assert.assertEquals(2, message.getExtensionCount(repeatedLazyMessageExtension   ));
     Assert.assertEquals(2, message.getExtensionCount(repeatedNestedEnumExtension    ));
     Assert.assertEquals(2, message.getExtensionCount(repeatedForeignEnumExtension   ));
     Assert.assertEquals(2, message.getExtensionCount(repeatedImportEnumExtension    ));
@@ -1473,6 +1527,7 @@
     assertEqualsExactType(218, message.getExtension(repeatedNestedMessageExtension , 0).getBb());
     assertEqualsExactType(219, message.getExtension(repeatedForeignMessageExtension, 0).getC());
     assertEqualsExactType(220, message.getExtension(repeatedImportMessageExtension , 0).getD());
+    assertEqualsExactType(227, message.getExtension(repeatedLazyMessageExtension   , 0).getBb());
 
     assertEqualsExactType(TestAllTypes.NestedEnum.BAR,
       message.getExtension(repeatedNestedEnumExtension, 0));
@@ -1504,6 +1559,7 @@
     assertEqualsExactType(318, message.getExtension(repeatedNestedMessageExtension , 1).getBb());
     assertEqualsExactType(319, message.getExtension(repeatedForeignMessageExtension, 1).getC());
     assertEqualsExactType(320, message.getExtension(repeatedImportMessageExtension , 1).getD());
+    assertEqualsExactType(327, message.getExtension(repeatedLazyMessageExtension   , 1).getBb());
 
     assertEqualsExactType(TestAllTypes.NestedEnum.BAZ,
       message.getExtension(repeatedNestedEnumExtension, 1));
@@ -1664,6 +1720,7 @@
     Assert.assertEquals(0, message.getExtensionCount(repeatedNestedMessageExtension ));
     Assert.assertEquals(0, message.getExtensionCount(repeatedForeignMessageExtension));
     Assert.assertEquals(0, message.getExtensionCount(repeatedImportMessageExtension ));
+    Assert.assertEquals(0, message.getExtensionCount(repeatedLazyMessageExtension   ));
     Assert.assertEquals(0, message.getExtensionCount(repeatedNestedEnumExtension    ));
     Assert.assertEquals(0, message.getExtensionCount(repeatedForeignEnumExtension   ));
     Assert.assertEquals(0, message.getExtensionCount(repeatedImportEnumExtension    ));
@@ -1692,6 +1749,7 @@
     Assert.assertEquals(0, message.getExtension(repeatedNestedMessageExtension ).size());
     Assert.assertEquals(0, message.getExtension(repeatedForeignMessageExtension).size());
     Assert.assertEquals(0, message.getExtension(repeatedImportMessageExtension ).size());
+    Assert.assertEquals(0, message.getExtension(repeatedLazyMessageExtension   ).size());
     Assert.assertEquals(0, message.getExtension(repeatedNestedEnumExtension    ).size());
     Assert.assertEquals(0, message.getExtension(repeatedForeignEnumExtension   ).size());
     Assert.assertEquals(0, message.getExtension(repeatedImportEnumExtension    ).size());
@@ -1783,6 +1841,7 @@
     Assert.assertEquals(2, message.getExtensionCount(repeatedNestedMessageExtension ));
     Assert.assertEquals(2, message.getExtensionCount(repeatedForeignMessageExtension));
     Assert.assertEquals(2, message.getExtensionCount(repeatedImportMessageExtension ));
+    Assert.assertEquals(2, message.getExtensionCount(repeatedLazyMessageExtension   ));
     Assert.assertEquals(2, message.getExtensionCount(repeatedNestedEnumExtension    ));
     Assert.assertEquals(2, message.getExtensionCount(repeatedForeignEnumExtension   ));
     Assert.assertEquals(2, message.getExtensionCount(repeatedImportEnumExtension    ));
@@ -1810,6 +1869,7 @@
     assertEqualsExactType(218, message.getExtension(repeatedNestedMessageExtension , 0).getBb());
     assertEqualsExactType(219, message.getExtension(repeatedForeignMessageExtension, 0).getC());
     assertEqualsExactType(220, message.getExtension(repeatedImportMessageExtension , 0).getD());
+    assertEqualsExactType(227, message.getExtension(repeatedLazyMessageExtension   , 0).getBb());
 
     assertEqualsExactType(TestAllTypes.NestedEnum.BAR,
       message.getExtension(repeatedNestedEnumExtension, 0));
@@ -1842,6 +1902,7 @@
     assertEqualsExactType(518, message.getExtension(repeatedNestedMessageExtension , 1).getBb());
     assertEqualsExactType(519, message.getExtension(repeatedForeignMessageExtension, 1).getC());
     assertEqualsExactType(520, message.getExtension(repeatedImportMessageExtension , 1).getD());
+    assertEqualsExactType(527, message.getExtension(repeatedLazyMessageExtension   , 1).getBb());
 
     assertEqualsExactType(TestAllTypes.NestedEnum.FOO,
       message.getExtension(repeatedNestedEnumExtension, 1));
@@ -1965,6 +2026,10 @@
       ForeignMessageLite.newBuilder().setC(119).build());
     message.setExtension(optionalImportMessageExtensionLite,
       ImportMessageLite.newBuilder().setD(120).build());
+    message.setExtension(optionalPublicImportMessageExtensionLite,
+      PublicImportMessageLite.newBuilder().setE(126).build());
+    message.setExtension(optionalLazyMessageExtensionLite,
+      TestAllTypesLite.NestedMessage.newBuilder().setBb(127).build());
 
     message.setExtension(optionalNestedEnumExtensionLite, TestAllTypesLite.NestedEnum.BAZ);
     message.setExtension(optionalForeignEnumExtensionLite, ForeignEnumLite.FOREIGN_LITE_BAZ);
@@ -1999,6 +2064,8 @@
       ForeignMessageLite.newBuilder().setC(219).build());
     message.addExtension(repeatedImportMessageExtensionLite,
       ImportMessageLite.newBuilder().setD(220).build());
+    message.addExtension(repeatedLazyMessageExtensionLite,
+      TestAllTypesLite.NestedMessage.newBuilder().setBb(227).build());
 
     message.addExtension(repeatedNestedEnumExtensionLite, TestAllTypesLite.NestedEnum.BAR);
     message.addExtension(repeatedForeignEnumExtensionLite, ForeignEnumLite.FOREIGN_LITE_BAR);
@@ -2032,6 +2099,8 @@
       ForeignMessageLite.newBuilder().setC(319).build());
     message.addExtension(repeatedImportMessageExtensionLite,
       ImportMessageLite.newBuilder().setD(320).build());
+    message.addExtension(repeatedLazyMessageExtensionLite,
+      TestAllTypesLite.NestedMessage.newBuilder().setBb(327).build());
 
     message.addExtension(repeatedNestedEnumExtensionLite, TestAllTypesLite.NestedEnum.BAZ);
     message.addExtension(repeatedForeignEnumExtensionLite, ForeignEnumLite.FOREIGN_LITE_BAZ);
@@ -2098,6 +2167,8 @@
       ForeignMessageLite.newBuilder().setC(519).build());
     message.setExtension(repeatedImportMessageExtensionLite, 1,
       ImportMessageLite.newBuilder().setD(520).build());
+    message.setExtension(repeatedLazyMessageExtensionLite, 1,
+      TestAllTypesLite.NestedMessage.newBuilder().setBb(527).build());
 
     message.setExtension(repeatedNestedEnumExtensionLite , 1, TestAllTypesLite.NestedEnum.FOO);
     message.setExtension(repeatedForeignEnumExtensionLite, 1, ForeignEnumLite.FOREIGN_LITE_FOO);
@@ -2168,6 +2239,9 @@
     assertEqualsExactType(118, message.getExtension(optionalNestedMessageExtensionLite ).getBb());
     assertEqualsExactType(119, message.getExtension(optionalForeignMessageExtensionLite).getC());
     assertEqualsExactType(120, message.getExtension(optionalImportMessageExtensionLite ).getD());
+    assertEqualsExactType(126, message.getExtension(
+        optionalPublicImportMessageExtensionLite).getE());
+    assertEqualsExactType(127, message.getExtension(optionalLazyMessageExtensionLite).getBb());
 
     assertEqualsExactType(TestAllTypesLite.NestedEnum.BAZ,
       message.getExtension(optionalNestedEnumExtensionLite));
@@ -2201,6 +2275,7 @@
     Assert.assertEquals(2, message.getExtensionCount(repeatedNestedMessageExtensionLite ));
     Assert.assertEquals(2, message.getExtensionCount(repeatedForeignMessageExtensionLite));
     Assert.assertEquals(2, message.getExtensionCount(repeatedImportMessageExtensionLite ));
+    Assert.assertEquals(2, message.getExtensionCount(repeatedLazyMessageExtensionLite   ));
     Assert.assertEquals(2, message.getExtensionCount(repeatedNestedEnumExtensionLite    ));
     Assert.assertEquals(2, message.getExtensionCount(repeatedForeignEnumExtensionLite   ));
     Assert.assertEquals(2, message.getExtensionCount(repeatedImportEnumExtensionLite    ));
@@ -2228,6 +2303,7 @@
     assertEqualsExactType(218, message.getExtension(repeatedNestedMessageExtensionLite ,0).getBb());
     assertEqualsExactType(219, message.getExtension(repeatedForeignMessageExtensionLite,0).getC());
     assertEqualsExactType(220, message.getExtension(repeatedImportMessageExtensionLite ,0).getD());
+    assertEqualsExactType(227, message.getExtension(repeatedLazyMessageExtensionLite   ,0).getBb());
 
     assertEqualsExactType(TestAllTypesLite.NestedEnum.BAR,
       message.getExtension(repeatedNestedEnumExtensionLite, 0));
@@ -2259,6 +2335,7 @@
     assertEqualsExactType(318, message.getExtension(repeatedNestedMessageExtensionLite ,1).getBb());
     assertEqualsExactType(319, message.getExtension(repeatedForeignMessageExtensionLite,1).getC());
     assertEqualsExactType(320, message.getExtension(repeatedImportMessageExtensionLite ,1).getD());
+    assertEqualsExactType(327, message.getExtension(repeatedLazyMessageExtensionLite   ,1).getBb());
 
     assertEqualsExactType(TestAllTypesLite.NestedEnum.BAZ,
       message.getExtension(repeatedNestedEnumExtensionLite, 1));
@@ -2348,10 +2425,12 @@
     Assert.assertFalse(message.hasExtension(optionalStringExtensionLite  ));
     Assert.assertFalse(message.hasExtension(optionalBytesExtensionLite   ));
 
-    Assert.assertFalse(message.hasExtension(optionalGroupExtensionLite         ));
-    Assert.assertFalse(message.hasExtension(optionalNestedMessageExtensionLite ));
-    Assert.assertFalse(message.hasExtension(optionalForeignMessageExtensionLite));
-    Assert.assertFalse(message.hasExtension(optionalImportMessageExtensionLite ));
+    Assert.assertFalse(message.hasExtension(optionalGroupExtensionLite              ));
+    Assert.assertFalse(message.hasExtension(optionalNestedMessageExtensionLite      ));
+    Assert.assertFalse(message.hasExtension(optionalForeignMessageExtensionLite     ));
+    Assert.assertFalse(message.hasExtension(optionalImportMessageExtensionLite      ));
+    Assert.assertFalse(message.hasExtension(optionalPublicImportMessageExtensionLite));
+    Assert.assertFalse(message.hasExtension(optionalLazyMessageExtensionLite        ));
 
     Assert.assertFalse(message.hasExtension(optionalNestedEnumExtensionLite ));
     Assert.assertFalse(message.hasExtension(optionalForeignEnumExtensionLite));
@@ -2378,15 +2457,20 @@
     assertEqualsExactType(ByteString.EMPTY, message.getExtension(optionalBytesExtensionLite));
 
     // Embedded messages should also be clear.
-    Assert.assertFalse(message.getExtension(optionalGroupExtensionLite         ).hasA());
-    Assert.assertFalse(message.getExtension(optionalNestedMessageExtensionLite ).hasBb());
-    Assert.assertFalse(message.getExtension(optionalForeignMessageExtensionLite).hasC());
-    Assert.assertFalse(message.getExtension(optionalImportMessageExtensionLite ).hasD());
+    Assert.assertFalse(message.getExtension(optionalGroupExtensionLite              ).hasA());
+    Assert.assertFalse(message.getExtension(optionalNestedMessageExtensionLite      ).hasBb());
+    Assert.assertFalse(message.getExtension(optionalForeignMessageExtensionLite     ).hasC());
+    Assert.assertFalse(message.getExtension(optionalImportMessageExtensionLite      ).hasD());
+    Assert.assertFalse(message.getExtension(optionalPublicImportMessageExtensionLite).hasE());
+    Assert.assertFalse(message.getExtension(optionalLazyMessageExtensionLite        ).hasBb());
 
     assertEqualsExactType(0, message.getExtension(optionalGroupExtensionLite         ).getA());
     assertEqualsExactType(0, message.getExtension(optionalNestedMessageExtensionLite ).getBb());
     assertEqualsExactType(0, message.getExtension(optionalForeignMessageExtensionLite).getC());
     assertEqualsExactType(0, message.getExtension(optionalImportMessageExtensionLite ).getD());
+    assertEqualsExactType(0, message.getExtension(
+        optionalPublicImportMessageExtensionLite).getE());
+    assertEqualsExactType(0, message.getExtension(optionalLazyMessageExtensionLite   ).getBb());
 
     // Enums without defaults are set to the first value in the enum.
     assertEqualsExactType(TestAllTypesLite.NestedEnum.FOO,
@@ -2420,6 +2504,7 @@
     Assert.assertEquals(0, message.getExtensionCount(repeatedNestedMessageExtensionLite ));
     Assert.assertEquals(0, message.getExtensionCount(repeatedForeignMessageExtensionLite));
     Assert.assertEquals(0, message.getExtensionCount(repeatedImportMessageExtensionLite ));
+    Assert.assertEquals(0, message.getExtensionCount(repeatedLazyMessageExtensionLite   ));
     Assert.assertEquals(0, message.getExtensionCount(repeatedNestedEnumExtensionLite    ));
     Assert.assertEquals(0, message.getExtensionCount(repeatedForeignEnumExtensionLite   ));
     Assert.assertEquals(0, message.getExtensionCount(repeatedImportEnumExtensionLite    ));
@@ -2511,6 +2596,7 @@
     Assert.assertEquals(2, message.getExtensionCount(repeatedNestedMessageExtensionLite ));
     Assert.assertEquals(2, message.getExtensionCount(repeatedForeignMessageExtensionLite));
     Assert.assertEquals(2, message.getExtensionCount(repeatedImportMessageExtensionLite ));
+    Assert.assertEquals(2, message.getExtensionCount(repeatedLazyMessageExtensionLite   ));
     Assert.assertEquals(2, message.getExtensionCount(repeatedNestedEnumExtensionLite    ));
     Assert.assertEquals(2, message.getExtensionCount(repeatedForeignEnumExtensionLite   ));
     Assert.assertEquals(2, message.getExtensionCount(repeatedImportEnumExtensionLite    ));
@@ -2538,6 +2624,7 @@
     assertEqualsExactType(218, message.getExtension(repeatedNestedMessageExtensionLite ,0).getBb());
     assertEqualsExactType(219, message.getExtension(repeatedForeignMessageExtensionLite,0).getC());
     assertEqualsExactType(220, message.getExtension(repeatedImportMessageExtensionLite ,0).getD());
+    assertEqualsExactType(227, message.getExtension(repeatedLazyMessageExtensionLite   ,0).getBb());
 
     assertEqualsExactType(TestAllTypesLite.NestedEnum.BAR,
       message.getExtension(repeatedNestedEnumExtensionLite, 0));
@@ -2570,6 +2657,7 @@
     assertEqualsExactType(518, message.getExtension(repeatedNestedMessageExtensionLite ,1).getBb());
     assertEqualsExactType(519, message.getExtension(repeatedForeignMessageExtensionLite,1).getC());
     assertEqualsExactType(520, message.getExtension(repeatedImportMessageExtensionLite ,1).getD());
+    assertEqualsExactType(527, message.getExtension(repeatedLazyMessageExtensionLite   ,1).getBb());
 
     assertEqualsExactType(TestAllTypesLite.NestedEnum.FOO,
       message.getExtension(repeatedNestedEnumExtensionLite, 1));
@@ -2674,18 +2762,21 @@
 
     private final Descriptors.FileDescriptor file;
     private final Descriptors.FileDescriptor importFile;
+    private final Descriptors.FileDescriptor publicImportFile;
 
     private final Descriptors.Descriptor optionalGroup;
     private final Descriptors.Descriptor repeatedGroup;
     private final Descriptors.Descriptor nestedMessage;
     private final Descriptors.Descriptor foreignMessage;
     private final Descriptors.Descriptor importMessage;
+    private final Descriptors.Descriptor publicImportMessage;
 
     private final Descriptors.FieldDescriptor groupA;
     private final Descriptors.FieldDescriptor repeatedGroupA;
     private final Descriptors.FieldDescriptor nestedB;
     private final Descriptors.FieldDescriptor foreignC;
     private final Descriptors.FieldDescriptor importD;
+    private final Descriptors.FieldDescriptor importE;
 
     private final Descriptors.EnumDescriptor nestedEnum;
     private final Descriptors.EnumDescriptor foreignEnum;
@@ -2722,6 +2813,7 @@
       this.file = baseDescriptor.getFile();
       Assert.assertEquals(1, file.getDependencies().size());
       this.importFile = file.getDependencies().get(0);
+      this.publicImportFile = importFile.getDependencies().get(0);
 
       Descriptors.Descriptor testAllTypes;
       if (baseDescriptor.getName() == "TestAllTypes") {
@@ -2748,6 +2840,8 @@
       this.nestedMessage = testAllTypes.findNestedTypeByName("NestedMessage");
       this.foreignMessage = file.findMessageTypeByName("ForeignMessage");
       this.importMessage = importFile.findMessageTypeByName("ImportMessage");
+      this.publicImportMessage = publicImportFile.findMessageTypeByName(
+          "PublicImportMessage");
 
       this.nestedEnum = testAllTypes.findEnumTypeByName("NestedEnum");
       this.foreignEnum = file.findEnumTypeByName("ForeignEnum");
@@ -2765,6 +2859,7 @@
       this.nestedB  = nestedMessage .findFieldByName("bb");
       this.foreignC = foreignMessage.findFieldByName("c");
       this.importD  = importMessage .findFieldByName("d");
+      this.importE  = publicImportMessage.findFieldByName("e");
       this.nestedFoo = nestedEnum.findValueByName("FOO");
       this.nestedBar = nestedEnum.findValueByName("BAR");
       this.nestedBaz = nestedEnum.findValueByName("BAZ");
@@ -2783,6 +2878,7 @@
       Assert.assertNotNull(nestedB       );
       Assert.assertNotNull(foreignC      );
       Assert.assertNotNull(importD       );
+      Assert.assertNotNull(importE       );
       Assert.assertNotNull(nestedFoo     );
       Assert.assertNotNull(nestedBar     );
       Assert.assertNotNull(nestedBaz     );
@@ -2863,6 +2959,12 @@
       message.setField(f("optional_import_message"),
         newBuilderForField(message, f("optional_import_message"))
                .setField(importD, 120).build());
+      message.setField(f("optional_public_import_message"),
+        newBuilderForField(message, f("optional_public_import_message"))
+               .setField(importE, 126).build());
+      message.setField(f("optional_lazy_message"),
+        newBuilderForField(message, f("optional_lazy_message"))
+               .setField(nestedB, 127).build());
 
       message.setField(f("optional_nested_enum" ),  nestedBaz);
       message.setField(f("optional_foreign_enum"), foreignBaz);
@@ -2901,6 +3003,9 @@
       message.addRepeatedField(f("repeated_import_message"),
         newBuilderForField(message, f("repeated_import_message"))
                .setField(importD, 220).build());
+      message.addRepeatedField(f("repeated_lazy_message"),
+        newBuilderForField(message, f("repeated_lazy_message"))
+               .setField(nestedB, 227).build());
 
       message.addRepeatedField(f("repeated_nested_enum" ),  nestedBar);
       message.addRepeatedField(f("repeated_foreign_enum"), foreignBar);
@@ -2938,6 +3043,9 @@
       message.addRepeatedField(f("repeated_import_message"),
         newBuilderForField(message, f("repeated_import_message"))
                .setField(importD, 320).build());
+      message.addRepeatedField(f("repeated_lazy_message"),
+        newBuilderForField(message, f("repeated_lazy_message"))
+               .setField(nestedB, 327).build());
 
       message.addRepeatedField(f("repeated_nested_enum" ),  nestedBaz);
       message.addRepeatedField(f("repeated_foreign_enum"), foreignBaz);
@@ -3008,6 +3116,9 @@
       message.setRepeatedField(f("repeated_import_message"), 1,
         newBuilderForField(message, f("repeated_import_message"))
                .setField(importD, 520).build());
+      message.setRepeatedField(f("repeated_lazy_message"), 1,
+        newBuilderForField(message, f("repeated_lazy_message"))
+               .setField(nestedB, 527).build());
 
       message.setRepeatedField(f("repeated_nested_enum" ), 1,  nestedFoo);
       message.setRepeatedField(f("repeated_foreign_enum"), 1, foreignFoo);
@@ -3092,6 +3203,12 @@
       Assert.assertEquals(120,
         ((Message)message.getField(f("optional_import_message")))
                          .getField(importD));
+      Assert.assertEquals(126,
+        ((Message)message.getField(f("optional_public_import_message")))
+                         .getField(importE));
+      Assert.assertEquals(127,
+        ((Message)message.getField(f("optional_lazy_message")))
+                         .getField(nestedB));
 
       Assert.assertEquals( nestedBaz, message.getField(f("optional_nested_enum" )));
       Assert.assertEquals(foreignBaz, message.getField(f("optional_foreign_enum")));
@@ -3122,6 +3239,7 @@
       Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_nested_message" )));
       Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_foreign_message")));
       Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_import_message" )));
+      Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_lazy_message" )));
       Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_nested_enum"    )));
       Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_foreign_enum"   )));
       Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_import_enum"    )));
@@ -3157,6 +3275,9 @@
       Assert.assertEquals(220,
         ((Message)message.getRepeatedField(f("repeated_import_message"), 0))
                          .getField(importD));
+      Assert.assertEquals(227,
+        ((Message)message.getRepeatedField(f("repeated_lazy_message"), 0))
+                         .getField(nestedB));
 
       Assert.assertEquals( nestedBar, message.getRepeatedField(f("repeated_nested_enum" ),0));
       Assert.assertEquals(foreignBar, message.getRepeatedField(f("repeated_foreign_enum"),0));
@@ -3193,6 +3314,9 @@
       Assert.assertEquals(320,
         ((Message)message.getRepeatedField(f("repeated_import_message"), 1))
                          .getField(importD));
+      Assert.assertEquals(327,
+        ((Message)message.getRepeatedField(f("repeated_lazy_message"), 1))
+                         .getField(nestedB));
 
       Assert.assertEquals( nestedBaz, message.getRepeatedField(f("repeated_nested_enum" ),1));
       Assert.assertEquals(foreignBaz, message.getRepeatedField(f("repeated_foreign_enum"),1));
@@ -3316,6 +3440,12 @@
       Assert.assertFalse(
         ((Message)message.getField(f("optional_import_message")))
                          .hasField(importD));
+      Assert.assertFalse(
+        ((Message)message.getField(f("optional_public_import_message")))
+                         .hasField(importE));
+      Assert.assertFalse(
+        ((Message)message.getField(f("optional_lazy_message")))
+                         .hasField(nestedB));
 
       Assert.assertEquals(0,
         ((Message)message.getField(f("optionalgroup"))).getField(groupA));
@@ -3328,6 +3458,12 @@
       Assert.assertEquals(0,
         ((Message)message.getField(f("optional_import_message")))
                          .getField(importD));
+      Assert.assertEquals(0,
+        ((Message)message.getField(f("optional_public_import_message")))
+                         .getField(importE));
+      Assert.assertEquals(0,
+        ((Message)message.getField(f("optional_lazy_message")))
+                         .getField(nestedB));
 
       // Enums without defaults are set to the first value in the enum.
       Assert.assertEquals( nestedFoo, message.getField(f("optional_nested_enum" )));
@@ -3358,6 +3494,7 @@
       Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_nested_message" )));
       Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_foreign_message")));
       Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_import_message" )));
+      Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_lazy_message"   )));
       Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_nested_enum"    )));
       Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_foreign_enum"   )));
       Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_import_enum"    )));
@@ -3442,6 +3579,7 @@
       Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_nested_message" )));
       Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_foreign_message")));
       Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_import_message" )));
+      Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_lazy_message"   )));
       Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_nested_enum"    )));
       Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_foreign_enum"   )));
       Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_import_enum"    )));
@@ -3477,6 +3615,9 @@
       Assert.assertEquals(220,
         ((Message)message.getRepeatedField(f("repeated_import_message"), 0))
                          .getField(importD));
+      Assert.assertEquals(227,
+        ((Message)message.getRepeatedField(f("repeated_lazy_message"), 0))
+                         .getField(nestedB));
 
       Assert.assertEquals( nestedBar, message.getRepeatedField(f("repeated_nested_enum" ),0));
       Assert.assertEquals(foreignBar, message.getRepeatedField(f("repeated_foreign_enum"),0));
@@ -3513,6 +3654,9 @@
       Assert.assertEquals(520,
         ((Message)message.getRepeatedField(f("repeated_import_message"), 1))
                          .getField(importD));
+      Assert.assertEquals(527,
+        ((Message)message.getRepeatedField(f("repeated_lazy_message"), 1))
+                         .getField(nestedB));
 
       Assert.assertEquals( nestedFoo, message.getRepeatedField(f("repeated_nested_enum" ),1));
       Assert.assertEquals(foreignFoo, message.getRepeatedField(f("repeated_foreign_enum"),1));
diff --git a/third_party/protobuf/java/src/test/java/com/google/protobuf/TextFormatTest.java b/third_party/protobuf/java/src/test/java/com/google/protobuf/TextFormatTest.java
index 47690d1..5323d70 100644
--- a/third_party/protobuf/java/src/test/java/com/google/protobuf/TextFormatTest.java
+++ b/third_party/protobuf/java/src/test/java/com/google/protobuf/TextFormatTest.java
@@ -121,6 +121,18 @@
     assertEquals(allFieldsSetText, javaText);
   }
 
+  /** Print TestAllTypes as Builder and compare with golden file. */
+  public void testPrintMessageBuilder() throws Exception {
+    String javaText = TextFormat.printToString(TestUtil.getAllSetBuilder());
+
+    // Java likes to add a trailing ".0" to floats and doubles.  C printf
+    // (with %g format) does not.  Our golden files are used for both
+    // C++ and Java TextFormat classes, so we need to conform.
+    javaText = javaText.replace(".0\n", "\n");
+
+    assertEquals(allFieldsSetText, javaText);
+  }
+
   /** Print TestAllExtensions and compare with golden file. */
   public void testPrintExtensions() throws Exception {
     String javaText = TextFormat.printToString(TestUtil.getAllExtensionsSet());
@@ -749,4 +761,26 @@
         + " 0xabcdef1234567890",
         TextFormat.shortDebugString(makeUnknownFieldSet()));
   }
+
+  public void testPrintToUnicodeString() {
+    assertEquals(
+        "optional_string: \"abc\u3042efg\"\n" +
+        "optional_bytes: \"\\343\\201\\202\"\n" +
+        "repeated_string: \"\u3093XYZ\"\n",
+        TextFormat.printToUnicodeString(TestAllTypes.newBuilder()
+            .setOptionalString("abc\u3042efg")
+            .setOptionalBytes(bytes(0xe3, 0x81, 0x82))
+            .addRepeatedString("\u3093XYZ")
+            .build()));
+  }
+
+  public void testPrintToUnicodeString_unknown() {
+    assertEquals(
+        "1: \"\\343\\201\\202\"\n",
+        TextFormat.printToUnicodeString(UnknownFieldSet.newBuilder()
+            .addField(1,
+                UnknownFieldSet.Field.newBuilder()
+                .addLengthDelimited(bytes(0xe3, 0x81, 0x82)).build())
+            .build()));
+  }
 }
diff --git a/third_party/protobuf/java/src/test/java/com/google/protobuf/WireFormatTest.java b/third_party/protobuf/java/src/test/java/com/google/protobuf/WireFormatTest.java
index 5ea1dd6..94f6213 100644
--- a/third_party/protobuf/java/src/test/java/com/google/protobuf/WireFormatTest.java
+++ b/third_party/protobuf/java/src/test/java/com/google/protobuf/WireFormatTest.java
@@ -34,6 +34,7 @@
 
 import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
+import java.util.List;
 
 import protobuf_unittest.UnittestProto;
 import protobuf_unittest.UnittestProto.TestAllExtensions;
@@ -328,7 +329,17 @@
   private static final int TYPE_ID_2 =
     TestMessageSetExtension2.getDescriptor().getExtensions().get(0).getNumber();
 
-  public void testSerializeMessageSet() throws Exception {
+  public void testSerializeMessageSetEagerly() throws Exception {
+    testSerializeMessageSetWithFlag(true);
+  }
+
+  public void testSerializeMessageSetNotEagerly() throws Exception {
+    testSerializeMessageSetWithFlag(false);
+  }
+
+  private void testSerializeMessageSetWithFlag(boolean eagerParsing)
+      throws Exception {
+    ExtensionRegistryLite.setEagerlyParseMessageSets(eagerParsing);
     // Set up a TestMessageSet with two known messages and an unknown one.
     TestMessageSet messageSet =
       TestMessageSet.newBuilder()
@@ -372,7 +383,17 @@
     assertEquals("bar", raw.getItem(2).getMessage().toStringUtf8());
   }
 
-  public void testParseMessageSet() throws Exception {
+  public void testParseMessageSetEagerly() throws Exception {
+    testParseMessageSetWithFlag(true);
+  }
+
+  public void testParseMessageSetNotEagerly()throws Exception {
+    testParseMessageSetWithFlag(false);
+  }
+
+  private void testParseMessageSetWithFlag(boolean eagerParsing)
+      throws Exception {
+    ExtensionRegistryLite.setEagerlyParseMessageSets(eagerParsing);
     ExtensionRegistry extensionRegistry = ExtensionRegistry.newInstance();
     extensionRegistry.add(TestMessageSetExtension1.messageSetExtension);
     extensionRegistry.add(TestMessageSetExtension2.messageSetExtension);
@@ -424,4 +445,136 @@
     assertEquals(1, field.getLengthDelimitedList().size());
     assertEquals("bar", field.getLengthDelimitedList().get(0).toStringUtf8());
   }
+
+  public void testParseMessageSetExtensionEagerly() throws Exception {
+    testParseMessageSetExtensionWithFlag(true);
+  }
+
+  public void testParseMessageSetExtensionNotEagerly() throws Exception {
+    testParseMessageSetExtensionWithFlag(false);
+  }
+
+  private void testParseMessageSetExtensionWithFlag(boolean eagerParsing)
+      throws Exception {
+    ExtensionRegistryLite.setEagerlyParseMessageSets(eagerParsing);
+    ExtensionRegistry extensionRegistry = ExtensionRegistry.newInstance();
+    extensionRegistry.add(TestMessageSetExtension1.messageSetExtension);
+
+    // Set up a RawMessageSet with a known messages.
+    int TYPE_ID_1 =
+        TestMessageSetExtension1
+            .getDescriptor().getExtensions().get(0).getNumber();
+    RawMessageSet raw =
+      RawMessageSet.newBuilder()
+        .addItem(
+          RawMessageSet.Item.newBuilder()
+            .setTypeId(TYPE_ID_1)
+            .setMessage(
+              TestMessageSetExtension1.newBuilder()
+                .setI(123)
+                .build().toByteString())
+            .build())
+        .build();
+
+    ByteString data = raw.toByteString();
+
+    // Parse as a TestMessageSet and check the contents.
+    TestMessageSet messageSet =
+        TestMessageSet.parseFrom(data, extensionRegistry);
+    assertEquals(123, messageSet.getExtension(
+        TestMessageSetExtension1.messageSetExtension).getI());
+  }
+
+  public void testMergeLazyMessageSetExtensionEagerly() throws Exception {
+    testMergeLazyMessageSetExtensionWithFlag(true);
+  }
+
+  public void testMergeLazyMessageSetExtensionNotEagerly() throws Exception {
+    testMergeLazyMessageSetExtensionWithFlag(false);
+  }
+
+  private void testMergeLazyMessageSetExtensionWithFlag(boolean eagerParsing)
+      throws Exception {
+    ExtensionRegistryLite.setEagerlyParseMessageSets(eagerParsing);
+    ExtensionRegistry extensionRegistry = ExtensionRegistry.newInstance();
+    extensionRegistry.add(TestMessageSetExtension1.messageSetExtension);
+
+    // Set up a RawMessageSet with a known messages.
+    int TYPE_ID_1 =
+        TestMessageSetExtension1
+            .getDescriptor().getExtensions().get(0).getNumber();
+    RawMessageSet raw =
+      RawMessageSet.newBuilder()
+        .addItem(
+          RawMessageSet.Item.newBuilder()
+            .setTypeId(TYPE_ID_1)
+            .setMessage(
+              TestMessageSetExtension1.newBuilder()
+                .setI(123)
+                .build().toByteString())
+            .build())
+        .build();
+
+    ByteString data = raw.toByteString();
+
+    // Parse as a TestMessageSet and store value into lazy field
+    TestMessageSet messageSet =
+        TestMessageSet.parseFrom(data, extensionRegistry);
+    // Merge lazy field check the contents.
+    messageSet =
+        messageSet.toBuilder().mergeFrom(data, extensionRegistry).build();
+    assertEquals(123, messageSet.getExtension(
+        TestMessageSetExtension1.messageSetExtension).getI());
+  }
+
+  public void testMergeMessageSetExtensionEagerly() throws Exception {
+    testMergeMessageSetExtensionWithFlag(true);
+  }
+
+  public void testMergeMessageSetExtensionNotEagerly() throws Exception {
+    testMergeMessageSetExtensionWithFlag(false);
+  }
+
+  private void testMergeMessageSetExtensionWithFlag(boolean eagerParsing)
+      throws Exception {
+    ExtensionRegistryLite.setEagerlyParseMessageSets(eagerParsing);
+    ExtensionRegistry extensionRegistry = ExtensionRegistry.newInstance();
+    extensionRegistry.add(TestMessageSetExtension1.messageSetExtension);
+
+    // Set up a RawMessageSet with a known messages.
+    int TYPE_ID_1 =
+        TestMessageSetExtension1
+            .getDescriptor().getExtensions().get(0).getNumber();
+    RawMessageSet raw =
+      RawMessageSet.newBuilder()
+        .addItem(
+          RawMessageSet.Item.newBuilder()
+            .setTypeId(TYPE_ID_1)
+            .setMessage(
+              TestMessageSetExtension1.newBuilder()
+                .setI(123)
+                .build().toByteString())
+            .build())
+        .build();
+
+    // Serialize RawMessageSet unnormally (message value before type id)
+    ByteString.CodedBuilder out = ByteString.newCodedBuilder(
+        raw.getSerializedSize());
+    CodedOutputStream output = out.getCodedOutput();
+    List<RawMessageSet.Item> items = raw.getItemList();
+    for (int i = 0; i < items.size(); i++) {
+      RawMessageSet.Item item = items.get(i);
+      output.writeTag(1, WireFormat.WIRETYPE_START_GROUP);
+      output.writeBytes(3, item.getMessage());
+      output.writeInt32(2, item.getTypeId());
+      output.writeTag(1, WireFormat.WIRETYPE_END_GROUP);
+    }
+    ByteString data = out.build();
+
+    // Merge bytes into TestMessageSet and check the contents.
+    TestMessageSet messageSet =
+        TestMessageSet.newBuilder().mergeFrom(data, extensionRegistry).build();
+    assertEquals(123, messageSet.getExtension(
+        TestMessageSetExtension1.messageSetExtension).getI());
+  }
 }
diff --git a/third_party/protobuf/java/src/test/java/com/google/protobuf/test_bad_identifiers.proto b/third_party/protobuf/java/src/test/java/com/google/protobuf/test_bad_identifiers.proto
index 9610e9d..6e67d97 100644
--- a/third_party/protobuf/java/src/test/java/com/google/protobuf/test_bad_identifiers.proto
+++ b/third_party/protobuf/java/src/test/java/com/google/protobuf/test_bad_identifiers.proto
@@ -46,6 +46,23 @@
 message TestMessage {
 }
 
+message Descriptor {
+  option no_standard_descriptor_accessor = true;
+  optional string descriptor = 1;
+  message NestedDescriptor {
+    option no_standard_descriptor_accessor = true;
+    optional string descriptor = 1;
+  }
+  optional NestedDescriptor nested_descriptor = 2;
+}
+
+message Parser {
+  enum ParserEnum {
+    PARSER = 1;
+  }
+  optional ParserEnum parser = 1;
+}
+
 message Deprecated {
   enum TestEnum {
     FOO = 1;
@@ -62,6 +79,7 @@
 
 message Object {
   optional int32 object = 1;
+  optional string string_object = 2;
 }
 
 message String {
diff --git a/third_party/protobuf/protobuf.gyp b/third_party/protobuf/protobuf.gyp
index df0f6e5..44bcdd6 100644
--- a/third_party/protobuf/protobuf.gyp
+++ b/third_party/protobuf/protobuf.gyp
@@ -22,6 +22,7 @@
               4244,  # implicit conversion, possible loss of data
               4355,  # 'this' used in base member initializer list
               4267,  # size_t to int truncation
+              4291,  # no matching operator delete for a placement new
             ],
             'defines!': [
               'WIN32_LEAN_AND_MEAN',  # Protobuf defines this itself.
@@ -161,6 +162,7 @@
             'src/google/protobuf/descriptor.pb.h',
             'src/google/protobuf/descriptor_database.h',
             'src/google/protobuf/dynamic_message.h',
+            'src/google/protobuf/generated_enum_reflection.h',
             'src/google/protobuf/generated_message_reflection.h',
             'src/google/protobuf/message.h',
             'src/google/protobuf/reflection_ops.h',
@@ -174,17 +176,27 @@
             'src/google/protobuf/compiler/code_generator.h',
             'src/google/protobuf/compiler/command_line_interface.h',
             'src/google/protobuf/compiler/importer.h',
+            'src/google/protobuf/compiler/java/java_doc_comment.cc',
+            'src/google/protobuf/compiler/java/java_doc_comment.h',
             'src/google/protobuf/compiler/parser.h',
 
             'src/google/protobuf/stubs/strutil.cc',
             'src/google/protobuf/stubs/strutil.h',
             'src/google/protobuf/stubs/substitute.cc',
             'src/google/protobuf/stubs/substitute.h',
+            'src/google/protobuf/stubs/stl_util.h',
+            'src/google/protobuf/stubs/stringprintf.cc',
+            'src/google/protobuf/stubs/stringprintf.h',
             'src/google/protobuf/stubs/structurally_valid.cc',
+            'src/google/protobuf/stubs/template_util.h',
+            'src/google/protobuf/stubs/type_traits.h',
+
             'src/google/protobuf/descriptor.cc',
             'src/google/protobuf/descriptor.pb.cc',
             'src/google/protobuf/descriptor_database.cc',
             'src/google/protobuf/dynamic_message.cc',
+            'src/google/protobuf/extension_set.cc',
+            'src/google/protobuf/extension_set.h',
             'src/google/protobuf/extension_set_heavy.cc',
             'src/google/protobuf/generated_message_reflection.cc',
             'src/google/protobuf/message.cc',
@@ -314,7 +326,10 @@
               'files': [
                 'python/google/protobuf/__init__.py',
                 'python/google/protobuf/descriptor.py',
+                'python/google/protobuf/descriptor_database.py',
+                'python/google/protobuf/descriptor_pool.py',
                 'python/google/protobuf/message.py',
+                'python/google/protobuf/message_factory.py',
                 'python/google/protobuf/reflection.py',
                 'python/google/protobuf/service.py',
                 'python/google/protobuf/service_reflection.py',
@@ -340,6 +355,7 @@
                 'python/google/protobuf/internal/cpp_message.py',
                 'python/google/protobuf/internal/decoder.py',
                 'python/google/protobuf/internal/encoder.py',
+                'python/google/protobuf/internal/enum_type_wrapper.py',
                 'python/google/protobuf/internal/generator_test.py',
                 'python/google/protobuf/internal/message_listener.py',
                 'python/google/protobuf/internal/python_message.py',
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 f29686a..bed5990 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
@@ -24,13 +24,16 @@
 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 \
@@ -48,7 +51,6 @@
 	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 \
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 1ef7fc0..6614ab9 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
@@ -24,13 +24,16 @@
 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 \
@@ -48,7 +51,6 @@
 	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 \
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 c542ad0..9285232 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
@@ -24,13 +24,16 @@
 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 \
@@ -48,7 +51,6 @@
 	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 \
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 4fa32d2..0f0b8b4 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
@@ -24,13 +24,16 @@
 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 \
@@ -48,7 +51,6 @@
 	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 \
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 c8047bb..dcc523d 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
@@ -24,13 +24,16 @@
 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 \
@@ -48,7 +51,6 @@
 	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 \
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 1562026..6edfc29 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
@@ -24,13 +24,16 @@
 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 \
@@ -48,7 +51,6 @@
 	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 \
diff --git a/third_party/protobuf/python/google/protobuf/descriptor.py b/third_party/protobuf/python/google/protobuf/descriptor.py
index cf609be..eb13eda 100755
--- a/third_party/protobuf/python/google/protobuf/descriptor.py
+++ b/third_party/protobuf/python/google/protobuf/descriptor.py
@@ -39,13 +39,20 @@
 
 
 if api_implementation.Type() == 'cpp':
-  from google.protobuf.internal import cpp_message
+  if api_implementation.Version() == 2:
+    from google.protobuf.internal.cpp import _message
+  else:
+    from google.protobuf.internal import cpp_message
 
 
 class Error(Exception):
   """Base error for this module."""
 
 
+class TypeTransformationError(Error):
+  """Error transforming between python proto type and corresponding C++ type."""
+
+
 class DescriptorBase(object):
 
   """Descriptors base class.
@@ -72,6 +79,18 @@
     # Does this descriptor have non-default options?
     self.has_options = options is not None
 
+  def _SetOptions(self, options, options_class_name):
+    """Sets the descriptor's options
+
+    This function is used in generated proto2 files to update descriptor
+    options. It must not be used outside proto2.
+    """
+    self._options = options
+    self._options_class_name = options_class_name
+
+    # Does this descriptor have non-default options?
+    self.has_options = options is not None
+
   def GetOptions(self):
     """Retrieves descriptor options.
 
@@ -250,6 +269,24 @@
     self._serialized_start = serialized_start
     self._serialized_end = serialized_end
 
+  def EnumValueName(self, enum, value):
+    """Returns the string name of an enum value.
+
+    This is just a small helper method to simplify a common operation.
+
+    Args:
+      enum: string name of the Enum.
+      value: int, value of the enum.
+
+    Returns:
+      string name of the enum value.
+
+    Raises:
+      KeyError if either the Enum doesn't exist or the value is not a valid
+        value for the enum.
+    """
+    return self.enum_types_by_name[enum].values_by_number[value].name
+
   def CopyToProto(self, proto):
     """Copies this to a descriptor_pb2.DescriptorProto.
 
@@ -275,7 +312,7 @@
 
   """Descriptor for a single field in a .proto file.
 
-  A FieldDescriptor instance has the following attriubtes:
+  A FieldDescriptor instance has the following attributes:
 
     name: (str) Name of this field, exactly as it appears in .proto.
     full_name: (str) Name of this field, including containing scope.  This is
@@ -358,6 +395,27 @@
   CPPTYPE_MESSAGE     = 10
   MAX_CPPTYPE         = 10
 
+  _PYTHON_TO_CPP_PROTO_TYPE_MAP = {
+      TYPE_DOUBLE: CPPTYPE_DOUBLE,
+      TYPE_FLOAT: CPPTYPE_FLOAT,
+      TYPE_ENUM: CPPTYPE_ENUM,
+      TYPE_INT64: CPPTYPE_INT64,
+      TYPE_SINT64: CPPTYPE_INT64,
+      TYPE_SFIXED64: CPPTYPE_INT64,
+      TYPE_UINT64: CPPTYPE_UINT64,
+      TYPE_FIXED64: CPPTYPE_UINT64,
+      TYPE_INT32: CPPTYPE_INT32,
+      TYPE_SFIXED32: CPPTYPE_INT32,
+      TYPE_SINT32: CPPTYPE_INT32,
+      TYPE_UINT32: CPPTYPE_UINT32,
+      TYPE_FIXED32: CPPTYPE_UINT32,
+      TYPE_BYTES: CPPTYPE_STRING,
+      TYPE_STRING: CPPTYPE_STRING,
+      TYPE_BOOL: CPPTYPE_BOOL,
+      TYPE_MESSAGE: CPPTYPE_MESSAGE,
+      TYPE_GROUP: CPPTYPE_MESSAGE
+      }
+
   # Must be consistent with C++ FieldDescriptor::Label enum in
   # descriptor.h.
   #
@@ -395,12 +453,38 @@
     self.extension_scope = extension_scope
     if api_implementation.Type() == 'cpp':
       if is_extension:
-        self._cdescriptor = cpp_message.GetExtensionDescriptor(full_name)
+        if api_implementation.Version() == 2:
+          self._cdescriptor = _message.GetExtensionDescriptor(full_name)
+        else:
+          self._cdescriptor = cpp_message.GetExtensionDescriptor(full_name)
       else:
-        self._cdescriptor = cpp_message.GetFieldDescriptor(full_name)
+        if api_implementation.Version() == 2:
+          self._cdescriptor = _message.GetFieldDescriptor(full_name)
+        else:
+          self._cdescriptor = cpp_message.GetFieldDescriptor(full_name)
     else:
       self._cdescriptor = None
 
+  @staticmethod
+  def ProtoTypeToCppProtoType(proto_type):
+    """Converts from a Python proto type to a C++ Proto Type.
+
+    The Python ProtocolBuffer classes specify both the 'Python' datatype and the
+    'C++' datatype - and they're not the same. This helper method should
+    translate from one to another.
+
+    Args:
+      proto_type: the Python proto type (descriptor.FieldDescriptor.TYPE_*)
+    Returns:
+      descriptor.FieldDescriptor.CPPTYPE_*, the C++ type.
+    Raises:
+      TypeTransformationError: when the Python proto type isn't known.
+    """
+    try:
+      return FieldDescriptor._PYTHON_TO_CPP_PROTO_TYPE_MAP[proto_type]
+    except KeyError:
+      raise TypeTransformationError('Unknown proto_type: %s' % proto_type)
+
 
 class EnumDescriptor(_NestedDescriptorBase):
 
@@ -577,7 +661,10 @@
     self.serialized_pb = serialized_pb
     if (api_implementation.Type() == 'cpp' and
         self.serialized_pb is not None):
-      cpp_message.BuildFile(self.serialized_pb)
+      if api_implementation.Version() == 2:
+        _message.BuildFile(self.serialized_pb)
+      else:
+        cpp_message.BuildFile(self.serialized_pb)
 
   def CopyToProto(self, proto):
     """Copies this to a descriptor_pb2.FileDescriptorProto.
@@ -596,3 +683,31 @@
   """
   message.ParseFromString(string)
   return message
+
+
+def MakeDescriptor(desc_proto, package=''):
+  """Make a protobuf Descriptor given a DescriptorProto protobuf.
+
+  Args:
+    desc_proto: The descriptor_pb2.DescriptorProto protobuf message.
+    package: Optional package name for the new message Descriptor (string).
+
+  Returns:
+    A Descriptor for protobuf messages.
+  """
+  full_message_name = [desc_proto.name]
+  if package: full_message_name.insert(0, package)
+  fields = []
+  for field_proto in desc_proto.field:
+    full_name = '.'.join(full_message_name + [field_proto.name])
+    field = FieldDescriptor(
+        field_proto.name, full_name, field_proto.number - 1,
+        field_proto.number, field_proto.type,
+        FieldDescriptor.ProtoTypeToCppProtoType(field_proto.type),
+        field_proto.label, None, None, None, None, False, None,
+        has_default_value=False)
+    fields.append(field)
+
+  desc_name = '.'.join(full_message_name)
+  return Descriptor(desc_proto.name, desc_name, None, None, fields,
+                    [], [], [])
diff --git a/third_party/protobuf/python/google/protobuf/descriptor_database.py b/third_party/protobuf/python/google/protobuf/descriptor_database.py
new file mode 100644
index 0000000..8665d3c
--- /dev/null
+++ b/third_party/protobuf/python/google/protobuf/descriptor_database.py
@@ -0,0 +1,120 @@
+# Protocol Buffers - Google's data interchange format
+# Copyright 2008 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.
+
+"""Provides a container for DescriptorProtos."""
+
+__author__ = 'matthewtoia@google.com (Matt Toia)'
+
+
+class DescriptorDatabase(object):
+  """A container accepting FileDescriptorProtos and maps DescriptorProtos."""
+
+  def __init__(self):
+    self._file_desc_protos_by_file = {}
+    self._file_desc_protos_by_symbol = {}
+
+  def Add(self, file_desc_proto):
+    """Adds the FileDescriptorProto and its types to this database.
+
+    Args:
+      file_desc_proto: The FileDescriptorProto to add.
+    """
+
+    self._file_desc_protos_by_file[file_desc_proto.name] = file_desc_proto
+    package = file_desc_proto.package
+    for message in file_desc_proto.message_type:
+      self._file_desc_protos_by_symbol.update(
+          (name, file_desc_proto) for name in _ExtractSymbols(message, package))
+    for enum in file_desc_proto.enum_type:
+      self._file_desc_protos_by_symbol[
+          '.'.join((package, enum.name))] = file_desc_proto
+
+  def FindFileByName(self, name):
+    """Finds the file descriptor proto by file name.
+
+    Typically the file name is a relative path ending to a .proto file. The
+    proto with the given name will have to have been added to this database
+    using the Add method or else an error will be raised.
+
+    Args:
+      name: The file name to find.
+
+    Returns:
+      The file descriptor proto matching the name.
+
+    Raises:
+      KeyError if no file by the given name was added.
+    """
+
+    return self._file_desc_protos_by_file[name]
+
+  def FindFileContainingSymbol(self, symbol):
+    """Finds the file descriptor proto containing the specified symbol.
+
+    The symbol should be a fully qualified name including the file descriptor's
+    package and any containing messages. Some examples:
+
+    'some.package.name.Message'
+    'some.package.name.Message.NestedEnum'
+
+    The file descriptor proto containing the specified symbol must be added to
+    this database using the Add method or else an error will be raised.
+
+    Args:
+      symbol: The fully qualified symbol name.
+
+    Returns:
+      The file descriptor proto containing the symbol.
+
+    Raises:
+      KeyError if no file contains the specified symbol.
+    """
+
+    return self._file_desc_protos_by_symbol[symbol]
+
+
+def _ExtractSymbols(desc_proto, package):
+  """Pulls out all the symbols from a descriptor proto.
+
+  Args:
+    desc_proto: The proto to extract symbols from.
+    package: The package containing the descriptor type.
+
+  Yields:
+    The fully qualified name found in the descriptor.
+  """
+
+  message_name = '.'.join((package, desc_proto.name))
+  yield message_name
+  for nested_type in desc_proto.nested_type:
+    for symbol in _ExtractSymbols(nested_type, message_name):
+      yield symbol
+    for enum_type in desc_proto.enum_type:
+      yield '.'.join((message_name, enum_type.name))
diff --git a/third_party/protobuf/python/google/protobuf/descriptor_pool.py b/third_party/protobuf/python/google/protobuf/descriptor_pool.py
new file mode 100644
index 0000000..8f1f445
--- /dev/null
+++ b/third_party/protobuf/python/google/protobuf/descriptor_pool.py
@@ -0,0 +1,527 @@
+# Protocol Buffers - Google's data interchange format
+# Copyright 2008 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.
+
+"""Provides DescriptorPool to use as a container for proto2 descriptors.
+
+The DescriptorPool is used in conjection with a DescriptorDatabase to maintain
+a collection of protocol buffer descriptors for use when dynamically creating
+message types at runtime.
+
+For most applications protocol buffers should be used via modules generated by
+the protocol buffer compiler tool. This should only be used when the type of
+protocol buffers used in an application or library cannot be predetermined.
+
+Below is a straightforward example on how to use this class:
+
+  pool = DescriptorPool()
+  file_descriptor_protos = [ ... ]
+  for file_descriptor_proto in file_descriptor_protos:
+    pool.Add(file_descriptor_proto)
+  my_message_descriptor = pool.FindMessageTypeByName('some.package.MessageType')
+
+The message descriptor can be used in conjunction with the message_factory
+module in order to create a protocol buffer class that can be encoded and
+decoded.
+"""
+
+__author__ = 'matthewtoia@google.com (Matt Toia)'
+
+from google.protobuf import descriptor_pb2
+from google.protobuf import descriptor
+from google.protobuf import descriptor_database
+
+
+class DescriptorPool(object):
+  """A collection of protobufs dynamically constructed by descriptor protos."""
+
+  def __init__(self, descriptor_db=None):
+    """Initializes a Pool of proto buffs.
+
+    The descriptor_db argument to the constructor is provided to allow
+    specialized file descriptor proto lookup code to be triggered on demand. An
+    example would be an implementation which will read and compile a file
+    specified in a call to FindFileByName() and not require the call to Add()
+    at all. Results from this database will be cached internally here as well.
+
+    Args:
+      descriptor_db: A secondary source of file descriptors.
+    """
+
+    self._internal_db = descriptor_database.DescriptorDatabase()
+    self._descriptor_db = descriptor_db
+    self._descriptors = {}
+    self._enum_descriptors = {}
+    self._file_descriptors = {}
+
+  def Add(self, file_desc_proto):
+    """Adds the FileDescriptorProto and its types to this pool.
+
+    Args:
+      file_desc_proto: The FileDescriptorProto to add.
+    """
+
+    self._internal_db.Add(file_desc_proto)
+
+  def FindFileByName(self, file_name):
+    """Gets a FileDescriptor by file name.
+
+    Args:
+      file_name: The path to the file to get a descriptor for.
+
+    Returns:
+      A FileDescriptor for the named file.
+
+    Raises:
+      KeyError: if the file can not be found in the pool.
+    """
+
+    try:
+      file_proto = self._internal_db.FindFileByName(file_name)
+    except KeyError as error:
+      if self._descriptor_db:
+        file_proto = self._descriptor_db.FindFileByName(file_name)
+      else:
+        raise error
+    if not file_proto:
+      raise KeyError('Cannot find a file named %s' % file_name)
+    return self._ConvertFileProtoToFileDescriptor(file_proto)
+
+  def FindFileContainingSymbol(self, symbol):
+    """Gets the FileDescriptor for the file containing the specified symbol.
+
+    Args:
+      symbol: The name of the symbol to search for.
+
+    Returns:
+      A FileDescriptor that contains the specified symbol.
+
+    Raises:
+      KeyError: if the file can not be found in the pool.
+    """
+
+    try:
+      file_proto = self._internal_db.FindFileContainingSymbol(symbol)
+    except KeyError as error:
+      if self._descriptor_db:
+        file_proto = self._descriptor_db.FindFileContainingSymbol(symbol)
+      else:
+        raise error
+    if not file_proto:
+      raise KeyError('Cannot find a file containing %s' % symbol)
+    return self._ConvertFileProtoToFileDescriptor(file_proto)
+
+  def FindMessageTypeByName(self, full_name):
+    """Loads the named descriptor from the pool.
+
+    Args:
+      full_name: The full name of the descriptor to load.
+
+    Returns:
+      The descriptor for the named type.
+    """
+
+    full_name = full_name.lstrip('.')  # fix inconsistent qualified name formats
+    if full_name not in self._descriptors:
+      self.FindFileContainingSymbol(full_name)
+    return self._descriptors[full_name]
+
+  def FindEnumTypeByName(self, full_name):
+    """Loads the named enum descriptor from the pool.
+
+    Args:
+      full_name: The full name of the enum descriptor to load.
+
+    Returns:
+      The enum descriptor for the named type.
+    """
+
+    full_name = full_name.lstrip('.')  # fix inconsistent qualified name formats
+    if full_name not in self._enum_descriptors:
+      self.FindFileContainingSymbol(full_name)
+    return self._enum_descriptors[full_name]
+
+  def _ConvertFileProtoToFileDescriptor(self, file_proto):
+    """Creates a FileDescriptor from a proto or returns a cached copy.
+
+    This method also has the side effect of loading all the symbols found in
+    the file into the appropriate dictionaries in the pool.
+
+    Args:
+      file_proto: The proto to convert.
+
+    Returns:
+      A FileDescriptor matching the passed in proto.
+    """
+
+    if file_proto.name not in self._file_descriptors:
+      file_descriptor = descriptor.FileDescriptor(
+          name=file_proto.name,
+          package=file_proto.package,
+          options=file_proto.options,
+          serialized_pb=file_proto.SerializeToString())
+      scope = {}
+      dependencies = list(self._GetDeps(file_proto))
+
+      for dependency in dependencies:
+        dep_desc = self.FindFileByName(dependency.name)
+        dep_proto = descriptor_pb2.FileDescriptorProto.FromString(
+            dep_desc.serialized_pb)
+        package = '.' + dep_proto.package
+        package_prefix = package + '.'
+
+        def _strip_package(symbol):
+          if symbol.startswith(package_prefix):
+            return symbol[len(package_prefix):]
+          return symbol
+
+        symbols = list(self._ExtractSymbols(dep_proto.message_type, package))
+        scope.update(symbols)
+        scope.update((_strip_package(k), v) for k, v in symbols)
+
+        symbols = list(self._ExtractEnums(dep_proto.enum_type, package))
+        scope.update(symbols)
+        scope.update((_strip_package(k), v) for k, v in symbols)
+
+      for message_type in file_proto.message_type:
+        message_desc = self._ConvertMessageDescriptor(
+            message_type, file_proto.package, file_descriptor, scope)
+        file_descriptor.message_types_by_name[message_desc.name] = message_desc
+      for enum_type in file_proto.enum_type:
+        self._ConvertEnumDescriptor(enum_type, file_proto.package,
+                                    file_descriptor, None, scope)
+      for desc_proto in self._ExtractMessages(file_proto.message_type):
+        self._SetFieldTypes(desc_proto, scope)
+
+      for desc_proto in file_proto.message_type:
+        desc = scope[desc_proto.name]
+        file_descriptor.message_types_by_name[desc_proto.name] = desc
+      self.Add(file_proto)
+      self._file_descriptors[file_proto.name] = file_descriptor
+
+    return self._file_descriptors[file_proto.name]
+
+  def _ConvertMessageDescriptor(self, desc_proto, package=None, file_desc=None,
+                                scope=None):
+    """Adds the proto to the pool in the specified package.
+
+    Args:
+      desc_proto: The descriptor_pb2.DescriptorProto protobuf message.
+      package: The package the proto should be located in.
+      file_desc: The file containing this message.
+      scope: Dict mapping short and full symbols to message and enum types.
+
+    Returns:
+      The added descriptor.
+    """
+
+    if package:
+      desc_name = '.'.join((package, desc_proto.name))
+    else:
+      desc_name = desc_proto.name
+
+    if file_desc is None:
+      file_name = None
+    else:
+      file_name = file_desc.name
+
+    if scope is None:
+      scope = {}
+
+    nested = [
+        self._ConvertMessageDescriptor(nested, desc_name, file_desc, scope)
+        for nested in desc_proto.nested_type]
+    enums = [
+        self._ConvertEnumDescriptor(enum, desc_name, file_desc, None, scope)
+        for enum in desc_proto.enum_type]
+    fields = [self._MakeFieldDescriptor(field, desc_name, index)
+              for index, field in enumerate(desc_proto.field)]
+    extensions = [self._MakeFieldDescriptor(extension, desc_name, True)
+                  for index, extension in enumerate(desc_proto.extension)]
+    extension_ranges = [(r.start, r.end) for r in desc_proto.extension_range]
+    if extension_ranges:
+      is_extendable = True
+    else:
+      is_extendable = False
+    desc = descriptor.Descriptor(
+        name=desc_proto.name,
+        full_name=desc_name,
+        filename=file_name,
+        containing_type=None,
+        fields=fields,
+        nested_types=nested,
+        enum_types=enums,
+        extensions=extensions,
+        options=desc_proto.options,
+        is_extendable=is_extendable,
+        extension_ranges=extension_ranges,
+        file=file_desc,
+        serialized_start=None,
+        serialized_end=None)
+    for nested in desc.nested_types:
+      nested.containing_type = desc
+    for enum in desc.enum_types:
+      enum.containing_type = desc
+    scope[desc_proto.name] = desc
+    scope['.' + desc_name] = desc
+    self._descriptors[desc_name] = desc
+    return desc
+
+  def _ConvertEnumDescriptor(self, enum_proto, package=None, file_desc=None,
+                             containing_type=None, scope=None):
+    """Make a protobuf EnumDescriptor given an EnumDescriptorProto protobuf.
+
+    Args:
+      enum_proto: The descriptor_pb2.EnumDescriptorProto protobuf message.
+      package: Optional package name for the new message EnumDescriptor.
+      file_desc: The file containing the enum descriptor.
+      containing_type: The type containing this enum.
+      scope: Scope containing available types.
+
+    Returns:
+      The added descriptor
+    """
+
+    if package:
+      enum_name = '.'.join((package, enum_proto.name))
+    else:
+      enum_name = enum_proto.name
+
+    if file_desc is None:
+      file_name = None
+    else:
+      file_name = file_desc.name
+
+    values = [self._MakeEnumValueDescriptor(value, index)
+              for index, value in enumerate(enum_proto.value)]
+    desc = descriptor.EnumDescriptor(name=enum_proto.name,
+                                     full_name=enum_name,
+                                     filename=file_name,
+                                     file=file_desc,
+                                     values=values,
+                                     containing_type=containing_type,
+                                     options=enum_proto.options)
+    scope[enum_proto.name] = desc
+    scope['.%s' % enum_name] = desc
+    self._enum_descriptors[enum_name] = desc
+    return desc
+
+  def _MakeFieldDescriptor(self, field_proto, message_name, index,
+                           is_extension=False):
+    """Creates a field descriptor from a FieldDescriptorProto.
+
+    For message and enum type fields, this method will do a look up
+    in the pool for the appropriate descriptor for that type. If it
+    is unavailable, it will fall back to the _source function to
+    create it. If this type is still unavailable, construction will
+    fail.
+
+    Args:
+      field_proto: The proto describing the field.
+      message_name: The name of the containing message.
+      index: Index of the field
+      is_extension: Indication that this field is for an extension.
+
+    Returns:
+      An initialized FieldDescriptor object
+    """
+
+    if message_name:
+      full_name = '.'.join((message_name, field_proto.name))
+    else:
+      full_name = field_proto.name
+
+    return descriptor.FieldDescriptor(
+        name=field_proto.name,
+        full_name=full_name,
+        index=index,
+        number=field_proto.number,
+        type=field_proto.type,
+        cpp_type=None,
+        message_type=None,
+        enum_type=None,
+        containing_type=None,
+        label=field_proto.label,
+        has_default_value=False,
+        default_value=None,
+        is_extension=is_extension,
+        extension_scope=None,
+        options=field_proto.options)
+
+  def _SetFieldTypes(self, desc_proto, scope):
+    """Sets the field's type, cpp_type, message_type and enum_type.
+
+    Args:
+      desc_proto: The message descriptor to update.
+      scope: Enclosing scope of available types.
+    """
+
+    desc = scope[desc_proto.name]
+    for field_proto, field_desc in zip(desc_proto.field, desc.fields):
+      if field_proto.type_name:
+        type_name = field_proto.type_name
+        if type_name not in scope:
+          type_name = '.' + type_name
+        desc = scope[type_name]
+      else:
+        desc = None
+
+      if not field_proto.HasField('type'):
+        if isinstance(desc, descriptor.Descriptor):
+          field_proto.type = descriptor.FieldDescriptor.TYPE_MESSAGE
+        else:
+          field_proto.type = descriptor.FieldDescriptor.TYPE_ENUM
+
+      field_desc.cpp_type = descriptor.FieldDescriptor.ProtoTypeToCppProtoType(
+          field_proto.type)
+
+      if (field_proto.type == descriptor.FieldDescriptor.TYPE_MESSAGE
+          or field_proto.type == descriptor.FieldDescriptor.TYPE_GROUP):
+        field_desc.message_type = desc
+
+      if field_proto.type == descriptor.FieldDescriptor.TYPE_ENUM:
+        field_desc.enum_type = desc
+
+      if field_proto.label == descriptor.FieldDescriptor.LABEL_REPEATED:
+        field_desc.has_default = False
+        field_desc.default_value = []
+      elif field_proto.HasField('default_value'):
+        field_desc.has_default = True
+        if (field_proto.type == descriptor.FieldDescriptor.TYPE_DOUBLE or
+            field_proto.type == descriptor.FieldDescriptor.TYPE_FLOAT):
+          field_desc.default_value = float(field_proto.default_value)
+        elif field_proto.type == descriptor.FieldDescriptor.TYPE_STRING:
+          field_desc.default_value = field_proto.default_value
+        elif field_proto.type == descriptor.FieldDescriptor.TYPE_BOOL:
+          field_desc.default_value = field_proto.default_value.lower() == 'true'
+        elif field_proto.type == descriptor.FieldDescriptor.TYPE_ENUM:
+          field_desc.default_value = field_desc.enum_type.values_by_name[
+              field_proto.default_value].index
+        else:
+          field_desc.default_value = int(field_proto.default_value)
+      else:
+        field_desc.has_default = False
+        field_desc.default_value = None
+
+      field_desc.type = field_proto.type
+
+    for nested_type in desc_proto.nested_type:
+      self._SetFieldTypes(nested_type, scope)
+
+  def _MakeEnumValueDescriptor(self, value_proto, index):
+    """Creates a enum value descriptor object from a enum value proto.
+
+    Args:
+      value_proto: The proto describing the enum value.
+      index: The index of the enum value.
+
+    Returns:
+      An initialized EnumValueDescriptor object.
+    """
+
+    return descriptor.EnumValueDescriptor(
+        name=value_proto.name,
+        index=index,
+        number=value_proto.number,
+        options=value_proto.options,
+        type=None)
+
+  def _ExtractSymbols(self, desc_protos, package):
+    """Pulls out all the symbols from descriptor protos.
+
+    Args:
+      desc_protos: The protos to extract symbols from.
+      package: The package containing the descriptor type.
+    Yields:
+      A two element tuple of the type name and descriptor object.
+    """
+
+    for desc_proto in desc_protos:
+      if package:
+        message_name = '.'.join((package, desc_proto.name))
+      else:
+        message_name = desc_proto.name
+      message_desc = self.FindMessageTypeByName(message_name)
+      yield (message_name, message_desc)
+      for symbol in self._ExtractSymbols(desc_proto.nested_type, message_name):
+        yield symbol
+      for symbol in self._ExtractEnums(desc_proto.enum_type, message_name):
+        yield symbol
+
+  def _ExtractEnums(self, enum_protos, package):
+    """Pulls out all the symbols from enum protos.
+
+    Args:
+      enum_protos: The protos to extract symbols from.
+      package: The package containing the enum type.
+
+    Yields:
+      A two element tuple of the type name and enum descriptor object.
+    """
+
+    for enum_proto in enum_protos:
+      if package:
+        enum_name = '.'.join((package, enum_proto.name))
+      else:
+        enum_name = enum_proto.name
+      enum_desc = self.FindEnumTypeByName(enum_name)
+      yield (enum_name, enum_desc)
+
+  def _ExtractMessages(self, desc_protos):
+    """Pulls out all the message protos from descriptos.
+
+    Args:
+      desc_protos: The protos to extract symbols from.
+
+    Yields:
+      Descriptor protos.
+    """
+
+    for desc_proto in desc_protos:
+      yield desc_proto
+      for message in self._ExtractMessages(desc_proto.nested_type):
+        yield message
+
+  def _GetDeps(self, file_proto):
+    """Recursively finds dependencies for file protos.
+
+    Args:
+      file_proto: The proto to get dependencies from.
+
+    Yields:
+      Each direct and indirect dependency.
+    """
+
+    for dependency in file_proto.dependency:
+      dep_desc = self.FindFileByName(dependency)
+      dep_proto = descriptor_pb2.FileDescriptorProto.FromString(
+          dep_desc.serialized_pb)
+      yield dep_proto
+      for parent_dep in self._GetDeps(dep_proto):
+        yield parent_dep
diff --git a/third_party/protobuf/python/google/protobuf/internal/api_implementation.py b/third_party/protobuf/python/google/protobuf/internal/api_implementation.py
index b3e412e..ce02a32 100644
--- a/third_party/protobuf/python/google/protobuf/internal/api_implementation.py
+++ b/third_party/protobuf/python/google/protobuf/internal/api_implementation.py
@@ -56,9 +56,32 @@
   #  _implementation_type = 'python'
 
 
+# This environment variable can be used to switch between the two
+# 'cpp' implementations. Right now only 1 and 2 are valid values. Any
+# other value will be ignored.
+_implementation_version_str = os.getenv(
+    'PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION_VERSION',
+    '1')
+
+
+if _implementation_version_str not in ('1', '2'):
+  raise ValueError(
+      "unsupported PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION_VERSION: '" +
+      _implementation_version_str + "' (supported versions: 1, 2)"
+      )
+
+
+_implementation_version = int(_implementation_version_str)
+
+
+
 # Usage of this function is discouraged. Clients shouldn't care which
 # implementation of the API is in use. Note that there is no guarantee
 # that differences between APIs will be maintained.
 # Please don't use this function if possible.
 def Type():
   return _implementation_type
+
+# See comment on 'Type' above.
+def Version():
+  return _implementation_version
diff --git a/third_party/protobuf/python/google/protobuf/internal/containers.py b/third_party/protobuf/python/google/protobuf/internal/containers.py
index 097a3c2..34b35f8 100755
--- a/third_party/protobuf/python/google/protobuf/internal/containers.py
+++ b/third_party/protobuf/python/google/protobuf/internal/containers.py
@@ -78,8 +78,13 @@
   def __repr__(self):
     return repr(self._values)
 
-  def sort(self, sort_function=cmp):
-    self._values.sort(sort_function)
+  def sort(self, *args, **kwargs):
+    # Continue to support the old sort_function keyword argument.
+    # This is expected to be a rare occurrence, so use LBYL to avoid
+    # the overhead of actually catching KeyError.
+    if 'sort_function' in kwargs:
+      kwargs['cmp'] = kwargs.pop('sort_function')
+    self._values.sort(*args, **kwargs)
 
 
 class RepeatedScalarFieldContainer(BaseContainer):
@@ -235,6 +240,11 @@
     """
     self.extend(other._values)
 
+  def remove(self, elem):
+    """Removes an item from the list. Similar to list.remove()."""
+    self._values.remove(elem)
+    self._message_listener.Modified()
+
   def __getslice__(self, start, stop):
     """Retrieves the subset of items from between the specified indices."""
     return self._values[start:stop]
diff --git a/third_party/protobuf/python/google/protobuf/internal/cpp_message.py b/third_party/protobuf/python/google/protobuf/internal/cpp_message.py
index 3f42650..23ab9ba 100644
--- a/third_party/protobuf/python/google/protobuf/internal/cpp_message.py
+++ b/third_party/protobuf/python/google/protobuf/internal/cpp_message.py
@@ -34,8 +34,10 @@
 
 __author__ = 'petar@google.com (Petar Petrov)'
 
+import copy_reg
 import operator
 from google.protobuf.internal import _net_proto2___python
+from google.protobuf.internal import enum_type_wrapper
 from google.protobuf import message
 
 
@@ -156,10 +158,12 @@
   def __hash__(self):
     raise TypeError('unhashable object')
 
-  def sort(self, sort_function=cmp):
-    values = self[slice(None, None, None)]
-    values.sort(sort_function)
-    self._cmsg.AssignRepeatedScalar(self._cfield_descriptor, values)
+  def sort(self, *args, **kwargs):
+    # Maintain compatibility with the previous interface.
+    if 'sort_function' in kwargs:
+      kwargs['cmp'] = kwargs.pop('sort_function')
+    self._cmsg.AssignRepeatedScalar(self._cfield_descriptor,
+                                    sorted(self, *args, **kwargs))
 
 
 def RepeatedScalarProperty(cdescriptor):
@@ -202,6 +206,12 @@
     for message in elem_seq:
       self.add().MergeFrom(message)
 
+  def remove(self, value):
+    # TODO(protocol-devel): This is inefficient as it needs to generate a
+    # message pointer for each message only to do index().  Move this to a C++
+    # extension function.
+    self.__delitem__(self[slice(None, None, None)].index(value))
+
   def MergeFrom(self, other):
     for message in other[:]:
       self.add().MergeFrom(message)
@@ -236,27 +246,29 @@
   def __hash__(self):
     raise TypeError('unhashable object')
 
-  def sort(self, sort_function=cmp):
-    messages = []
-    for index in range(len(self)):
-      # messages[i][0] is where the i-th element of the new array has to come
-      # from.
-      # messages[i][1] is where the i-th element of the old array has to go.
-      messages.append([index, 0, self[index]])
-    messages.sort(lambda x,y: sort_function(x[2], y[2]))
+  def sort(self, cmp=None, key=None, reverse=False, **kwargs):
+    # Maintain compatibility with the old interface.
+    if cmp is None and 'sort_function' in kwargs:
+      cmp = kwargs.pop('sort_function')
 
-    # Remember which position each elements has to move to.
-    for i in range(len(messages)):
-      messages[messages[i][0]][1] = i
+    # The cmp function, if provided, is passed the results of the key function,
+    # so we only need to wrap one of them.
+    if key is None:
+      index_key = self.__getitem__
+    else:
+      index_key = lambda i: key(self[i])
+
+    # Sort the list of current indexes by the underlying object.
+    indexes = range(len(self))
+    indexes.sort(cmp=cmp, key=index_key, reverse=reverse)
 
     # Apply the transposition.
-    for i in range(len(messages)):
-      from_position = messages[i][0]
-      if i == from_position:
+    for dest, src in enumerate(indexes):
+      if dest == src:
         continue
-      self._cmsg.SwapRepeatedFieldElements(
-          self._cfield_descriptor, i, from_position)
-      messages[messages[i][1]][0] = from_position
+      self._cmsg.SwapRepeatedFieldElements(self._cfield_descriptor, dest, src)
+      # Don't swap the same value twice.
+      indexes[src] = src
 
 
 def RepeatedCompositeProperty(cdescriptor, message_type):
@@ -359,11 +371,12 @@
     return None
 
 
-def NewMessage(message_descriptor, dictionary):
+def NewMessage(bases, message_descriptor, dictionary):
   """Creates a new protocol message *class*."""
   _AddClassAttributesForNestedExtensions(message_descriptor, dictionary)
   _AddEnumValues(message_descriptor, dictionary)
   _AddDescriptors(message_descriptor, dictionary)
+  return bases
 
 
 def InitMessage(message_descriptor, cls):
@@ -372,6 +385,7 @@
   _AddInitMethod(message_descriptor, cls)
   _AddMessageMethods(message_descriptor, cls)
   _AddPropertiesForExtensions(message_descriptor, cls)
+  copy_reg.pickle(cls, lambda obj: (cls, (), obj.__getstate__()))
 
 
 def _AddDescriptors(message_descriptor, dictionary):
@@ -387,7 +401,7 @@
         field.full_name)
 
   dictionary['__slots__'] = list(dictionary['__descriptors'].iterkeys()) + [
-      '_cmsg', '_owner', '_composite_fields', 'Extensions']
+      '_cmsg', '_owner', '_composite_fields', 'Extensions', '_HACK_REFCOUNTS']
 
 
 def _AddEnumValues(message_descriptor, dictionary):
@@ -398,6 +412,7 @@
     dictionary: Class dictionary that should be populated.
   """
   for enum_type in message_descriptor.enum_types:
+    dictionary[enum_type.name] = enum_type_wrapper.EnumTypeWrapper(enum_type)
     for enum_value in enum_type.values:
       dictionary[enum_value.name] = enum_value.number
 
@@ -439,28 +454,35 @@
   def Init(self, **kwargs):
     """Message constructor."""
     cmessage = kwargs.pop('__cmessage', None)
-    if cmessage is None:
-      self._cmsg = NewCMessage(message_descriptor.full_name)
-    else:
+    if cmessage:
       self._cmsg = cmessage
+    else:
+      self._cmsg = NewCMessage(message_descriptor.full_name)
 
     # Keep a reference to the owner, as the owner keeps a reference to the
     # underlying protocol buffer message.
     owner = kwargs.pop('__owner', None)
-    if owner is not None:
+    if owner:
       self._owner = owner
 
-    self.Extensions = ExtensionDict(self)
+    if message_descriptor.is_extendable:
+      self.Extensions = ExtensionDict(self)
+    else:
+      # Reference counting in the C++ code is broken and depends on
+      # the Extensions reference to keep this object alive during unit
+      # tests (see b/4856052).  Remove this once b/4945904 is fixed.
+      self._HACK_REFCOUNTS = self
     self._composite_fields = {}
 
     for field_name, field_value in kwargs.iteritems():
       field_cdescriptor = self.__descriptors.get(field_name, None)
-      if field_cdescriptor is None:
+      if not field_cdescriptor:
         raise ValueError('Protocol message has no "%s" field.' % field_name)
       if field_cdescriptor.label == _LABEL_REPEATED:
         if field_cdescriptor.cpp_type == _CPPTYPE_MESSAGE:
+          field_name = getattr(self, field_name)
           for val in field_value:
-            getattr(self, field_name).add().MergeFrom(val)
+            field_name.add().MergeFrom(val)
         else:
           getattr(self, field_name).extend(field_value)
       elif field_cdescriptor.cpp_type == _CPPTYPE_MESSAGE:
@@ -497,12 +519,34 @@
     return self._cmsg.HasField(field_name)
 
   def ClearField(self, field_name):
+    child_cmessage = None
     if field_name in self._composite_fields:
+      child_field = self._composite_fields[field_name]
       del self._composite_fields[field_name]
-    self._cmsg.ClearField(field_name)
+
+      child_cdescriptor = self.__descriptors[field_name]
+      # TODO(anuraag): Support clearing repeated message fields as well.
+      if (child_cdescriptor.label != _LABEL_REPEATED and
+          child_cdescriptor.cpp_type == _CPPTYPE_MESSAGE):
+        child_field._owner = None
+        child_cmessage = child_field._cmsg
+
+    if child_cmessage is not None:
+      self._cmsg.ClearField(field_name, child_cmessage)
+    else:
+      self._cmsg.ClearField(field_name)
 
   def Clear(self):
-    return self._cmsg.Clear()
+    cmessages_to_release = []
+    for field_name, child_field in self._composite_fields.iteritems():
+      child_cdescriptor = self.__descriptors[field_name]
+      # TODO(anuraag): Support clearing repeated message fields as well.
+      if (child_cdescriptor.label != _LABEL_REPEATED and
+          child_cdescriptor.cpp_type == _CPPTYPE_MESSAGE):
+        child_field._owner = None
+        cmessages_to_release.append((child_cdescriptor, child_field._cmsg))
+    self._composite_fields.clear()
+    self._cmsg.Clear(cmessages_to_release)
 
   def IsInitialized(self, errors=None):
     if self._cmsg.IsInitialized():
@@ -514,8 +558,8 @@
   def SerializeToString(self):
     if not self.IsInitialized():
       raise message.EncodeError(
-          'Message is missing required fields: ' +
-          ','.join(self.FindInitializationErrors()))
+          'Message %s is missing required fields: %s' % (
+          self._cmsg.full_name, ','.join(self.FindInitializationErrors())))
     return self._cmsg.SerializeToString()
 
   def SerializePartialToString(self):
@@ -534,7 +578,8 @@
   def MergeFrom(self, msg):
     if not isinstance(msg, cls):
       raise TypeError(
-          "Parameter to MergeFrom() must be instance of same class.")
+          "Parameter to MergeFrom() must be instance of same class: "
+          "expected %s got %s." % (cls.__name__, type(msg).__name__))
     self._cmsg.MergeFrom(msg._cmsg)
 
   def CopyFrom(self, msg):
@@ -581,6 +626,8 @@
     raise TypeError('unhashable object')
 
   def __unicode__(self):
+    # Lazy import to prevent circular import when text_format imports this file.
+    from google.protobuf import text_format
     return text_format.MessageToString(self, as_utf8=True).decode('utf-8')
 
   # Attach the local methods to the message class.
diff --git a/third_party/protobuf/python/google/protobuf/internal/decoder.py b/third_party/protobuf/python/google/protobuf/internal/decoder.py
index 55f746f..cb6f572 100755
--- a/third_party/protobuf/python/google/protobuf/internal/decoder.py
+++ b/third_party/protobuf/python/google/protobuf/internal/decoder.py
@@ -576,6 +576,7 @@
   local_SkipField = SkipField
 
   def DecodeItem(buffer, pos, end, message, field_dict):
+    message_set_item_start = pos
     type_id = -1
     message_start = -1
     message_end = -1
@@ -614,6 +615,11 @@
         # The only reason _InternalParse would return early is if it encountered
         # an end-group tag.
         raise _DecodeError('Unexpected end-group tag.')
+    else:
+      if not message._unknown_fields:
+        message._unknown_fields = []
+      message._unknown_fields.append((MESSAGE_SET_ITEM_TAG,
+                                      buffer[message_set_item_start:pos]))
 
     return pos
 
diff --git a/third_party/protobuf/python/google/protobuf/internal/descriptor_database_test.py b/third_party/protobuf/python/google/protobuf/internal/descriptor_database_test.py
new file mode 100644
index 0000000..d0ca789
--- /dev/null
+++ b/third_party/protobuf/python/google/protobuf/internal/descriptor_database_test.py
@@ -0,0 +1,63 @@
+#! /usr/bin/python
+#
+# Protocol Buffers - Google's data interchange format
+# Copyright 2008 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.
+
+"""Tests for google.protobuf.descriptor_database."""
+
+__author__ = 'matthewtoia@google.com (Matt Toia)'
+
+import unittest
+from google.protobuf import descriptor_pb2
+from google.protobuf.internal import factory_test2_pb2
+from google.protobuf import descriptor_database
+
+
+class DescriptorDatabaseTest(unittest.TestCase):
+
+  def testAdd(self):
+    db = descriptor_database.DescriptorDatabase()
+    file_desc_proto = descriptor_pb2.FileDescriptorProto.FromString(
+        factory_test2_pb2.DESCRIPTOR.serialized_pb)
+    db.Add(file_desc_proto)
+
+    self.assertEquals(file_desc_proto, db.FindFileByName(
+        'net/proto2/python/internal/factory_test2.proto'))
+    self.assertEquals(file_desc_proto, db.FindFileContainingSymbol(
+        'net.proto2.python.internal.Factory2Message'))
+    self.assertEquals(file_desc_proto, db.FindFileContainingSymbol(
+        'net.proto2.python.internal.Factory2Message.NestedFactory2Message'))
+    self.assertEquals(file_desc_proto, db.FindFileContainingSymbol(
+        'net.proto2.python.internal.Factory2Enum'))
+    self.assertEquals(file_desc_proto, db.FindFileContainingSymbol(
+        'net.proto2.python.internal.Factory2Message.NestedFactory2Enum'))
+
+if __name__ == '__main__':
+  unittest.main()
diff --git a/third_party/protobuf/python/google/protobuf/internal/descriptor_pool_test.py b/third_party/protobuf/python/google/protobuf/internal/descriptor_pool_test.py
new file mode 100644
index 0000000..a615d78
--- /dev/null
+++ b/third_party/protobuf/python/google/protobuf/internal/descriptor_pool_test.py
@@ -0,0 +1,220 @@
+#! /usr/bin/python
+#
+# Protocol Buffers - Google's data interchange format
+# Copyright 2008 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.
+
+"""Tests for google.protobuf.descriptor_pool."""
+
+__author__ = 'matthewtoia@google.com (Matt Toia)'
+
+import unittest
+from google.protobuf import descriptor_pb2
+from google.protobuf.internal import factory_test1_pb2
+from google.protobuf.internal import factory_test2_pb2
+from google.protobuf import descriptor
+from google.protobuf import descriptor_database
+from google.protobuf import descriptor_pool
+
+
+class DescriptorPoolTest(unittest.TestCase):
+
+  def setUp(self):
+    self.pool = descriptor_pool.DescriptorPool()
+    self.factory_test1_fd = descriptor_pb2.FileDescriptorProto.FromString(
+        factory_test1_pb2.DESCRIPTOR.serialized_pb)
+    self.factory_test2_fd = descriptor_pb2.FileDescriptorProto.FromString(
+        factory_test2_pb2.DESCRIPTOR.serialized_pb)
+    self.pool.Add(self.factory_test1_fd)
+    self.pool.Add(self.factory_test2_fd)
+
+  def testFindFileByName(self):
+    name1 = 'net/proto2/python/internal/factory_test1.proto'
+    file_desc1 = self.pool.FindFileByName(name1)
+    self.assertIsInstance(file_desc1, descriptor.FileDescriptor)
+    self.assertEquals(name1, file_desc1.name)
+    self.assertEquals('net.proto2.python.internal', file_desc1.package)
+    self.assertIn('Factory1Message', file_desc1.message_types_by_name)
+
+    name2 = 'net/proto2/python/internal/factory_test2.proto'
+    file_desc2 = self.pool.FindFileByName(name2)
+    self.assertIsInstance(file_desc2, descriptor.FileDescriptor)
+    self.assertEquals(name2, file_desc2.name)
+    self.assertEquals('net.proto2.python.internal', file_desc2.package)
+    self.assertIn('Factory2Message', file_desc2.message_types_by_name)
+
+  def testFindFileByNameFailure(self):
+    try:
+      self.pool.FindFileByName('Does not exist')
+      self.fail('Expected KeyError')
+    except KeyError:
+      pass
+
+  def testFindFileContainingSymbol(self):
+    file_desc1 = self.pool.FindFileContainingSymbol(
+        'net.proto2.python.internal.Factory1Message')
+    self.assertIsInstance(file_desc1, descriptor.FileDescriptor)
+    self.assertEquals('net/proto2/python/internal/factory_test1.proto',
+                      file_desc1.name)
+    self.assertEquals('net.proto2.python.internal', file_desc1.package)
+    self.assertIn('Factory1Message', file_desc1.message_types_by_name)
+
+    file_desc2 = self.pool.FindFileContainingSymbol(
+        'net.proto2.python.internal.Factory2Message')
+    self.assertIsInstance(file_desc2, descriptor.FileDescriptor)
+    self.assertEquals('net/proto2/python/internal/factory_test2.proto',
+                      file_desc2.name)
+    self.assertEquals('net.proto2.python.internal', file_desc2.package)
+    self.assertIn('Factory2Message', file_desc2.message_types_by_name)
+
+  def testFindFileContainingSymbolFailure(self):
+    try:
+      self.pool.FindFileContainingSymbol('Does not exist')
+      self.fail('Expected KeyError')
+    except KeyError:
+      pass
+
+  def testFindMessageTypeByName(self):
+    msg1 = self.pool.FindMessageTypeByName(
+        'net.proto2.python.internal.Factory1Message')
+    self.assertIsInstance(msg1, descriptor.Descriptor)
+    self.assertEquals('Factory1Message', msg1.name)
+    self.assertEquals('net.proto2.python.internal.Factory1Message',
+                      msg1.full_name)
+    self.assertEquals(None, msg1.containing_type)
+
+    nested_msg1 = msg1.nested_types[0]
+    self.assertEquals('NestedFactory1Message', nested_msg1.name)
+    self.assertEquals(msg1, nested_msg1.containing_type)
+
+    nested_enum1 = msg1.enum_types[0]
+    self.assertEquals('NestedFactory1Enum', nested_enum1.name)
+    self.assertEquals(msg1, nested_enum1.containing_type)
+
+    self.assertEquals(nested_msg1, msg1.fields_by_name[
+        'nested_factory_1_message'].message_type)
+    self.assertEquals(nested_enum1, msg1.fields_by_name[
+        'nested_factory_1_enum'].enum_type)
+
+    msg2 = self.pool.FindMessageTypeByName(
+        'net.proto2.python.internal.Factory2Message')
+    self.assertIsInstance(msg2, descriptor.Descriptor)
+    self.assertEquals('Factory2Message', msg2.name)
+    self.assertEquals('net.proto2.python.internal.Factory2Message',
+                      msg2.full_name)
+    self.assertIsNone(msg2.containing_type)
+
+    nested_msg2 = msg2.nested_types[0]
+    self.assertEquals('NestedFactory2Message', nested_msg2.name)
+    self.assertEquals(msg2, nested_msg2.containing_type)
+
+    nested_enum2 = msg2.enum_types[0]
+    self.assertEquals('NestedFactory2Enum', nested_enum2.name)
+    self.assertEquals(msg2, nested_enum2.containing_type)
+
+    self.assertEquals(nested_msg2, msg2.fields_by_name[
+        'nested_factory_2_message'].message_type)
+    self.assertEquals(nested_enum2, msg2.fields_by_name[
+        'nested_factory_2_enum'].enum_type)
+
+    self.assertTrue(msg2.fields_by_name['int_with_default'].has_default)
+    self.assertEquals(
+        1776, msg2.fields_by_name['int_with_default'].default_value)
+
+    self.assertTrue(msg2.fields_by_name['double_with_default'].has_default)
+    self.assertEquals(
+        9.99, msg2.fields_by_name['double_with_default'].default_value)
+
+    self.assertTrue(msg2.fields_by_name['string_with_default'].has_default)
+    self.assertEquals(
+        'hello world', msg2.fields_by_name['string_with_default'].default_value)
+
+    self.assertTrue(msg2.fields_by_name['bool_with_default'].has_default)
+    self.assertFalse(msg2.fields_by_name['bool_with_default'].default_value)
+
+    self.assertTrue(msg2.fields_by_name['enum_with_default'].has_default)
+    self.assertEquals(
+        1, msg2.fields_by_name['enum_with_default'].default_value)
+
+    msg3 = self.pool.FindMessageTypeByName(
+        'net.proto2.python.internal.Factory2Message.NestedFactory2Message')
+    self.assertEquals(nested_msg2, msg3)
+
+  def testFindMessageTypeByNameFailure(self):
+    try:
+      self.pool.FindMessageTypeByName('Does not exist')
+      self.fail('Expected KeyError')
+    except KeyError:
+      pass
+
+  def testFindEnumTypeByName(self):
+    enum1 = self.pool.FindEnumTypeByName(
+        'net.proto2.python.internal.Factory1Enum')
+    self.assertIsInstance(enum1, descriptor.EnumDescriptor)
+    self.assertEquals(0, enum1.values_by_name['FACTORY_1_VALUE_0'].number)
+    self.assertEquals(1, enum1.values_by_name['FACTORY_1_VALUE_1'].number)
+
+    nested_enum1 = self.pool.FindEnumTypeByName(
+        'net.proto2.python.internal.Factory1Message.NestedFactory1Enum')
+    self.assertIsInstance(nested_enum1, descriptor.EnumDescriptor)
+    self.assertEquals(
+        0, nested_enum1.values_by_name['NESTED_FACTORY_1_VALUE_0'].number)
+    self.assertEquals(
+        1, nested_enum1.values_by_name['NESTED_FACTORY_1_VALUE_1'].number)
+
+    enum2 = self.pool.FindEnumTypeByName(
+        'net.proto2.python.internal.Factory2Enum')
+    self.assertIsInstance(enum2, descriptor.EnumDescriptor)
+    self.assertEquals(0, enum2.values_by_name['FACTORY_2_VALUE_0'].number)
+    self.assertEquals(1, enum2.values_by_name['FACTORY_2_VALUE_1'].number)
+
+    nested_enum2 = self.pool.FindEnumTypeByName(
+        'net.proto2.python.internal.Factory2Message.NestedFactory2Enum')
+    self.assertIsInstance(nested_enum2, descriptor.EnumDescriptor)
+    self.assertEquals(
+        0, nested_enum2.values_by_name['NESTED_FACTORY_2_VALUE_0'].number)
+    self.assertEquals(
+        1, nested_enum2.values_by_name['NESTED_FACTORY_2_VALUE_1'].number)
+
+  def testFindEnumTypeByNameFailure(self):
+    try:
+      self.pool.FindEnumTypeByName('Does not exist')
+      self.fail('Expected KeyError')
+    except KeyError:
+      pass
+
+  def testUserDefinedDB(self):
+    db = descriptor_database.DescriptorDatabase()
+    self.pool = descriptor_pool.DescriptorPool(db)
+    db.Add(self.factory_test1_fd)
+    db.Add(self.factory_test2_fd)
+    self.testFindMessageTypeByName()
+
+if __name__ == '__main__':
+  unittest.main()
diff --git a/third_party/protobuf/python/google/protobuf/internal/descriptor_test.py b/third_party/protobuf/python/google/protobuf/internal/descriptor_test.py
index 05c2745..c74f882 100755
--- a/third_party/protobuf/python/google/protobuf/internal/descriptor_test.py
+++ b/third_party/protobuf/python/google/protobuf/internal/descriptor_test.py
@@ -35,6 +35,7 @@
 __author__ = 'robinson@google.com (Will Robinson)'
 
 import unittest
+from google.protobuf import unittest_custom_options_pb2
 from google.protobuf import unittest_import_pb2
 from google.protobuf import unittest_pb2
 from google.protobuf import descriptor_pb2
@@ -101,6 +102,15 @@
             self.my_method
         ])
 
+  def testEnumValueName(self):
+    self.assertEqual(self.my_message.EnumValueName('ForeignEnum', 4),
+                     'FOREIGN_FOO')
+
+    self.assertEqual(
+        self.my_message.enum_types_by_name[
+            'ForeignEnum'].values_by_number[4].name,
+        self.my_message.EnumValueName('ForeignEnum', 4))
+
   def testEnumFixups(self):
     self.assertEqual(self.my_enum, self.my_enum.values[0].type)
 
@@ -125,6 +135,257 @@
     self.assertEqual(self.my_service.GetOptions(),
                      descriptor_pb2.ServiceOptions())
 
+  def testSimpleCustomOptions(self):
+    file_descriptor = unittest_custom_options_pb2.DESCRIPTOR
+    message_descriptor =\
+        unittest_custom_options_pb2.TestMessageWithCustomOptions.DESCRIPTOR
+    field_descriptor = message_descriptor.fields_by_name["field1"]
+    enum_descriptor = message_descriptor.enum_types_by_name["AnEnum"]
+    enum_value_descriptor =\
+        message_descriptor.enum_values_by_name["ANENUM_VAL2"]
+    service_descriptor =\
+        unittest_custom_options_pb2.TestServiceWithCustomOptions.DESCRIPTOR
+    method_descriptor = service_descriptor.FindMethodByName("Foo")
+
+    file_options = file_descriptor.GetOptions()
+    file_opt1 = unittest_custom_options_pb2.file_opt1
+    self.assertEqual(9876543210, file_options.Extensions[file_opt1])
+    message_options = message_descriptor.GetOptions()
+    message_opt1 = unittest_custom_options_pb2.message_opt1
+    self.assertEqual(-56, message_options.Extensions[message_opt1])
+    field_options = field_descriptor.GetOptions()
+    field_opt1 = unittest_custom_options_pb2.field_opt1
+    self.assertEqual(8765432109, field_options.Extensions[field_opt1])
+    field_opt2 = unittest_custom_options_pb2.field_opt2
+    self.assertEqual(42, field_options.Extensions[field_opt2])
+    enum_options = enum_descriptor.GetOptions()
+    enum_opt1 = unittest_custom_options_pb2.enum_opt1
+    self.assertEqual(-789, enum_options.Extensions[enum_opt1])
+    enum_value_options = enum_value_descriptor.GetOptions()
+    enum_value_opt1 = unittest_custom_options_pb2.enum_value_opt1
+    self.assertEqual(123, enum_value_options.Extensions[enum_value_opt1])
+
+    service_options = service_descriptor.GetOptions()
+    service_opt1 = unittest_custom_options_pb2.service_opt1
+    self.assertEqual(-9876543210, service_options.Extensions[service_opt1])
+    method_options = method_descriptor.GetOptions()
+    method_opt1 = unittest_custom_options_pb2.method_opt1
+    self.assertEqual(unittest_custom_options_pb2.METHODOPT1_VAL2,
+                     method_options.Extensions[method_opt1])
+
+  def testDifferentCustomOptionTypes(self):
+    kint32min = -2**31
+    kint64min = -2**63
+    kint32max = 2**31 - 1
+    kint64max = 2**63 - 1
+    kuint32max = 2**32 - 1
+    kuint64max = 2**64 - 1
+
+    message_descriptor =\
+        unittest_custom_options_pb2.CustomOptionMinIntegerValues.DESCRIPTOR
+    message_options = message_descriptor.GetOptions()
+    self.assertEqual(False, message_options.Extensions[
+        unittest_custom_options_pb2.bool_opt])
+    self.assertEqual(kint32min, message_options.Extensions[
+        unittest_custom_options_pb2.int32_opt])
+    self.assertEqual(kint64min, message_options.Extensions[
+        unittest_custom_options_pb2.int64_opt])
+    self.assertEqual(0, message_options.Extensions[
+        unittest_custom_options_pb2.uint32_opt])
+    self.assertEqual(0, message_options.Extensions[
+        unittest_custom_options_pb2.uint64_opt])
+    self.assertEqual(kint32min, message_options.Extensions[
+        unittest_custom_options_pb2.sint32_opt])
+    self.assertEqual(kint64min, message_options.Extensions[
+        unittest_custom_options_pb2.sint64_opt])
+    self.assertEqual(0, message_options.Extensions[
+        unittest_custom_options_pb2.fixed32_opt])
+    self.assertEqual(0, message_options.Extensions[
+        unittest_custom_options_pb2.fixed64_opt])
+    self.assertEqual(kint32min, message_options.Extensions[
+        unittest_custom_options_pb2.sfixed32_opt])
+    self.assertEqual(kint64min, message_options.Extensions[
+        unittest_custom_options_pb2.sfixed64_opt])
+
+    message_descriptor =\
+        unittest_custom_options_pb2.CustomOptionMaxIntegerValues.DESCRIPTOR
+    message_options = message_descriptor.GetOptions()
+    self.assertEqual(True, message_options.Extensions[
+        unittest_custom_options_pb2.bool_opt])
+    self.assertEqual(kint32max, message_options.Extensions[
+        unittest_custom_options_pb2.int32_opt])
+    self.assertEqual(kint64max, message_options.Extensions[
+        unittest_custom_options_pb2.int64_opt])
+    self.assertEqual(kuint32max, message_options.Extensions[
+        unittest_custom_options_pb2.uint32_opt])
+    self.assertEqual(kuint64max, message_options.Extensions[
+        unittest_custom_options_pb2.uint64_opt])
+    self.assertEqual(kint32max, message_options.Extensions[
+        unittest_custom_options_pb2.sint32_opt])
+    self.assertEqual(kint64max, message_options.Extensions[
+        unittest_custom_options_pb2.sint64_opt])
+    self.assertEqual(kuint32max, message_options.Extensions[
+        unittest_custom_options_pb2.fixed32_opt])
+    self.assertEqual(kuint64max, message_options.Extensions[
+        unittest_custom_options_pb2.fixed64_opt])
+    self.assertEqual(kint32max, message_options.Extensions[
+        unittest_custom_options_pb2.sfixed32_opt])
+    self.assertEqual(kint64max, message_options.Extensions[
+        unittest_custom_options_pb2.sfixed64_opt])
+
+    message_descriptor =\
+        unittest_custom_options_pb2.CustomOptionOtherValues.DESCRIPTOR
+    message_options = message_descriptor.GetOptions()
+    self.assertEqual(-100, message_options.Extensions[
+        unittest_custom_options_pb2.int32_opt])
+    self.assertAlmostEqual(12.3456789, message_options.Extensions[
+        unittest_custom_options_pb2.float_opt], 6)
+    self.assertAlmostEqual(1.234567890123456789, message_options.Extensions[
+        unittest_custom_options_pb2.double_opt])
+    self.assertEqual("Hello, \"World\"", message_options.Extensions[
+        unittest_custom_options_pb2.string_opt])
+    self.assertEqual("Hello\0World", message_options.Extensions[
+        unittest_custom_options_pb2.bytes_opt])
+    dummy_enum = unittest_custom_options_pb2.DummyMessageContainingEnum
+    self.assertEqual(
+        dummy_enum.TEST_OPTION_ENUM_TYPE2,
+        message_options.Extensions[unittest_custom_options_pb2.enum_opt])
+
+    message_descriptor =\
+        unittest_custom_options_pb2.SettingRealsFromPositiveInts.DESCRIPTOR
+    message_options = message_descriptor.GetOptions()
+    self.assertAlmostEqual(12, message_options.Extensions[
+        unittest_custom_options_pb2.float_opt], 6)
+    self.assertAlmostEqual(154, message_options.Extensions[
+        unittest_custom_options_pb2.double_opt])
+
+    message_descriptor =\
+        unittest_custom_options_pb2.SettingRealsFromNegativeInts.DESCRIPTOR
+    message_options = message_descriptor.GetOptions()
+    self.assertAlmostEqual(-12, message_options.Extensions[
+        unittest_custom_options_pb2.float_opt], 6)
+    self.assertAlmostEqual(-154, message_options.Extensions[
+        unittest_custom_options_pb2.double_opt])
+
+  def testComplexExtensionOptions(self):
+    descriptor =\
+        unittest_custom_options_pb2.VariousComplexOptions.DESCRIPTOR
+    options = descriptor.GetOptions()
+    self.assertEqual(42, options.Extensions[
+        unittest_custom_options_pb2.complex_opt1].foo)
+    self.assertEqual(324, options.Extensions[
+        unittest_custom_options_pb2.complex_opt1].Extensions[
+            unittest_custom_options_pb2.quux])
+    self.assertEqual(876, options.Extensions[
+        unittest_custom_options_pb2.complex_opt1].Extensions[
+            unittest_custom_options_pb2.corge].qux)
+    self.assertEqual(987, options.Extensions[
+        unittest_custom_options_pb2.complex_opt2].baz)
+    self.assertEqual(654, options.Extensions[
+        unittest_custom_options_pb2.complex_opt2].Extensions[
+            unittest_custom_options_pb2.grault])
+    self.assertEqual(743, options.Extensions[
+        unittest_custom_options_pb2.complex_opt2].bar.foo)
+    self.assertEqual(1999, options.Extensions[
+        unittest_custom_options_pb2.complex_opt2].bar.Extensions[
+            unittest_custom_options_pb2.quux])
+    self.assertEqual(2008, options.Extensions[
+        unittest_custom_options_pb2.complex_opt2].bar.Extensions[
+            unittest_custom_options_pb2.corge].qux)
+    self.assertEqual(741, options.Extensions[
+        unittest_custom_options_pb2.complex_opt2].Extensions[
+            unittest_custom_options_pb2.garply].foo)
+    self.assertEqual(1998, options.Extensions[
+        unittest_custom_options_pb2.complex_opt2].Extensions[
+            unittest_custom_options_pb2.garply].Extensions[
+                unittest_custom_options_pb2.quux])
+    self.assertEqual(2121, options.Extensions[
+        unittest_custom_options_pb2.complex_opt2].Extensions[
+            unittest_custom_options_pb2.garply].Extensions[
+                unittest_custom_options_pb2.corge].qux)
+    self.assertEqual(1971, options.Extensions[
+        unittest_custom_options_pb2.ComplexOptionType2
+        .ComplexOptionType4.complex_opt4].waldo)
+    self.assertEqual(321, options.Extensions[
+        unittest_custom_options_pb2.complex_opt2].fred.waldo)
+    self.assertEqual(9, options.Extensions[
+        unittest_custom_options_pb2.complex_opt3].qux)
+    self.assertEqual(22, options.Extensions[
+        unittest_custom_options_pb2.complex_opt3].complexoptiontype5.plugh)
+    self.assertEqual(24, options.Extensions[
+        unittest_custom_options_pb2.complexopt6].xyzzy)
+
+  # Check that aggregate options were parsed and saved correctly in
+  # the appropriate descriptors.
+  def testAggregateOptions(self):
+    file_descriptor = unittest_custom_options_pb2.DESCRIPTOR
+    message_descriptor =\
+        unittest_custom_options_pb2.AggregateMessage.DESCRIPTOR
+    field_descriptor = message_descriptor.fields_by_name["fieldname"]
+    enum_descriptor = unittest_custom_options_pb2.AggregateEnum.DESCRIPTOR
+    enum_value_descriptor = enum_descriptor.values_by_name["VALUE"]
+    service_descriptor =\
+        unittest_custom_options_pb2.AggregateService.DESCRIPTOR
+    method_descriptor = service_descriptor.FindMethodByName("Method")
+
+    # Tests for the different types of data embedded in fileopt
+    file_options = file_descriptor.GetOptions().Extensions[
+        unittest_custom_options_pb2.fileopt]
+    self.assertEqual(100, file_options.i)
+    self.assertEqual("FileAnnotation", file_options.s)
+    self.assertEqual("NestedFileAnnotation", file_options.sub.s)
+    self.assertEqual("FileExtensionAnnotation", file_options.file.Extensions[
+        unittest_custom_options_pb2.fileopt].s)
+    self.assertEqual("EmbeddedMessageSetElement", file_options.mset.Extensions[
+        unittest_custom_options_pb2.AggregateMessageSetElement
+        .message_set_extension].s)
+
+    # Simple tests for all the other types of annotations
+    self.assertEqual(
+        "MessageAnnotation",
+        message_descriptor.GetOptions().Extensions[
+            unittest_custom_options_pb2.msgopt].s)
+    self.assertEqual(
+        "FieldAnnotation",
+        field_descriptor.GetOptions().Extensions[
+            unittest_custom_options_pb2.fieldopt].s)
+    self.assertEqual(
+        "EnumAnnotation",
+        enum_descriptor.GetOptions().Extensions[
+            unittest_custom_options_pb2.enumopt].s)
+    self.assertEqual(
+        "EnumValueAnnotation",
+        enum_value_descriptor.GetOptions().Extensions[
+            unittest_custom_options_pb2.enumvalopt].s)
+    self.assertEqual(
+        "ServiceAnnotation",
+        service_descriptor.GetOptions().Extensions[
+            unittest_custom_options_pb2.serviceopt].s)
+    self.assertEqual(
+        "MethodAnnotation",
+        method_descriptor.GetOptions().Extensions[
+            unittest_custom_options_pb2.methodopt].s)
+
+  def testNestedOptions(self):
+    nested_message =\
+        unittest_custom_options_pb2.NestedOptionType.NestedMessage.DESCRIPTOR
+    self.assertEqual(1001, nested_message.GetOptions().Extensions[
+        unittest_custom_options_pb2.message_opt1])
+    nested_field = nested_message.fields_by_name["nested_field"]
+    self.assertEqual(1002, nested_field.GetOptions().Extensions[
+        unittest_custom_options_pb2.field_opt1])
+    outer_message =\
+        unittest_custom_options_pb2.NestedOptionType.DESCRIPTOR
+    nested_enum = outer_message.enum_types_by_name["NestedEnum"]
+    self.assertEqual(1003, nested_enum.GetOptions().Extensions[
+        unittest_custom_options_pb2.enum_opt1])
+    nested_enum_value = outer_message.enum_values_by_name["NESTED_ENUM_VALUE"]
+    self.assertEqual(1004, nested_enum_value.GetOptions().Extensions[
+        unittest_custom_options_pb2.enum_value_opt1])
+    nested_extension = outer_message.extensions_by_name["nested_extension"]
+    self.assertEqual(1005, nested_extension.GetOptions().Extensions[
+        unittest_custom_options_pb2.field_opt2])
+
   def testFileDescriptorReferences(self):
     self.assertEqual(self.my_enum.file, self.my_file)
     self.assertEqual(self.my_message.file, self.my_file)
@@ -273,6 +534,7 @@
     UNITTEST_IMPORT_FILE_DESCRIPTOR_ASCII = ("""
       name: 'google/protobuf/unittest_import.proto'
       package: 'protobuf_unittest_import'
+      dependency: 'google/protobuf/unittest_import_public.proto'
       message_type: <
         name: 'ImportMessage'
         field: <
@@ -302,6 +564,7 @@
         java_package: 'com.google.protobuf.test'
         optimize_for: 1  # SPEED
       >
+      public_dependency: 0
       """)
 
     self._InternalTestCopyToProto(
@@ -330,5 +593,21 @@
         TEST_SERVICE_ASCII)
 
 
+class MakeDescriptorTest(unittest.TestCase):
+  def testMakeDescriptorWithUnsignedIntField(self):
+    file_descriptor_proto = descriptor_pb2.FileDescriptorProto()
+    file_descriptor_proto.name = 'Foo'
+    message_type = file_descriptor_proto.message_type.add()
+    message_type.name = file_descriptor_proto.name
+    field = message_type.field.add()
+    field.number = 1
+    field.name = 'uint64_field'
+    field.label = descriptor.FieldDescriptor.LABEL_REQUIRED
+    field.type = descriptor.FieldDescriptor.TYPE_UINT64
+    result = descriptor.MakeDescriptor(message_type)
+    self.assertEqual(result.fields[0].cpp_type,
+                     descriptor.FieldDescriptor.CPPTYPE_UINT64)
+
+
 if __name__ == '__main__':
   unittest.main()
diff --git a/third_party/protobuf/python/google/protobuf/internal/enum_type_wrapper.py b/third_party/protobuf/python/google/protobuf/internal/enum_type_wrapper.py
new file mode 100644
index 0000000..7b28645
--- /dev/null
+++ b/third_party/protobuf/python/google/protobuf/internal/enum_type_wrapper.py
@@ -0,0 +1,89 @@
+# Protocol Buffers - Google's data interchange format
+# Copyright 2008 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.
+
+"""A simple wrapper around enum types to expose utility functions.
+
+Instances are created as properties with the same name as the enum they wrap
+on proto classes.  For usage, see:
+  reflection_test.py
+"""
+
+__author__ = 'rabsatt@google.com (Kevin Rabsatt)'
+
+
+class EnumTypeWrapper(object):
+  """A utility for finding the names of enum values."""
+
+  DESCRIPTOR = None
+
+  def __init__(self, enum_type):
+    """Inits EnumTypeWrapper with an EnumDescriptor."""
+    self._enum_type = enum_type
+    self.DESCRIPTOR = enum_type;
+
+  def Name(self, number):
+    """Returns a string containing the name of an enum value."""
+    if number in self._enum_type.values_by_number:
+      return self._enum_type.values_by_number[number].name
+    raise ValueError('Enum %s has no name defined for value %d' % (
+        self._enum_type.name, number))
+
+  def Value(self, name):
+    """Returns the value coresponding to the given enum name."""
+    if name in self._enum_type.values_by_name:
+      return self._enum_type.values_by_name[name].number
+    raise ValueError('Enum %s has no value defined for name %s' % (
+        self._enum_type.name, name))
+
+  def keys(self):
+    """Return a list of the string names in the enum.
+
+    These are returned in the order they were defined in the .proto file.
+    """
+
+    return [value_descriptor.name
+            for value_descriptor in self._enum_type.values]
+
+  def values(self):
+    """Return a list of the integer values in the enum.
+
+    These are returned in the order they were defined in the .proto file.
+    """
+
+    return [value_descriptor.number
+            for value_descriptor in self._enum_type.values]
+
+  def items(self):
+    """Return a list of the (name, value) pairs of the enum.
+
+    These are returned in the order they were defined in the .proto file.
+    """
+    return [(value_descriptor.name, value_descriptor.number)
+            for value_descriptor in self._enum_type.values]
diff --git a/third_party/protobuf/python/google/protobuf/internal/factory_test1.proto b/third_party/protobuf/python/google/protobuf/internal/factory_test1.proto
new file mode 100644
index 0000000..9f55e03
--- /dev/null
+++ b/third_party/protobuf/python/google/protobuf/internal/factory_test1.proto
@@ -0,0 +1,55 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 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.
+
+// Author: matthewtoia@google.com (Matt Toia)
+
+
+package google.protobuf.python.internal;
+
+
+enum Factory1Enum {
+  FACTORY_1_VALUE_0 = 0;
+  FACTORY_1_VALUE_1 = 1;
+}
+
+message Factory1Message {
+  optional Factory1Enum factory_1_enum = 1;
+  enum NestedFactory1Enum {
+    NESTED_FACTORY_1_VALUE_0 = 0;
+    NESTED_FACTORY_1_VALUE_1 = 1;
+  }
+  optional NestedFactory1Enum nested_factory_1_enum = 2;
+  message NestedFactory1Message {
+    optional string value = 1;
+  }
+  optional NestedFactory1Message nested_factory_1_message = 3;
+  optional int32 scalar_value = 4;
+  repeated string list_value = 5;
+}
diff --git a/third_party/protobuf/python/google/protobuf/internal/factory_test2.proto b/third_party/protobuf/python/google/protobuf/internal/factory_test2.proto
new file mode 100644
index 0000000..d3ce4d7
--- /dev/null
+++ b/third_party/protobuf/python/google/protobuf/internal/factory_test2.proto
@@ -0,0 +1,77 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 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.
+
+// Author: matthewtoia@google.com (Matt Toia)
+
+
+package google.protobuf.python.internal;
+
+import "google/protobuf/internal/factory_test1.proto";
+
+
+enum Factory2Enum {
+  FACTORY_2_VALUE_0 = 0;
+  FACTORY_2_VALUE_1 = 1;
+}
+
+message Factory2Message {
+  required int32 mandatory = 1;
+  optional Factory2Enum factory_2_enum = 2;
+  enum NestedFactory2Enum {
+    NESTED_FACTORY_2_VALUE_0 = 0;
+    NESTED_FACTORY_2_VALUE_1 = 1;
+  }
+  optional NestedFactory2Enum nested_factory_2_enum = 3;
+  message NestedFactory2Message {
+    optional string value = 1;
+  }
+  optional NestedFactory2Message nested_factory_2_message = 4;
+  optional Factory1Message factory_1_message = 5;
+  optional Factory1Enum factory_1_enum = 6;
+  optional Factory1Message.NestedFactory1Enum nested_factory_1_enum = 7;
+  optional Factory1Message.NestedFactory1Message nested_factory_1_message = 8;
+  optional Factory2Message circular_message = 9;
+  optional string scalar_value = 10;
+  repeated string list_value = 11;
+  repeated group Grouped = 12 {
+    optional string part_1 = 13;
+    optional string part_2 = 14;
+  }
+  optional LoopMessage loop = 15;
+  optional int32 int_with_default = 16 [default = 1776];
+  optional double double_with_default = 17 [default = 9.99];
+  optional string string_with_default = 18 [default = "hello world"];
+  optional bool bool_with_default = 19 [default = false];
+  optional Factory2Enum enum_with_default = 20 [default = FACTORY_2_VALUE_1];
+}
+
+message LoopMessage {
+  optional Factory2Message loop = 1;
+}
diff --git a/third_party/protobuf/python/google/protobuf/internal/generator_test.py b/third_party/protobuf/python/google/protobuf/internal/generator_test.py
index b3f7d9b..8343aba 100755
--- a/third_party/protobuf/python/google/protobuf/internal/generator_test.py
+++ b/third_party/protobuf/python/google/protobuf/internal/generator_test.py
@@ -42,8 +42,10 @@
 __author__ = 'robinson@google.com (Will Robinson)'
 
 import unittest
+from google.protobuf.internal import test_bad_identifiers_pb2
 from google.protobuf import unittest_custom_options_pb2
 from google.protobuf import unittest_import_pb2
+from google.protobuf import unittest_import_public_pb2
 from google.protobuf import unittest_mset_pb2
 from google.protobuf import unittest_pb2
 from google.protobuf import unittest_no_generic_services_pb2
@@ -239,6 +241,29 @@
         unittest_pb2._TESTALLTYPES_NESTEDMESSAGE.name in
         file_type.message_types_by_name)
 
+  def testPublicImports(self):
+    # Test public imports as embedded message.
+    all_type_proto = unittest_pb2.TestAllTypes()
+    self.assertEqual(0, all_type_proto.optional_public_import_message.e)
+
+    # PublicImportMessage is actually defined in unittest_import_public_pb2
+    # module, and is public imported by unittest_import_pb2 module.
+    public_import_proto = unittest_import_pb2.PublicImportMessage()
+    self.assertEqual(0, public_import_proto.e)
+    self.assertTrue(unittest_import_public_pb2.PublicImportMessage is
+                    unittest_import_pb2.PublicImportMessage)
+
+  def testBadIdentifiers(self):
+    # We're just testing that the code was imported without problems.
+    message = test_bad_identifiers_pb2.TestBadIdentifiers()
+    self.assertEqual(message.Extensions[test_bad_identifiers_pb2.message],
+                     "foo")
+    self.assertEqual(message.Extensions[test_bad_identifiers_pb2.descriptor],
+                     "bar")
+    self.assertEqual(message.Extensions[test_bad_identifiers_pb2.reflection],
+                     "baz")
+    self.assertEqual(message.Extensions[test_bad_identifiers_pb2.service],
+                     "qux")
 
 if __name__ == '__main__':
   unittest.main()
diff --git a/third_party/protobuf/python/google/protobuf/internal/message_cpp_test.py b/third_party/protobuf/python/google/protobuf/internal/message_cpp_test.py
new file mode 100644
index 0000000..0d84b32
--- /dev/null
+++ b/third_party/protobuf/python/google/protobuf/internal/message_cpp_test.py
@@ -0,0 +1,45 @@
+#! /usr/bin/python
+#
+# Protocol Buffers - Google's data interchange format
+# Copyright 2008 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.
+
+"""Tests for google.protobuf.internal.message_cpp."""
+
+__author__ = 'shahms@google.com (Shahms King)'
+
+import os
+os.environ['PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION'] = 'cpp'
+
+import unittest
+from google.protobuf.internal.message_test import *
+
+
+if __name__ == '__main__':
+  unittest.main()
diff --git a/third_party/protobuf/python/google/protobuf/internal/message_factory_test.py b/third_party/protobuf/python/google/protobuf/internal/message_factory_test.py
new file mode 100644
index 0000000..0bc9be9
--- /dev/null
+++ b/third_party/protobuf/python/google/protobuf/internal/message_factory_test.py
@@ -0,0 +1,113 @@
+#! /usr/bin/python
+#
+# Protocol Buffers - Google's data interchange format
+# Copyright 2008 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.
+
+"""Tests for google.protobuf.message_factory."""
+
+__author__ = 'matthewtoia@google.com (Matt Toia)'
+
+import unittest
+from google.protobuf import descriptor_pb2
+from google.protobuf.internal import factory_test1_pb2
+from google.protobuf.internal import factory_test2_pb2
+from google.protobuf import descriptor_database
+from google.protobuf import descriptor_pool
+from google.protobuf import message_factory
+
+
+class MessageFactoryTest(unittest.TestCase):
+
+  def setUp(self):
+    self.factory_test1_fd = descriptor_pb2.FileDescriptorProto.FromString(
+        factory_test1_pb2.DESCRIPTOR.serialized_pb)
+    self.factory_test2_fd = descriptor_pb2.FileDescriptorProto.FromString(
+        factory_test2_pb2.DESCRIPTOR.serialized_pb)
+
+  def _ExerciseDynamicClass(self, cls):
+    msg = cls()
+    msg.mandatory = 42
+    msg.nested_factory_2_enum = 0
+    msg.nested_factory_2_message.value = 'nested message value'
+    msg.factory_1_message.factory_1_enum = 1
+    msg.factory_1_message.nested_factory_1_enum = 0
+    msg.factory_1_message.nested_factory_1_message.value = (
+        'nested message value')
+    msg.factory_1_message.scalar_value = 22
+    msg.factory_1_message.list_value.extend(['one', 'two', 'three'])
+    msg.factory_1_message.list_value.append('four')
+    msg.factory_1_enum = 1
+    msg.nested_factory_1_enum = 0
+    msg.nested_factory_1_message.value = 'nested message value'
+    msg.circular_message.mandatory = 1
+    msg.circular_message.circular_message.mandatory = 2
+    msg.circular_message.scalar_value = 'one deep'
+    msg.scalar_value = 'zero deep'
+    msg.list_value.extend(['four', 'three', 'two'])
+    msg.list_value.append('one')
+    msg.grouped.add()
+    msg.grouped[0].part_1 = 'hello'
+    msg.grouped[0].part_2 = 'world'
+    msg.grouped.add(part_1='testing', part_2='123')
+    msg.loop.loop.mandatory = 2
+    msg.loop.loop.loop.loop.mandatory = 4
+    serialized = msg.SerializeToString()
+    converted = factory_test2_pb2.Factory2Message.FromString(serialized)
+    reserialized = converted.SerializeToString()
+    self.assertEquals(serialized, reserialized)
+    result = cls.FromString(reserialized)
+    self.assertEquals(msg, result)
+
+  def testGetPrototype(self):
+    db = descriptor_database.DescriptorDatabase()
+    pool = descriptor_pool.DescriptorPool(db)
+    db.Add(self.factory_test1_fd)
+    db.Add(self.factory_test2_fd)
+    factory = message_factory.MessageFactory()
+    cls = factory.GetPrototype(pool.FindMessageTypeByName(
+        'net.proto2.python.internal.Factory2Message'))
+    self.assertIsNot(cls, factory_test2_pb2.Factory2Message)
+    self._ExerciseDynamicClass(cls)
+    cls2 = factory.GetPrototype(pool.FindMessageTypeByName(
+        'net.proto2.python.internal.Factory2Message'))
+    self.assertIs(cls, cls2)
+
+  def testGetMessages(self):
+    messages = message_factory.GetMessages([self.factory_test2_fd,
+                                            self.factory_test1_fd])
+    self.assertContainsSubset(
+        ['net.proto2.python.internal.Factory2Message',
+         'net.proto2.python.internal.Factory1Message'],
+        messages.keys())
+    self._ExerciseDynamicClass(
+        messages['net.proto2.python.internal.Factory2Message'])
+
+if __name__ == '__main__':
+  unittest.main()
diff --git a/third_party/protobuf/python/google/protobuf/internal/message_test.py b/third_party/protobuf/python/google/protobuf/internal/message_test.py
index 6517437..53e9d50 100755
--- a/third_party/protobuf/python/google/protobuf/internal/message_test.py
+++ b/third_party/protobuf/python/google/protobuf/internal/message_test.py
@@ -45,10 +45,15 @@
 
 import copy
 import math
+import operator
+import pickle
+
 import unittest
 from google.protobuf import unittest_import_pb2
 from google.protobuf import unittest_pb2
+from google.protobuf.internal import api_implementation
 from google.protobuf.internal import test_util
+from google.protobuf import message
 
 # Python pre-2.6 does not have isinf() or isnan() functions, so we have
 # to provide our own.
@@ -70,9 +75,9 @@
     golden_message = unittest_pb2.TestAllTypes()
     golden_message.ParseFromString(golden_data)
     test_util.ExpectAllFieldsSet(self, golden_message)
-    self.assertTrue(golden_message.SerializeToString() == golden_data)
+    self.assertEqual(golden_data, golden_message.SerializeToString())
     golden_copy = copy.deepcopy(golden_message)
-    self.assertTrue(golden_copy.SerializeToString() == golden_data)
+    self.assertEqual(golden_data, golden_copy.SerializeToString())
 
   def testGoldenExtensions(self):
     golden_data = test_util.GoldenFile('golden_message').read()
@@ -81,9 +86,9 @@
     all_set = unittest_pb2.TestAllExtensions()
     test_util.SetAllExtensions(all_set)
     self.assertEquals(all_set, golden_message)
-    self.assertTrue(golden_message.SerializeToString() == golden_data)
+    self.assertEqual(golden_data, golden_message.SerializeToString())
     golden_copy = copy.deepcopy(golden_message)
-    self.assertTrue(golden_copy.SerializeToString() == golden_data)
+    self.assertEqual(golden_data, golden_copy.SerializeToString())
 
   def testGoldenPackedMessage(self):
     golden_data = test_util.GoldenFile('golden_packed_fields_message').read()
@@ -92,9 +97,9 @@
     all_set = unittest_pb2.TestPackedTypes()
     test_util.SetAllPackedFields(all_set)
     self.assertEquals(all_set, golden_message)
-    self.assertTrue(all_set.SerializeToString() == golden_data)
+    self.assertEqual(golden_data, all_set.SerializeToString())
     golden_copy = copy.deepcopy(golden_message)
-    self.assertTrue(golden_copy.SerializeToString() == golden_data)
+    self.assertEqual(golden_data, golden_copy.SerializeToString())
 
   def testGoldenPackedExtensions(self):
     golden_data = test_util.GoldenFile('golden_packed_fields_message').read()
@@ -103,9 +108,28 @@
     all_set = unittest_pb2.TestPackedExtensions()
     test_util.SetAllPackedExtensions(all_set)
     self.assertEquals(all_set, golden_message)
-    self.assertTrue(all_set.SerializeToString() == golden_data)
+    self.assertEqual(golden_data, all_set.SerializeToString())
     golden_copy = copy.deepcopy(golden_message)
-    self.assertTrue(golden_copy.SerializeToString() == golden_data)
+    self.assertEqual(golden_data, golden_copy.SerializeToString())
+
+  def testPickleSupport(self):
+    golden_data = test_util.GoldenFile('golden_message').read()
+    golden_message = unittest_pb2.TestAllTypes()
+    golden_message.ParseFromString(golden_data)
+    pickled_message = pickle.dumps(golden_message)
+
+    unpickled_message = pickle.loads(pickled_message)
+    self.assertEquals(unpickled_message, golden_message)
+
+  def testPickleIncompleteProto(self):
+    golden_message = unittest_pb2.TestRequired(a=1)
+    pickled_message = pickle.dumps(golden_message)
+
+    unpickled_message = pickle.loads(pickled_message)
+    self.assertEquals(unpickled_message, golden_message)
+    self.assertEquals(unpickled_message.a, 1)
+    # This is still an incomplete proto - so serializing should fail
+    self.assertRaises(message.EncodeError, unpickled_message.SerializeToString)
 
   def testPositiveInfinity(self):
     golden_data = ('\x5D\x00\x00\x80\x7F'
@@ -118,7 +142,7 @@
     self.assertTrue(IsPosInf(golden_message.optional_double))
     self.assertTrue(IsPosInf(golden_message.repeated_float[0]))
     self.assertTrue(IsPosInf(golden_message.repeated_double[0]))
-    self.assertTrue(golden_message.SerializeToString() == golden_data)
+    self.assertEqual(golden_data, golden_message.SerializeToString())
 
   def testNegativeInfinity(self):
     golden_data = ('\x5D\x00\x00\x80\xFF'
@@ -131,7 +155,7 @@
     self.assertTrue(IsNegInf(golden_message.optional_double))
     self.assertTrue(IsNegInf(golden_message.repeated_float[0]))
     self.assertTrue(IsNegInf(golden_message.repeated_double[0]))
-    self.assertTrue(golden_message.SerializeToString() == golden_data)
+    self.assertEqual(golden_data, golden_message.SerializeToString())
 
   def testNotANumber(self):
     golden_data = ('\x5D\x00\x00\xC0\x7F'
@@ -144,7 +168,18 @@
     self.assertTrue(isnan(golden_message.optional_double))
     self.assertTrue(isnan(golden_message.repeated_float[0]))
     self.assertTrue(isnan(golden_message.repeated_double[0]))
-    self.assertTrue(golden_message.SerializeToString() == golden_data)
+
+    # The protocol buffer may serialize to any one of multiple different
+    # representations of a NaN.  Rather than verify a specific representation,
+    # verify the serialized string can be converted into a correctly
+    # behaving protocol buffer.
+    serialized = golden_message.SerializeToString()
+    message = unittest_pb2.TestAllTypes()
+    message.ParseFromString(serialized)
+    self.assertTrue(isnan(message.optional_float))
+    self.assertTrue(isnan(message.optional_double))
+    self.assertTrue(isnan(message.repeated_float[0]))
+    self.assertTrue(isnan(message.repeated_double[0]))
 
   def testPositiveInfinityPacked(self):
     golden_data = ('\xA2\x06\x04\x00\x00\x80\x7F'
@@ -153,7 +188,7 @@
     golden_message.ParseFromString(golden_data)
     self.assertTrue(IsPosInf(golden_message.packed_float[0]))
     self.assertTrue(IsPosInf(golden_message.packed_double[0]))
-    self.assertTrue(golden_message.SerializeToString() == golden_data)
+    self.assertEqual(golden_data, golden_message.SerializeToString())
 
   def testNegativeInfinityPacked(self):
     golden_data = ('\xA2\x06\x04\x00\x00\x80\xFF'
@@ -162,7 +197,7 @@
     golden_message.ParseFromString(golden_data)
     self.assertTrue(IsNegInf(golden_message.packed_float[0]))
     self.assertTrue(IsNegInf(golden_message.packed_double[0]))
-    self.assertTrue(golden_message.SerializeToString() == golden_data)
+    self.assertEqual(golden_data, golden_message.SerializeToString())
 
   def testNotANumberPacked(self):
     golden_data = ('\xA2\x06\x04\x00\x00\xC0\x7F'
@@ -171,7 +206,12 @@
     golden_message.ParseFromString(golden_data)
     self.assertTrue(isnan(golden_message.packed_float[0]))
     self.assertTrue(isnan(golden_message.packed_double[0]))
-    self.assertTrue(golden_message.SerializeToString() == golden_data)
+
+    serialized = golden_message.SerializeToString()
+    message = unittest_pb2.TestPackedTypes()
+    message.ParseFromString(serialized)
+    self.assertTrue(isnan(message.packed_float[0]))
+    self.assertTrue(isnan(message.packed_double[0]))
 
   def testExtremeFloatValues(self):
     message = unittest_pb2.TestAllTypes()
@@ -218,7 +258,7 @@
     message.ParseFromString(message.SerializeToString())
     self.assertTrue(message.optional_float == -kMostNegExponentOneSigBit)
 
-  def testExtremeFloatValues(self):
+  def testExtremeDoubleValues(self):
     message = unittest_pb2.TestAllTypes()
 
     # Most positive exponent, no significand bits set.
@@ -338,6 +378,117 @@
     self.assertEqual(message.repeated_nested_message[4].bb, 5)
     self.assertEqual(message.repeated_nested_message[5].bb, 6)
 
+  def testRepeatedCompositeFieldSortArguments(self):
+    """Check sorting a repeated composite field using list.sort() arguments."""
+    message = unittest_pb2.TestAllTypes()
+
+    get_bb = operator.attrgetter('bb')
+    cmp_bb = lambda a, b: cmp(a.bb, b.bb)
+    message.repeated_nested_message.add().bb = 1
+    message.repeated_nested_message.add().bb = 3
+    message.repeated_nested_message.add().bb = 2
+    message.repeated_nested_message.add().bb = 6
+    message.repeated_nested_message.add().bb = 5
+    message.repeated_nested_message.add().bb = 4
+    message.repeated_nested_message.sort(key=get_bb)
+    self.assertEqual([k.bb for k in message.repeated_nested_message],
+                     [1, 2, 3, 4, 5, 6])
+    message.repeated_nested_message.sort(key=get_bb, reverse=True)
+    self.assertEqual([k.bb for k in message.repeated_nested_message],
+                     [6, 5, 4, 3, 2, 1])
+    message.repeated_nested_message.sort(sort_function=cmp_bb)
+    self.assertEqual([k.bb for k in message.repeated_nested_message],
+                     [1, 2, 3, 4, 5, 6])
+    message.repeated_nested_message.sort(cmp=cmp_bb, reverse=True)
+    self.assertEqual([k.bb for k in message.repeated_nested_message],
+                     [6, 5, 4, 3, 2, 1])
+
+  def testRepeatedScalarFieldSortArguments(self):
+    """Check sorting a scalar field using list.sort() arguments."""
+    message = unittest_pb2.TestAllTypes()
+
+    abs_cmp = lambda a, b: cmp(abs(a), abs(b))
+    message.repeated_int32.append(-3)
+    message.repeated_int32.append(-2)
+    message.repeated_int32.append(-1)
+    message.repeated_int32.sort(key=abs)
+    self.assertEqual(list(message.repeated_int32), [-1, -2, -3])
+    message.repeated_int32.sort(key=abs, reverse=True)
+    self.assertEqual(list(message.repeated_int32), [-3, -2, -1])
+    message.repeated_int32.sort(sort_function=abs_cmp)
+    self.assertEqual(list(message.repeated_int32), [-1, -2, -3])
+    message.repeated_int32.sort(cmp=abs_cmp, reverse=True)
+    self.assertEqual(list(message.repeated_int32), [-3, -2, -1])
+
+    len_cmp = lambda a, b: cmp(len(a), len(b))
+    message.repeated_string.append('aaa')
+    message.repeated_string.append('bb')
+    message.repeated_string.append('c')
+    message.repeated_string.sort(key=len)
+    self.assertEqual(list(message.repeated_string), ['c', 'bb', 'aaa'])
+    message.repeated_string.sort(key=len, reverse=True)
+    self.assertEqual(list(message.repeated_string), ['aaa', 'bb', 'c'])
+    message.repeated_string.sort(sort_function=len_cmp)
+    self.assertEqual(list(message.repeated_string), ['c', 'bb', 'aaa'])
+    message.repeated_string.sort(cmp=len_cmp, reverse=True)
+    self.assertEqual(list(message.repeated_string), ['aaa', 'bb', 'c'])
+
+  def testParsingMerge(self):
+    """Check the merge behavior when a required or optional field appears
+    multiple times in the input."""
+    messages = [
+        unittest_pb2.TestAllTypes(),
+        unittest_pb2.TestAllTypes(),
+        unittest_pb2.TestAllTypes() ]
+    messages[0].optional_int32 = 1
+    messages[1].optional_int64 = 2
+    messages[2].optional_int32 = 3
+    messages[2].optional_string = 'hello'
+
+    merged_message = unittest_pb2.TestAllTypes()
+    merged_message.optional_int32 = 3
+    merged_message.optional_int64 = 2
+    merged_message.optional_string = 'hello'
+
+    generator = unittest_pb2.TestParsingMerge.RepeatedFieldsGenerator()
+    generator.field1.extend(messages)
+    generator.field2.extend(messages)
+    generator.field3.extend(messages)
+    generator.ext1.extend(messages)
+    generator.ext2.extend(messages)
+    generator.group1.add().field1.MergeFrom(messages[0])
+    generator.group1.add().field1.MergeFrom(messages[1])
+    generator.group1.add().field1.MergeFrom(messages[2])
+    generator.group2.add().field1.MergeFrom(messages[0])
+    generator.group2.add().field1.MergeFrom(messages[1])
+    generator.group2.add().field1.MergeFrom(messages[2])
+
+    data = generator.SerializeToString()
+    parsing_merge = unittest_pb2.TestParsingMerge()
+    parsing_merge.ParseFromString(data)
+
+    # Required and optional fields should be merged.
+    self.assertEqual(parsing_merge.required_all_types, merged_message)
+    self.assertEqual(parsing_merge.optional_all_types, merged_message)
+    self.assertEqual(parsing_merge.optionalgroup.optional_group_all_types,
+                     merged_message)
+    self.assertEqual(parsing_merge.Extensions[
+                     unittest_pb2.TestParsingMerge.optional_ext],
+                     merged_message)
+
+    # Repeated fields should not be merged.
+    self.assertEqual(len(parsing_merge.repeated_all_types), 3)
+    self.assertEqual(len(parsing_merge.repeatedgroup), 3)
+    self.assertEqual(len(parsing_merge.Extensions[
+        unittest_pb2.TestParsingMerge.repeated_ext]), 3)
+
+
+  def testSortEmptyRepeatedCompositeContainer(self):
+    """Exercise a scenario that has led to segfaults in the past.
+    """
+    m = unittest_pb2.TestAllTypes()
+    m.repeated_nested_message.sort()
+
 
 if __name__ == '__main__':
   unittest.main()
diff --git a/third_party/protobuf/python/google/protobuf/internal/more_extensions_dynamic.proto b/third_party/protobuf/python/google/protobuf/internal/more_extensions_dynamic.proto
new file mode 100644
index 0000000..df98ac4
--- /dev/null
+++ b/third_party/protobuf/python/google/protobuf/internal/more_extensions_dynamic.proto
@@ -0,0 +1,49 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 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.
+
+// Author: jasonh@google.com (Jason Hsueh)
+//
+// This file is used to test a corner case in the CPP implementation where the
+// generated C++ type is available for the extendee, but the extension is
+// defined in a file whose C++ type is not in the binary.
+
+
+import "google/protobuf/internal/more_extensions.proto";
+
+package google.protobuf.internal;
+
+message DynamicMessageType {
+  optional int32 a = 1;
+}
+
+extend ExtendedMessage {
+  optional int32 dynamic_int32_extension = 100;
+  optional DynamicMessageType dynamic_message_extension = 101;
+}
diff --git a/third_party/protobuf/python/google/protobuf/internal/python_message.py b/third_party/protobuf/python/google/protobuf/internal/python_message.py
index 66fca91..4bea57a 100644
--- a/third_party/protobuf/python/google/protobuf/internal/python_message.py
+++ b/third_party/protobuf/python/google/protobuf/internal/python_message.py
@@ -54,6 +54,7 @@
   from cStringIO import StringIO
 except ImportError:
   from StringIO import StringIO
+import copy_reg
 import struct
 import weakref
 
@@ -61,6 +62,7 @@
 from google.protobuf.internal import containers
 from google.protobuf.internal import decoder
 from google.protobuf.internal import encoder
+from google.protobuf.internal import enum_type_wrapper
 from google.protobuf.internal import message_listener as message_listener_mod
 from google.protobuf.internal import type_checkers
 from google.protobuf.internal import wire_format
@@ -71,9 +73,10 @@
 _FieldDescriptor = descriptor_mod.FieldDescriptor
 
 
-def NewMessage(descriptor, dictionary):
+def NewMessage(bases, descriptor, dictionary):
   _AddClassAttributesForNestedExtensions(descriptor, dictionary)
   _AddSlots(descriptor, dictionary)
+  return bases
 
 
 def InitMessage(descriptor, cls):
@@ -96,6 +99,7 @@
   _AddStaticMethods(cls)
   _AddMessageMethods(descriptor, cls)
   _AddPrivateHelperMethods(cls)
+  copy_reg.pickle(cls, lambda obj: (cls, (), obj.__getstate__()))
 
 
 # Stateless helpers for GeneratedProtocolMessageType below.
@@ -145,6 +149,10 @@
   if not extension_handle.is_extension:
     raise KeyError('"%s" is not an extension.' % extension_handle.full_name)
 
+  if not extension_handle.containing_type:
+    raise KeyError('"%s" is missing a containing_type.'
+                   % extension_handle.full_name)
+
   if extension_handle.containing_type is not message.DESCRIPTOR:
     raise KeyError('Extension "%s" extends message type "%s", but this '
                    'message is of type "%s".' %
@@ -164,6 +172,7 @@
   dictionary['__slots__'] = ['_cached_byte_size',
                              '_cached_byte_size_dirty',
                              '_fields',
+                             '_unknown_fields',
                              '_is_present_in_parent',
                              '_listener',
                              '_listener_for_children',
@@ -224,11 +233,14 @@
 def _AddEnumValues(descriptor, cls):
   """Sets class-level attributes for all enum fields defined in this message.
 
+  Also exporting a class-level object that can name enum values.
+
   Args:
     descriptor: Descriptor object for this message type.
     cls: Class we're constructing for this message type.
   """
   for enum_type in descriptor.enum_types:
+    setattr(cls, enum_type.name, enum_type_wrapper.EnumTypeWrapper(enum_type))
     for enum_value in enum_type.values:
       setattr(cls, enum_value.name, enum_value.number)
 
@@ -248,7 +260,7 @@
   """
 
   if field.label == _FieldDescriptor.LABEL_REPEATED:
-    if field.default_value != []:
+    if field.has_default_value and field.default_value != []:
       raise ValueError('Repeated field default value not empty list: %s' % (
           field.default_value))
     if field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE:
@@ -276,6 +288,8 @@
     return MakeSubMessageDefault
 
   def MakeScalarDefault(message):
+    # TODO(protobuf-team): This may be broken since there may not be
+    # default_value.  Combine with has_default_value somehow.
     return field.default_value
   return MakeScalarDefault
 
@@ -287,6 +301,9 @@
     self._cached_byte_size = 0
     self._cached_byte_size_dirty = len(kwargs) > 0
     self._fields = {}
+    # _unknown_fields is () when empty for efficiency, and will be turned into
+    # a list if fields are added.
+    self._unknown_fields = ()
     self._is_present_in_parent = False
     self._listener = message_listener_mod.NullMessageListener()
     self._listener_for_children = _Listener(self)
@@ -428,6 +445,8 @@
   valid_values = set()
 
   def getter(self):
+    # TODO(protobuf-team): This may be broken since there may not be
+    # default_value.  Combine with has_default_value somehow.
     return self._fields.get(field, default_value)
   getter.__module__ = None
   getter.__doc__ = 'Getter for %s.' % proto_field_name
@@ -462,13 +481,18 @@
   # for non-repeated scalars.
   proto_field_name = field.name
   property_name = _PropertyName(proto_field_name)
+
+  # TODO(komarek): Can anyone explain to me why we cache the message_type this
+  # way, instead of referring to field.message_type inside of getter(self)?
+  # What if someone sets message_type later on (which makes for simpler
+  # dyanmic proto descriptor and class creation code).
   message_type = field.message_type
 
   def getter(self):
     field_value = self._fields.get(field)
     if field_value is None:
       # Construct a new object to represent this field.
-      field_value = message_type._concrete_class()
+      field_value = message_type._concrete_class()  # use field.message_type?
       field_value._SetListener(self._listener_for_children)
 
       # Atomically check if another thread has preempted us and, if not, swap
@@ -620,6 +644,7 @@
   def Clear(self):
     # Clear fields.
     self._fields = {}
+    self._unknown_fields = ()
     self._Modified()
   cls.Clear = Clear
 
@@ -649,7 +674,16 @@
     if self is other:
       return True
 
-    return self.ListFields() == other.ListFields()
+    if not self.ListFields() == other.ListFields():
+      return False
+
+    # Sort unknown fields because their order shouldn't affect equality test.
+    unknown_fields = list(self._unknown_fields)
+    unknown_fields.sort()
+    other_unknown_fields = list(other._unknown_fields)
+    other_unknown_fields.sort()
+
+    return unknown_fields == other_unknown_fields
 
   cls.__eq__ = __eq__
 
@@ -710,6 +744,9 @@
     for field_descriptor, field_value in self.ListFields():
       size += field_descriptor._sizer(field_value)
 
+    for tag_bytes, value_bytes in self._unknown_fields:
+      size += len(tag_bytes) + len(value_bytes)
+
     self._cached_byte_size = size
     self._cached_byte_size_dirty = False
     self._listener_for_children.dirty = False
@@ -726,8 +763,8 @@
     errors = []
     if not self.IsInitialized():
       raise message_mod.EncodeError(
-          'Message is missing required fields: ' +
-          ','.join(self.FindInitializationErrors()))
+          'Message %s is missing required fields: %s' % (
+          self.DESCRIPTOR.full_name, ','.join(self.FindInitializationErrors())))
     return self.SerializePartialToString()
   cls.SerializeToString = SerializeToString
 
@@ -744,6 +781,9 @@
   def InternalSerialize(self, write_bytes):
     for field_descriptor, field_value in self.ListFields():
       field_descriptor._encoder(write_bytes, field_value)
+    for tag_bytes, value_bytes in self._unknown_fields:
+      write_bytes(tag_bytes)
+      write_bytes(value_bytes)
   cls._InternalSerialize = InternalSerialize
 
 
@@ -770,13 +810,18 @@
   def InternalParse(self, buffer, pos, end):
     self._Modified()
     field_dict = self._fields
+    unknown_field_list = self._unknown_fields
     while pos != end:
       (tag_bytes, new_pos) = local_ReadTag(buffer, pos)
       field_decoder = decoders_by_tag.get(tag_bytes)
       if field_decoder is None:
+        value_start_pos = new_pos
         new_pos = local_SkipField(buffer, new_pos, end, tag_bytes)
         if new_pos == -1:
           return pos
+        if not unknown_field_list:
+          unknown_field_list = self._unknown_fields = []
+        unknown_field_list.append((tag_bytes, buffer[value_start_pos:new_pos]))
         pos = new_pos
       else:
         pos = field_decoder(buffer, new_pos, end, self, field_dict)
@@ -873,7 +918,8 @@
   def MergeFrom(self, msg):
     if not isinstance(msg, cls):
       raise TypeError(
-          "Parameter to MergeFrom() must be instance of same class.")
+          "Parameter to MergeFrom() must be instance of same class: "
+          "expected %s got %s." % (cls.__name__, type(msg).__name__))
 
     assert msg is not self
     self._Modified()
@@ -898,6 +944,12 @@
           field_value.MergeFrom(value)
       else:
         self._fields[field] = value
+
+    if msg._unknown_fields:
+      if not self._unknown_fields:
+        self._unknown_fields = []
+      self._unknown_fields.extend(msg._unknown_fields)
+
   cls.MergeFrom = MergeFrom
 
 
diff --git a/third_party/protobuf/python/google/protobuf/internal/reflection_cpp_generated_test.py b/third_party/protobuf/python/google/protobuf/internal/reflection_cpp_generated_test.py
new file mode 100644
index 0000000..2a0a512
--- /dev/null
+++ b/third_party/protobuf/python/google/protobuf/internal/reflection_cpp_generated_test.py
@@ -0,0 +1,91 @@
+#! /usr/bin/python
+# -*- coding: utf-8 -*-
+#
+# Protocol Buffers - Google's data interchange format
+# Copyright 2008 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.
+
+"""Unittest for reflection.py, which tests the generated C++ implementation."""
+
+__author__ = 'jasonh@google.com (Jason Hsueh)'
+
+import os
+os.environ['PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION'] = 'cpp'
+
+import unittest
+from google.protobuf.internal import api_implementation
+from google.protobuf.internal import more_extensions_dynamic_pb2
+from google.protobuf.internal import more_extensions_pb2
+from google.protobuf.internal.reflection_test import *
+
+
+class ReflectionCppTest(unittest.TestCase):
+  def testImplementationSetting(self):
+    self.assertEqual('cpp', api_implementation.Type())
+
+  def testExtensionOfGeneratedTypeInDynamicFile(self):
+    """Tests that a file built dynamically can extend a generated C++ type.
+
+    The C++ implementation uses a DescriptorPool that has the generated
+    DescriptorPool as an underlay. Typically, a type can only find
+    extensions in its own pool. With the python C-extension, the generated C++
+    extendee may be available, but not the extension. This tests that the
+    C-extension implements the correct special handling to make such extensions
+    available.
+    """
+    pb1 = more_extensions_pb2.ExtendedMessage()
+    # Test that basic accessors work.
+    self.assertFalse(
+        pb1.HasExtension(more_extensions_dynamic_pb2.dynamic_int32_extension))
+    self.assertFalse(
+        pb1.HasExtension(more_extensions_dynamic_pb2.dynamic_message_extension))
+    pb1.Extensions[more_extensions_dynamic_pb2.dynamic_int32_extension] = 17
+    pb1.Extensions[more_extensions_dynamic_pb2.dynamic_message_extension].a = 24
+    self.assertTrue(
+        pb1.HasExtension(more_extensions_dynamic_pb2.dynamic_int32_extension))
+    self.assertTrue(
+        pb1.HasExtension(more_extensions_dynamic_pb2.dynamic_message_extension))
+
+    # Now serialize the data and parse to a new message.
+    pb2 = more_extensions_pb2.ExtendedMessage()
+    pb2.MergeFromString(pb1.SerializeToString())
+
+    self.assertTrue(
+        pb2.HasExtension(more_extensions_dynamic_pb2.dynamic_int32_extension))
+    self.assertTrue(
+        pb2.HasExtension(more_extensions_dynamic_pb2.dynamic_message_extension))
+    self.assertEqual(
+        17, pb2.Extensions[more_extensions_dynamic_pb2.dynamic_int32_extension])
+    self.assertEqual(
+        24,
+        pb2.Extensions[more_extensions_dynamic_pb2.dynamic_message_extension].a)
+
+
+if __name__ == '__main__':
+  unittest.main()
diff --git a/third_party/protobuf/python/google/protobuf/internal/reflection_test.py b/third_party/protobuf/python/google/protobuf/internal/reflection_test.py
index 7b9d339..ed28646 100755
--- a/third_party/protobuf/python/google/protobuf/internal/reflection_test.py
+++ b/third_party/protobuf/python/google/protobuf/internal/reflection_test.py
@@ -37,6 +37,7 @@
 
 __author__ = 'robinson@google.com (Will Robinson)'
 
+import gc
 import operator
 import struct
 
@@ -318,15 +319,6 @@
       # ...and ensure that the scalar field has returned to its default.
       self.assertEqual(0, getattr(composite_field, scalar_field_name))
 
-      # Finally, ensure that modifications to the old composite field object
-      # don't have any effect on the parent. Possible only with the pure-python
-      # implementation of the API.
-      #
-      # (NOTE that when we clear the composite field in the parent, we actually
-      # don't recursively clear down the tree.  Instead, we just disconnect the
-      # cleared composite from the tree.)
-      if api_implementation.Type() != 'python':
-        return
       self.assertTrue(old_composite_field is not composite_field)
       setattr(old_composite_field, scalar_field_name, new_val)
       self.assertTrue(not composite_field.HasField(scalar_field_name))
@@ -348,8 +340,6 @@
     nested.bb = 23
 
   def testDisconnectingNestedMessageBeforeSettingField(self):
-    if api_implementation.Type() != 'python':
-      return
     proto = unittest_pb2.TestAllTypes()
     nested = proto.optional_nested_message
     proto.ClearField('optional_nested_message')  # Should disconnect from parent
@@ -358,6 +348,64 @@
     self.assertTrue(not proto.HasField('optional_nested_message'))
     self.assertEqual(0, proto.optional_nested_message.bb)
 
+  def testGetDefaultMessageAfterDisconnectingDefaultMessage(self):
+    proto = unittest_pb2.TestAllTypes()
+    nested = proto.optional_nested_message
+    proto.ClearField('optional_nested_message')
+    del proto
+    del nested
+    # Force a garbage collect so that the underlying CMessages are freed along
+    # with the Messages they point to. This is to make sure we're not deleting
+    # default message instances.
+    gc.collect()
+    proto = unittest_pb2.TestAllTypes()
+    nested = proto.optional_nested_message
+
+  def testDisconnectingNestedMessageAfterSettingField(self):
+    proto = unittest_pb2.TestAllTypes()
+    nested = proto.optional_nested_message
+    nested.bb = 5
+    self.assertTrue(proto.HasField('optional_nested_message'))
+    proto.ClearField('optional_nested_message')  # Should disconnect from parent
+    self.assertEqual(5, nested.bb)
+    self.assertEqual(0, proto.optional_nested_message.bb)
+    self.assertTrue(nested is not proto.optional_nested_message)
+    nested.bb = 23
+    self.assertTrue(not proto.HasField('optional_nested_message'))
+    self.assertEqual(0, proto.optional_nested_message.bb)
+
+  def testDisconnectingNestedMessageBeforeGettingField(self):
+    proto = unittest_pb2.TestAllTypes()
+    self.assertTrue(not proto.HasField('optional_nested_message'))
+    proto.ClearField('optional_nested_message')
+    self.assertTrue(not proto.HasField('optional_nested_message'))
+
+  def testDisconnectingNestedMessageAfterMerge(self):
+    # This test exercises the code path that does not use ReleaseMessage().
+    # The underlying fear is that if we use ReleaseMessage() incorrectly,
+    # we will have memory leaks.  It's hard to check that that doesn't happen,
+    # but at least we can exercise that code path to make sure it works.
+    proto1 = unittest_pb2.TestAllTypes()
+    proto2 = unittest_pb2.TestAllTypes()
+    proto2.optional_nested_message.bb = 5
+    proto1.MergeFrom(proto2)
+    self.assertTrue(proto1.HasField('optional_nested_message'))
+    proto1.ClearField('optional_nested_message')
+    self.assertTrue(not proto1.HasField('optional_nested_message'))
+
+  def testDisconnectingLazyNestedMessage(self):
+    # This test exercises releasing a nested message that is lazy. This test
+    # only exercises real code in the C++ implementation as Python does not
+    # support lazy parsing, but the current C++ implementation results in
+    # memory corruption and a crash.
+    if api_implementation.Type() != 'python':
+      return
+    proto = unittest_pb2.TestAllTypes()
+    proto.optional_lazy_message.bb = 5
+    proto.ClearField('optional_lazy_message')
+    del proto
+    gc.collect()
+
   def testHasBitsWhenModifyingRepeatedFields(self):
     # Test nesting when we add an element to a repeated field in a submessage.
     proto = unittest_pb2.TestNestedMessageHasBits()
@@ -635,6 +683,77 @@
     self.assertEqual(3, proto.BAZ)
     self.assertEqual(3, unittest_pb2.TestAllTypes.BAZ)
 
+  def testEnum_Name(self):
+    self.assertEqual('FOREIGN_FOO',
+                     unittest_pb2.ForeignEnum.Name(unittest_pb2.FOREIGN_FOO))
+    self.assertEqual('FOREIGN_BAR',
+                     unittest_pb2.ForeignEnum.Name(unittest_pb2.FOREIGN_BAR))
+    self.assertEqual('FOREIGN_BAZ',
+                     unittest_pb2.ForeignEnum.Name(unittest_pb2.FOREIGN_BAZ))
+    self.assertRaises(ValueError,
+                      unittest_pb2.ForeignEnum.Name, 11312)
+
+    proto = unittest_pb2.TestAllTypes()
+    self.assertEqual('FOO',
+                     proto.NestedEnum.Name(proto.FOO))
+    self.assertEqual('FOO',
+                     unittest_pb2.TestAllTypes.NestedEnum.Name(proto.FOO))
+    self.assertEqual('BAR',
+                     proto.NestedEnum.Name(proto.BAR))
+    self.assertEqual('BAR',
+                     unittest_pb2.TestAllTypes.NestedEnum.Name(proto.BAR))
+    self.assertEqual('BAZ',
+                     proto.NestedEnum.Name(proto.BAZ))
+    self.assertEqual('BAZ',
+                     unittest_pb2.TestAllTypes.NestedEnum.Name(proto.BAZ))
+    self.assertRaises(ValueError,
+                      proto.NestedEnum.Name, 11312)
+    self.assertRaises(ValueError,
+                      unittest_pb2.TestAllTypes.NestedEnum.Name, 11312)
+
+  def testEnum_Value(self):
+    self.assertEqual(unittest_pb2.FOREIGN_FOO,
+                     unittest_pb2.ForeignEnum.Value('FOREIGN_FOO'))
+    self.assertEqual(unittest_pb2.FOREIGN_BAR,
+                     unittest_pb2.ForeignEnum.Value('FOREIGN_BAR'))
+    self.assertEqual(unittest_pb2.FOREIGN_BAZ,
+                     unittest_pb2.ForeignEnum.Value('FOREIGN_BAZ'))
+    self.assertRaises(ValueError,
+                      unittest_pb2.ForeignEnum.Value, 'FO')
+
+    proto = unittest_pb2.TestAllTypes()
+    self.assertEqual(proto.FOO,
+                     proto.NestedEnum.Value('FOO'))
+    self.assertEqual(proto.FOO,
+                     unittest_pb2.TestAllTypes.NestedEnum.Value('FOO'))
+    self.assertEqual(proto.BAR,
+                     proto.NestedEnum.Value('BAR'))
+    self.assertEqual(proto.BAR,
+                     unittest_pb2.TestAllTypes.NestedEnum.Value('BAR'))
+    self.assertEqual(proto.BAZ,
+                     proto.NestedEnum.Value('BAZ'))
+    self.assertEqual(proto.BAZ,
+                     unittest_pb2.TestAllTypes.NestedEnum.Value('BAZ'))
+    self.assertRaises(ValueError,
+                      proto.NestedEnum.Value, 'Foo')
+    self.assertRaises(ValueError,
+                      unittest_pb2.TestAllTypes.NestedEnum.Value, 'Foo')
+
+  def testEnum_KeysAndValues(self):
+    self.assertEqual(['FOREIGN_FOO', 'FOREIGN_BAR', 'FOREIGN_BAZ'],
+                     unittest_pb2.ForeignEnum.keys())
+    self.assertEqual([4, 5, 6],
+                     unittest_pb2.ForeignEnum.values())
+    self.assertEqual([('FOREIGN_FOO', 4), ('FOREIGN_BAR', 5),
+                      ('FOREIGN_BAZ', 6)],
+                     unittest_pb2.ForeignEnum.items())
+
+    proto = unittest_pb2.TestAllTypes()
+    self.assertEqual(['FOO', 'BAR', 'BAZ'], proto.NestedEnum.keys())
+    self.assertEqual([1, 2, 3], proto.NestedEnum.values())
+    self.assertEqual([('FOO', 1), ('BAR', 2), ('BAZ', 3)],
+                     proto.NestedEnum.items())
+
   def testRepeatedScalars(self):
     proto = unittest_pb2.TestAllTypes()
 
@@ -826,6 +945,35 @@
     self.assertEqual(1, len(proto.repeated_nested_message))
     self.assertEqual(23, proto.repeated_nested_message[0].bb)
 
+  def testRepeatedCompositeRemove(self):
+    proto = unittest_pb2.TestAllTypes()
+
+    self.assertEqual(0, len(proto.repeated_nested_message))
+    m0 = proto.repeated_nested_message.add()
+    # Need to set some differentiating variable so m0 != m1 != m2:
+    m0.bb = len(proto.repeated_nested_message)
+    m1 = proto.repeated_nested_message.add()
+    m1.bb = len(proto.repeated_nested_message)
+    self.assertTrue(m0 != m1)
+    m2 = proto.repeated_nested_message.add()
+    m2.bb = len(proto.repeated_nested_message)
+    self.assertListsEqual([m0, m1, m2], proto.repeated_nested_message)
+
+    self.assertEqual(3, len(proto.repeated_nested_message))
+    proto.repeated_nested_message.remove(m0)
+    self.assertEqual(2, len(proto.repeated_nested_message))
+    self.assertEqual(m1, proto.repeated_nested_message[0])
+    self.assertEqual(m2, proto.repeated_nested_message[1])
+
+    # Removing m0 again or removing None should raise error
+    self.assertRaises(ValueError, proto.repeated_nested_message.remove, m0)
+    self.assertRaises(ValueError, proto.repeated_nested_message.remove, None)
+    self.assertEqual(2, len(proto.repeated_nested_message))
+
+    proto.repeated_nested_message.remove(m2)
+    self.assertEqual(1, len(proto.repeated_nested_message))
+    self.assertEqual(m1, proto.repeated_nested_message[0])
+
   def testHandWrittenReflection(self):
     # Hand written extensions are only supported by the pure-Python
     # implementation of the API.
@@ -856,6 +1004,68 @@
     self.assertEqual(23, myproto_instance.foo_field)
     self.assertTrue(myproto_instance.HasField('foo_field'))
 
+  def testDescriptorProtoSupport(self):
+    # Hand written descriptors/reflection are only supported by the pure-Python
+    # implementation of the API.
+    if api_implementation.Type() != 'python':
+      return
+
+    def AddDescriptorField(proto, field_name, field_type):
+      AddDescriptorField.field_index += 1
+      new_field = proto.field.add()
+      new_field.name = field_name
+      new_field.type = field_type
+      new_field.number = AddDescriptorField.field_index
+      new_field.label = descriptor_pb2.FieldDescriptorProto.LABEL_OPTIONAL
+
+    AddDescriptorField.field_index = 0
+
+    desc_proto = descriptor_pb2.DescriptorProto()
+    desc_proto.name = 'Car'
+    fdp = descriptor_pb2.FieldDescriptorProto
+    AddDescriptorField(desc_proto, 'name', fdp.TYPE_STRING)
+    AddDescriptorField(desc_proto, 'year', fdp.TYPE_INT64)
+    AddDescriptorField(desc_proto, 'automatic', fdp.TYPE_BOOL)
+    AddDescriptorField(desc_proto, 'price', fdp.TYPE_DOUBLE)
+    # Add a repeated field
+    AddDescriptorField.field_index += 1
+    new_field = desc_proto.field.add()
+    new_field.name = 'owners'
+    new_field.type = fdp.TYPE_STRING
+    new_field.number = AddDescriptorField.field_index
+    new_field.label = descriptor_pb2.FieldDescriptorProto.LABEL_REPEATED
+
+    desc = descriptor.MakeDescriptor(desc_proto)
+    self.assertTrue(desc.fields_by_name.has_key('name'))
+    self.assertTrue(desc.fields_by_name.has_key('year'))
+    self.assertTrue(desc.fields_by_name.has_key('automatic'))
+    self.assertTrue(desc.fields_by_name.has_key('price'))
+    self.assertTrue(desc.fields_by_name.has_key('owners'))
+
+    class CarMessage(message.Message):
+      __metaclass__ = reflection.GeneratedProtocolMessageType
+      DESCRIPTOR = desc
+
+    prius = CarMessage()
+    prius.name = 'prius'
+    prius.year = 2010
+    prius.automatic = True
+    prius.price = 25134.75
+    prius.owners.extend(['bob', 'susan'])
+
+    serialized_prius = prius.SerializeToString()
+    new_prius = reflection.ParseMessage(desc, serialized_prius)
+    self.assertTrue(new_prius is not prius)
+    self.assertEqual(prius, new_prius)
+
+    # these are unnecessary assuming message equality works as advertised but
+    # explicitly check to be safe since we're mucking about in metaclass foo
+    self.assertEqual(prius.name, new_prius.name)
+    self.assertEqual(prius.year, new_prius.year)
+    self.assertEqual(prius.automatic, new_prius.automatic)
+    self.assertEqual(prius.price, new_prius.price)
+    self.assertEqual(prius.owners, new_prius.owners)
+
   def testTopLevelExtensionsForOptionalScalar(self):
     extendee_proto = unittest_pb2.TestAllExtensions()
     extension = unittest_pb2.optional_int32_extension
@@ -1243,7 +1453,12 @@
 
   def testClear(self):
     proto = unittest_pb2.TestAllTypes()
-    test_util.SetAllFields(proto)
+    # C++ implementation does not support lazy fields right now so leave it
+    # out for now.
+    if api_implementation.Type() == 'python':
+      test_util.SetAllFields(proto)
+    else:
+      test_util.SetAllNonLazyFields(proto)
     # Clear the message.
     proto.Clear()
     self.assertEquals(proto.ByteSize(), 0)
@@ -1259,6 +1474,33 @@
     empty_proto = unittest_pb2.TestAllExtensions()
     self.assertEquals(proto, empty_proto)
 
+  def testDisconnectingBeforeClear(self):
+    proto = unittest_pb2.TestAllTypes()
+    nested = proto.optional_nested_message
+    proto.Clear()
+    self.assertTrue(nested is not proto.optional_nested_message)
+    nested.bb = 23
+    self.assertTrue(not proto.HasField('optional_nested_message'))
+    self.assertEqual(0, proto.optional_nested_message.bb)
+
+    proto = unittest_pb2.TestAllTypes()
+    nested = proto.optional_nested_message
+    nested.bb = 5
+    foreign = proto.optional_foreign_message
+    foreign.c = 6
+
+    proto.Clear()
+    self.assertTrue(nested is not proto.optional_nested_message)
+    self.assertTrue(foreign is not proto.optional_foreign_message)
+    self.assertEqual(5, nested.bb)
+    self.assertEqual(6, foreign.c)
+    nested.bb = 15
+    foreign.c = 16
+    self.assertTrue(not proto.HasField('optional_nested_message'))
+    self.assertEqual(0, proto.optional_nested_message.bb)
+    self.assertTrue(not proto.HasField('optional_foreign_message'))
+    self.assertEqual(0, proto.optional_foreign_message.c)
+
   def assertInitialized(self, proto):
     self.assertTrue(proto.IsInitialized())
     # Neither method should raise an exception.
@@ -1408,7 +1650,7 @@
     unicode_decode_failed = False
     try:
       message2.MergeFromString(bytes)
-    except UnicodeDecodeError, e:
+    except UnicodeDecodeError as e:
       unicode_decode_failed = True
     string_field = message2.str
     self.assertTrue(unicode_decode_failed or type(string_field) == str)
@@ -2119,7 +2361,7 @@
     """This method checks if the excpetion type and message are as expected."""
     try:
       callable_obj()
-    except exc_class, ex:
+    except exc_class as ex:
       # Check if the exception message is the right one.
       self.assertEqual(exception, str(ex))
       return
@@ -2131,15 +2373,22 @@
     self._CheckRaises(
         message.EncodeError,
         proto.SerializeToString,
-        'Message is missing required fields: a,b,c')
+        'Message protobuf_unittest.TestRequired is missing required fields: '
+        'a,b,c')
     # Shouldn't raise exceptions.
     partial = proto.SerializePartialToString()
 
+    proto2 = unittest_pb2.TestRequired()
+    self.assertFalse(proto2.HasField('a'))
+    # proto2 ParseFromString does not check that required fields are set.
+    proto2.ParseFromString(partial)
+    self.assertFalse(proto2.HasField('a'))
+
     proto.a = 1
     self._CheckRaises(
         message.EncodeError,
         proto.SerializeToString,
-        'Message is missing required fields: b,c')
+        'Message protobuf_unittest.TestRequired is missing required fields: b,c')
     # Shouldn't raise exceptions.
     partial = proto.SerializePartialToString()
 
@@ -2147,7 +2396,7 @@
     self._CheckRaises(
         message.EncodeError,
         proto.SerializeToString,
-        'Message is missing required fields: c')
+        'Message protobuf_unittest.TestRequired is missing required fields: c')
     # Shouldn't raise exceptions.
     partial = proto.SerializePartialToString()
 
@@ -2176,7 +2425,8 @@
     self._CheckRaises(
         message.EncodeError,
         proto.SerializeToString,
-        'Message is missing required fields: '
+        'Message protobuf_unittest.TestRequiredForeign '
+        'is missing required fields: '
         'optional_message.b,optional_message.c')
 
     proto.optional_message.b = 2
@@ -2188,7 +2438,7 @@
     self._CheckRaises(
         message.EncodeError,
         proto.SerializeToString,
-        'Message is missing required fields: '
+        'Message protobuf_unittest.TestRequiredForeign is missing required fields: '
         'repeated_message[0].b,repeated_message[0].c,'
         'repeated_message[1].a,repeated_message[1].c')
 
diff --git a/third_party/protobuf/python/google/protobuf/internal/test_bad_identifiers.proto b/third_party/protobuf/python/google/protobuf/internal/test_bad_identifiers.proto
new file mode 100644
index 0000000..6a82299
--- /dev/null
+++ b/third_party/protobuf/python/google/protobuf/internal/test_bad_identifiers.proto
@@ -0,0 +1,52 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 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.
+
+// Author: kenton@google.com (Kenton Varda)
+
+
+package protobuf_unittest;
+
+option py_generic_services = true;
+
+message TestBadIdentifiers {
+  extensions 100 to max;
+}
+
+// Make sure these reasonable extension names don't conflict with internal
+// variables.
+extend TestBadIdentifiers {
+  optional string message = 100 [default="foo"];
+  optional string descriptor = 101 [default="bar"];
+  optional string reflection = 102 [default="baz"];
+  optional string service = 103 [default="qux"];
+}
+
+message AnotherMessage {}
+service AnotherService {}
diff --git a/third_party/protobuf/python/google/protobuf/internal/test_util.py b/third_party/protobuf/python/google/protobuf/internal/test_util.py
index 1df1619..be8ae7b 100755
--- a/third_party/protobuf/python/google/protobuf/internal/test_util.py
+++ b/third_party/protobuf/python/google/protobuf/internal/test_util.py
@@ -42,8 +42,8 @@
 from google.protobuf import unittest_pb2
 
 
-def SetAllFields(message):
-  """Sets every field in the message to a unique value.
+def SetAllNonLazyFields(message):
+  """Sets every non-lazy field in the message to a unique value.
 
   Args:
     message: A unittest_pb2.TestAllTypes instance.
@@ -79,6 +79,7 @@
   message.optional_nested_message.bb = 118
   message.optional_foreign_message.c = 119
   message.optional_import_message.d = 120
+  message.optional_public_import_message.e = 126
 
   message.optional_nested_enum = unittest_pb2.TestAllTypes.BAZ
   message.optional_foreign_enum = unittest_pb2.FOREIGN_BAZ
@@ -111,6 +112,7 @@
   message.repeated_nested_message.add().bb = 218
   message.repeated_foreign_message.add().c = 219
   message.repeated_import_message.add().d = 220
+  message.repeated_lazy_message.add().bb = 227
 
   message.repeated_nested_enum.append(unittest_pb2.TestAllTypes.BAR)
   message.repeated_foreign_enum.append(unittest_pb2.FOREIGN_BAR)
@@ -140,6 +142,7 @@
   message.repeated_nested_message.add().bb = 318
   message.repeated_foreign_message.add().c = 319
   message.repeated_import_message.add().d = 320
+  message.repeated_lazy_message.add().bb = 327
 
   message.repeated_nested_enum.append(unittest_pb2.TestAllTypes.BAZ)
   message.repeated_foreign_enum.append(unittest_pb2.FOREIGN_BAZ)
@@ -176,6 +179,11 @@
   message.default_cord = '425'
 
 
+def SetAllFields(message):
+  SetAllNonLazyFields(message)
+  message.optional_lazy_message.bb = 127
+
+
 def SetAllExtensions(message):
   """Sets every extension in the message to a unique value.
 
@@ -211,6 +219,8 @@
   extensions[pb2.optional_nested_message_extension].bb = 118
   extensions[pb2.optional_foreign_message_extension].c = 119
   extensions[pb2.optional_import_message_extension].d = 120
+  extensions[pb2.optional_public_import_message_extension].e = 126
+  extensions[pb2.optional_lazy_message_extension].bb = 127
 
   extensions[pb2.optional_nested_enum_extension] = pb2.TestAllTypes.BAZ
   extensions[pb2.optional_nested_enum_extension] = pb2.TestAllTypes.BAZ
@@ -244,6 +254,7 @@
   extensions[pb2.repeated_nested_message_extension].add().bb = 218
   extensions[pb2.repeated_foreign_message_extension].add().c = 219
   extensions[pb2.repeated_import_message_extension].add().d = 220
+  extensions[pb2.repeated_lazy_message_extension].add().bb = 227
 
   extensions[pb2.repeated_nested_enum_extension].append(pb2.TestAllTypes.BAR)
   extensions[pb2.repeated_foreign_enum_extension].append(pb2.FOREIGN_BAR)
@@ -273,6 +284,7 @@
   extensions[pb2.repeated_nested_message_extension].add().bb = 318
   extensions[pb2.repeated_foreign_message_extension].add().c = 319
   extensions[pb2.repeated_import_message_extension].add().d = 320
+  extensions[pb2.repeated_lazy_message_extension].add().bb = 327
 
   extensions[pb2.repeated_nested_enum_extension].append(pb2.TestAllTypes.BAZ)
   extensions[pb2.repeated_foreign_enum_extension].append(pb2.FOREIGN_BAZ)
@@ -407,6 +419,8 @@
   test_case.assertEqual(118, message.optional_nested_message.bb)
   test_case.assertEqual(119, message.optional_foreign_message.c)
   test_case.assertEqual(120, message.optional_import_message.d)
+  test_case.assertEqual(126, message.optional_public_import_message.e)
+  test_case.assertEqual(127, message.optional_lazy_message.bb)
 
   test_case.assertEqual(unittest_pb2.TestAllTypes.BAZ,
                         message.optional_nested_enum)
@@ -464,6 +478,7 @@
   test_case.assertEqual(218, message.repeated_nested_message[0].bb)
   test_case.assertEqual(219, message.repeated_foreign_message[0].c)
   test_case.assertEqual(220, message.repeated_import_message[0].d)
+  test_case.assertEqual(227, message.repeated_lazy_message[0].bb)
 
   test_case.assertEqual(unittest_pb2.TestAllTypes.BAR,
                         message.repeated_nested_enum[0])
@@ -492,6 +507,7 @@
   test_case.assertEqual(318, message.repeated_nested_message[1].bb)
   test_case.assertEqual(319, message.repeated_foreign_message[1].c)
   test_case.assertEqual(320, message.repeated_import_message[1].d)
+  test_case.assertEqual(327, message.repeated_lazy_message[1].bb)
 
   test_case.assertEqual(unittest_pb2.TestAllTypes.BAZ,
                         message.repeated_nested_enum[1])
diff --git a/third_party/protobuf/python/google/protobuf/internal/text_format_test.py b/third_party/protobuf/python/google/protobuf/internal/text_format_test.py
index 73d97d1..23b50eb 100755
--- a/third_party/protobuf/python/google/protobuf/internal/text_format_test.py
+++ b/third_party/protobuf/python/google/protobuf/internal/text_format_test.py
@@ -94,6 +94,28 @@
       '  }\n'
       '}\n')
 
+  def testPrintBadEnumValue(self):
+    message = unittest_pb2.TestAllTypes()
+    message.optional_nested_enum = 100
+    message.optional_foreign_enum = 101
+    message.optional_import_enum = 102
+    self.CompareToGoldenText(
+        text_format.MessageToString(message),
+        'optional_nested_enum: 100\n'
+        'optional_foreign_enum: 101\n'
+        'optional_import_enum: 102\n')
+
+  def testPrintBadEnumValueExtensions(self):
+    message = unittest_pb2.TestAllExtensions()
+    message.Extensions[unittest_pb2.optional_nested_enum_extension] = 100
+    message.Extensions[unittest_pb2.optional_foreign_enum_extension] = 101
+    message.Extensions[unittest_pb2.optional_import_enum_extension] = 102
+    self.CompareToGoldenText(
+        text_format.MessageToString(message),
+        '[protobuf_unittest.optional_nested_enum_extension]: 100\n'
+        '[protobuf_unittest.optional_foreign_enum_extension]: 101\n'
+        '[protobuf_unittest.optional_import_enum_extension]: 102\n')
+
   def testPrintExotic(self):
     message = unittest_pb2.TestAllTypes()
     message.repeated_int64.append(-9223372036854775808)
@@ -399,6 +421,14 @@
          'has no value with number 100.'),
         text_format.Merge, text, message)
 
+  def testMergeBadIntValue(self):
+    message = unittest_pb2.TestAllTypes()
+    text = 'optional_int32: bork'
+    self.assertRaisesWithMessage(
+        text_format.ParseError,
+        ('1:17 : Couldn\'t parse integer: bork'),
+        text_format.Merge, text, message)
+
   def assertRaisesWithMessage(self, e_class, e, func, *args, **kwargs):
     """Same as assertRaises, but also compares the exception message."""
     if hasattr(e_class, '__name__'):
@@ -408,7 +438,7 @@
 
     try:
       func(*args, **kwargs)
-    except e_class, expr:
+    except e_class as expr:
       if str(expr) != e:
         msg = '%s raised, but with wrong message: "%s" instead of "%s"'
         raise self.failureException(msg % (exc_name,
@@ -427,7 +457,7 @@
             'identifiER_4 : 1.1e+2 ID5:-0.23 ID6:\'aaaa\\\'bbbb\'\n'
             'ID7 : "aa\\"bb"\n\n\n\n ID8: {A:inf B:-inf C:true D:false}\n'
             'ID9: 22 ID10: -111111111111111111 ID11: -22\n'
-            'ID12: 2222222222222222222 '
+            'ID12: 2222222222222222222 ID13: 1.23456f ID14: 1.2e+2f '
             'false_bool:  0 true_BOOL:t \n true_bool1:  1 false_BOOL1:f ' )
     tokenizer = text_format._Tokenizer(text)
     methods = [(tokenizer.ConsumeIdentifier, 'identifier1'),
@@ -456,10 +486,10 @@
                '{',
                (tokenizer.ConsumeIdentifier, 'A'),
                ':',
-               (tokenizer.ConsumeFloat, text_format._INFINITY),
+               (tokenizer.ConsumeFloat, float('inf')),
                (tokenizer.ConsumeIdentifier, 'B'),
                ':',
-               (tokenizer.ConsumeFloat, -text_format._INFINITY),
+               (tokenizer.ConsumeFloat, -float('inf')),
                (tokenizer.ConsumeIdentifier, 'C'),
                ':',
                (tokenizer.ConsumeBool, True),
@@ -479,6 +509,12 @@
                (tokenizer.ConsumeIdentifier, 'ID12'),
                ':',
                (tokenizer.ConsumeUint64, 2222222222222222222),
+               (tokenizer.ConsumeIdentifier, 'ID13'),
+               ':',
+               (tokenizer.ConsumeFloat, 1.23456),
+               (tokenizer.ConsumeIdentifier, 'ID14'),
+               ':',
+               (tokenizer.ConsumeFloat, 1.2e+2),
                (tokenizer.ConsumeIdentifier, 'false_bool'),
                ':',
                (tokenizer.ConsumeBool, False),
@@ -556,16 +592,6 @@
     tokenizer = text_format._Tokenizer(text)
     self.assertRaises(text_format.ParseError, tokenizer.ConsumeBool)
 
-  def testInfNan(self):
-    # Make sure our infinity and NaN definitions are sound.
-    self.assertEquals(float, type(text_format._INFINITY))
-    self.assertEquals(float, type(text_format._NAN))
-    self.assertTrue(text_format._NAN != text_format._NAN)
-
-    inf_times_zero = text_format._INFINITY * 0
-    self.assertTrue(inf_times_zero != inf_times_zero)
-    self.assertTrue(text_format._INFINITY > 0)
-
 
 if __name__ == '__main__':
   unittest.main()
diff --git a/third_party/protobuf/python/google/protobuf/internal/unknown_fields_test.py b/third_party/protobuf/python/google/protobuf/internal/unknown_fields_test.py
new file mode 100644
index 0000000..84984b4
--- /dev/null
+++ b/third_party/protobuf/python/google/protobuf/internal/unknown_fields_test.py
@@ -0,0 +1,170 @@
+#! /usr/bin/python
+# -*- coding: utf-8 -*-
+#
+# Protocol Buffers - Google's data interchange format
+# Copyright 2008 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.
+
+"""Test for preservation of unknown fields in the pure Python implementation."""
+
+__author__ = 'bohdank@google.com (Bohdan Koval)'
+
+import unittest
+from google.protobuf import unittest_mset_pb2
+from google.protobuf import unittest_pb2
+from google.protobuf.internal import encoder
+from google.protobuf.internal import test_util
+from google.protobuf.internal import type_checkers
+
+
+class UnknownFieldsTest(unittest.TestCase):
+
+  def setUp(self):
+    self.descriptor = unittest_pb2.TestAllTypes.DESCRIPTOR
+    self.all_fields = unittest_pb2.TestAllTypes()
+    test_util.SetAllFields(self.all_fields)
+    self.all_fields_data = self.all_fields.SerializeToString()
+    self.empty_message = unittest_pb2.TestEmptyMessage()
+    self.empty_message.ParseFromString(self.all_fields_data)
+    self.unknown_fields = self.empty_message._unknown_fields
+
+  def GetField(self, name):
+    field_descriptor = self.descriptor.fields_by_name[name]
+    wire_type = type_checkers.FIELD_TYPE_TO_WIRE_TYPE[field_descriptor.type]
+    field_tag = encoder.TagBytes(field_descriptor.number, wire_type)
+    for tag_bytes, value in self.unknown_fields:
+      if tag_bytes == field_tag:
+        decoder = unittest_pb2.TestAllTypes._decoders_by_tag[tag_bytes]
+        result_dict = {}
+        decoder(value, 0, len(value), self.all_fields, result_dict)
+        return result_dict[field_descriptor]
+
+  def testVarint(self):
+    value = self.GetField('optional_int32')
+    self.assertEqual(self.all_fields.optional_int32, value)
+
+  def testFixed32(self):
+    value = self.GetField('optional_fixed32')
+    self.assertEqual(self.all_fields.optional_fixed32, value)
+
+  def testFixed64(self):
+    value = self.GetField('optional_fixed64')
+    self.assertEqual(self.all_fields.optional_fixed64, value)
+
+  def testLengthDelimited(self):
+    value = self.GetField('optional_string')
+    self.assertEqual(self.all_fields.optional_string, value)
+
+  def testGroup(self):
+    value = self.GetField('optionalgroup')
+    self.assertEqual(self.all_fields.optionalgroup, value)
+
+  def testSerialize(self):
+    data = self.empty_message.SerializeToString()
+
+    # Don't use assertEqual because we don't want to dump raw binary data to
+    # stdout.
+    self.assertTrue(data == self.all_fields_data)
+
+  def testCopyFrom(self):
+    message = unittest_pb2.TestEmptyMessage()
+    message.CopyFrom(self.empty_message)
+    self.assertEqual(self.unknown_fields, message._unknown_fields)
+
+  def testMergeFrom(self):
+    message = unittest_pb2.TestAllTypes()
+    message.optional_int32 = 1
+    message.optional_uint32 = 2
+    source = unittest_pb2.TestEmptyMessage()
+    source.ParseFromString(message.SerializeToString())
+
+    message.ClearField('optional_int32')
+    message.optional_int64 = 3
+    message.optional_uint32 = 4
+    destination = unittest_pb2.TestEmptyMessage()
+    destination.ParseFromString(message.SerializeToString())
+    unknown_fields = destination._unknown_fields[:]
+
+    destination.MergeFrom(source)
+    self.assertEqual(unknown_fields + source._unknown_fields,
+                     destination._unknown_fields)
+
+  def testClear(self):
+    self.empty_message.Clear()
+    self.assertEqual(0, len(self.empty_message._unknown_fields))
+
+  def testByteSize(self):
+    self.assertEqual(self.all_fields.ByteSize(), self.empty_message.ByteSize())
+
+  def testUnknownExtensions(self):
+    message = unittest_pb2.TestEmptyMessageWithExtensions()
+    message.ParseFromString(self.all_fields_data)
+    self.assertEqual(self.empty_message._unknown_fields,
+                     message._unknown_fields)
+
+  def testListFields(self):
+    # Make sure ListFields doesn't return unknown fields.
+    self.assertEqual(0, len(self.empty_message.ListFields()))
+
+  def testSerializeMessageSetWireFormatUnknownExtension(self):
+    # Create a message using the message set wire format with an unknown
+    # message.
+    raw = unittest_mset_pb2.RawMessageSet()
+
+    # Add an unknown extension.
+    item = raw.item.add()
+    item.type_id = 1545009
+    message1 = unittest_mset_pb2.TestMessageSetExtension1()
+    message1.i = 12345
+    item.message = message1.SerializeToString()
+
+    serialized = raw.SerializeToString()
+
+    # Parse message using the message set wire format.
+    proto = unittest_mset_pb2.TestMessageSet()
+    proto.MergeFromString(serialized)
+
+    # Verify that the unknown extension is serialized unchanged
+    reserialized = proto.SerializeToString()
+    new_raw = unittest_mset_pb2.RawMessageSet()
+    new_raw.MergeFromString(reserialized)
+    self.assertEqual(raw, new_raw)
+
+  def testEquals(self):
+    message = unittest_pb2.TestEmptyMessage()
+    message.ParseFromString(self.all_fields_data)
+    self.assertEqual(self.empty_message, message)
+
+    self.all_fields.ClearField('optional_string')
+    message.ParseFromString(self.all_fields.SerializeToString())
+    self.assertNotEqual(self.empty_message, message)
+
+
+if __name__ == '__main__':
+  unittest.main()
diff --git a/third_party/protobuf/python/google/protobuf/message.py b/third_party/protobuf/python/google/protobuf/message.py
index 6f19f85..6ec2f8b 100755
--- a/third_party/protobuf/python/google/protobuf/message.py
+++ b/third_party/protobuf/python/google/protobuf/message.py
@@ -73,6 +73,7 @@
     return clone
 
   def __eq__(self, other_msg):
+    """Recursively compares two messages by value and structure."""
     raise NotImplementedError
 
   def __ne__(self, other_msg):
@@ -83,9 +84,11 @@
     raise TypeError('unhashable object')
 
   def __str__(self):
+    """Outputs a human-readable representation of the message."""
     raise NotImplementedError
 
   def __unicode__(self):
+    """Outputs a human-readable representation of the message."""
     raise NotImplementedError
 
   def MergeFrom(self, other_msg):
@@ -266,3 +269,12 @@
     via a previous _SetListener() call.
     """
     raise NotImplementedError
+
+  def __getstate__(self):
+    """Support the pickle protocol."""
+    return dict(serialized=self.SerializePartialToString())
+
+  def __setstate__(self, state):
+    """Support the pickle protocol."""
+    self.__init__()
+    self.ParseFromString(state['serialized'])
diff --git a/third_party/protobuf/python/google/protobuf/message_factory.py b/third_party/protobuf/python/google/protobuf/message_factory.py
new file mode 100644
index 0000000..36e2fef
--- /dev/null
+++ b/third_party/protobuf/python/google/protobuf/message_factory.py
@@ -0,0 +1,113 @@
+# Protocol Buffers - Google's data interchange format
+# Copyright 2008 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.
+
+"""Provides a factory class for generating dynamic messages."""
+
+__author__ = 'matthewtoia@google.com (Matt Toia)'
+
+from google.protobuf import descriptor_database
+from google.protobuf import descriptor_pool
+from google.protobuf import message
+from google.protobuf import reflection
+
+
+class MessageFactory(object):
+  """Factory for creating Proto2 messages from descriptors in a pool."""
+
+  def __init__(self):
+    """Initializes a new factory."""
+    self._classes = {}
+
+  def GetPrototype(self, descriptor):
+    """Builds a proto2 message class based on the passed in descriptor.
+
+    Passing a descriptor with a fully qualified name matching a previous
+    invocation will cause the same class to be returned.
+
+    Args:
+      descriptor: The descriptor to build from.
+
+    Returns:
+      A class describing the passed in descriptor.
+    """
+
+    if descriptor.full_name not in self._classes:
+      result_class = reflection.GeneratedProtocolMessageType(
+          descriptor.name.encode('ascii', 'ignore'),
+          (message.Message,),
+          {'DESCRIPTOR': descriptor})
+      self._classes[descriptor.full_name] = result_class
+      for field in descriptor.fields:
+        if field.message_type:
+          self.GetPrototype(field.message_type)
+    return self._classes[descriptor.full_name]
+
+
+_DB = descriptor_database.DescriptorDatabase()
+_POOL = descriptor_pool.DescriptorPool(_DB)
+_FACTORY = MessageFactory()
+
+
+def GetMessages(file_protos):
+  """Builds a dictionary of all the messages available in a set of files.
+
+  Args:
+    file_protos: A sequence of file protos to build messages out of.
+
+  Returns:
+    A dictionary containing all the message types in the files mapping the
+    fully qualified name to a Message subclass for the descriptor.
+  """
+
+  result = {}
+  for file_proto in file_protos:
+    _DB.Add(file_proto)
+  for file_proto in file_protos:
+    for desc in _GetAllDescriptors(file_proto.message_type, file_proto.package):
+      result[desc.full_name] = _FACTORY.GetPrototype(desc)
+  return result
+
+
+def _GetAllDescriptors(desc_protos, package):
+  """Gets all levels of nested message types as a flattened list of descriptors.
+
+  Args:
+    desc_protos: The descriptor protos to process.
+    package: The package where the protos are defined.
+
+  Yields:
+    Each message descriptor for each nested type.
+  """
+
+  for desc_proto in desc_protos:
+    name = '.'.join((package, desc_proto.name))
+    yield _POOL.FindMessageTypeByName(name)
+    for nested_desc in _GetAllDescriptors(desc_proto.nested_type, name):
+      yield nested_desc
diff --git a/third_party/protobuf/python/google/protobuf/pyext/python-proto2.cc b/third_party/protobuf/python/google/protobuf/pyext/python-proto2.cc
index 181d7e9..6275341 100644
--- a/third_party/protobuf/python/google/protobuf/pyext/python-proto2.cc
+++ b/third_party/protobuf/python/google/protobuf/pyext/python-proto2.cc
@@ -207,9 +207,9 @@
           "Clears and sets the values of a repeated scalar field."),
   CMETHOD(ByteSize, METH_NOARGS,
           "Returns the size of the message in bytes."),
-  CMETHOD(Clear, METH_NOARGS,
+  CMETHOD(Clear, METH_O,
           "Clears a protocol message."),
-  CMETHOD(ClearField, METH_O,
+  CMETHOD(ClearField, METH_VARARGS,
           "Clears a protocol message field by name."),
   CMETHOD(ClearFieldByDescriptor, METH_O,
           "Clears a protocol message field by descriptor."),
@@ -274,7 +274,7 @@
 PyTypeObject CMessage_Type = {
   PyObject_HEAD_INIT(&PyType_Type)
   0,
-  C("google3.net.google.protobuf.python.internal."
+  C("google.protobuf.internal."
     "_net_proto2___python."
     "CMessage"),                       // tp_name
   sizeof(CMessage),                    //  tp_basicsize
@@ -319,14 +319,12 @@
 // ------ Helper Functions:
 
 static void FormatTypeError(PyObject* arg, char* expected_types) {
-  PyObject* s = PyObject_Str(PyObject_Type(arg));
-  PyObject* repr = PyObject_Repr(PyObject_Type(arg));
+  PyObject* repr = PyObject_Repr(arg);
   PyErr_Format(PyExc_TypeError,
                "%.100s has type %.100s, but expected one of: %s",
                PyString_AS_STRING(repr),
-               PyString_AS_STRING(s),
+               arg->ob_type->tp_name,
                expected_types);
-  Py_DECREF(s);
   Py_DECREF(repr);
 }
 
@@ -398,6 +396,28 @@
   return global_message_factory->GetPrototype(descriptor);
 }
 
+static void ReleaseSubMessage(google::protobuf::Message* message,
+                           const google::protobuf::FieldDescriptor* field_descriptor,
+                           CMessage* child_cmessage) {
+  Message* released_message = message->GetReflection()->ReleaseMessage(
+      message, field_descriptor, global_message_factory);
+  GOOGLE_DCHECK(child_cmessage->message != NULL);
+  // ReleaseMessage will return NULL which differs from
+  // child_cmessage->message, if the field does not exist.  In this case,
+  // the latter points to the default instance via a const_cast<>, so we
+  // have to reset it to a new mutable object since we are taking ownership.
+  if (released_message == NULL) {
+    const Message* prototype = global_message_factory->GetPrototype(
+        child_cmessage->message->GetDescriptor());
+    GOOGLE_DCHECK(prototype != NULL);
+    child_cmessage->message = prototype->New();
+  }
+  child_cmessage->parent = NULL;
+  child_cmessage->parent_field = NULL;
+  child_cmessage->free_message = true;
+  child_cmessage->read_only = false;
+}
+
 static bool CheckAndSetString(
     PyObject* arg, google::protobuf::Message* message,
     const google::protobuf::FieldDescriptor* descriptor,
@@ -407,6 +427,9 @@
   GOOGLE_DCHECK(descriptor->type() == google::protobuf::FieldDescriptor::TYPE_STRING ||
          descriptor->type() == google::protobuf::FieldDescriptor::TYPE_BYTES);
   if (descriptor->type() == google::protobuf::FieldDescriptor::TYPE_STRING) {
+#else
+  if (descriptor->file()->options().cc_api_version() == 2 &&
+      descriptor->type() == google::protobuf::FieldDescriptor::TYPE_STRING) {
     if (!PyString_Check(arg) && !PyUnicode_Check(arg)) {
       FormatTypeError(arg, "str, unicode");
       return false;
@@ -434,6 +457,9 @@
 
   PyObject* encoded_string = NULL;
   if (descriptor->type() == google::protobuf::FieldDescriptor::TYPE_STRING) {
+#else
+  if (descriptor->file()->options().cc_api_version() == 2 &&
+      descriptor->type() == google::protobuf::FieldDescriptor::TYPE_STRING) {
     if (PyString_Check(arg)) {
       encoded_string = PyString_AsEncodedObject(arg, "utf-8", NULL);
     } else {
@@ -504,8 +530,6 @@
   self->message = reflection->MutableMessage(
       message, self->parent_field->descriptor, global_message_factory);
   self->read_only = false;
-  self->parent = NULL;
-  self->parent_field = NULL;
 }
 
 static PyObject* InternalGetScalar(
@@ -955,9 +979,41 @@
 
 // ------ Methods:
 
-static PyObject* CMessage_Clear(CMessage* self, PyObject* args) {
+static PyObject* CMessage_Clear(CMessage* self, PyObject* arg) {
   AssureWritable(self);
-  self->message->Clear();
+  google::protobuf::Message* message = self->message;
+
+  // This block of code is equivalent to the following:
+  // for cfield_descriptor, child_cmessage in arg:
+  //   ReleaseSubMessage(cfield_descriptor, child_cmessage)
+  if (!PyList_Check(arg)) {
+    PyErr_SetString(PyExc_TypeError, "Must be a list");
+    return NULL;
+  }
+  PyObject* messages_to_clear = arg;
+  Py_ssize_t num_messages_to_clear = PyList_GET_SIZE(messages_to_clear);
+  for(int i = 0; i < num_messages_to_clear; ++i) {
+    PyObject* message_tuple = PyList_GET_ITEM(messages_to_clear, i);
+    if (!PyTuple_Check(message_tuple) || PyTuple_GET_SIZE(message_tuple) != 2) {
+      PyErr_SetString(PyExc_TypeError, "Must be a tuple of size 2");
+      return NULL;
+    }
+
+    PyObject* py_cfield_descriptor = PyTuple_GET_ITEM(message_tuple, 0);
+    PyObject* py_child_cmessage = PyTuple_GET_ITEM(message_tuple, 1);
+    if (!PyObject_TypeCheck(py_cfield_descriptor, &CFieldDescriptor_Type) ||
+        !PyObject_TypeCheck(py_child_cmessage, &CMessage_Type)) {
+      PyErr_SetString(PyExc_ValueError, "Invalid Tuple");
+      return NULL;
+    }
+
+    CFieldDescriptor* cfield_descriptor = reinterpret_cast<CFieldDescriptor *>(
+        py_cfield_descriptor);
+    CMessage* child_cmessage = reinterpret_cast<CMessage *>(py_child_cmessage);
+    ReleaseSubMessage(message, cfield_descriptor->descriptor, child_cmessage);
+  }
+
+  message->Clear();
   Py_RETURN_NONE;
 }
 
@@ -1039,9 +1095,11 @@
   Py_RETURN_NONE;
 }
 
-static PyObject* CMessage_ClearField(CMessage* self, PyObject* arg) {
+static PyObject* CMessage_ClearField(CMessage* self, PyObject* args) {
   char* field_name;
-  if (PyString_AsStringAndSize(arg, &field_name, NULL) < 0) {
+  CMessage* child_cmessage = NULL;
+  if (!PyArg_ParseTuple(args, C("s|O!:ClearField"), &field_name,
+                        &CMessage_Type, &child_cmessage)) {
     return NULL;
   }
 
@@ -1054,7 +1112,11 @@
     return NULL;
   }
 
-  message->GetReflection()->ClearField(message, field_descriptor);
+  if (child_cmessage != NULL && !FIELD_IS_REPEATED(field_descriptor)) {
+    ReleaseSubMessage(message, field_descriptor, child_cmessage);
+  } else {
+    message->GetReflection()->ClearField(message, field_descriptor);
+  }
   Py_RETURN_NONE;
 }
 
@@ -1313,6 +1375,7 @@
   AssureWritable(self);
   google::protobuf::io::CodedInputStream input(
       reinterpret_cast<const uint8*>(data), data_length);
+  input.SetExtensionRegistry(GetDescriptorPool(), global_message_factory);
   bool success = self->message->MergePartialFromCodedStream(&input);
   if (success) {
     return PyInt_FromLong(self->message->ByteSize());
diff --git a/third_party/protobuf/python/google/protobuf/pyext/python_descriptor.cc b/third_party/protobuf/python/google/protobuf/pyext/python_descriptor.cc
index fb87bad..5e3e9ea 100644
--- a/third_party/protobuf/python/google/protobuf/pyext/python_descriptor.cc
+++ b/third_party/protobuf/python/google/protobuf/pyext/python_descriptor.cc
@@ -31,6 +31,7 @@
 // Author: petar@google.com (Petar Petrov)
 
 #include <Python.h>
+#include <string>
 
 #include <google/protobuf/pyext/python_descriptor.h>
 #include <google/protobuf/descriptor.pb.h>
@@ -41,6 +42,7 @@
 namespace protobuf {
 namespace python {
 
+
 static void CFieldDescriptorDealloc(CFieldDescriptor* self);
 
 static google::protobuf::DescriptorPool* g_descriptor_pool = NULL;
@@ -93,7 +95,7 @@
 PyTypeObject CFieldDescriptor_Type = {
   PyObject_HEAD_INIT(&PyType_Type)
   0,
-  C("google3.net.google.protobuf.python.internal."
+  C("google.protobuf.internal."
     "_net_proto2___python."
     "CFieldDescriptor"),                // tp_name
   sizeof(CFieldDescriptor),             // tp_basicsize
@@ -181,6 +183,8 @@
   const google::protobuf::FieldDescriptor* field_descriptor = NULL;
 
   field_descriptor = self->pool->FindFieldByName(full_field_name);
+
+
   if (field_descriptor == NULL) {
     PyErr_Format(PyExc_TypeError, "Couldn't find field %.200s",
                  full_field_name);
@@ -223,7 +227,7 @@
 PyTypeObject CDescriptorPool_Type = {
   PyObject_HEAD_INIT(&PyType_Type)
   0,
-  C("google3.net.google.protobuf.python.internal."
+  C("google.protobuf.internal."
     "_net_proto2___python."
     "CFieldDescriptor"),               // tp_name
   sizeof(CDescriptorPool),             // tp_basicsize
@@ -301,7 +305,6 @@
     return NULL;
   }
 
-  // If this file is already in the generated pool, don't add it again.
   if (google::protobuf::DescriptorPool::generated_pool()->FindFileByName(
       file_proto.name()) != NULL) {
     Py_RETURN_NONE;
diff --git a/third_party/protobuf/python/google/protobuf/reflection.py b/third_party/protobuf/python/google/protobuf/reflection.py
index 1373c88..9570fd5 100755
--- a/third_party/protobuf/python/google/protobuf/reflection.py
+++ b/third_party/protobuf/python/google/protobuf/reflection.py
@@ -50,13 +50,20 @@
 
 from google.protobuf.internal import api_implementation
 from google.protobuf import descriptor as descriptor_mod
+from google.protobuf import message
+
 _FieldDescriptor = descriptor_mod.FieldDescriptor
 
 
 if api_implementation.Type() == 'cpp':
-  from google.protobuf.internal import cpp_message
-  _NewMessage = cpp_message.NewMessage
-  _InitMessage = cpp_message.InitMessage
+  if api_implementation.Version() == 2:
+    from google.protobuf.internal.cpp import cpp_message
+    _NewMessage = cpp_message.NewMessage
+    _InitMessage = cpp_message.InitMessage
+  else:
+    from google.protobuf.internal import cpp_message
+    _NewMessage = cpp_message.NewMessage
+    _InitMessage = cpp_message.InitMessage
 else:
   from google.protobuf.internal import python_message
   _NewMessage = python_message.NewMessage
@@ -112,7 +119,7 @@
       Newly-allocated class.
     """
     descriptor = dictionary[GeneratedProtocolMessageType._DESCRIPTOR_KEY]
-    _NewMessage(descriptor, dictionary)
+    bases = _NewMessage(bases, descriptor, dictionary)
     superclass = super(GeneratedProtocolMessageType, cls)
 
     new_class = superclass.__new__(cls, name, bases, dictionary)
@@ -140,3 +147,23 @@
     _InitMessage(descriptor, cls)
     superclass = super(GeneratedProtocolMessageType, cls)
     superclass.__init__(name, bases, dictionary)
+
+
+def ParseMessage(descriptor, byte_str):
+  """Generate a new Message instance from this Descriptor and a byte string.
+
+  Args:
+    descriptor: Protobuf Descriptor object
+    byte_str: Serialized protocol buffer byte string
+
+  Returns:
+    Newly created protobuf Message object.
+  """
+
+  class _ResultClass(message.Message):
+    __metaclass__ = GeneratedProtocolMessageType
+    DESCRIPTOR = descriptor
+
+  new_msg = _ResultClass()
+  new_msg.ParseFromString(byte_str)
+  return new_msg
diff --git a/third_party/protobuf/python/google/protobuf/text_format.py b/third_party/protobuf/python/google/protobuf/text_format.py
index c3a1cf6..0714c39 100755
--- a/third_party/protobuf/python/google/protobuf/text_format.py
+++ b/third_party/protobuf/python/google/protobuf/text_format.py
@@ -43,10 +43,12 @@
             'PrintFieldValue', 'Merge' ]
 
 
-# Infinity and NaN are not explicitly supported by Python pre-2.6, and
-# float('inf') does not work on Windows (pre-2.6).
-_INFINITY = 1e10000    # overflows, thus will actually be infinity.
-_NAN = _INFINITY * 0
+_INTEGER_CHECKERS = (type_checkers.Uint32ValueChecker(),
+                     type_checkers.Int32ValueChecker(),
+                     type_checkers.Uint64ValueChecker(),
+                     type_checkers.Int64ValueChecker())
+_FLOAT_INFINITY = re.compile('-?inf(?:inity)?f?', re.IGNORECASE)
+_FLOAT_NAN = re.compile('nanf?', re.IGNORECASE)
 
 
 class ParseError(Exception):
@@ -120,7 +122,11 @@
       PrintMessage(value, out, indent + 2, as_utf8, as_one_line)
       out.write(' ' * indent + '}')
   elif field.cpp_type == descriptor.FieldDescriptor.CPPTYPE_ENUM:
-    out.write(field.enum_type.values_by_number[value].name)
+    enum_value = field.enum_type.values_by_number.get(value, None)
+    if enum_value is not None:
+      out.write(enum_value.name)
+    else:
+      out.write(str(value))
   elif field.cpp_type == descriptor.FieldDescriptor.CPPTYPE_STRING:
     out.write('\"')
     if type(value) is unicode:
@@ -271,24 +277,7 @@
   elif field.type == descriptor.FieldDescriptor.TYPE_BYTES:
     value = tokenizer.ConsumeByteString()
   elif field.type == descriptor.FieldDescriptor.TYPE_ENUM:
-    # Enum can be specified by a number (the enum value), or by
-    # a string literal (the enum name).
-    enum_descriptor = field.enum_type
-    if tokenizer.LookingAtInteger():
-      number = tokenizer.ConsumeInt32()
-      enum_value = enum_descriptor.values_by_number.get(number, None)
-      if enum_value is None:
-        raise tokenizer.ParseErrorPreviousToken(
-            'Enum type "%s" has no value with number %d.' % (
-                enum_descriptor.full_name, number))
-    else:
-      identifier = tokenizer.ConsumeIdentifier()
-      enum_value = enum_descriptor.values_by_name.get(identifier, None)
-      if enum_value is None:
-        raise tokenizer.ParseErrorPreviousToken(
-            'Enum type "%s" has no value named %s.' % (
-                enum_descriptor.full_name, identifier))
-    value = enum_value.number
+    value = tokenizer.ConsumeEnum(field)
   else:
     raise RuntimeError('Unknown field type %d' % field.type)
 
@@ -320,12 +309,6 @@
       '\"([^\"\n\\\\]|\\\\.)*(\"|\\\\?$)|'  # a double-quoted string
       '\'([^\'\n\\\\]|\\\\.)*(\'|\\\\?$)')  # a single-quoted string
   _IDENTIFIER = re.compile('\w+')
-  _INTEGER_CHECKERS = [type_checkers.Uint32ValueChecker(),
-                       type_checkers.Int32ValueChecker(),
-                       type_checkers.Uint64ValueChecker(),
-                       type_checkers.Int64ValueChecker()]
-  _FLOAT_INFINITY = re.compile('-?inf(inity)?f?', re.IGNORECASE)
-  _FLOAT_NAN = re.compile("nanf?", re.IGNORECASE)
 
   def __init__(self, text_message):
     self._text_message = text_message
@@ -394,17 +377,6 @@
     if not self.TryConsume(token):
       raise self._ParseError('Expected "%s".' % token)
 
-  def LookingAtInteger(self):
-    """Checks if the current token is an integer.
-
-    Returns:
-      True iff the current token is an integer.
-    """
-    if not self.token:
-      return False
-    c = self.token[0]
-    return (c >= '0' and c <= '9') or c == '-' or c == '+'
-
   def ConsumeIdentifier(self):
     """Consumes protocol message field identifier.
 
@@ -430,9 +402,9 @@
       ParseError: If a signed 32bit integer couldn't be consumed.
     """
     try:
-      result = self._ParseInteger(self.token, is_signed=True, is_long=False)
+      result = ParseInteger(self.token, is_signed=True, is_long=False)
     except ValueError, e:
-      raise self._IntegerParseError(e)
+      raise self._ParseError(str(e))
     self.NextToken()
     return result
 
@@ -446,9 +418,9 @@
       ParseError: If an unsigned 32bit integer couldn't be consumed.
     """
     try:
-      result = self._ParseInteger(self.token, is_signed=False, is_long=False)
+      result = ParseInteger(self.token, is_signed=False, is_long=False)
     except ValueError, e:
-      raise self._IntegerParseError(e)
+      raise self._ParseError(str(e))
     self.NextToken()
     return result
 
@@ -462,9 +434,9 @@
       ParseError: If a signed 64bit integer couldn't be consumed.
     """
     try:
-      result = self._ParseInteger(self.token, is_signed=True, is_long=True)
+      result = ParseInteger(self.token, is_signed=True, is_long=True)
     except ValueError, e:
-      raise self._IntegerParseError(e)
+      raise self._ParseError(str(e))
     self.NextToken()
     return result
 
@@ -478,9 +450,9 @@
       ParseError: If an unsigned 64bit integer couldn't be consumed.
     """
     try:
-      result = self._ParseInteger(self.token, is_signed=False, is_long=True)
+      result = ParseInteger(self.token, is_signed=False, is_long=True)
     except ValueError, e:
-      raise self._IntegerParseError(e)
+      raise self._ParseError(str(e))
     self.NextToken()
     return result
 
@@ -493,21 +465,10 @@
     Raises:
       ParseError: If a floating point number couldn't be consumed.
     """
-    text = self.token
-    if self._FLOAT_INFINITY.match(text):
-      self.NextToken()
-      if text.startswith('-'):
-        return -_INFINITY
-      return _INFINITY
-
-    if self._FLOAT_NAN.match(text):
-      self.NextToken()
-      return _NAN
-
     try:
-      result = float(text)
+      result = ParseFloat(self.token)
     except ValueError, e:
-      raise self._FloatParseError(e)
+      raise self._ParseError(str(e))
     self.NextToken()
     return result
 
@@ -520,14 +481,12 @@
     Raises:
       ParseError: If a boolean value couldn't be consumed.
     """
-    if self.token in ('true', 't', '1'):
-      self.NextToken()
-      return True
-    elif self.token in ('false', 'f', '0'):
-      self.NextToken()
-      return False
-    else:
-      raise self._ParseError('Expected "true" or "false".')
+    try:
+      result = ParseBool(self.token)
+    except ValueError, e:
+      raise self._ParseError(str(e))
+    self.NextToken()
+    return result
 
   def ConsumeString(self):
     """Consumes a string value.
@@ -567,7 +526,7 @@
     """
     text = self.token
     if len(text) < 1 or text[0] not in ('\'', '"'):
-      raise self._ParseError('Exptected string.')
+      raise self._ParseError('Expected string.')
 
     if len(text) < 2 or text[-1] != text[0]:
       raise self._ParseError('String missing ending quote.')
@@ -579,36 +538,12 @@
     self.NextToken()
     return result
 
-  def _ParseInteger(self, text, is_signed=False, is_long=False):
-    """Parses an integer.
-
-    Args:
-      text: The text to parse.
-      is_signed: True if a signed integer must be parsed.
-      is_long: True if a long integer must be parsed.
-
-    Returns:
-      The integer value.
-
-    Raises:
-      ValueError: Thrown Iff the text is not a valid integer.
-    """
-    pos = 0
-    if text.startswith('-'):
-      pos += 1
-
-    base = 10
-    if text.startswith('0x', pos) or text.startswith('0X', pos):
-      base = 16
-    elif text.startswith('0', pos):
-      base = 8
-
-    # Do the actual parsing. Exception handling is propagated to caller.
-    result = int(text, base)
-
-    # Check if the integer is sane. Exceptions handled by callers.
-    checker = self._INTEGER_CHECKERS[2 * int(is_long) + int(is_signed)]
-    checker.CheckValue(result)
+  def ConsumeEnum(self, field):
+    try:
+      result = ParseEnum(field, self.token)
+    except ValueError, e:
+      raise self._ParseError(str(e))
+    self.NextToken()
     return result
 
   def ParseErrorPreviousToken(self, message):
@@ -626,13 +561,7 @@
   def _ParseError(self, message):
     """Creates and *returns* a ParseError for the current token."""
     return ParseError('%d:%d : %s' % (
-        self._line + 1, self._column - len(self.token) + 1, message))
-
-  def _IntegerParseError(self, e):
-    return self._ParseError('Couldn\'t parse integer: ' + str(e))
-
-  def _FloatParseError(self, e):
-    return self._ParseError('Couldn\'t parse number: ' + str(e))
+        self._line + 1, self._column + 1, message))
 
   def _StringParseError(self, e):
     return self._ParseError('Couldn\'t parse string: ' + str(e))
@@ -689,3 +618,117 @@
   # allow single-digit hex escapes (like '\xf').
   result = _CUNESCAPE_HEX.sub(ReplaceHex, text)
   return result.decode('string_escape')
+
+
+def ParseInteger(text, is_signed=False, is_long=False):
+  """Parses an integer.
+
+  Args:
+    text: The text to parse.
+    is_signed: True if a signed integer must be parsed.
+    is_long: True if a long integer must be parsed.
+
+  Returns:
+    The integer value.
+
+  Raises:
+    ValueError: Thrown Iff the text is not a valid integer.
+  """
+  # Do the actual parsing. Exception handling is propagated to caller.
+  try:
+    result = int(text, 0)
+  except ValueError:
+    raise ValueError('Couldn\'t parse integer: %s' % text)
+
+  # Check if the integer is sane. Exceptions handled by callers.
+  checker = _INTEGER_CHECKERS[2 * int(is_long) + int(is_signed)]
+  checker.CheckValue(result)
+  return result
+
+
+def ParseFloat(text):
+  """Parse a floating point number.
+
+  Args:
+    text: Text to parse.
+
+  Returns:
+    The number parsed.
+
+  Raises:
+    ValueError: If a floating point number couldn't be parsed.
+  """
+  try:
+    # Assume Python compatible syntax.
+    return float(text)
+  except ValueError:
+    # Check alternative spellings.
+    if _FLOAT_INFINITY.match(text):
+      if text[0] == '-':
+        return float('-inf')
+      else:
+        return float('inf')
+    elif _FLOAT_NAN.match(text):
+      return float('nan')
+    else:
+      # assume '1.0f' format
+      try:
+        return float(text.rstrip('f'))
+      except ValueError:
+        raise ValueError('Couldn\'t parse float: %s' % text)
+
+
+def ParseBool(text):
+  """Parse a boolean value.
+
+  Args:
+    text: Text to parse.
+
+  Returns:
+    Boolean values parsed
+
+  Raises:
+    ValueError: If text is not a valid boolean.
+  """
+  if text in ('true', 't', '1'):
+    return True
+  elif text in ('false', 'f', '0'):
+    return False
+  else:
+    raise ValueError('Expected "true" or "false".')
+
+
+def ParseEnum(field, value):
+  """Parse an enum value.
+
+  The value can be specified by a number (the enum value), or by
+  a string literal (the enum name).
+
+  Args:
+    field: Enum field descriptor.
+    value: String value.
+
+  Returns:
+    Enum value number.
+
+  Raises:
+    ValueError: If the enum value could not be parsed.
+  """
+  enum_descriptor = field.enum_type
+  try:
+    number = int(value, 0)
+  except ValueError:
+    # Identifier.
+    enum_value = enum_descriptor.values_by_name.get(value, None)
+    if enum_value is None:
+      raise ValueError(
+          'Enum type "%s" has no value named %s.' % (
+              enum_descriptor.full_name, value))
+  else:
+    # Numeric value.
+    enum_value = enum_descriptor.values_by_number.get(number, None)
+    if enum_value is None:
+      raise ValueError(
+          'Enum type "%s" has no value with number %d.' % (
+              enum_descriptor.full_name, number))
+  return enum_value.number
diff --git a/third_party/protobuf/python/setup.py b/third_party/protobuf/python/setup.py
index 7d9714e..fbe2766 100755
--- a/third_party/protobuf/python/setup.py
+++ b/third_party/protobuf/python/setup.py
@@ -1,18 +1,28 @@
 #! /usr/bin/python
 #
 # See README for usage instructions.
-
-# We must use setuptools, not distutils, because we need to use the
-# namespace_packages option for the "google" package.
-from ez_setup import use_setuptools
-use_setuptools()
-
-from setuptools import setup, Extension
-from distutils.spawn import find_executable
 import sys
 import os
 import subprocess
 
+# We must use setuptools, not distutils, because we need to use the
+# namespace_packages option for the "google" package.
+try:
+  from setuptools import setup, Extension
+except ImportError:
+  try:
+    from ez_setup import use_setuptools
+    use_setuptools()
+    from setuptools import setup, Extension
+  except ImportError:
+    sys.stderr.write(
+        "Could not import setuptools; make sure you have setuptools or "
+        "ez_setup installed.\n")
+    raise
+from distutils.command.clean import clean as _clean
+from distutils.command.build_py import build_py as _build_py
+from distutils.spawn import find_executable
+
 maintainer_email = "protobuf@googlegroups.com"
 
 # Find the Protocol Compiler.
@@ -34,15 +44,15 @@
 
   output = source.replace(".proto", "_pb2.py").replace("../src/", "")
 
-  if not os.path.exists(source):
-    print "Can't find required file: " + source
-    sys.exit(-1)
-
   if (not os.path.exists(output) or
       (os.path.exists(source) and
        os.path.getmtime(source) > os.path.getmtime(output))):
     print "Generating %s..." % output
 
+    if not os.path.exists(source):
+      sys.stderr.write("Can't find required file: %s\n" % source)
+      sys.exit(-1)
+
     if protoc == None:
       sys.stderr.write(
           "protoc is not installed nor found in ../src.  Please compile it "
@@ -53,19 +63,26 @@
     if subprocess.call(protoc_command) != 0:
       sys.exit(-1)
 
+def GenerateUnittestProtos():
+  generate_proto("../src/google/protobuf/unittest.proto")
+  generate_proto("../src/google/protobuf/unittest_custom_options.proto")
+  generate_proto("../src/google/protobuf/unittest_import.proto")
+  generate_proto("../src/google/protobuf/unittest_import_public.proto")
+  generate_proto("../src/google/protobuf/unittest_mset.proto")
+  generate_proto("../src/google/protobuf/unittest_no_generic_services.proto")
+  generate_proto("google/protobuf/internal/test_bad_identifiers.proto")
+  generate_proto("google/protobuf/internal/more_extensions.proto")
+  generate_proto("google/protobuf/internal/more_extensions_dynamic.proto")
+  generate_proto("google/protobuf/internal/more_messages.proto")
+  generate_proto("google/protobuf/internal/factory_test1.proto")
+  generate_proto("google/protobuf/internal/factory_test2.proto")
+
 def MakeTestSuite():
   # This is apparently needed on some systems to make sure that the tests
   # work even if a previous version is already installed.
   if 'google' in sys.modules:
     del sys.modules['google']
-
-  generate_proto("../src/google/protobuf/unittest.proto")
-  generate_proto("../src/google/protobuf/unittest_custom_options.proto")
-  generate_proto("../src/google/protobuf/unittest_import.proto")
-  generate_proto("../src/google/protobuf/unittest_mset.proto")
-  generate_proto("../src/google/protobuf/unittest_no_generic_services.proto")
-  generate_proto("google/protobuf/internal/more_extensions.proto")
-  generate_proto("google/protobuf/internal/more_messages.proto")
+  GenerateUnittestProtos()
 
   import unittest
   import google.protobuf.internal.generator_test     as generator_test
@@ -75,6 +92,14 @@
     as service_reflection_test
   import google.protobuf.internal.text_format_test   as text_format_test
   import google.protobuf.internal.wire_format_test   as wire_format_test
+  import google.protobuf.internal.unknown_fields_test as unknown_fields_test
+  import google.protobuf.internal.descriptor_database_test \
+      as descriptor_database_test
+  import google.protobuf.internal.descriptor_pool_test as descriptor_pool_test
+  import google.protobuf.internal.message_factory_test as message_factory_test
+  import google.protobuf.internal.message_cpp_test as message_cpp_test
+  import google.protobuf.internal.reflection_cpp_generated_test \
+      as reflection_cpp_generated_test
 
   loader = unittest.defaultTestLoader
   suite = unittest.TestSuite()
@@ -88,22 +113,33 @@
 
   return suite
 
-if __name__ == '__main__':
-  # TODO(kenton):  Integrate this into setuptools somehow?
-  if len(sys.argv) >= 2 and sys.argv[1] == "clean":
-    # Delete generated _pb2.py files and .pyc files in the code tree.
+
+class clean(_clean):
+  def run(self):
+    # Delete generated files in the code tree.
     for (dirpath, dirnames, filenames) in os.walk("."):
       for filename in filenames:
         filepath = os.path.join(dirpath, filename)
         if filepath.endswith("_pb2.py") or filepath.endswith(".pyc") or \
-          filepath.endswith(".so") or filepath.endswith(".o"):
+          filepath.endswith(".so") or filepath.endswith(".o") or \
+          filepath.endswith('google/protobuf/compiler/__init__.py'):
           os.remove(filepath)
-  else:
+    # _clean is an old-style class, so super() doesn't work.
+    _clean.run(self)
+
+class build_py(_build_py):
+  def run(self):
     # Generate necessary .proto file if it doesn't exist.
-    # TODO(kenton):  Maybe we should hook this into a distutils command?
     generate_proto("../src/google/protobuf/descriptor.proto")
     generate_proto("../src/google/protobuf/compiler/plugin.proto")
 
+    GenerateUnittestProtos()
+    # Make sure google.protobuf.compiler is a valid package.
+    open('google/protobuf/compiler/__init__.py', 'a').close()
+    # _build_py is an old-style class, so super() doesn't work.
+    _build_py.run(self)
+
+if __name__ == '__main__':
   ext_module_list = []
 
   # C++ implementation extension
@@ -137,10 +173,15 @@
           'google.protobuf.descriptor_pb2',
           'google.protobuf.compiler.plugin_pb2',
           'google.protobuf.message',
+          'google.protobuf.descriptor_database',
+          'google.protobuf.descriptor_pool',
+          'google.protobuf.message_factory',
           'google.protobuf.reflection',
           'google.protobuf.service',
           'google.protobuf.service_reflection',
           'google.protobuf.text_format' ],
+        cmdclass = { 'clean': clean, 'build_py': build_py },
+        install_requires = ['setuptools'],
         ext_modules = ext_module_list,
         url = 'http://code.google.com/p/protobuf/',
         maintainer = maintainer_email,
diff --git a/third_party/protobuf/src/Makefile.am b/third_party/protobuf/src/Makefile.am
index db9e7af..172d0cd 100644
--- a/third_party/protobuf/src/Makefile.am
+++ b/third_party/protobuf/src/Makefile.am
@@ -52,6 +52,7 @@
   google/protobuf/descriptor_database.h                        \
   google/protobuf/dynamic_message.h                            \
   google/protobuf/extension_set.h                              \
+  google/protobuf/generated_enum_reflection.h                  \
   google/protobuf/generated_message_util.h                     \
   google/protobuf/generated_message_reflection.h               \
   google/protobuf/message.h                                    \
@@ -91,7 +92,11 @@
   google/protobuf/stubs/once.cc                                \
   google/protobuf/stubs/hash.h                                 \
   google/protobuf/stubs/map-util.h                             \
-  google/protobuf/stubs/stl_util-inl.h                         \
+  google/protobuf/stubs/stl_util.h                             \
+  google/protobuf/stubs/stringprintf.cc                        \
+  google/protobuf/stubs/stringprintf.h                         \
+  google/protobuf/stubs/template_util.h                        \
+  google/protobuf/stubs/type_traits.h                          \
   google/protobuf/extension_set.cc                             \
   google/protobuf/generated_message_util.cc                    \
   google/protobuf/message_lite.cc                              \
@@ -158,6 +163,7 @@
   google/protobuf/compiler/cpp/cpp_message.h                   \
   google/protobuf/compiler/cpp/cpp_message_field.cc            \
   google/protobuf/compiler/cpp/cpp_message_field.h             \
+  google/protobuf/compiler/cpp/cpp_options.h                   \
   google/protobuf/compiler/cpp/cpp_primitive_field.cc          \
   google/protobuf/compiler/cpp/cpp_primitive_field.h           \
   google/protobuf/compiler/cpp/cpp_service.cc                  \
@@ -187,6 +193,8 @@
   google/protobuf/compiler/java/java_service.h                 \
   google/protobuf/compiler/java/java_string_field.cc           \
   google/protobuf/compiler/java/java_string_field.h            \
+  google/protobuf/compiler/java/java_doc_comment.cc            \
+  google/protobuf/compiler/java/java_doc_comment.h             \
   google/protobuf/compiler/python/python_generator.cc
 
 bin_PROGRAMS = protoc
@@ -199,12 +207,14 @@
   google/protobuf/unittest.proto                               \
   google/protobuf/unittest_empty.proto                         \
   google/protobuf/unittest_import.proto                        \
+  google/protobuf/unittest_import_public.proto                 \
   google/protobuf/unittest_mset.proto                          \
   google/protobuf/unittest_optimize_for.proto                  \
   google/protobuf/unittest_embed_optimize_for.proto            \
   google/protobuf/unittest_custom_options.proto                \
   google/protobuf/unittest_lite.proto                          \
   google/protobuf/unittest_import_lite.proto                   \
+  google/protobuf/unittest_import_public_lite.proto            \
   google/protobuf/unittest_lite_imports_nonlite.proto          \
   google/protobuf/unittest_no_generic_services.proto           \
   google/protobuf/compiler/cpp/cpp_test_bad_identifiers.proto
@@ -228,7 +238,9 @@
   google/protobuf/unittest_lite.pb.cc                          \
   google/protobuf/unittest_lite.pb.h                           \
   google/protobuf/unittest_import_lite.pb.cc                   \
-  google/protobuf/unittest_import_lite.pb.h
+  google/protobuf/unittest_import_lite.pb.h                    \
+  google/protobuf/unittest_import_public_lite.pb.cc            \
+  google/protobuf/unittest_import_public_lite.pb.h
 
 protoc_outputs =                                               \
   $(protoc_lite_outputs)                                       \
@@ -238,6 +250,8 @@
   google/protobuf/unittest_empty.pb.h                          \
   google/protobuf/unittest_import.pb.cc                        \
   google/protobuf/unittest_import.pb.h                         \
+  google/protobuf/unittest_import_public.pb.cc                 \
+  google/protobuf/unittest_import_public.pb.h                  \
   google/protobuf/unittest_mset.pb.cc                          \
   google/protobuf/unittest_mset.pb.h                           \
   google/protobuf/unittest_optimize_for.pb.cc                  \
@@ -298,6 +312,9 @@
   google/protobuf/stubs/once_unittest.cc                       \
   google/protobuf/stubs/strutil_unittest.cc                    \
   google/protobuf/stubs/structurally_valid_unittest.cc         \
+  google/protobuf/stubs/stringprintf_unittest.cc               \
+  google/protobuf/stubs/template_util_unittest.cc              \
+  google/protobuf/stubs/type_traits_unittest.cc                \
   google/protobuf/descriptor_database_unittest.cc              \
   google/protobuf/descriptor_unittest.cc                       \
   google/protobuf/dynamic_message_unittest.cc                  \
@@ -306,6 +323,7 @@
   google/protobuf/message_unittest.cc                          \
   google/protobuf/reflection_ops_unittest.cc                   \
   google/protobuf/repeated_field_unittest.cc                   \
+  google/protobuf/repeated_field_reflection_unittest.cc        \
   google/protobuf/text_format_unittest.cc                      \
   google/protobuf/unknown_field_set_unittest.cc                \
   google/protobuf/wire_format_unittest.cc                      \
@@ -319,9 +337,11 @@
   google/protobuf/compiler/mock_code_generator.h               \
   google/protobuf/compiler/parser_unittest.cc                  \
   google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc       \
+  google/protobuf/compiler/cpp/cpp_unittest.h                  \
   google/protobuf/compiler/cpp/cpp_unittest.cc                 \
   google/protobuf/compiler/cpp/cpp_plugin_unittest.cc          \
   google/protobuf/compiler/java/java_plugin_unittest.cc        \
+  google/protobuf/compiler/java/java_doc_comment_unittest.cc   \
   google/protobuf/compiler/python/python_plugin_unittest.cc    \
   $(COMMON_TEST_SOURCES)
 nodist_protobuf_test_SOURCES = $(protoc_outputs)
diff --git a/third_party/protobuf/src/google/protobuf/compiler/command_line_interface.cc b/third_party/protobuf/src/google/protobuf/compiler/command_line_interface.cc
index c5be9b4..b9293c9 100644
--- a/third_party/protobuf/src/google/protobuf/compiler/command_line_interface.cc
+++ b/third_party/protobuf/src/google/protobuf/compiler/command_line_interface.cc
@@ -59,12 +59,13 @@
 #include <google/protobuf/descriptor.h>
 #include <google/protobuf/text_format.h>
 #include <google/protobuf/dynamic_message.h>
+#include <google/protobuf/io/coded_stream.h>
 #include <google/protobuf/io/zero_copy_stream_impl.h>
 #include <google/protobuf/io/printer.h>
 #include <google/protobuf/stubs/strutil.h>
 #include <google/protobuf/stubs/substitute.h>
 #include <google/protobuf/stubs/map-util.h>
-#include <google/protobuf/stubs/stl_util-inl.h>
+#include <google/protobuf/stubs/stl_util.h>
 
 
 namespace google {
@@ -145,7 +146,7 @@
 bool VerifyDirectoryExists(const string& path) {
   if (path.empty()) return true;
 
-  if (access(path.c_str(), W_OK) == -1) {
+  if (access(path.c_str(), F_OK) == -1) {
     cerr << path << ": " << strerror(errno) << endl;
     return false;
   } else {
@@ -566,6 +567,7 @@
   : mode_(MODE_COMPILE),
     error_format_(ERROR_FORMAT_GCC),
     imports_in_descriptor_set_(false),
+    source_info_in_descriptor_set_(false),
     disallow_services_(false),
     inputs_are_proto_path_relative_(false) {}
 CommandLineInterface::~CommandLineInterface() {}
@@ -574,9 +576,23 @@
                                              CodeGenerator* generator,
                                              const string& help_text) {
   GeneratorInfo info;
+  info.flag_name = flag_name;
   info.generator = generator;
   info.help_text = help_text;
-  generators_[flag_name] = info;
+  generators_by_flag_name_[flag_name] = info;
+}
+
+void CommandLineInterface::RegisterGenerator(const string& flag_name,
+                                             const string& option_flag_name,
+                                             CodeGenerator* generator,
+                                             const string& help_text) {
+  GeneratorInfo info;
+  info.flag_name = flag_name;
+  info.option_flag_name = option_flag_name;
+  info.generator = generator;
+  info.help_text = help_text;
+  generators_by_flag_name_[flag_name] = info;
+  generators_by_option_name_[option_flag_name] = info;
 }
 
 void CommandLineInterface::AllowPlugins(const string& exe_name_prefix) {
@@ -585,7 +601,14 @@
 
 int CommandLineInterface::Run(int argc, const char* const argv[]) {
   Clear();
-  if (!ParseArguments(argc, argv)) return 1;
+  switch (ParseArguments(argc, argv)) {
+    case PARSE_ARGUMENT_DONE_AND_EXIT:
+      return 0;
+    case PARSE_ARGUMENT_FAIL:
+      return 1;
+    case PARSE_ARGUMENT_DONE_AND_CONTINUE:
+      break;
+  }
 
   // Set up the source tree.
   DiskSourceTree source_tree;
@@ -713,6 +736,7 @@
 
   mode_ = MODE_COMPILE;
   imports_in_descriptor_set_ = false;
+  source_info_in_descriptor_set_ = false;
   disallow_services_ = false;
 }
 
@@ -755,7 +779,8 @@
   return true;
 }
 
-bool CommandLineInterface::ParseArguments(int argc, const char* const argv[]) {
+CommandLineInterface::ParseArgumentStatus
+CommandLineInterface::ParseArguments(int argc, const char* const argv[]) {
   executable_name_ = argv[0];
 
   // Iterate through all arguments and parse them.
@@ -769,41 +794,50 @@
         if (name == "--decode") {
           cerr << "To decode an unknown message, use --decode_raw." << endl;
         }
-        return false;
+        return PARSE_ARGUMENT_FAIL;
       } else {
         ++i;
         value = argv[i];
       }
     }
 
-    if (!InterpretArgument(name, value)) return false;
+    ParseArgumentStatus status = InterpretArgument(name, value);
+    if (status != PARSE_ARGUMENT_DONE_AND_CONTINUE)
+      return status;
   }
 
   // If no --proto_path was given, use the current working directory.
   if (proto_path_.empty()) {
-    proto_path_.push_back(make_pair<string, string>("", "."));
+    // Don't use make_pair as the old/default standard library on Solaris
+    // doesn't support it without explicit template parameters, which are
+    // incompatible with C++0x's make_pair.
+    proto_path_.push_back(pair<string, string>("", "."));
   }
 
   // Check some errror cases.
   bool decoding_raw = (mode_ == MODE_DECODE) && codec_type_.empty();
   if (decoding_raw && !input_files_.empty()) {
     cerr << "When using --decode_raw, no input files should be given." << endl;
-    return false;
+    return PARSE_ARGUMENT_FAIL;
   } else if (!decoding_raw && input_files_.empty()) {
     cerr << "Missing input file." << endl;
-    return false;
+    return PARSE_ARGUMENT_FAIL;
   }
   if (mode_ == MODE_COMPILE && output_directives_.empty() &&
       descriptor_set_name_.empty()) {
     cerr << "Missing output directives." << endl;
-    return false;
+    return PARSE_ARGUMENT_FAIL;
   }
   if (imports_in_descriptor_set_ && descriptor_set_name_.empty()) {
     cerr << "--include_imports only makes sense when combined with "
             "--descriptor_set_out." << endl;
   }
+  if (source_info_in_descriptor_set_ && descriptor_set_name_.empty()) {
+    cerr << "--include_source_info only makes sense when combined with "
+            "--descriptor_set_out." << endl;
+  }
 
-  return true;
+  return PARSE_ARGUMENT_DONE_AND_CONTINUE;
 }
 
 bool CommandLineInterface::ParseArgument(const char* arg,
@@ -853,6 +887,7 @@
   if (*name == "-h" || *name == "--help" ||
       *name == "--disallow_services" ||
       *name == "--include_imports" ||
+      *name == "--include_source_info" ||
       *name == "--version" ||
       *name == "--decode_raw") {
     // HACK:  These are the only flags that don't take a value.
@@ -865,8 +900,9 @@
   return true;
 }
 
-bool CommandLineInterface::InterpretArgument(const string& name,
-                                             const string& value) {
+CommandLineInterface::ParseArgumentStatus
+CommandLineInterface::InterpretArgument(const string& name,
+                                        const string& value) {
   if (name.empty()) {
     // Not a flag.  Just a filename.
     if (value.empty()) {
@@ -874,7 +910,7 @@
               "arguments to " << executable_name_ << ".  This is actually "
               "sort of hard to do.  Congrats.  Unfortunately it is not valid "
               "input so the program is going to die now." << endl;
-      return false;
+      return PARSE_ARGUMENT_FAIL;
     }
 
     input_files_.push_back(value);
@@ -902,7 +938,7 @@
       if (disk_path.empty()) {
         cerr << "--proto_path passed empty directory name.  (Use \".\" for "
                 "current directory.)" << endl;
-        return false;
+        return PARSE_ARGUMENT_FAIL;
       }
 
       // Make sure disk path exists, warn otherwise.
@@ -910,35 +946,45 @@
         cerr << disk_path << ": warning: directory does not exist." << endl;
       }
 
-      proto_path_.push_back(make_pair(virtual_path, disk_path));
+      // Don't use make_pair as the old/default standard library on Solaris
+      // doesn't support it without explicit template parameters, which are
+      // incompatible with C++0x's make_pair.
+      proto_path_.push_back(pair<string, string>(virtual_path, disk_path));
     }
 
   } else if (name == "-o" || name == "--descriptor_set_out") {
     if (!descriptor_set_name_.empty()) {
       cerr << name << " may only be passed once." << endl;
-      return false;
+      return PARSE_ARGUMENT_FAIL;
     }
     if (value.empty()) {
       cerr << name << " requires a non-empty value." << endl;
-      return false;
+      return PARSE_ARGUMENT_FAIL;
     }
     if (mode_ != MODE_COMPILE) {
       cerr << "Cannot use --encode or --decode and generate descriptors at the "
               "same time." << endl;
-      return false;
+      return PARSE_ARGUMENT_FAIL;
     }
     descriptor_set_name_ = value;
 
   } else if (name == "--include_imports") {
     if (imports_in_descriptor_set_) {
       cerr << name << " may only be passed once." << endl;
-      return false;
+      return PARSE_ARGUMENT_FAIL;
     }
     imports_in_descriptor_set_ = true;
 
+  } else if (name == "--include_source_info") {
+    if (source_info_in_descriptor_set_) {
+      cerr << name << " may only be passed once." << endl;
+      return PARSE_ARGUMENT_FAIL;
+    }
+    source_info_in_descriptor_set_ = true;
+
   } else if (name == "-h" || name == "--help") {
     PrintHelpText();
-    return false;  // Exit without running compiler.
+    return PARSE_ARGUMENT_DONE_AND_EXIT;  // Exit without running compiler.
 
   } else if (name == "--version") {
     if (!version_info_.empty()) {
@@ -947,7 +993,7 @@
     cout << "libprotoc "
          << protobuf::internal::VersionString(GOOGLE_PROTOBUF_VERSION)
          << endl;
-    return false;  // Exit without running compiler.
+    return PARSE_ARGUMENT_DONE_AND_EXIT;  // Exit without running compiler.
 
   } else if (name == "--disallow_services") {
     disallow_services_ = true;
@@ -956,12 +1002,12 @@
              name == "--decode_raw") {
     if (mode_ != MODE_COMPILE) {
       cerr << "Only one of --encode and --decode can be specified." << endl;
-      return false;
+      return PARSE_ARGUMENT_FAIL;
     }
     if (!output_directives_.empty() || !descriptor_set_name_.empty()) {
       cerr << "Cannot use " << name
            << " and generate code or descriptors at the same time." << endl;
-      return false;
+      return PARSE_ARGUMENT_FAIL;
     }
 
     mode_ = (name == "--encode") ? MODE_ENCODE : MODE_DECODE;
@@ -971,10 +1017,10 @@
       if (name == "--decode") {
         cerr << "To decode an unknown message, use --decode_raw." << endl;
       }
-      return false;
+      return PARSE_ARGUMENT_FAIL;
     } else if (!value.empty() && name == "--decode_raw") {
       cerr << "--decode_raw does not take a parameter." << endl;
-      return false;
+      return PARSE_ARGUMENT_FAIL;
     }
 
     codec_type_ = value;
@@ -986,16 +1032,16 @@
       error_format_ = ERROR_FORMAT_MSVS;
     } else {
       cerr << "Unknown error format: " << value << endl;
-      return false;
+      return PARSE_ARGUMENT_FAIL;
     }
 
   } else if (name == "--plugin") {
     if (plugin_prefix_.empty()) {
       cerr << "This compiler does not support plugins." << endl;
-      return false;
+      return PARSE_ARGUMENT_FAIL;
     }
 
-    string name;
+    string plugin_name;
     string path;
 
     string::size_type equals_pos = value.find_first_of('=');
@@ -1003,57 +1049,68 @@
       // Use the basename of the file.
       string::size_type slash_pos = value.find_last_of('/');
       if (slash_pos == string::npos) {
-        name = value;
+        plugin_name = value;
       } else {
-        name = value.substr(slash_pos + 1);
+        plugin_name = value.substr(slash_pos + 1);
       }
       path = value;
     } else {
-      name = value.substr(0, equals_pos);
+      plugin_name = value.substr(0, equals_pos);
       path = value.substr(equals_pos + 1);
     }
 
-    plugins_[name] = path;
+    plugins_[plugin_name] = path;
 
   } else {
     // Some other flag.  Look it up in the generators list.
-    const GeneratorInfo* generator_info = FindOrNull(generators_, name);
+    const GeneratorInfo* generator_info =
+        FindOrNull(generators_by_flag_name_, name);
     if (generator_info == NULL &&
         (plugin_prefix_.empty() || !HasSuffixString(name, "_out"))) {
-      cerr << "Unknown flag: " << name << endl;
-      return false;
-    }
-
-    // It's an output flag.  Add it to the output directives.
-    if (mode_ != MODE_COMPILE) {
-      cerr << "Cannot use --encode or --decode and generate code at the "
-              "same time." << endl;
-      return false;
-    }
-
-    OutputDirective directive;
-    directive.name = name;
-    if (generator_info == NULL) {
-      directive.generator = NULL;
+      // Check if it's a generator option flag.
+      generator_info = FindOrNull(generators_by_option_name_, name);
+      if (generator_info == NULL) {
+        cerr << "Unknown flag: " << name << endl;
+        return PARSE_ARGUMENT_FAIL;
+      } else {
+        string* parameters = &generator_parameters_[generator_info->flag_name];
+        if (!parameters->empty()) {
+          parameters->append(",");
+        }
+        parameters->append(value);
+      }
     } else {
-      directive.generator = generator_info->generator;
-    }
+      // It's an output flag.  Add it to the output directives.
+      if (mode_ != MODE_COMPILE) {
+        cerr << "Cannot use --encode or --decode and generate code at the "
+                "same time." << endl;
+        return PARSE_ARGUMENT_FAIL;
+      }
 
-    // Split value at ':' to separate the generator parameter from the
-    // filename.  However, avoid doing this if the colon is part of a valid
-    // Windows-style absolute path.
-    string::size_type colon_pos = value.find_first_of(':');
-    if (colon_pos == string::npos || IsWindowsAbsolutePath(value)) {
-      directive.output_location = value;
-    } else {
-      directive.parameter = value.substr(0, colon_pos);
-      directive.output_location = value.substr(colon_pos + 1);
-    }
+      OutputDirective directive;
+      directive.name = name;
+      if (generator_info == NULL) {
+        directive.generator = NULL;
+      } else {
+        directive.generator = generator_info->generator;
+      }
 
-    output_directives_.push_back(directive);
+      // Split value at ':' to separate the generator parameter from the
+      // filename.  However, avoid doing this if the colon is part of a valid
+      // Windows-style absolute path.
+      string::size_type colon_pos = value.find_first_of(':');
+      if (colon_pos == string::npos || IsWindowsAbsolutePath(value)) {
+        directive.output_location = value;
+      } else {
+        directive.parameter = value.substr(0, colon_pos);
+        directive.output_location = value.substr(colon_pos + 1);
+      }
+
+      output_directives_.push_back(directive);
+    }
   }
 
-  return true;
+  return PARSE_ARGUMENT_DONE_AND_CONTINUE;
 }
 
 void CommandLineInterface::PrintHelpText() {
@@ -1086,6 +1143,12 @@
 "  --include_imports           When using --descriptor_set_out, also include\n"
 "                              all dependencies of the input files in the\n"
 "                              set, so that the set is self-contained.\n"
+"  --include_source_info       When using --descriptor_set_out, do not strip\n"
+"                              SourceCodeInfo from the FileDescriptorProto.\n"
+"                              This results in vastly larger descriptors that\n"
+"                              include information about the original\n"
+"                              location of each decl in the source file as\n"
+"                              well as surrounding comments.\n"
 "  --error_format=FORMAT       Set the format in which to print errors.\n"
 "                              FORMAT may be 'gcc' (the default) or 'msvs'\n"
 "                              (Microsoft Visual Studio format)." << endl;
@@ -1101,8 +1164,8 @@
 "                              the executable's own name differs." << endl;
   }
 
-  for (GeneratorMap::iterator iter = generators_.begin();
-       iter != generators_.end(); ++iter) {
+  for (GeneratorMap::iterator iter = generators_by_flag_name_.begin();
+       iter != generators_by_flag_name_.end(); ++iter) {
     // FIXME(kenton):  If the text is long enough it will wrap, which is ugly,
     //   but fixing this nicely (e.g. splitting on spaces) is probably more
     //   trouble than it's worth.
@@ -1136,10 +1199,16 @@
     }
   } else {
     // Regular generator.
+    string parameters = output_directive.parameter;
+    if (!generator_parameters_[output_directive.name].empty()) {
+      if (!parameters.empty()) {
+        parameters.append(",");
+      }
+      parameters.append(generator_parameters_[output_directive.name]);
+    }
     for (int i = 0; i < parsed_files.size(); i++) {
-      if (!output_directive.generator->Generate(
-          parsed_files[i], output_directive.parameter,
-          generator_context, &error)) {
+      if (!output_directive.generator->Generate(parsed_files[i], parameters,
+                                                generator_context, &error)) {
         // Generator returned an error.
         cerr << output_directive.name << ": " << parsed_files[i]->name() << ": "
              << error << endl;
@@ -1168,8 +1237,9 @@
   set<const FileDescriptor*> already_seen;
   for (int i = 0; i < parsed_files.size(); i++) {
     request.add_file_to_generate(parsed_files[i]->name());
-    GetTransitiveDependencies(parsed_files[i], &already_seen,
-                              request.mutable_proto_file());
+    GetTransitiveDependencies(parsed_files[i],
+                              true,  // Include source code info.
+                              &already_seen, request.mutable_proto_file());
   }
 
   // Invoke the plugin.
@@ -1299,12 +1369,17 @@
   if (imports_in_descriptor_set_) {
     set<const FileDescriptor*> already_seen;
     for (int i = 0; i < parsed_files.size(); i++) {
-      GetTransitiveDependencies(
-          parsed_files[i], &already_seen, file_set.mutable_file());
+      GetTransitiveDependencies(parsed_files[i],
+                                source_info_in_descriptor_set_,
+                                &already_seen, file_set.mutable_file());
     }
   } else {
     for (int i = 0; i < parsed_files.size(); i++) {
-      parsed_files[i]->CopyTo(file_set.add_file());
+      FileDescriptorProto* file_proto = file_set.add_file();
+      parsed_files[i]->CopyTo(file_proto);
+      if (source_info_in_descriptor_set_) {
+        parsed_files[i]->CopySourceCodeInfoTo(file_proto);
+      }
     }
   }
 
@@ -1334,7 +1409,7 @@
 }
 
 void CommandLineInterface::GetTransitiveDependencies(
-    const FileDescriptor* file,
+    const FileDescriptor* file, bool include_source_code_info,
     set<const FileDescriptor*>* already_seen,
     RepeatedPtrField<FileDescriptorProto>* output) {
   if (!already_seen->insert(file).second) {
@@ -1344,11 +1419,16 @@
 
   // Add all dependencies.
   for (int i = 0; i < file->dependency_count(); i++) {
-    GetTransitiveDependencies(file->dependency(i), already_seen, output);
+    GetTransitiveDependencies(file->dependency(i), include_source_code_info,
+                              already_seen, output);
   }
 
   // Add this file.
-  file->CopyTo(output->Add());
+  FileDescriptorProto* new_descriptor = output->Add();
+  file->CopyTo(new_descriptor);
+  if (include_source_code_info) {
+    file->CopySourceCodeInfoTo(new_descriptor);
+  }
 }
 
 
diff --git a/third_party/protobuf/src/google/protobuf/compiler/command_line_interface.h b/third_party/protobuf/src/google/protobuf/compiler/command_line_interface.h
index 0b507d8..86ea9bd 100644
--- a/third_party/protobuf/src/google/protobuf/compiler/command_line_interface.h
+++ b/third_party/protobuf/src/google/protobuf/compiler/command_line_interface.h
@@ -112,6 +112,19 @@
                          CodeGenerator* generator,
                          const string& help_text);
 
+  // Register a code generator for a language.
+  // Besides flag_name you can specify another option_flag_name that could be
+  // used to pass extra parameters to the registered code generator.
+  // Suppose you have registered a generator by calling:
+  //   command_line_interface.RegisterGenerator("--foo_out", "--foo_opt", ...)
+  // Then you could invoke the compiler with a command like:
+  //   protoc --foo_out=enable_bar:outdir --foo_opt=enable_baz
+  // This will pass "enable_bar,enable_baz" as the parameter to the generator.
+  void RegisterGenerator(const string& flag_name,
+                         const string& option_flag_name,
+                         CodeGenerator* generator,
+                         const string& help_text);
+
   // Enables "plugins".  In this mode, if a command-line flag ends with "_out"
   // but does not match any registered generator, the compiler will attempt to
   // find a "plugin" to implement the generator.  Plugins are just executables.
@@ -186,8 +199,15 @@
   bool MakeInputsBeProtoPathRelative(
     DiskSourceTree* source_tree);
 
+  // Return status for ParseArguments() and InterpretArgument().
+  enum ParseArgumentStatus {
+    PARSE_ARGUMENT_DONE_AND_CONTINUE,
+    PARSE_ARGUMENT_DONE_AND_EXIT,
+    PARSE_ARGUMENT_FAIL
+  };
+
   // Parse all command-line arguments.
-  bool ParseArguments(int argc, const char* const argv[]);
+  ParseArgumentStatus ParseArguments(int argc, const char* const argv[]);
 
   // Parses a command-line argument into a name/value pair.  Returns
   // true if the next argument in the argv should be used as the value,
@@ -203,7 +223,8 @@
   bool ParseArgument(const char* arg, string* name, string* value);
 
   // Interprets arguments parsed with ParseArgument.
-  bool InterpretArgument(const string& name, const string& value);
+  ParseArgumentStatus InterpretArgument(const string& name,
+                                        const string& value);
 
   // Print the --help text to stderr.
   void PrintHelpText();
@@ -230,9 +251,11 @@
   // protos will be ordered such that every file is listed before any file that
   // depends on it, so that you can call DescriptorPool::BuildFile() on them
   // in order.  Any files in *already_seen will not be added, and each file
-  // added will be inserted into *already_seen.
+  // added will be inserted into *already_seen.  If include_source_code_info is
+  // true then include the source code information in the FileDescriptorProtos.
   static void GetTransitiveDependencies(
       const FileDescriptor* file,
+      bool include_source_code_info,
       set<const FileDescriptor*>* already_seen,
       RepeatedPtrField<FileDescriptorProto>* output);
 
@@ -244,13 +267,21 @@
   // Version info set with SetVersionInfo().
   string version_info_;
 
-  // Map from flag names to registered generators.
+  // Registered generators.
   struct GeneratorInfo {
+    string flag_name;
+    string option_flag_name;
     CodeGenerator* generator;
     string help_text;
   };
   typedef map<string, GeneratorInfo> GeneratorMap;
-  GeneratorMap generators_;
+  GeneratorMap generators_by_flag_name_;
+  GeneratorMap generators_by_option_name_;
+  // A map from generator names to the parameters specified using the option
+  // flag. For example, if the user invokes the compiler with:
+  //   protoc --foo_out=outputdir --foo_opt=enable_bar ...
+  // Then there will be an entry ("--foo_out", "enable_bar") in this map.
+  map<string, string> generator_parameters_;
 
   // See AllowPlugins().  If this is empty, plugins aren't allowed.
   string plugin_prefix_;
@@ -302,6 +333,10 @@
   // the .proto files listed on the command-line are added.
   bool imports_in_descriptor_set_;
 
+  // True if --include_source_info was given, meaning that we should not strip
+  // SourceCodeInfo from the DescriptorSet.
+  bool source_info_in_descriptor_set_;
+
   // Was the --disallow_services flag used?
   bool disallow_services_;
 
diff --git a/third_party/protobuf/src/google/protobuf/compiler/command_line_interface_unittest.cc b/third_party/protobuf/src/google/protobuf/compiler/command_line_interface_unittest.cc
index d5b3a1d..1655992 100644
--- a/third_party/protobuf/src/google/protobuf/compiler/command_line_interface_unittest.cc
+++ b/third_party/protobuf/src/google/protobuf/compiler/command_line_interface_unittest.cc
@@ -122,6 +122,10 @@
   // substring.
   void ExpectErrorSubstring(const string& expected_substring);
 
+  // Like ExpectErrorSubstring, but checks that Run() returned zero.
+  void ExpectErrorSubstringWithZeroReturnCode(
+      const string& expected_substring);
+
   // Returns true if ExpectErrorSubstring(expected_substring) would pass, but
   // does not fail otherwise.
   bool HasAlternateErrorSubstring(const string& expected_substring);
@@ -225,7 +229,7 @@
   // Register generators.
   CodeGenerator* generator = new MockCodeGenerator("test_generator");
   mock_generators_to_delete_.push_back(generator);
-  cli_.RegisterGenerator("--test_out", generator, "Test output.");
+  cli_.RegisterGenerator("--test_out", "--test_opt", generator, "Test output.");
   cli_.RegisterGenerator("-t", generator, "Test output.");
 
   generator = new MockCodeGenerator("alt_generator");
@@ -345,6 +349,12 @@
   EXPECT_PRED_FORMAT2(testing::IsSubstring, expected_substring, error_text_);
 }
 
+void CommandLineInterfaceTest::ExpectErrorSubstringWithZeroReturnCode(
+    const string& expected_substring) {
+  EXPECT_EQ(0, return_code_);
+  EXPECT_PRED_FORMAT2(testing::IsSubstring, expected_substring, error_text_);
+}
+
 bool CommandLineInterfaceTest::HasAlternateErrorSubstring(
     const string& expected_substring) {
   EXPECT_NE(0, return_code_);
@@ -544,6 +554,32 @@
   ExpectGenerated("test_plugin", "TestPluginParameter", "foo.proto", "Foo");
 }
 
+TEST_F(CommandLineInterfaceTest, ExtraGeneratorParameters) {
+  // Test that generator parameters specified with the option flag are
+  // correctly passed to the code generator.
+
+  CreateTempFile("foo.proto",
+    "syntax = \"proto2\";\n"
+    "message Foo {}\n");
+  // Create the "a" and "b" sub-directories.
+  CreateTempDir("a");
+  CreateTempDir("b");
+
+  Run("protocol_compiler "
+      "--test_opt=foo1 "
+      "--test_out=bar:$tmpdir/a "
+      "--test_opt=foo2 "
+      "--test_out=baz:$tmpdir/b "
+      "--test_opt=foo3 "
+      "--proto_path=$tmpdir foo.proto");
+
+  ExpectNoErrors();
+  ExpectGenerated(
+      "test_generator", "bar,foo1,foo2,foo3", "foo.proto", "Foo", "a");
+  ExpectGenerated(
+      "test_generator", "baz,foo1,foo2,foo3", "foo.proto", "Foo", "b");
+}
+
 TEST_F(CommandLineInterfaceTest, Insert) {
   // Test running a generator that inserts code into another's output.
 
@@ -779,6 +815,33 @@
   if (HasFatalFailure()) return;
   ASSERT_EQ(1, descriptor_set.file_size());
   EXPECT_EQ("bar.proto", descriptor_set.file(0).name());
+  // Descriptor set should not have source code info.
+  EXPECT_FALSE(descriptor_set.file(0).has_source_code_info());
+}
+
+TEST_F(CommandLineInterfaceTest, WriteDescriptorSetWithSourceInfo) {
+  CreateTempFile("foo.proto",
+    "syntax = \"proto2\";\n"
+    "message Foo {}\n");
+  CreateTempFile("bar.proto",
+    "syntax = \"proto2\";\n"
+    "import \"foo.proto\";\n"
+    "message Bar {\n"
+    "  optional Foo foo = 1;\n"
+    "}\n");
+
+  Run("protocol_compiler --descriptor_set_out=$tmpdir/descriptor_set "
+      "--include_source_info --proto_path=$tmpdir bar.proto");
+
+  ExpectNoErrors();
+
+  FileDescriptorSet descriptor_set;
+  ReadDescriptorSet("descriptor_set", &descriptor_set);
+  if (HasFatalFailure()) return;
+  ASSERT_EQ(1, descriptor_set.file_size());
+  EXPECT_EQ("bar.proto", descriptor_set.file(0).name());
+  // Source code info included.
+  EXPECT_TRUE(descriptor_set.file(0).has_source_code_info());
 }
 
 TEST_F(CommandLineInterfaceTest, WriteTransitiveDescriptorSet) {
@@ -807,6 +870,40 @@
   }
   EXPECT_EQ("foo.proto", descriptor_set.file(0).name());
   EXPECT_EQ("bar.proto", descriptor_set.file(1).name());
+  // Descriptor set should not have source code info.
+  EXPECT_FALSE(descriptor_set.file(0).has_source_code_info());
+  EXPECT_FALSE(descriptor_set.file(1).has_source_code_info());
+}
+
+TEST_F(CommandLineInterfaceTest, WriteTransitiveDescriptorSetWithSourceInfo) {
+  CreateTempFile("foo.proto",
+    "syntax = \"proto2\";\n"
+    "message Foo {}\n");
+  CreateTempFile("bar.proto",
+    "syntax = \"proto2\";\n"
+    "import \"foo.proto\";\n"
+    "message Bar {\n"
+    "  optional Foo foo = 1;\n"
+    "}\n");
+
+  Run("protocol_compiler --descriptor_set_out=$tmpdir/descriptor_set "
+      "--include_imports --include_source_info --proto_path=$tmpdir bar.proto");
+
+  ExpectNoErrors();
+
+  FileDescriptorSet descriptor_set;
+  ReadDescriptorSet("descriptor_set", &descriptor_set);
+  if (HasFatalFailure()) return;
+  ASSERT_EQ(2, descriptor_set.file_size());
+  if (descriptor_set.file(0).name() == "bar.proto") {
+    std::swap(descriptor_set.mutable_file()->mutable_data()[0],
+              descriptor_set.mutable_file()->mutable_data()[1]);
+  }
+  EXPECT_EQ("foo.proto", descriptor_set.file(0).name());
+  EXPECT_EQ("bar.proto", descriptor_set.file(1).name());
+  // Source code info included.
+  EXPECT_TRUE(descriptor_set.file(0).has_source_code_info());
+  EXPECT_TRUE(descriptor_set.file(1).has_source_code_info());
 }
 
 // -------------------------------------------------------------------
@@ -1129,6 +1226,17 @@
 #endif
 }
 
+TEST_F(CommandLineInterfaceTest, PluginReceivesSourceCodeInfo) {
+  CreateTempFile("foo.proto",
+    "syntax = \"proto2\";\n"
+    "message MockCodeGenerator_HasSourceCodeInfo {}\n");
+
+  Run("protocol_compiler --plug_out=$tmpdir --proto_path=$tmpdir foo.proto");
+
+  ExpectErrorSubstring(
+      "Saw message type MockCodeGenerator_HasSourceCodeInfo: 1.");
+}
+
 TEST_F(CommandLineInterfaceTest, GeneratorPluginNotFound) {
   // Test what happens if the plugin isn't found.
 
@@ -1171,11 +1279,11 @@
 TEST_F(CommandLineInterfaceTest, HelpText) {
   Run("test_exec_name --help");
 
-  ExpectErrorSubstring("Usage: test_exec_name ");
-  ExpectErrorSubstring("--test_out=OUT_DIR");
-  ExpectErrorSubstring("Test output.");
-  ExpectErrorSubstring("--alt_out=OUT_DIR");
-  ExpectErrorSubstring("Alt output.");
+  ExpectErrorSubstringWithZeroReturnCode("Usage: test_exec_name ");
+  ExpectErrorSubstringWithZeroReturnCode("--test_out=OUT_DIR");
+  ExpectErrorSubstringWithZeroReturnCode("Test output.");
+  ExpectErrorSubstringWithZeroReturnCode("--alt_out=OUT_DIR");
+  ExpectErrorSubstringWithZeroReturnCode("Alt output.");
 }
 
 TEST_F(CommandLineInterfaceTest, GccFormatErrors) {
diff --git a/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc b/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc
index bcfa502..b7c1766 100644
--- a/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc
+++ b/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc
@@ -48,8 +48,8 @@
 #include <google/protobuf/compiler/importer.h>
 #include <google/protobuf/descriptor.h>
 #include <google/protobuf/io/zero_copy_stream_impl.h>
-#include <google/protobuf/stubs/stl_util-inl.h>
 #include <google/protobuf/stubs/map-util.h>
+#include <google/protobuf/stubs/stl_util.h>
 #include <google/protobuf/stubs/strutil.h>
 #include <google/protobuf/stubs/substitute.h>
 
diff --git a/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_enum.cc b/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_enum.cc
index 76d2b79..67c12d7 100644
--- a/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_enum.cc
+++ b/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_enum.cc
@@ -46,10 +46,10 @@
 namespace cpp {
 
 EnumGenerator::EnumGenerator(const EnumDescriptor* descriptor,
-                             const string& dllexport_decl)
+                             const Options& options)
   : descriptor_(descriptor),
     classname_(ClassName(descriptor, false)),
-    dllexport_decl_(dllexport_decl) {
+    options_(options) {
 }
 
 EnumGenerator::~EnumGenerator() {}
@@ -88,10 +88,10 @@
   vars["min_name"] = min_value->name();
   vars["max_name"] = max_value->name();
 
-  if (dllexport_decl_.empty()) {
+  if (options_.dllexport_decl.empty()) {
     vars["dllexport"] = "";
   } else {
-    vars["dllexport"] = dllexport_decl_ + " ";
+    vars["dllexport"] = options_.dllexport_decl + " ";
   }
 
   printer->Print(vars,
diff --git a/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_enum.h b/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_enum.h
index 58f7721..2e85a0b 100644
--- a/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_enum.h
+++ b/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_enum.h
@@ -36,8 +36,10 @@
 #define GOOGLE_PROTOBUF_COMPILER_CPP_ENUM_H__
 
 #include <string>
+#include <google/protobuf/compiler/cpp/cpp_options.h>
 #include <google/protobuf/descriptor.h>
 
+
 namespace google {
 namespace protobuf {
   namespace io {
@@ -53,7 +55,7 @@
  public:
   // See generator.cc for the meaning of dllexport_decl.
   explicit EnumGenerator(const EnumDescriptor* descriptor,
-                         const string& dllexport_decl);
+                         const Options& options);
   ~EnumGenerator();
 
   // Header stuff.
@@ -86,7 +88,7 @@
  private:
   const EnumDescriptor* descriptor_;
   string classname_;
-  string dllexport_decl_;
+  Options options_;
 
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(EnumGenerator);
 };
diff --git a/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_enum_field.cc b/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_enum_field.cc
index a369f41..6e1620d 100644
--- a/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_enum_field.cc
+++ b/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_enum_field.cc
@@ -46,8 +46,9 @@
 namespace {
 
 void SetEnumVariables(const FieldDescriptor* descriptor,
-                      map<string, string>* variables) {
-  SetCommonFieldVariables(descriptor, variables);
+                      map<string, string>* variables,
+                      const Options& options) {
+  SetCommonFieldVariables(descriptor, variables, options);
   const EnumValueDescriptor* default_value = descriptor->default_value_enum();
   (*variables)["type"] = ClassName(descriptor->enum_type(), true);
   (*variables)["default"] = SimpleItoa(default_value->number());
@@ -58,9 +59,10 @@
 // ===================================================================
 
 EnumFieldGenerator::
-EnumFieldGenerator(const FieldDescriptor* descriptor)
+EnumFieldGenerator(const FieldDescriptor* descriptor,
+                   const Options& options)
   : descriptor_(descriptor) {
-  SetEnumVariables(descriptor, &variables_);
+  SetEnumVariables(descriptor, &variables_, options);
 }
 
 EnumFieldGenerator::~EnumFieldGenerator() {}
@@ -84,7 +86,7 @@
     "  return static_cast< $type$ >($name$_);\n"
     "}\n"
     "inline void $classname$::set_$name$($type$ value) {\n"
-    "  GOOGLE_DCHECK($type$_IsValid(value));\n"
+    "  assert($type$_IsValid(value));\n"
     "  set_has_$name$();\n"
     "  $name$_ = value;\n"
     "}\n");
@@ -152,9 +154,10 @@
 // ===================================================================
 
 RepeatedEnumFieldGenerator::
-RepeatedEnumFieldGenerator(const FieldDescriptor* descriptor)
+RepeatedEnumFieldGenerator(const FieldDescriptor* descriptor,
+                           const Options& options)
   : descriptor_(descriptor) {
-  SetEnumVariables(descriptor, &variables_);
+  SetEnumVariables(descriptor, &variables_, options);
 }
 
 RepeatedEnumFieldGenerator::~RepeatedEnumFieldGenerator() {}
@@ -187,11 +190,11 @@
     "  return static_cast< $type$ >($name$_.Get(index));\n"
     "}\n"
     "inline void $classname$::set_$name$(int index, $type$ value) {\n"
-    "  GOOGLE_DCHECK($type$_IsValid(value));\n"
+    "  assert($type$_IsValid(value));\n"
     "  $name$_.Set(index, value);\n"
     "}\n"
     "inline void $classname$::add_$name$($type$ value) {\n"
-    "  GOOGLE_DCHECK($type$_IsValid(value));\n"
+    "  assert($type$_IsValid(value));\n"
     "  $name$_.Add(value);\n"
     "}\n");
   printer->Print(variables_,
@@ -345,7 +348,9 @@
       "  total_size += $tag_size$ +\n"
       "    ::google::protobuf::internal::WireFormatLite::Int32Size(data_size);\n"
       "}\n"
+      "GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();\n"
       "_$name$_cached_byte_size_ = data_size;\n"
+      "GOOGLE_SAFE_CONCURRENT_WRITES_END();\n"
       "total_size += data_size;\n");
   } else {
     printer->Print(variables_,
diff --git a/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_enum_field.h b/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_enum_field.h
index 0793430..6577008 100644
--- a/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_enum_field.h
+++ b/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_enum_field.h
@@ -46,7 +46,8 @@
 
 class EnumFieldGenerator : public FieldGenerator {
  public:
-  explicit EnumFieldGenerator(const FieldDescriptor* descriptor);
+  explicit EnumFieldGenerator(const FieldDescriptor* descriptor,
+                              const Options& options);
   ~EnumFieldGenerator();
 
   // implements FieldGenerator ---------------------------------------
@@ -71,7 +72,8 @@
 
 class RepeatedEnumFieldGenerator : public FieldGenerator {
  public:
-  explicit RepeatedEnumFieldGenerator(const FieldDescriptor* descriptor);
+  explicit RepeatedEnumFieldGenerator(const FieldDescriptor* descriptor,
+                                      const Options& options);
   ~RepeatedEnumFieldGenerator();
 
   // implements FieldGenerator ---------------------------------------
diff --git a/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_extension.cc b/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_extension.cc
index 658a707..ef56b5e 100644
--- a/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_extension.cc
+++ b/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_extension.cc
@@ -57,9 +57,9 @@
 }  // anonymous namespace
 
 ExtensionGenerator::ExtensionGenerator(const FieldDescriptor* descriptor,
-                                       const string& dllexport_decl)
+                                       const Options& options)
   : descriptor_(descriptor),
-    dllexport_decl_(dllexport_decl) {
+    options_(options) {
   // Construct type_traits_.
   if (descriptor_->is_repeated()) {
     type_traits_ = "Repeated";
@@ -106,8 +106,8 @@
   // export/import specifier.
   if (descriptor_->extension_scope() == NULL) {
     vars["qualifier"] = "extern";
-    if (!dllexport_decl_.empty()) {
-      vars["qualifier"] = dllexport_decl_ + " " + vars["qualifier"];
+    if (!options_.dllexport_decl.empty()) {
+      vars["qualifier"] = options_.dllexport_decl + " " + vars["qualifier"];
     }
   } else {
     vars["qualifier"] = "static";
diff --git a/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_extension.h b/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_extension.h
index 3068b09..50ad035 100644
--- a/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_extension.h
+++ b/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_extension.h
@@ -37,6 +37,7 @@
 
 #include <string>
 #include <google/protobuf/stubs/common.h>
+#include <google/protobuf/compiler/cpp/cpp_options.h>
 
 namespace google {
 namespace protobuf {
@@ -56,8 +57,8 @@
 class ExtensionGenerator {
  public:
   // See generator.cc for the meaning of dllexport_decl.
-  explicit ExtensionGenerator(const FieldDescriptor* descriptor,
-                              const string& dllexport_decl);
+  explicit ExtensionGenerator(const FieldDescriptor* desycriptor,
+                              const Options& options);
   ~ExtensionGenerator();
 
   // Header stuff.
@@ -72,7 +73,7 @@
  private:
   const FieldDescriptor* descriptor_;
   string type_traits_;
-  string dllexport_decl_;
+  Options options_;
 
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ExtensionGenerator);
 };
diff --git a/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_field.cc b/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_field.cc
index 103cac4..0786176 100644
--- a/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_field.cc
+++ b/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_field.cc
@@ -52,7 +52,8 @@
 using internal::WireFormat;
 
 void SetCommonFieldVariables(const FieldDescriptor* descriptor,
-                             map<string, string>* variables) {
+                             map<string, string>* variables,
+                             const Options& options) {
   (*variables)["name"] = FieldName(descriptor);
   (*variables)["index"] = SimpleItoa(descriptor->index());
   (*variables)["number"] = SimpleItoa(descriptor->number());
@@ -64,6 +65,7 @@
   (*variables)["deprecation"] = descriptor->options().deprecated()
       ? " PROTOBUF_DEPRECATED" : "";
 
+  (*variables)["cppget"] = "Get";
 }
 
 FieldGenerator::~FieldGenerator() {}
@@ -80,46 +82,47 @@
 
 }
 
-FieldGeneratorMap::FieldGeneratorMap(const Descriptor* descriptor)
+FieldGeneratorMap::FieldGeneratorMap(const Descriptor* descriptor,
+                                     const Options& options)
   : descriptor_(descriptor),
-    field_generators_(
-      new scoped_ptr<FieldGenerator>[descriptor->field_count()]) {
+    field_generators_(new scoped_ptr<FieldGenerator>[descriptor->field_count()]) {
   // Construct all the FieldGenerators.
   for (int i = 0; i < descriptor->field_count(); i++) {
-    field_generators_[i].reset(MakeGenerator(descriptor->field(i)));
+    field_generators_[i].reset(MakeGenerator(descriptor->field(i), options));
   }
 }
 
-FieldGenerator* FieldGeneratorMap::MakeGenerator(const FieldDescriptor* field) {
+FieldGenerator* FieldGeneratorMap::MakeGenerator(const FieldDescriptor* field,
+                                                 const Options& options) {
   if (field->is_repeated()) {
     switch (field->cpp_type()) {
       case FieldDescriptor::CPPTYPE_MESSAGE:
-        return new RepeatedMessageFieldGenerator(field);
+        return new RepeatedMessageFieldGenerator(field, options);
       case FieldDescriptor::CPPTYPE_STRING:
         switch (field->options().ctype()) {
           default:  // RepeatedStringFieldGenerator handles unknown ctypes.
           case FieldOptions::STRING:
-            return new RepeatedStringFieldGenerator(field);
+            return new RepeatedStringFieldGenerator(field, options);
         }
       case FieldDescriptor::CPPTYPE_ENUM:
-        return new RepeatedEnumFieldGenerator(field);
+        return new RepeatedEnumFieldGenerator(field, options);
       default:
-        return new RepeatedPrimitiveFieldGenerator(field);
+        return new RepeatedPrimitiveFieldGenerator(field, options);
     }
   } else {
     switch (field->cpp_type()) {
       case FieldDescriptor::CPPTYPE_MESSAGE:
-        return new MessageFieldGenerator(field);
+        return new MessageFieldGenerator(field, options);
       case FieldDescriptor::CPPTYPE_STRING:
         switch (field->options().ctype()) {
           default:  // StringFieldGenerator handles unknown ctypes.
           case FieldOptions::STRING:
-            return new StringFieldGenerator(field);
+            return new StringFieldGenerator(field, options);
         }
       case FieldDescriptor::CPPTYPE_ENUM:
-        return new EnumFieldGenerator(field);
+        return new EnumFieldGenerator(field, options);
       default:
-        return new PrimitiveFieldGenerator(field);
+        return new PrimitiveFieldGenerator(field, options);
     }
   }
 }
diff --git a/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_field.h b/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_field.h
index c303a33..f7d99b1 100644
--- a/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_field.h
+++ b/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_field.h
@@ -40,6 +40,7 @@
 
 #include <google/protobuf/stubs/common.h>
 #include <google/protobuf/descriptor.h>
+#include <google/protobuf/compiler/cpp/cpp_options.h>
 
 namespace google {
 namespace protobuf {
@@ -57,7 +58,8 @@
 // ['name', 'index', 'number', 'classname', 'declared_type', 'tag_size',
 // 'deprecation'].
 void SetCommonFieldVariables(const FieldDescriptor* descriptor,
-                             map<string, string>* variables);
+                             map<string, string>* variables,
+                             const Options& options);
 
 class FieldGenerator {
  public:
@@ -114,6 +116,13 @@
   // Most field types don't need this, so the default implementation is empty.
   virtual void GenerateDestructorCode(io::Printer* printer) const {}
 
+  // Generate code that allocates the fields's default instance.
+  virtual void GenerateDefaultInstanceAllocator(io::Printer* printer) const {}
+
+  // Generate code that should be run when ShutdownProtobufLibrary() is called,
+  // to delete all dynamically-allocated objects.
+  virtual void GenerateShutdownCode(io::Printer* printer) const {}
+
   // Generate lines to decode this field, which will be placed inside the
   // message's MergeFromCodedStream() method.
   virtual void GenerateMergeFromCodedStream(io::Printer* printer) const = 0;
@@ -144,7 +153,7 @@
 // Convenience class which constructs FieldGenerators for a Descriptor.
 class FieldGeneratorMap {
  public:
-  explicit FieldGeneratorMap(const Descriptor* descriptor);
+  explicit FieldGeneratorMap(const Descriptor* descriptor, const Options& options);
   ~FieldGeneratorMap();
 
   const FieldGenerator& get(const FieldDescriptor* field) const;
@@ -153,7 +162,8 @@
   const Descriptor* descriptor_;
   scoped_array<scoped_ptr<FieldGenerator> > field_generators_;
 
-  static FieldGenerator* MakeGenerator(const FieldDescriptor* field);
+  static FieldGenerator* MakeGenerator(const FieldDescriptor* field,
+                                       const Options& options);
 
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FieldGeneratorMap);
 };
diff --git a/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_file.cc b/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_file.cc
index 3e6d414..4eb89f4 100644
--- a/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_file.cc
+++ b/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_file.cc
@@ -51,7 +51,7 @@
 // ===================================================================
 
 FileGenerator::FileGenerator(const FileDescriptor* file,
-                             const string& dllexport_decl)
+                             const Options& options)
   : file_(file),
     message_generators_(
       new scoped_ptr<MessageGenerator>[file->message_type_count()]),
@@ -61,26 +61,26 @@
       new scoped_ptr<ServiceGenerator>[file->service_count()]),
     extension_generators_(
       new scoped_ptr<ExtensionGenerator>[file->extension_count()]),
-    dllexport_decl_(dllexport_decl) {
+    options_(options) {
 
   for (int i = 0; i < file->message_type_count(); i++) {
     message_generators_[i].reset(
-      new MessageGenerator(file->message_type(i), dllexport_decl));
+      new MessageGenerator(file->message_type(i), options));
   }
 
   for (int i = 0; i < file->enum_type_count(); i++) {
     enum_generators_[i].reset(
-      new EnumGenerator(file->enum_type(i), dllexport_decl));
+      new EnumGenerator(file->enum_type(i), options));
   }
 
   for (int i = 0; i < file->service_count(); i++) {
     service_generators_[i].reset(
-      new ServiceGenerator(file->service(i), dllexport_decl));
+      new ServiceGenerator(file->service(i), options));
   }
 
   for (int i = 0; i < file->extension_count(); i++) {
     extension_generators_[i].reset(
-      new ExtensionGenerator(file->extension(i), dllexport_decl));
+      new ExtensionGenerator(file->extension(i), options));
   }
 
   SplitStringUsing(file_->package(), ".", &package_parts_);
@@ -104,6 +104,7 @@
     "filename", file_->name(),
     "filename_identifier", filename_identifier);
 
+
   printer->Print(
     "#include <google/protobuf/stubs/common.h>\n"
     "\n");
@@ -128,7 +129,17 @@
 
   // OK, it's now safe to #include other files.
   printer->Print(
-    "#include <google/protobuf/generated_message_util.h>\n"
+    "#include <google/protobuf/generated_message_util.h>\n");
+  if (file_->message_type_count() > 0) {
+    if (HasDescriptorMethods(file_)) {
+      printer->Print(
+        "#include <google/protobuf/message.h>\n");
+    } else {
+      printer->Print(
+        "#include <google/protobuf/message_lite.h>\n");
+    }
+  }
+  printer->Print(
     "#include <google/protobuf/repeated_field.h>\n"
     "#include <google/protobuf/extension_set.h>\n");
 
@@ -137,9 +148,9 @@
       "#include <google/protobuf/unknown_field_set.h>\n");
   }
 
-  if (HasDescriptorMethods(file_)) {
+  if (HasDescriptorMethods(file_) && HasEnumDefinitions(file_)) {
     printer->Print(
-      "#include <google/protobuf/generated_message_reflection.h>\n");
+      "#include <google/protobuf/generated_enum_reflection.h>\n");
   }
 
   if (HasGenericServices(file_)) {
@@ -147,6 +158,11 @@
       "#include <google/protobuf/service.h>\n");
   }
 
+  if (HasUnknownFields(file_) && file_->message_type_count() > 0) {
+    printer->Print(
+      "#include <google/protobuf/unknown_field_set.h>\n");
+  }
+
 
   for (int i = 0; i < file_->dependency_count(); i++) {
     printer->Print(
@@ -154,9 +170,11 @@
       "dependency", StripProto(file_->dependency(i)->name()));
   }
 
+
   printer->Print(
     "// @@protoc_insertion_point(includes)\n");
 
+
   // Open namespace.
   GenerateNamespaceOpeners(printer);
 
@@ -167,7 +185,7 @@
     "// Internal implementation detail -- do not call these.\n"
     "void $dllexport_decl$ $adddescriptorsname$();\n",
     "adddescriptorsname", GlobalAddDescriptorsName(file_->name()),
-    "dllexport_decl", dllexport_decl_);
+    "dllexport_decl", options_.dllexport_decl);
 
   printer->Print(
     // Note that we don't put dllexport_decl on these because they are only
@@ -287,6 +305,7 @@
 void FileGenerator::GenerateSource(io::Printer* printer) {
   printer->Print(
     "// Generated by the protocol buffer compiler.  DO NOT EDIT!\n"
+    "// source: $filename$\n"
     "\n"
 
     // The generated code calls accessors that might be deprecated. We don't
@@ -296,14 +315,17 @@
     "\n"
     "#include <algorithm>\n"    // for swap()
     "\n"
+    "#include <google/protobuf/stubs/common.h>\n"
     "#include <google/protobuf/stubs/once.h>\n"
     "#include <google/protobuf/io/coded_stream.h>\n"
     "#include <google/protobuf/wire_format_lite_inl.h>\n",
+    "filename", file_->name(),
     "basename", StripProto(file_->name()));
 
   if (HasDescriptorMethods(file_)) {
     printer->Print(
       "#include <google/protobuf/descriptor.h>\n"
+      "#include <google/protobuf/generated_message_reflection.h>\n"
       "#include <google/protobuf/reflection_ops.h>\n"
       "#include <google/protobuf/wire_format.h>\n");
   }
@@ -509,10 +531,12 @@
     "  static bool already_here = false;\n"
     "  if (already_here) return;\n"
     "  already_here = true;\n"
-    "  GOOGLE_PROTOBUF_VERIFY_VERSION;\n",
+    "  GOOGLE_PROTOBUF_VERIFY_VERSION;\n"
+    "\n",
     // Without.
     "void $adddescriptorsname$_impl() {\n"
-    "  GOOGLE_PROTOBUF_VERIFY_VERSION;\n",
+    "  GOOGLE_PROTOBUF_VERIFY_VERSION;\n"
+    "\n",
     // Vars.
     "adddescriptorsname", GlobalAddDescriptorsName(file_->name()));
 
@@ -526,9 +550,9 @@
     vector<string> dependency_package_parts;
     SplitStringUsing(dependency->package(), ".", &dependency_package_parts);
     printer->Print("::");
-    for (int i = 0; i < dependency_package_parts.size(); i++) {
+    for (int j = 0; j < dependency_package_parts.size(); j++) {
       printer->Print("$name$::",
-                     "name", dependency_package_parts[i]);
+                     "name", dependency_package_parts[j]);
     }
     // Call its AddDescriptors function.
     printer->Print(
@@ -552,10 +576,12 @@
     static const int kBytesPerLine = 40;
     for (int i = 0; i < file_data.size(); i += kBytesPerLine) {
       printer->Print("\n  \"$data$\"",
-        "data", EscapeTrigraphs(CEscape(file_data.substr(i, kBytesPerLine))));
+                     "data",
+                     EscapeTrigraphs(
+                         CEscape(file_data.substr(i, kBytesPerLine))));
     }
     printer->Print(
-      ", $size$);\n",
+        ", $size$);\n",
       "size", SimpleItoa(file_data.size()));
 
     // Call MessageFactory::InternalRegisterGeneratedFile().
diff --git a/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_file.h b/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_file.h
index b4e0128..2deefaa 100644
--- a/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_file.h
+++ b/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_file.h
@@ -39,6 +39,7 @@
 #include <vector>
 #include <google/protobuf/stubs/common.h>
 #include <google/protobuf/compiler/cpp/cpp_field.h>
+#include <google/protobuf/compiler/cpp/cpp_options.h>
 
 namespace google {
 namespace protobuf {
@@ -61,7 +62,7 @@
  public:
   // See generator.cc for the meaning of dllexport_decl.
   explicit FileGenerator(const FileDescriptor* file,
-                         const string& dllexport_decl);
+                         const Options& options);
   ~FileGenerator();
 
   void GenerateHeader(io::Printer* printer);
@@ -85,7 +86,7 @@
   // E.g. if the package is foo.bar, package_parts_ is {"foo", "bar"}.
   vector<string> package_parts_;
 
-  string dllexport_decl_;
+  const Options options_;
 
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FileGenerator);
 };
diff --git a/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_generator.cc b/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_generator.cc
index bb84e2a..1813510 100644
--- a/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_generator.cc
+++ b/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_generator.cc
@@ -78,11 +78,13 @@
   //   }
   // FOO_EXPORT is a macro which should expand to __declspec(dllexport) or
   // __declspec(dllimport) depending on what is being compiled.
-  string dllexport_decl;
+  Options file_options;
 
   for (int i = 0; i < options.size(); i++) {
     if (options[i].first == "dllexport_decl") {
-      dllexport_decl = options[i].second;
+      file_options.dllexport_decl = options[i].second;
+    } else if (options[i].first == "safe_boundary_check") {
+      file_options.safe_boundary_check = true;
     } else {
       *error = "Unknown generator option: " + options[i].first;
       return false;
@@ -95,7 +97,7 @@
   string basename = StripProto(file->name());
   basename.append(".pb");
 
-  FileGenerator file_generator(file, dllexport_decl);
+  FileGenerator file_generator(file, file_options);
 
   // Generate header.
   {
diff --git a/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_helpers.cc b/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_helpers.cc
index c4b868c..c53d5d3 100644
--- a/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_helpers.cc
+++ b/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_helpers.cc
@@ -148,7 +148,7 @@
 string ClassName(const EnumDescriptor* enum_descriptor, bool qualified) {
   if (enum_descriptor->containing_type() == NULL) {
     if (qualified) {
-      return DotsToColons(enum_descriptor->full_name());
+      return "::" + DotsToColons(enum_descriptor->full_name());
     } else {
       return enum_descriptor->name();
     }
@@ -259,10 +259,27 @@
 string DefaultValue(const FieldDescriptor* field) {
   switch (field->cpp_type()) {
     case FieldDescriptor::CPPTYPE_INT32:
+      // gcc rejects the decimal form of kint32min and kint64min.
+      if (field->default_value_int32() == kint32min) {
+        // Make sure we are in a 2's complement system.
+        GOOGLE_COMPILE_ASSERT(
+            (uint32)kint32min == (uint32)0 - (uint32)0x80000000,
+            kint32min_value_error);
+        return "-0x80000000";
+      }
       return SimpleItoa(field->default_value_int32());
     case FieldDescriptor::CPPTYPE_UINT32:
       return SimpleItoa(field->default_value_uint32()) + "u";
     case FieldDescriptor::CPPTYPE_INT64:
+      // See the comments for CPPTYPE_INT32.
+      if (field->default_value_int64() == kint64min) {
+        // Make sure we are in a 2's complement system.
+        GOOGLE_COMPILE_ASSERT(
+            (uint64)kint64min ==
+                (uint64)0 - (uint64)GOOGLE_LONGLONG(0x8000000000000000),
+            kint64min_value_error);
+        return "GOOGLE_LONGLONG(-0x8000000000000000)";
+      }
       return "GOOGLE_LONGLONG(" + SimpleItoa(field->default_value_int64()) + ")";
     case FieldDescriptor::CPPTYPE_UINT64:
       return "GOOGLE_ULONGLONG(" + SimpleItoa(field->default_value_uint64())+ ")";
@@ -308,8 +325,9 @@
           ClassName(field->enum_type(), true),
           field->default_value_enum()->number());
     case FieldDescriptor::CPPTYPE_STRING:
-      return "\"" + EscapeTrigraphs(CEscape(field->default_value_string())) +
-             "\"";
+      return "\"" + EscapeTrigraphs(
+        CEscape(field->default_value_string())) +
+        "\"";
     case FieldDescriptor::CPPTYPE_MESSAGE:
       return FieldMessageTypeName(field) + "::default_instance()";
   }
@@ -401,6 +419,23 @@
   }
 }
 
+
+static bool HasEnumDefinitions(const Descriptor* message_type) {
+  if (message_type->enum_type_count() > 0) return true;
+  for (int i = 0; i < message_type->nested_type_count(); ++i) {
+    if (HasEnumDefinitions(message_type->nested_type(i))) return true;
+  }
+  return false;
+}
+
+bool HasEnumDefinitions(const FileDescriptor* file) {
+  if (file->enum_type_count() > 0) return true;
+  for (int i = 0; i < file->message_type_count(); ++i) {
+    if (HasEnumDefinitions(file->message_type(i))) return true;
+  }
+  return false;
+}
+
 }  // namespace cpp
 }  // namespace compiler
 }  // namespace protobuf
diff --git a/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_helpers.h b/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_helpers.h
index 690fbec..1b5b1ac 100644
--- a/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_helpers.h
+++ b/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_helpers.h
@@ -122,24 +122,27 @@
 string EscapeTrigraphs(const string& to_escape);
 
 // Do message classes in this file keep track of unknown fields?
-inline bool HasUnknownFields(const FileDescriptor *file) {
+inline bool HasUnknownFields(const FileDescriptor* file) {
   return file->options().optimize_for() != FileOptions::LITE_RUNTIME ||
          file->options().retain_unknown_fields();
 }
 
+// Does this file have any enum type definitions?
+bool HasEnumDefinitions(const FileDescriptor* file);
+
 // Does this file have generated parsing, serialization, and other
 // standard methods for which reflection-based fallback implementations exist?
-inline bool HasGeneratedMethods(const FileDescriptor *file) {
+inline bool HasGeneratedMethods(const FileDescriptor* file) {
   return file->options().optimize_for() != FileOptions::CODE_SIZE;
 }
 
 // Do message classes in this file have descriptor and refelction methods?
-inline bool HasDescriptorMethods(const FileDescriptor *file) {
+inline bool HasDescriptorMethods(const FileDescriptor* file) {
   return file->options().optimize_for() != FileOptions::LITE_RUNTIME;
 }
 
 // Should we generate generic services for this file?
-inline bool HasGenericServices(const FileDescriptor *file) {
+inline bool HasGenericServices(const FileDescriptor* file) {
   return file->service_count() > 0 &&
          file->options().optimize_for() != FileOptions::LITE_RUNTIME &&
          file->options().cc_generic_services();
@@ -174,6 +177,7 @@
     io::Printer* printer, const char* with_static_init,
     const char* without_static_init);
 
+
 }  // namespace cpp
 }  // namespace compiler
 }  // namespace protobuf
diff --git a/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_message.cc b/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_message.cc
index 4248747..a7a81b0 100644
--- a/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_message.cc
+++ b/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_message.cc
@@ -48,6 +48,7 @@
 #include <google/protobuf/wire_format.h>
 #include <google/protobuf/descriptor.pb.h>
 
+
 namespace google {
 namespace protobuf {
 namespace compiler {
@@ -103,6 +104,13 @@
   }
 };
 
+// Returns true if the "required" restriction check should be ignored for the
+// given field.
+inline static bool ShouldIgnoreRequiredFieldCheck(
+    const FieldDescriptor* field) {
+  return false;
+}
+
 // Returns true if the message type has any required fields.  If it doesn't,
 // we can optimize out calls to its IsInitialized() method.
 //
@@ -129,7 +137,8 @@
     if (field->is_required()) {
       return true;
     }
-    if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
+    if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE &&
+        !ShouldIgnoreRequiredFieldCheck(field)) {
       if (HasRequiredFields(field->message_type(), already_seen)) {
         return true;
       }
@@ -280,11 +289,11 @@
 // ===================================================================
 
 MessageGenerator::MessageGenerator(const Descriptor* descriptor,
-                                   const string& dllexport_decl)
+                                   const Options& options)
   : descriptor_(descriptor),
     classname_(ClassName(descriptor, false)),
-    dllexport_decl_(dllexport_decl),
-    field_generators_(descriptor),
+    options_(options),
+    field_generators_(descriptor, options),
     nested_generators_(new scoped_ptr<MessageGenerator>[
       descriptor->nested_type_count()]),
     enum_generators_(new scoped_ptr<EnumGenerator>[
@@ -294,17 +303,17 @@
 
   for (int i = 0; i < descriptor->nested_type_count(); i++) {
     nested_generators_[i].reset(
-      new MessageGenerator(descriptor->nested_type(i), dllexport_decl));
+      new MessageGenerator(descriptor->nested_type(i), options));
   }
 
   for (int i = 0; i < descriptor->enum_type_count(); i++) {
     enum_generators_[i].reset(
-      new EnumGenerator(descriptor->enum_type(i), dllexport_decl));
+      new EnumGenerator(descriptor->enum_type(i), options));
   }
 
   for (int i = 0; i < descriptor->extension_count(); i++) {
     extension_generators_[i].reset(
-      new ExtensionGenerator(descriptor->extension(i), dllexport_decl));
+      new ExtensionGenerator(descriptor->extension(i), options));
   }
 }
 
@@ -349,7 +358,7 @@
     PrintFieldComment(printer, field);
 
     map<string, string> vars;
-    SetCommonFieldVariables(field, &vars);
+    SetCommonFieldVariables(field, &vars, options_);
     vars["constant_name"] = FieldConstantName(field);
 
     if (field->is_repeated()) {
@@ -386,7 +395,7 @@
     PrintFieldComment(printer, field);
 
     map<string, string> vars;
-    SetCommonFieldVariables(field, &vars);
+    SetCommonFieldVariables(field, &vars, options_);
 
     // Generate has_$name$() or $name$_size().
     if (field->is_repeated()) {
@@ -446,10 +455,10 @@
   map<string, string> vars;
   vars["classname"] = classname_;
   vars["field_count"] = SimpleItoa(descriptor_->field_count());
-  if (dllexport_decl_.empty()) {
+  if (options_.dllexport_decl.empty()) {
     vars["dllexport"] = "";
   } else {
-    vars["dllexport"] = dllexport_decl_ + " ";
+    vars["dllexport"] = options_.dllexport_decl + " ";
   }
   vars["superclass"] = SuperClassName(descriptor_);
 
@@ -507,6 +516,7 @@
       "\n");
   }
 
+
   printer->Print(vars,
     "void Swap($classname$* other);\n"
     "\n"
@@ -605,6 +615,7 @@
   printer->Print(" private:\n");
   printer->Indent();
 
+
   for (int i = 0; i < descriptor_->field_count(); i++) {
     if (!descriptor_->field(i)->is_repeated()) {
       printer->Print(
@@ -680,7 +691,7 @@
     // Without.
     "friend void $dllexport_decl$ $adddescriptorsname$_impl();\n",
     // Vars.
-    "dllexport_decl", dllexport_decl_,
+    "dllexport_decl", options_.dllexport_decl,
     "adddescriptorsname",
     GlobalAddDescriptorsName(descriptor_->file()->name()));
 
@@ -772,9 +783,11 @@
     printer->Print(vars,
       "    -1,\n");
   }
+  printer->Print(
+    "    ::google::protobuf::DescriptorPool::generated_pool(),\n");
   printer->Print(vars,
-    "    ::google::protobuf::DescriptorPool::generated_pool(),\n"
-    "    ::google::protobuf::MessageFactory::generated_factory(),\n"
+    "    ::google::protobuf::MessageFactory::generated_factory(),\n");
+  printer->Print(vars,
     "    sizeof($classname$));\n");
 
   // Handle nested types.
@@ -803,6 +816,13 @@
 
 void MessageGenerator::
 GenerateDefaultInstanceAllocator(io::Printer* printer) {
+  // Construct the default instances of all fields, as they will be used
+  // when creating the default instance of the entire message.
+  for (int i = 0; i < descriptor_->field_count(); i++) {
+    field_generators_.get(descriptor_->field(i))
+                     .GenerateDefaultInstanceAllocator(printer);
+  }
+
   // Construct the default instance.  We can't call InitAsDefaultInstance() yet
   // because we need to make sure all default instances that this one might
   // depend on are constructed first.
@@ -846,6 +866,12 @@
       "classname", classname_);
   }
 
+  // Handle default instances of fields.
+  for (int i = 0; i < descriptor_->field_count(); i++) {
+    field_generators_.get(descriptor_->field(i))
+                     .GenerateShutdownCode(printer);
+  }
+
   // Handle nested types.
   for (int i = 0; i < descriptor_->nested_type_count(); i++) {
     nested_generators_[i]->GenerateShutdownCode(printer);
@@ -1956,6 +1982,7 @@
   for (int i = 0; i < descriptor_->field_count(); i++) {
     const FieldDescriptor* field = descriptor_->field(i);
     if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE &&
+        !ShouldIgnoreRequiredFieldCheck(field) &&
         HasRequiredFields(field->message_type())) {
       if (field->is_repeated()) {
         printer->Print(
diff --git a/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_message.h b/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_message.h
index 04778f6..a7e43d9 100644
--- a/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_message.h
+++ b/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_message.h
@@ -38,6 +38,7 @@
 #include <string>
 #include <google/protobuf/stubs/common.h>
 #include <google/protobuf/compiler/cpp/cpp_field.h>
+#include <google/protobuf/compiler/cpp/cpp_options.h>
 
 namespace google {
 namespace protobuf {
@@ -57,7 +58,7 @@
  public:
   // See generator.cc for the meaning of dllexport_decl.
   explicit MessageGenerator(const Descriptor* descriptor,
-                            const string& dllexport_decl);
+                            const Options& options);
   ~MessageGenerator();
 
   // Header stuff.
@@ -153,7 +154,7 @@
 
   const Descriptor* descriptor_;
   string classname_;
-  string dllexport_decl_;
+  Options options_;
   FieldGeneratorMap field_generators_;
   scoped_array<scoped_ptr<MessageGenerator> > nested_generators_;
   scoped_array<scoped_ptr<EnumGenerator> > enum_generators_;
diff --git a/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_message_field.cc b/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_message_field.cc
index 7c785e7..447f975 100644
--- a/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_message_field.cc
+++ b/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_message_field.cc
@@ -45,8 +45,9 @@
 namespace {
 
 void SetMessageVariables(const FieldDescriptor* descriptor,
-                         map<string, string>* variables) {
-  SetCommonFieldVariables(descriptor, variables);
+                         map<string, string>* variables,
+                         const Options& options) {
+  SetCommonFieldVariables(descriptor, variables, options);
   (*variables)["type"] = FieldMessageTypeName(descriptor);
   (*variables)["stream_writer"] = (*variables)["declared_type"] +
       (HasFastArraySerialization(descriptor->message_type()->file()) ?
@@ -59,9 +60,10 @@
 // ===================================================================
 
 MessageFieldGenerator::
-MessageFieldGenerator(const FieldDescriptor* descriptor)
+MessageFieldGenerator(const FieldDescriptor* descriptor,
+                      const Options& options)
   : descriptor_(descriptor) {
-  SetMessageVariables(descriptor, &variables_);
+  SetMessageVariables(descriptor, &variables_, options);
 }
 
 MessageFieldGenerator::~MessageFieldGenerator() {}
@@ -76,7 +78,8 @@
   printer->Print(variables_,
     "inline const $type$& $name$() const$deprecation$;\n"
     "inline $type$* mutable_$name$()$deprecation$;\n"
-    "inline $type$* release_$name$()$deprecation$;\n");
+    "inline $type$* release_$name$()$deprecation$;\n"
+    "inline void set_allocated_$name$($type$* $name$)$deprecation$;\n");
 }
 
 void MessageFieldGenerator::
@@ -103,6 +106,15 @@
     "  $type$* temp = $name$_;\n"
     "  $name$_ = NULL;\n"
     "  return temp;\n"
+    "}\n"
+    "inline void $classname$::set_allocated_$name$($type$* $name$) {\n"
+    "  delete $name$_;\n"
+    "  $name$_ = $name$;\n"
+    "  if ($name$) {\n"
+    "    set_has_$name$();\n"
+    "  } else {\n"
+    "    clear_has_$name$();\n"
+    "  }\n"
     "}\n");
 }
 
@@ -167,9 +179,10 @@
 // ===================================================================
 
 RepeatedMessageFieldGenerator::
-RepeatedMessageFieldGenerator(const FieldDescriptor* descriptor)
+RepeatedMessageFieldGenerator(const FieldDescriptor* descriptor,
+                              const Options& options)
   : descriptor_(descriptor) {
-  SetMessageVariables(descriptor, &variables_);
+  SetMessageVariables(descriptor, &variables_, options);
 }
 
 RepeatedMessageFieldGenerator::~RepeatedMessageFieldGenerator() {}
@@ -197,7 +210,7 @@
 GenerateInlineAccessorDefinitions(io::Printer* printer) const {
   printer->Print(variables_,
     "inline const $type$& $classname$::$name$(int index) const {\n"
-    "  return $name$_.Get(index);\n"
+    "  return $name$_.$cppget$(index);\n"
     "}\n"
     "inline $type$* $classname$::mutable_$name$(int index) {\n"
     "  return $name$_.Mutable(index);\n"
diff --git a/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_message_field.h b/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_message_field.h
index f514727..a5ed68a 100644
--- a/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_message_field.h
+++ b/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_message_field.h
@@ -46,7 +46,8 @@
 
 class MessageFieldGenerator : public FieldGenerator {
  public:
-  explicit MessageFieldGenerator(const FieldDescriptor* descriptor);
+  explicit MessageFieldGenerator(const FieldDescriptor* descriptor,
+                                 const Options& options);
   ~MessageFieldGenerator();
 
   // implements FieldGenerator ---------------------------------------
@@ -71,7 +72,8 @@
 
 class RepeatedMessageFieldGenerator : public FieldGenerator {
  public:
-  explicit RepeatedMessageFieldGenerator(const FieldDescriptor* descriptor);
+  explicit RepeatedMessageFieldGenerator(const FieldDescriptor* descriptor,
+                                         const Options& options);
   ~RepeatedMessageFieldGenerator();
 
   // implements FieldGenerator ---------------------------------------
diff --git a/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_options.h b/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_options.h
new file mode 100644
index 0000000..7877066
--- /dev/null
+++ b/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_options.h
@@ -0,0 +1,58 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 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.
+
+// Author: rennie@google.com (Jeffrey Rennie)
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_CPP_OPTIONS_H__
+#define GOOGLE_PROTOBUF_COMPILER_CPP_OPTIONS_H__
+
+#include <string>
+
+#include <google/protobuf/stubs/common.h>
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace cpp {
+
+// Generator options:
+struct Options {
+  Options() : safe_boundary_check(false) {
+  }
+  string dllexport_decl;
+  bool safe_boundary_check;
+};
+
+}  // namespace cpp
+}  // namespace compiler
+}  // namespace protobuf
+
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_COMPILER_CPP_OPTIONS_H__
diff --git a/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_primitive_field.cc b/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_primitive_field.cc
index 5e8df0f..1c35fef 100644
--- a/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_primitive_field.cc
+++ b/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_primitive_field.cc
@@ -80,8 +80,9 @@
 }
 
 void SetPrimitiveVariables(const FieldDescriptor* descriptor,
-                           map<string, string>* variables) {
-  SetCommonFieldVariables(descriptor, variables);
+                           map<string, string>* variables,
+                           const Options& options) {
+  SetCommonFieldVariables(descriptor, variables, options);
   (*variables)["type"] = PrimitiveTypeName(descriptor->cpp_type());
   (*variables)["default"] = DefaultValue(descriptor);
   (*variables)["tag"] = SimpleItoa(internal::WireFormat::MakeTag(descriptor));
@@ -99,9 +100,10 @@
 // ===================================================================
 
 PrimitiveFieldGenerator::
-PrimitiveFieldGenerator(const FieldDescriptor* descriptor)
+PrimitiveFieldGenerator(const FieldDescriptor* descriptor,
+                        const Options& options)
   : descriptor_(descriptor) {
-  SetPrimitiveVariables(descriptor, &variables_);
+  SetPrimitiveVariables(descriptor, &variables_, options);
 }
 
 PrimitiveFieldGenerator::~PrimitiveFieldGenerator() {}
@@ -190,9 +192,10 @@
 // ===================================================================
 
 RepeatedPrimitiveFieldGenerator::
-RepeatedPrimitiveFieldGenerator(const FieldDescriptor* descriptor)
+RepeatedPrimitiveFieldGenerator(const FieldDescriptor* descriptor,
+                                const Options& options)
   : descriptor_(descriptor) {
-  SetPrimitiveVariables(descriptor, &variables_);
+  SetPrimitiveVariables(descriptor, &variables_, options);
 
   if (descriptor->options().packed()) {
     variables_["packed_reader"] = "ReadPackedPrimitive";
@@ -366,7 +369,9 @@
       "  total_size += $tag_size$ +\n"
       "    ::google::protobuf::internal::WireFormatLite::Int32Size(data_size);\n"
       "}\n"
+      "GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();\n"
       "_$name$_cached_byte_size_ = data_size;\n"
+      "GOOGLE_SAFE_CONCURRENT_WRITES_END();\n"
       "total_size += data_size;\n");
   } else {
     printer->Print(variables_,
diff --git a/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_primitive_field.h b/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_primitive_field.h
index 8fcd74a..48249c4 100644
--- a/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_primitive_field.h
+++ b/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_primitive_field.h
@@ -46,7 +46,8 @@
 
 class PrimitiveFieldGenerator : public FieldGenerator {
  public:
-  explicit PrimitiveFieldGenerator(const FieldDescriptor* descriptor);
+  explicit PrimitiveFieldGenerator(const FieldDescriptor* descriptor,
+                                   const Options& options);
   ~PrimitiveFieldGenerator();
 
   // implements FieldGenerator ---------------------------------------
@@ -71,7 +72,8 @@
 
 class RepeatedPrimitiveFieldGenerator : public FieldGenerator {
  public:
-  explicit RepeatedPrimitiveFieldGenerator(const FieldDescriptor* descriptor);
+  explicit RepeatedPrimitiveFieldGenerator(const FieldDescriptor* descriptor,
+                                           const Options& options);
   ~RepeatedPrimitiveFieldGenerator();
 
   // implements FieldGenerator ---------------------------------------
diff --git a/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_service.cc b/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_service.cc
index c282568..d20018e 100644
--- a/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_service.cc
+++ b/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_service.cc
@@ -43,14 +43,14 @@
 namespace cpp {
 
 ServiceGenerator::ServiceGenerator(const ServiceDescriptor* descriptor,
-                                   const string& dllexport_decl)
+                                   const Options& options)
   : descriptor_(descriptor) {
   vars_["classname"] = descriptor_->name();
   vars_["full_name"] = descriptor_->full_name();
-  if (dllexport_decl.empty()) {
+  if (options.dllexport_decl.empty()) {
     vars_["dllexport"] = "";
   } else {
-    vars_["dllexport"] = dllexport_decl + " ";
+    vars_["dllexport"] = options.dllexport_decl + " ";
   }
 }
 
diff --git a/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_service.h b/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_service.h
index 10e9dd3..820f9f5 100644
--- a/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_service.h
+++ b/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_service.h
@@ -38,6 +38,7 @@
 #include <map>
 #include <string>
 #include <google/protobuf/stubs/common.h>
+#include <google/protobuf/compiler/cpp/cpp_options.h>
 #include <google/protobuf/descriptor.h>
 
 namespace google {
@@ -55,7 +56,7 @@
  public:
   // See generator.cc for the meaning of dllexport_decl.
   explicit ServiceGenerator(const ServiceDescriptor* descriptor,
-                            const string& dllexport_decl);
+                            const Options& options);
   ~ServiceGenerator();
 
   // Header stuff.
diff --git a/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_string_field.cc b/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_string_field.cc
index 3cec2b6..9c0911a 100644
--- a/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_string_field.cc
+++ b/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_string_field.cc
@@ -46,11 +46,14 @@
 namespace {
 
 void SetStringVariables(const FieldDescriptor* descriptor,
-                        map<string, string>* variables) {
-  SetCommonFieldVariables(descriptor, variables);
+                        map<string, string>* variables,
+                        const Options& options) {
+  SetCommonFieldVariables(descriptor, variables, options);
   (*variables)["default"] = DefaultValue(descriptor);
+  (*variables)["default_length"] =
+      SimpleItoa(descriptor->default_value_string().length());
   (*variables)["default_variable"] = descriptor->default_value_string().empty()
-      ? "::google::protobuf::internal::kEmptyString"
+      ? "&::google::protobuf::internal::kEmptyString"
       : "_default_" + FieldName(descriptor) + "_";
   (*variables)["pointer_type"] =
       descriptor->type() == FieldDescriptor::TYPE_BYTES ? "void" : "char";
@@ -61,9 +64,10 @@
 // ===================================================================
 
 StringFieldGenerator::
-StringFieldGenerator(const FieldDescriptor* descriptor)
+StringFieldGenerator(const FieldDescriptor* descriptor,
+                     const Options& options)
   : descriptor_(descriptor) {
-  SetStringVariables(descriptor, &variables_);
+  SetStringVariables(descriptor, &variables_, options);
 }
 
 StringFieldGenerator::~StringFieldGenerator() {}
@@ -72,7 +76,7 @@
 GeneratePrivateMembers(io::Printer* printer) const {
   printer->Print(variables_, "::std::string* $name$_;\n");
   if (!descriptor_->default_value_string().empty()) {
-    printer->Print(variables_, "static const ::std::string $default_variable$;\n");
+    printer->Print(variables_, "static ::std::string* $default_variable$;\n");
   }
 }
 
@@ -109,7 +113,9 @@
     "inline void set_$name$(const $pointer_type$* value, size_t size)"
                  "$deprecation$;\n"
     "inline ::std::string* mutable_$name$()$deprecation$;\n"
-    "inline ::std::string* release_$name$()$deprecation$;\n");
+    "inline ::std::string* release_$name$()$deprecation$;\n"
+    "inline void set_allocated_$name$(::std::string* $name$)$deprecation$;\n");
+
 
   if (descriptor_->options().ctype() != FieldOptions::STRING) {
     printer->Outdent();
@@ -126,14 +132,14 @@
     "}\n"
     "inline void $classname$::set_$name$(const ::std::string& value) {\n"
     "  set_has_$name$();\n"
-    "  if ($name$_ == &$default_variable$) {\n"
+    "  if ($name$_ == $default_variable$) {\n"
     "    $name$_ = new ::std::string;\n"
     "  }\n"
     "  $name$_->assign(value);\n"
     "}\n"
     "inline void $classname$::set_$name$(const char* value) {\n"
     "  set_has_$name$();\n"
-    "  if ($name$_ == &$default_variable$) {\n"
+    "  if ($name$_ == $default_variable$) {\n"
     "    $name$_ = new ::std::string;\n"
     "  }\n"
     "  $name$_->assign(value);\n"
@@ -141,20 +147,20 @@
     "inline "
     "void $classname$::set_$name$(const $pointer_type$* value, size_t size) {\n"
     "  set_has_$name$();\n"
-    "  if ($name$_ == &$default_variable$) {\n"
+    "  if ($name$_ == $default_variable$) {\n"
     "    $name$_ = new ::std::string;\n"
     "  }\n"
     "  $name$_->assign(reinterpret_cast<const char*>(value), size);\n"
     "}\n"
     "inline ::std::string* $classname$::mutable_$name$() {\n"
     "  set_has_$name$();\n"
-    "  if ($name$_ == &$default_variable$) {\n");
+    "  if ($name$_ == $default_variable$) {\n");
   if (descriptor_->default_value_string().empty()) {
     printer->Print(variables_,
       "    $name$_ = new ::std::string;\n");
   } else {
     printer->Print(variables_,
-      "    $name$_ = new ::std::string($default_variable$);\n");
+      "    $name$_ = new ::std::string(*$default_variable$);\n");
   }
   printer->Print(variables_,
     "  }\n"
@@ -162,21 +168,34 @@
     "}\n"
     "inline ::std::string* $classname$::release_$name$() {\n"
     "  clear_has_$name$();\n"
-    "  if ($name$_ == &$default_variable$) {\n"
+    "  if ($name$_ == $default_variable$) {\n"
     "    return NULL;\n"
     "  } else {\n"
     "    ::std::string* temp = $name$_;\n"
-    "    $name$_ = const_cast< ::std::string*>(&$default_variable$);\n"
+    "    $name$_ = const_cast< ::std::string*>($default_variable$);\n"
     "    return temp;\n"
     "  }\n"
+    "}\n"
+    "inline void $classname$::set_allocated_$name$(::std::string* $name$) {\n"
+    "  if ($name$_ != $default_variable$) {\n"
+    "    delete $name$_;\n"
+    "  }\n"
+    "  if ($name$) {\n"
+    "    set_has_$name$();\n"
+    "    $name$_ = $name$;\n"
+    "  } else {\n"
+    "    clear_has_$name$();\n"
+    "    $name$_ = const_cast< ::std::string*>($default_variable$);\n"
+    "  }\n"
     "}\n");
 }
 
 void StringFieldGenerator::
 GenerateNonInlineAccessorDefinitions(io::Printer* printer) const {
   if (!descriptor_->default_value_string().empty()) {
+    // Initialized in GenerateDefaultInstanceAllocator.
     printer->Print(variables_,
-      "const ::std::string $classname$::$default_variable$($default$);\n");
+      "::std::string* $classname$::$default_variable$ = NULL;\n");
   }
 }
 
@@ -184,13 +203,13 @@
 GenerateClearingCode(io::Printer* printer) const {
   if (descriptor_->default_value_string().empty()) {
     printer->Print(variables_,
-      "if ($name$_ != &$default_variable$) {\n"
+      "if ($name$_ != $default_variable$) {\n"
       "  $name$_->clear();\n"
       "}\n");
   } else {
     printer->Print(variables_,
-      "if ($name$_ != &$default_variable$) {\n"
-      "  $name$_->assign($default_variable$);\n"
+      "if ($name$_ != $default_variable$) {\n"
+      "  $name$_->assign(*$default_variable$);\n"
       "}\n");
   }
 }
@@ -208,18 +227,35 @@
 void StringFieldGenerator::
 GenerateConstructorCode(io::Printer* printer) const {
   printer->Print(variables_,
-    "$name$_ = const_cast< ::std::string*>(&$default_variable$);\n");
+    "$name$_ = const_cast< ::std::string*>($default_variable$);\n");
 }
 
 void StringFieldGenerator::
 GenerateDestructorCode(io::Printer* printer) const {
   printer->Print(variables_,
-    "if ($name$_ != &$default_variable$) {\n"
+    "if ($name$_ != $default_variable$) {\n"
     "  delete $name$_;\n"
     "}\n");
 }
 
 void StringFieldGenerator::
+GenerateDefaultInstanceAllocator(io::Printer* printer) const {
+  if (!descriptor_->default_value_string().empty()) {
+    printer->Print(variables_,
+      "$classname$::$default_variable$ =\n"
+      "    new ::std::string($default$, $default_length$);\n");
+  }
+}
+
+void StringFieldGenerator::
+GenerateShutdownCode(io::Printer* printer) const {
+  if (!descriptor_->default_value_string().empty()) {
+    printer->Print(variables_,
+      "delete $classname$::$default_variable$;\n");
+  }
+}
+
+void StringFieldGenerator::
 GenerateMergeFromCodedStream(io::Printer* printer) const {
   printer->Print(variables_,
     "DO_(::google::protobuf::internal::WireFormatLite::Read$declared_type$(\n"
@@ -273,9 +309,10 @@
 // ===================================================================
 
 RepeatedStringFieldGenerator::
-RepeatedStringFieldGenerator(const FieldDescriptor* descriptor)
+RepeatedStringFieldGenerator(const FieldDescriptor* descriptor,
+                             const Options& options)
   : descriptor_(descriptor) {
-  SetStringVariables(descriptor, &variables_);
+  SetStringVariables(descriptor, &variables_, options);
 }
 
 RepeatedStringFieldGenerator::~RepeatedStringFieldGenerator() {}
@@ -328,7 +365,7 @@
 GenerateInlineAccessorDefinitions(io::Printer* printer) const {
   printer->Print(variables_,
     "inline const ::std::string& $classname$::$name$(int index) const {\n"
-    "  return $name$_.Get(index);\n"
+    "  return $name$_.$cppget$(index);\n"
     "}\n"
     "inline ::std::string* $classname$::mutable_$name$(int index) {\n"
     "  return $name$_.Mutable(index);\n"
diff --git a/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_string_field.h b/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_string_field.h
index 7f45107..3264134 100644
--- a/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_string_field.h
+++ b/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_string_field.h
@@ -46,7 +46,8 @@
 
 class StringFieldGenerator : public FieldGenerator {
  public:
-  explicit StringFieldGenerator(const FieldDescriptor* descriptor);
+  explicit StringFieldGenerator(const FieldDescriptor* descriptor,
+                                const Options& options);
   ~StringFieldGenerator();
 
   // implements FieldGenerator ---------------------------------------
@@ -59,6 +60,8 @@
   void GenerateSwappingCode(io::Printer* printer) const;
   void GenerateConstructorCode(io::Printer* printer) const;
   void GenerateDestructorCode(io::Printer* printer) const;
+  void GenerateDefaultInstanceAllocator(io::Printer* printer) const;
+  void GenerateShutdownCode(io::Printer* printer) const;
   void GenerateMergeFromCodedStream(io::Printer* printer) const;
   void GenerateSerializeWithCachedSizes(io::Printer* printer) const;
   void GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const;
@@ -73,7 +76,8 @@
 
 class RepeatedStringFieldGenerator : public FieldGenerator {
  public:
-  explicit RepeatedStringFieldGenerator(const FieldDescriptor* descriptor);
+  explicit RepeatedStringFieldGenerator(const FieldDescriptor* descriptor,
+                                        const Options& options);
   ~RepeatedStringFieldGenerator();
 
   // implements FieldGenerator ---------------------------------------
diff --git a/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_test_bad_identifiers.proto b/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_test_bad_identifiers.proto
index 54d830f..e14a818 100644
--- a/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_test_bad_identifiers.proto
+++ b/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_test_bad_identifiers.proto
@@ -103,9 +103,19 @@
   message DO {}
   optional DO do = 32;
 
+  // Some template parameter names for extensions.
+  optional int32 field_type = 33;
+  optional bool is_packed = 34;
+
   extensions 1000 to max;
 }
 
+message TestConflictingSymbolNamesExtension {
+  extend TestConflictingSymbolNames {
+    repeated int32 repeated_int32_ext = 20423638 [packed=true];
+  }
+}
+
 message DummyMessage {}
 
 service TestConflictingMethodNames {
diff --git a/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_unittest.cc b/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_unittest.cc
index 301a7ce..b5f9ab5 100644
--- a/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_unittest.cc
+++ b/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_unittest.cc
@@ -44,6 +44,8 @@
 // correctly and produces the interfaces we expect, which is why this test
 // is written this way.
 
+#include <google/protobuf/compiler/cpp/cpp_unittest.h>
+
 #include <vector>
 
 #include <google/protobuf/unittest.pb.h>
@@ -64,7 +66,7 @@
 #include <google/protobuf/stubs/substitute.h>
 #include <google/protobuf/testing/googletest.h>
 #include <gtest/gtest.h>
-#include <google/protobuf/stubs/stl_util-inl.h>
+#include <google/protobuf/stubs/stl_util.h>
 
 namespace google {
 namespace protobuf {
@@ -74,6 +76,8 @@
 // Can't use an anonymous namespace here due to brokenness of Tru64 compiler.
 namespace cpp_unittest {
 
+namespace protobuf_unittest = ::protobuf_unittest;
+
 
 class MockErrorCollector : public MultiFileErrorCollector {
  public:
@@ -174,6 +178,15 @@
   EXPECT_EQ("? ? ?? ?? ??? ?\?/ ?\?-", extreme_default.cpp_trigraph());
 }
 
+TEST(GeneratedMessageTest, ExtremeSmallIntegerDefault) {
+  const unittest::TestExtremeDefaultValues& extreme_default =
+      unittest::TestExtremeDefaultValues::default_instance();
+  EXPECT_EQ(-0x80000000, kint32min);
+  EXPECT_EQ(GOOGLE_LONGLONG(-0x8000000000000000), kint64min);
+  EXPECT_EQ(kint32min, extreme_default.really_small_int32());
+  EXPECT_EQ(kint64min, extreme_default.really_small_int64());
+}
+
 TEST(GeneratedMessageTest, Accessors) {
   // Set every field to a unique value then go back and check all those
   // values.
@@ -202,6 +215,13 @@
   EXPECT_EQ("hello", *message.mutable_default_string());
 }
 
+TEST(GeneratedMessageTest, StringDefaults) {
+  unittest::TestExtremeDefaultValues message;
+  // Check if '\000' can be used in default string value.
+  EXPECT_EQ(string("hel\000lo", 6), message.string_with_zero());
+  EXPECT_EQ(string("wor\000ld", 6), message.bytes_with_zero());
+}
+
 TEST(GeneratedMessageTest, ReleaseString) {
   // Check that release_foo() starts out NULL, and gives us a value
   // that we can delete after it's been set.
@@ -244,6 +264,49 @@
   EXPECT_FALSE(message.has_optional_nested_message());
 }
 
+TEST(GeneratedMessageTest, SetAllocatedString) {
+  // Check that set_allocated_foo() works for strings.
+  unittest::TestAllTypes message;
+
+  EXPECT_FALSE(message.has_optional_string());
+  const string kHello("hello");
+  message.set_optional_string(kHello);
+  EXPECT_TRUE(message.has_optional_string());
+
+  message.set_allocated_optional_string(NULL);
+  EXPECT_FALSE(message.has_optional_string());
+  EXPECT_EQ("", message.optional_string());
+
+  message.set_allocated_optional_string(new string(kHello));
+  EXPECT_TRUE(message.has_optional_string());
+  EXPECT_EQ(kHello, message.optional_string());
+}
+
+TEST(GeneratedMessageTest, SetAllocatedMessage) {
+  // Check that set_allocated_foo() can be called in all cases.
+  unittest::TestAllTypes message;
+
+  EXPECT_FALSE(message.has_optional_nested_message());
+
+  message.mutable_optional_nested_message()->set_bb(1);
+  EXPECT_TRUE(message.has_optional_nested_message());
+
+  message.set_allocated_optional_nested_message(NULL);
+  EXPECT_FALSE(message.has_optional_nested_message());
+  EXPECT_EQ(&unittest::TestAllTypes::NestedMessage::default_instance(),
+            &message.optional_nested_message());
+
+  message.mutable_optional_nested_message()->set_bb(1);
+  unittest::TestAllTypes::NestedMessage* nest =
+      message.release_optional_nested_message();
+  ASSERT_TRUE(nest != NULL);
+  EXPECT_FALSE(message.has_optional_nested_message());
+
+  message.set_allocated_optional_nested_message(nest);
+  EXPECT_TRUE(message.has_optional_nested_message());
+  EXPECT_EQ(1, message.optional_nested_message().bb());
+}
+
 TEST(GeneratedMessageTest, Clear) {
   // Set every field to a unique value, clear the message, then check that
   // it is cleared.
@@ -695,6 +758,13 @@
 
   message.set_friend_(5);
   EXPECT_EQ(5, message.friend_());
+
+  // Instantiate extension template functions to test conflicting template
+  // parameter names.
+  typedef protobuf_unittest::TestConflictingSymbolNamesExtension ExtensionMessage;
+  message.AddExtension(ExtensionMessage::repeated_int32_ext, 123);
+  EXPECT_EQ(123,
+            message.GetExtension(ExtensionMessage::repeated_int32_ext, 0));
 }
 
 #ifndef PROTOBUF_TEST_NO_DESCRIPTORS
@@ -869,11 +939,10 @@
   EXPECT_NE(null_pointer, &unittest::ForeignEnum_MAX);
   EXPECT_NE(null_pointer, &unittest::ForeignEnum_ARRAYSIZE);
 
-  // Make sure we can use _MIN, _MAX and _ARRAYSIZE as switch cases.
+  // Make sure we can use _MIN and _MAX as switch cases.
   switch (unittest::SPARSE_A) {
     case unittest::TestSparseEnum_MIN:
     case unittest::TestSparseEnum_MAX:
-    case unittest::TestSparseEnum_ARRAYSIZE:
       break;
     default:
       break;
diff --git a/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_unittest.h b/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_unittest.h
new file mode 100644
index 0000000..a3a1d1b
--- /dev/null
+++ b/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_unittest.h
@@ -0,0 +1,51 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 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 header declares the namespace google::protobuf::protobuf_unittest in order to expose
+// any problems with the generated class names. We use this header to ensure
+// unittest.cc will declare the namespace prior to other includes, while obeying
+// normal include ordering.
+//
+// When generating a class name of "foo.Bar" we must ensure we prefix the class
+// name with "::", in case the namespace google::protobuf::foo exists. We intentionally
+// trigger that case here by declaring google::protobuf::protobuf_unittest.
+//
+// See ClassName in helpers.h for more details.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_CPP_UNITTEST_H__
+#define GOOGLE_PROTOBUF_COMPILER_CPP_UNITTEST_H__
+
+namespace google {
+namespace protobuf {
+namespace protobuf_unittest {}
+}  // namespace protobuf
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_COMPILER_CPP_UNITTEST_H__
diff --git a/third_party/protobuf/src/google/protobuf/compiler/importer.h b/third_party/protobuf/src/google/protobuf/compiler/importer.h
index 7a2efc2..7a62fa0 100644
--- a/third_party/protobuf/src/google/protobuf/compiler/importer.h
+++ b/third_party/protobuf/src/google/protobuf/compiler/importer.h
@@ -280,8 +280,9 @@
     string virtual_path;
     string disk_path;
 
-    inline Mapping(const string& virtual_path, const string& disk_path)
-      : virtual_path(virtual_path), disk_path(disk_path) {}
+    inline Mapping(const string& virtual_path_param,
+                   const string& disk_path_param)
+      : virtual_path(virtual_path_param), disk_path(disk_path_param) {}
   };
   vector<Mapping> mappings_;
 
diff --git a/third_party/protobuf/src/google/protobuf/compiler/java/java_doc_comment.cc b/third_party/protobuf/src/google/protobuf/compiler/java/java_doc_comment.cc
new file mode 100644
index 0000000..60b4f2a
--- /dev/null
+++ b/third_party/protobuf/src/google/protobuf/compiler/java/java_doc_comment.cc
@@ -0,0 +1,236 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+
+#include <google/protobuf/compiler/java/java_doc_comment.h>
+
+#include <vector>
+
+#include <google/protobuf/io/printer.h>
+#include <google/protobuf/stubs/strutil.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace java {
+
+string EscapeJavadoc(const string& input) {
+  string result;
+  result.reserve(input.size() * 2);
+
+  char prev = '*';
+
+  for (string::size_type i = 0; i < input.size(); i++) {
+    char c = input[i];
+    switch (c) {
+      case '*':
+        // Avoid "/*".
+        if (prev == '/') {
+          result.append("&#42;");
+        } else {
+          result.push_back(c);
+        }
+        break;
+      case '/':
+        // Avoid "*/".
+        if (prev == '*') {
+          result.append("&#47;");
+        } else {
+          result.push_back(c);
+        }
+        break;
+      case '@':
+        // "{@" starts Javadoc markup.
+        if (prev == '{') {
+          result.append("&#64;");
+        } else {
+          result.push_back(c);
+        }
+        break;
+      case '<':
+        // Avoid interpretation as HTML.
+        result.append("&lt;");
+        break;
+      case '>':
+        // Avoid interpretation as HTML.
+        result.append("&gt;");
+        break;
+      case '&':
+        // Avoid interpretation as HTML.
+        result.append("&amp;");
+        break;
+      case '\\':
+        // Java interprets Unicode escape sequences anywhere!
+        result.append("&#92;");
+        break;
+      default:
+        result.push_back(c);
+        break;
+    }
+
+    prev = c;
+  }
+
+  return result;
+}
+
+static void WriteDocCommentBodyForLocation(
+    io::Printer* printer, const SourceLocation& location) {
+  string comments = location.leading_comments.empty() ?
+      location.trailing_comments : location.leading_comments;
+  if (!comments.empty()) {
+    // TODO(kenton):  Ideally we should parse the comment text as Markdown and
+    //   write it back as HTML, but this requires a Markdown parser.  For now
+    //   we just use <pre> to get fixed-width text formatting.
+
+    // If the comment itself contains block comment start or end markers,
+    // HTML-escape them so that they don't accidentally close the doc comment.
+    comments = EscapeJavadoc(comments);
+
+    vector<string> lines;
+    SplitStringAllowEmpty(comments, "\n", &lines);
+    while (!lines.empty() && lines.back().empty()) {
+      lines.pop_back();
+    }
+
+    printer->Print(
+        " *\n"
+        " * <pre>\n");
+    for (int i = 0; i < lines.size(); i++) {
+      // Most lines should start with a space.  Watch out for lines that start
+      // with a /, since putting that right after the leading asterisk will
+      // close the comment.
+      if (!lines[i].empty() && lines[i][0] == '/') {
+        printer->Print(" * $line$\n", "line", lines[i]);
+      } else {
+        printer->Print(" *$line$\n", "line", lines[i]);
+      }
+    }
+    printer->Print(" * </pre>\n");
+  }
+}
+
+template <typename DescriptorType>
+static void WriteDocCommentBody(
+    io::Printer* printer, const DescriptorType* descriptor) {
+  SourceLocation location;
+  if (descriptor->GetSourceLocation(&location)) {
+    WriteDocCommentBodyForLocation(printer, location);
+  }
+}
+
+static string FirstLineOf(const string& value) {
+  string result = value;
+
+  string::size_type pos = result.find_first_of('\n');
+  if (pos != string::npos) {
+    result.erase(pos);
+  }
+
+  // If line ends in an opening brace, make it "{ ... }" so it looks nice.
+  if (!result.empty() && result[result.size() - 1] == '{') {
+    result.append(" ... }");
+  }
+
+  return result;
+}
+
+void WriteMessageDocComment(io::Printer* printer, const Descriptor* message) {
+  printer->Print(
+    "/**\n"
+    " * Protobuf type {@code $fullname$}\n",
+    "fullname", EscapeJavadoc(message->full_name()));
+  WriteDocCommentBody(printer, message);
+  printer->Print(" */\n");
+}
+
+void WriteFieldDocComment(io::Printer* printer, const FieldDescriptor* field) {
+  // In theory we should have slightly different comments for setters, getters,
+  // etc., but in practice everyone already knows the difference between these
+  // so it's redundant information.
+
+  // We use the field declaration as the first line of the comment, e.g.:
+  //   optional string foo = 5;
+  // This communicates a lot of information about the field in a small space.
+  // If the field is a group, the debug string might end with {.
+  printer->Print(
+    "/**\n"
+    " * <code>$def$</code>\n",
+    "def", EscapeJavadoc(FirstLineOf(field->DebugString())));
+  WriteDocCommentBody(printer, field);
+  printer->Print(" */\n");
+}
+
+void WriteEnumDocComment(io::Printer* printer, const EnumDescriptor* enum_) {
+  printer->Print(
+    "/**\n"
+    " * Protobuf enum {@code $fullname$}\n",
+    "fullname", EscapeJavadoc(enum_->full_name()));
+  WriteDocCommentBody(printer, enum_);
+  printer->Print(" */\n");
+}
+
+void WriteEnumValueDocComment(io::Printer* printer,
+                              const EnumValueDescriptor* value) {
+  printer->Print(
+    "/**\n"
+    " * <code>$def$</code>\n",
+    "def", EscapeJavadoc(FirstLineOf(value->DebugString())));
+  WriteDocCommentBody(printer, value);
+  printer->Print(" */\n");
+}
+
+void WriteServiceDocComment(io::Printer* printer,
+                            const ServiceDescriptor* service) {
+  printer->Print(
+    "/**\n"
+    " * Protobuf service {@code $fullname$}\n",
+    "fullname", EscapeJavadoc(service->full_name()));
+  WriteDocCommentBody(printer, service);
+  printer->Print(" */\n");
+}
+
+void WriteMethodDocComment(io::Printer* printer,
+                           const MethodDescriptor* method) {
+  printer->Print(
+    "/**\n"
+    " * <code>$def$</code>\n",
+    "def", EscapeJavadoc(FirstLineOf(method->DebugString())));
+  WriteDocCommentBody(printer, method);
+  printer->Print(" */\n");
+}
+
+}  // namespace java
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
diff --git a/third_party/protobuf/src/google/protobuf/compiler/java/java_doc_comment.h b/third_party/protobuf/src/google/protobuf/compiler/java/java_doc_comment.h
new file mode 100644
index 0000000..f77720b
--- /dev/null
+++ b/third_party/protobuf/src/google/protobuf/compiler/java/java_doc_comment.h
@@ -0,0 +1,69 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_DOC_COMMENT_H__
+#define GOOGLE_PROTOBUF_COMPILER_JAVA_DOC_COMMENT_H__
+
+#include <google/protobuf/descriptor.h>
+
+namespace google {
+namespace protobuf {
+  namespace io {
+    class Printer;             // printer.h
+  }
+}
+
+namespace protobuf {
+namespace compiler {
+namespace java {
+
+void WriteMessageDocComment(io::Printer* printer, const Descriptor* message);
+void WriteFieldDocComment(io::Printer* printer, const FieldDescriptor* field);
+void WriteEnumDocComment(io::Printer* printer, const EnumDescriptor* enum_);
+void WriteEnumValueDocComment(io::Printer* printer,
+                              const EnumValueDescriptor* value);
+void WriteServiceDocComment(io::Printer* printer,
+                            const ServiceDescriptor* service);
+void WriteMethodDocComment(io::Printer* printer,
+                           const MethodDescriptor* method);
+
+// Exposed for testing only.
+string EscapeJavadoc(const string& input);
+
+}  // namespace java
+}  // namespace compiler
+}  // namespace protobuf
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_COMPILER_JAVA_DOC_COMMENT_H__
diff --git a/third_party/protobuf/src/google/protobuf/compiler/java/java_doc_comment_unittest.cc b/third_party/protobuf/src/google/protobuf/compiler/java/java_doc_comment_unittest.cc
new file mode 100644
index 0000000..28b6d8b
--- /dev/null
+++ b/third_party/protobuf/src/google/protobuf/compiler/java/java_doc_comment_unittest.cc
@@ -0,0 +1,66 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 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.
+
+// Author: kenton@google.com (Kenton Varda)
+
+#include <google/protobuf/compiler/java/java_doc_comment.h>
+
+#include <gtest/gtest.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace java {
+namespace {
+
+TEST(JavaDocCommentTest, Escaping) {
+  EXPECT_EQ("foo /&#42; bar *&#47; baz", EscapeJavadoc("foo /* bar */ baz"));
+  EXPECT_EQ("foo /&#42;&#47; baz", EscapeJavadoc("foo /*/ baz"));
+  EXPECT_EQ("{&#64;foo}", EscapeJavadoc("{@foo}"));
+  EXPECT_EQ("&lt;i&gt;&amp;&lt;/i&gt;", EscapeJavadoc("<i>&</i>"));
+  EXPECT_EQ("foo&#92;u1234bar", EscapeJavadoc("foo\\u1234bar"));
+}
+
+// TODO(kenton):  It's hard to write a robust test of the doc comments -- we
+//   can only really compare the output against a golden value, which is a
+//   fairly tedious and fragile testing strategy.  If we want to go that route,
+//   it probably makes sense to bite the bullet and write a test that compares
+//   the whole generated output for unittest.proto against a golden value, with
+//   a very simple script that can be run to regenerate it with the latest code.
+//   This would mean that updates to the golden file would have to be included
+//   in any change to the code generator, which would actually be fairly useful
+//   as it allows the reviewer to see clearly how the generated code is
+//   changing.
+
+}  // namespace
+}  // namespace java
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
diff --git a/third_party/protobuf/src/google/protobuf/compiler/java/java_enum.cc b/third_party/protobuf/src/google/protobuf/compiler/java/java_enum.cc
index 9d7bcab..cfed815 100644
--- a/third_party/protobuf/src/google/protobuf/compiler/java/java_enum.cc
+++ b/third_party/protobuf/src/google/protobuf/compiler/java/java_enum.cc
@@ -36,6 +36,7 @@
 #include <string>
 
 #include <google/protobuf/compiler/java/java_enum.h>
+#include <google/protobuf/compiler/java/java_doc_comment.h>
 #include <google/protobuf/compiler/java/java_helpers.h>
 #include <google/protobuf/io/printer.h>
 #include <google/protobuf/descriptor.pb.h>
@@ -67,6 +68,7 @@
 EnumGenerator::~EnumGenerator() {}
 
 void EnumGenerator::Generate(io::Printer* printer) {
+  WriteEnumDocComment(printer, descriptor_);
   if (HasDescriptorMethods(descriptor_)) {
     printer->Print(
       "public enum $classname$\n"
@@ -85,6 +87,7 @@
     vars["name"] = canonical_values_[i]->name();
     vars["index"] = SimpleItoa(canonical_values_[i]->index());
     vars["number"] = SimpleItoa(canonical_values_[i]->number());
+    WriteEnumValueDocComment(printer, canonical_values_[i]);
     printer->Print(vars,
       "$name$($index$, $number$),\n");
   }
@@ -100,6 +103,7 @@
     vars["classname"] = descriptor_->name();
     vars["name"] = aliases_[i].value->name();
     vars["canonical_name"] = aliases_[i].canonical_value->name();
+    WriteEnumValueDocComment(printer, aliases_[i].value);
     printer->Print(vars,
       "public static final $classname$ $name$ = $canonical_name$;\n");
   }
@@ -108,6 +112,7 @@
     map<string, string> vars;
     vars["name"] = descriptor_->value(i)->name();
     vars["number"] = SimpleItoa(descriptor_->value(i)->number());
+    WriteEnumValueDocComment(printer, descriptor_->value(i));
     printer->Print(vars,
       "public static final int $name$_VALUE = $number$;\n");
   }
@@ -187,19 +192,30 @@
     printer->Print(
       "}\n"
       "\n"
-      "private static final $classname$[] VALUES = {\n"
-      "  ",
+      "private static final $classname$[] VALUES = ",
       "classname", descriptor_->name());
 
-    for (int i = 0; i < descriptor_->value_count(); i++) {
-      printer->Print("$name$, ",
-        "name", descriptor_->value(i)->name());
+    if (CanUseEnumValues()) {
+      // If the constants we are going to output are exactly the ones we
+      // have declared in the Java enum in the same order, then we can use
+      // the values() method that the Java compiler automatically generates
+      // for every enum.
+      printer->Print("values();\n");
+    } else {
+      printer->Print(
+        "{\n"
+        "  ");
+      for (int i = 0; i < descriptor_->value_count(); i++) {
+        printer->Print("$name$, ",
+          "name", descriptor_->value(i)->name());
+      }
+      printer->Print(
+          "\n"
+          "};\n");
     }
 
     printer->Print(
       "\n"
-      "};\n"
-      "\n"
       "public static $classname$ valueOf(\n"
       "    com.google.protobuf.Descriptors.EnumValueDescriptor desc) {\n"
       "  if (desc.getType() != getDescriptor()) {\n"
@@ -237,6 +253,18 @@
   printer->Print("}\n\n");
 }
 
+bool EnumGenerator::CanUseEnumValues() {
+  if (canonical_values_.size() != descriptor_->value_count()) {
+    return false;
+  }
+  for (int i = 0; i < descriptor_->value_count(); i++) {
+    if (descriptor_->value(i)->name() != canonical_values_[i]->name()) {
+      return false;
+    }
+  }
+  return true;
+}
+
 }  // namespace java
 }  // namespace compiler
 }  // namespace protobuf
diff --git a/third_party/protobuf/src/google/protobuf/compiler/java/java_enum.h b/third_party/protobuf/src/google/protobuf/compiler/java/java_enum.h
index 05ece1f..9a9e574 100644
--- a/third_party/protobuf/src/google/protobuf/compiler/java/java_enum.h
+++ b/third_party/protobuf/src/google/protobuf/compiler/java/java_enum.h
@@ -73,6 +73,8 @@
   };
   vector<Alias> aliases_;
 
+  bool CanUseEnumValues();
+
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(EnumGenerator);
 };
 
diff --git a/third_party/protobuf/src/google/protobuf/compiler/java/java_enum_field.cc b/third_party/protobuf/src/google/protobuf/compiler/java/java_enum_field.cc
index 72caa10..ec0b067 100644
--- a/third_party/protobuf/src/google/protobuf/compiler/java/java_enum_field.cc
+++ b/third_party/protobuf/src/google/protobuf/compiler/java/java_enum_field.cc
@@ -36,6 +36,7 @@
 #include <string>
 
 #include <google/protobuf/compiler/java/java_enum_field.h>
+#include <google/protobuf/compiler/java/java_doc_comment.h>
 #include <google/protobuf/stubs/common.h>
 #include <google/protobuf/compiler/java/java_helpers.h>
 #include <google/protobuf/io/printer.h>
@@ -75,6 +76,7 @@
 
   // For singular messages and builders, one bit is used for the hasField bit.
   (*variables)["get_has_field_bit_message"] = GenerateGetBit(messageBitIndex);
+  (*variables)["set_has_field_bit_message"] = GenerateSetBit(messageBitIndex);
 
   (*variables)["get_has_field_bit_builder"] = GenerateGetBit(builderBitIndex);
   (*variables)["set_has_field_bit_builder"] = GenerateSetBit(builderBitIndex);
@@ -86,6 +88,13 @@
   (*variables)["set_mutable_bit_builder"] = GenerateSetBit(builderBitIndex);
   (*variables)["clear_mutable_bit_builder"] = GenerateClearBit(builderBitIndex);
 
+  // For repeated fields, one bit is used for whether the array is immutable
+  // in the parsing constructor.
+  (*variables)["get_mutable_bit_parser"] =
+      GenerateGetBitMutableLocal(builderBitIndex);
+  (*variables)["set_mutable_bit_parser"] =
+      GenerateSetBitMutableLocal(builderBitIndex);
+
   (*variables)["get_has_field_bit_from_local"] =
       GenerateGetBitFromLocal(builderBitIndex);
   (*variables)["set_has_field_bit_to_local"] =
@@ -117,18 +126,25 @@
 
 void EnumFieldGenerator::
 GenerateInterfaceMembers(io::Printer* printer) const {
+  WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$boolean has$capitalized_name$();\n"
+    "$deprecation$boolean has$capitalized_name$();\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
     "$deprecation$$type$ get$capitalized_name$();\n");
 }
 
 void EnumFieldGenerator::
 GenerateMembers(io::Printer* printer) const {
   printer->Print(variables_,
-    "private $type$ $name$_;\n"
+    "private $type$ $name$_;\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
     "$deprecation$public boolean has$capitalized_name$() {\n"
     "  return $get_has_field_bit_message$;\n"
-    "}\n"
+    "}\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
     "$deprecation$public $type$ get$capitalized_name$() {\n"
     "  return $name$_;\n"
     "}\n");
@@ -137,13 +153,19 @@
 void EnumFieldGenerator::
 GenerateBuilderMembers(io::Printer* printer) const {
   printer->Print(variables_,
-    "private $type$ $name$_ = $default$;\n"
+    "private $type$ $name$_ = $default$;\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
     "$deprecation$public boolean has$capitalized_name$() {\n"
     "  return $get_has_field_bit_builder$;\n"
-    "}\n"
+    "}\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
     "$deprecation$public $type$ get$capitalized_name$() {\n"
     "  return $name$_;\n"
-    "}\n"
+    "}\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
     "$deprecation$public Builder set$capitalized_name$($type$ value) {\n"
     "  if (value == null) {\n"
     "    throw new NullPointerException();\n"
@@ -152,7 +174,9 @@
     "  $name$_ = value;\n"
     "  $on_changed$\n"
     "  return this;\n"
-    "}\n"
+    "}\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
     "$deprecation$public Builder clear$capitalized_name$() {\n"
     "  $clear_has_field_bit_builder$;\n"
     "  $name$_ = $default$;\n"
@@ -210,12 +234,17 @@
       "if (value != null) {\n");
   }
   printer->Print(variables_,
-    "  $set_has_field_bit_builder$;\n"
+    "  $set_has_field_bit_message$;\n"
     "  $name$_ = value;\n"
     "}\n");
 }
 
 void EnumFieldGenerator::
+GenerateParsingDoneCode(io::Printer* printer) const {
+  // noop for enums
+}
+
+void EnumFieldGenerator::
 GenerateSerializationCode(io::Printer* printer) const {
   printer->Print(variables_,
     "if ($get_has_field_bit_message$) {\n"
@@ -273,22 +302,33 @@
 
 void RepeatedEnumFieldGenerator::
 GenerateInterfaceMembers(io::Printer* printer) const {
+  WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$java.util.List<$type$> get$capitalized_name$List();\n"
-    "$deprecation$int get$capitalized_name$Count();\n"
+    "$deprecation$java.util.List<$type$> get$capitalized_name$List();\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$int get$capitalized_name$Count();\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
     "$deprecation$$type$ get$capitalized_name$(int index);\n");
 }
 
 void RepeatedEnumFieldGenerator::
 GenerateMembers(io::Printer* printer) const {
   printer->Print(variables_,
-    "private java.util.List<$type$> $name$_;\n"
+    "private java.util.List<$type$> $name$_;\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
     "$deprecation$public java.util.List<$type$> get$capitalized_name$List() {\n"
     "  return $name$_;\n"   // note:  unmodifiable list
-    "}\n"
+    "}\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
     "$deprecation$public int get$capitalized_name$Count() {\n"
     "  return $name$_.size();\n"
-    "}\n"
+    "}\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
     "$deprecation$public $type$ get$capitalized_name$(int index) {\n"
     "  return $name$_.get(index);\n"
     "}\n");
@@ -320,21 +360,29 @@
     "    $name$_ = new java.util.ArrayList<$type$>($name$_);\n"
     "    $set_mutable_bit_builder$;\n"
     "  }\n"
-    "}\n"
+    "}\n");
 
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
     // Note:  We return an unmodifiable list because otherwise the caller
     //   could hold on to the returned list and modify it after the message
     //   has been built, thus mutating the message which is supposed to be
     //   immutable.
     "$deprecation$public java.util.List<$type$> get$capitalized_name$List() {\n"
     "  return java.util.Collections.unmodifiableList($name$_);\n"
-    "}\n"
+    "}\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
     "$deprecation$public int get$capitalized_name$Count() {\n"
     "  return $name$_.size();\n"
-    "}\n"
+    "}\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
     "$deprecation$public $type$ get$capitalized_name$(int index) {\n"
     "  return $name$_.get(index);\n"
-    "}\n"
+    "}\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
     "$deprecation$public Builder set$capitalized_name$(\n"
     "    int index, $type$ value) {\n"
     "  if (value == null) {\n"
@@ -344,7 +392,9 @@
     "  $name$_.set(index, value);\n"
     "  $on_changed$\n"
     "  return this;\n"
-    "}\n"
+    "}\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
     "$deprecation$public Builder add$capitalized_name$($type$ value) {\n"
     "  if (value == null) {\n"
     "    throw new NullPointerException();\n"
@@ -353,14 +403,18 @@
     "  $name$_.add(value);\n"
     "  $on_changed$\n"
     "  return this;\n"
-    "}\n"
+    "}\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
     "$deprecation$public Builder addAll$capitalized_name$(\n"
     "    java.lang.Iterable<? extends $type$> values) {\n"
     "  ensure$capitalized_name$IsMutable();\n"
     "  super.addAll(values, $name$_);\n"
     "  $on_changed$\n"
     "  return this;\n"
-    "}\n"
+    "}\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
     "$deprecation$public Builder clear$capitalized_name$() {\n"
     "  $name$_ = java.util.Collections.emptyList();\n"
     "  $clear_mutable_bit_builder$;\n"
@@ -434,7 +488,11 @@
       "if (value != null) {\n");
   }
   printer->Print(variables_,
-    "  add$capitalized_name$(value);\n"
+    "  if (!$get_mutable_bit_parser$) {\n"
+    "    $name$_ = new java.util.ArrayList<$type$>();\n"
+    "    $set_mutable_bit_parser$;\n"
+    "  }\n"
+    "  $name$_.add(value);\n"
     "}\n");
 }
 
@@ -457,6 +515,14 @@
 }
 
 void RepeatedEnumFieldGenerator::
+GenerateParsingDoneCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "if ($get_mutable_bit_parser$) {\n"
+    "  $name$_ = java.util.Collections.unmodifiableList($name$_);\n"
+    "}\n");
+}
+
+void RepeatedEnumFieldGenerator::
 GenerateSerializationCode(io::Printer* printer) const {
   if (descriptor_->options().packed()) {
     printer->Print(variables_,
diff --git a/third_party/protobuf/src/google/protobuf/compiler/java/java_enum_field.h b/third_party/protobuf/src/google/protobuf/compiler/java/java_enum_field.h
index 0cad6be..90fae63 100644
--- a/third_party/protobuf/src/google/protobuf/compiler/java/java_enum_field.h
+++ b/third_party/protobuf/src/google/protobuf/compiler/java/java_enum_field.h
@@ -61,6 +61,7 @@
   void GenerateMergingCode(io::Printer* printer) const;
   void GenerateBuildingCode(io::Printer* printer) const;
   void GenerateParsingCode(io::Printer* printer) const;
+  void GenerateParsingDoneCode(io::Printer* printer) const;
   void GenerateSerializationCode(io::Printer* printer) const;
   void GenerateSerializedSizeCode(io::Printer* printer) const;
   void GenerateFieldBuilderInitializationCode(io::Printer* printer) const;
@@ -96,6 +97,7 @@
   void GenerateBuildingCode(io::Printer* printer) const;
   void GenerateParsingCode(io::Printer* printer) const;
   void GenerateParsingCodeFromPacked(io::Printer* printer) const;
+  void GenerateParsingDoneCode(io::Printer* printer) const;
   void GenerateSerializationCode(io::Printer* printer) const;
   void GenerateSerializedSizeCode(io::Printer* printer) const;
   void GenerateFieldBuilderInitializationCode(io::Printer* printer) const;
diff --git a/third_party/protobuf/src/google/protobuf/compiler/java/java_extension.cc b/third_party/protobuf/src/google/protobuf/compiler/java/java_extension.cc
index 9b147c7..921fe65 100644
--- a/third_party/protobuf/src/google/protobuf/compiler/java/java_extension.cc
+++ b/third_party/protobuf/src/google/protobuf/compiler/java/java_extension.cc
@@ -33,6 +33,7 @@
 //  Sanjay Ghemawat, Jeff Dean, and others.
 
 #include <google/protobuf/compiler/java/java_extension.h>
+#include <google/protobuf/compiler/java/java_doc_comment.h>
 #include <google/protobuf/compiler/java/java_helpers.h>
 #include <google/protobuf/stubs/strutil.h>
 #include <google/protobuf/io/printer.h>
@@ -130,6 +131,7 @@
   printer->Print(vars,
       "public static final int $constant_name$ = $number$;\n");
 
+  WriteFieldDocComment(printer, descriptor_);
   if (HasDescriptorMethods(descriptor_->file())) {
     // Non-lite extensions
     if (descriptor_->extension_scope() == NULL) {
diff --git a/third_party/protobuf/src/google/protobuf/compiler/java/java_field.h b/third_party/protobuf/src/google/protobuf/compiler/java/java_field.h
index 6097f35..4dd0efd 100644
--- a/third_party/protobuf/src/google/protobuf/compiler/java/java_field.h
+++ b/third_party/protobuf/src/google/protobuf/compiler/java/java_field.h
@@ -66,6 +66,7 @@
   virtual void GenerateBuildingCode(io::Printer* printer) const = 0;
   virtual void GenerateParsingCode(io::Printer* printer) const = 0;
   virtual void GenerateParsingCodeFromPacked(io::Printer* printer) const;
+  virtual void GenerateParsingDoneCode(io::Printer* printer) const = 0;
   virtual void GenerateSerializationCode(io::Printer* printer) const = 0;
   virtual void GenerateSerializedSizeCode(io::Printer* printer) const = 0;
   virtual void GenerateFieldBuilderInitializationCode(io::Printer* printer)
diff --git a/third_party/protobuf/src/google/protobuf/compiler/java/java_file.cc b/third_party/protobuf/src/google/protobuf/compiler/java/java_file.cc
index 8968069..f43e550 100644
--- a/third_party/protobuf/src/google/protobuf/compiler/java/java_file.cc
+++ b/third_party/protobuf/src/google/protobuf/compiler/java/java_file.cc
@@ -42,6 +42,7 @@
 #include <google/protobuf/io/printer.h>
 #include <google/protobuf/io/zero_copy_stream.h>
 #include <google/protobuf/descriptor.pb.h>
+#include <google/protobuf/dynamic_message.h>
 #include <google/protobuf/stubs/strutil.h>
 
 namespace google {
@@ -51,18 +52,24 @@
 
 namespace {
 
-// Recursively searches the given message to see if it contains any extensions.
-bool UsesExtensions(const Message& message) {
+
+// Recursively searches the given message to collect extensions.
+// Returns true if all the extensions can be recognized. The extensions will be
+// appended in to the extensions parameter.
+// Returns false when there are unknown fields, in which case the data in the
+// extensions output parameter is not reliable and should be discarded.
+bool CollectExtensions(const Message& message,
+                       vector<const FieldDescriptor*>* extensions) {
   const Reflection* reflection = message.GetReflection();
 
-  // We conservatively assume that unknown fields are extensions.
-  if (reflection->GetUnknownFields(message).field_count() > 0) return true;
+  // There are unknown fields that could be extensions, thus this call fails.
+  if (reflection->GetUnknownFields(message).field_count() > 0) return false;
 
   vector<const FieldDescriptor*> fields;
   reflection->ListFields(message, &fields);
 
   for (int i = 0; i < fields.size(); i++) {
-    if (fields[i]->is_extension()) return true;
+    if (fields[i]->is_extension()) extensions->push_back(fields[i]);
 
     if (GetJavaType(fields[i]) == JAVATYPE_MESSAGE) {
       if (fields[i]->is_repeated()) {
@@ -70,16 +77,56 @@
         for (int j = 0; j < size; j++) {
           const Message& sub_message =
             reflection->GetRepeatedMessage(message, fields[i], j);
-          if (UsesExtensions(sub_message)) return true;
+          if (!CollectExtensions(sub_message, extensions)) return false;
         }
       } else {
         const Message& sub_message = reflection->GetMessage(message, fields[i]);
-        if (UsesExtensions(sub_message)) return true;
+        if (!CollectExtensions(sub_message, extensions)) return false;
       }
     }
   }
 
-  return false;
+  return true;
+}
+
+// Finds all extensions in the given message and its sub-messages.  If the
+// message contains unknown fields (which could be extensions), then those
+// extensions are defined in alternate_pool.
+// The message will be converted to a DynamicMessage backed by alternate_pool
+// in order to handle this case.
+void CollectExtensions(const FileDescriptorProto& file_proto,
+                       const DescriptorPool& alternate_pool,
+                       vector<const FieldDescriptor*>* extensions,
+                       const string& file_data) {
+  if (!CollectExtensions(file_proto, extensions)) {
+    // There are unknown fields in the file_proto, which are probably
+    // extensions. We need to parse the data into a dynamic message based on the
+    // builder-pool to find out all extensions.
+    const Descriptor* file_proto_desc = alternate_pool.FindMessageTypeByName(
+        file_proto.GetDescriptor()->full_name());
+    GOOGLE_CHECK(file_proto_desc)
+        << "Find unknown fields in FileDescriptorProto when building "
+        << file_proto.name()
+        << ". It's likely that those fields are custom options, however, "
+           "descriptor.proto is not in the transitive dependencies. "
+           "This normally should not happen. Please report a bug.";
+    DynamicMessageFactory factory;
+    scoped_ptr<Message> dynamic_file_proto(
+        factory.GetPrototype(file_proto_desc)->New());
+    GOOGLE_CHECK(dynamic_file_proto.get() != NULL);
+    GOOGLE_CHECK(dynamic_file_proto->ParseFromString(file_data));
+
+    // Collect the extensions again from the dynamic message. There should be no
+    // more unknown fields this time, i.e. all the custom options should be
+    // parsed as extensions now.
+    extensions->clear();
+    GOOGLE_CHECK(CollectExtensions(*dynamic_file_proto, extensions))
+        << "Find unknown fields in FileDescriptorProto when building "
+        << file_proto.name()
+        << ". It's likely that those fields are custom options, however, "
+           "those options cannot be recognized in the builder pool. "
+           "This normally should not happen. Please report a bug.";
+  }
 }
 
 
@@ -306,19 +353,32 @@
         .GenerateNonNestedInitializationCode(printer);
   }
 
-  if (UsesExtensions(file_proto)) {
-    // Must construct an ExtensionRegistry containing all possible extensions
+  // Proto compiler builds a DescriptorPool, which holds all the descriptors to
+  // generate, when processing the ".proto" files. We call this DescriptorPool
+  // the parsed pool (a.k.a. file_->pool()).
+  //
+  // Note that when users try to extend the (.*)DescriptorProto in their
+  // ".proto" files, it does not affect the pre-built FileDescriptorProto class
+  // in proto compiler. When we put the descriptor data in the file_proto, those
+  // extensions become unknown fields.
+  //
+  // Now we need to find out all the extension value to the (.*)DescriptorProto
+  // in the file_proto message, and prepare an ExtensionRegistry to return.
+  //
+  // To find those extensions, we need to parse the data into a dynamic message
+  // of the FileDescriptor based on the builder-pool, then we can use
+  // reflections to find all extension fields
+  vector<const FieldDescriptor*> extensions;
+  CollectExtensions(file_proto, *file_->pool(), &extensions, file_data);
+
+  if (extensions.size() > 0) {
+    // Must construct an ExtensionRegistry containing all existing extensions
     // and return it.
     printer->Print(
       "com.google.protobuf.ExtensionRegistry registry =\n"
-      "  com.google.protobuf.ExtensionRegistry.newInstance();\n"
-      "registerAllExtensions(registry);\n");
-    for (int i = 0; i < file_->dependency_count(); i++) {
-      if (ShouldIncludeDependency(file_->dependency(i))) {
-        printer->Print(
-            "$dependency$.registerAllExtensions(registry);\n",
-            "dependency", ClassName(file_->dependency(i)));
-      }
+      "  com.google.protobuf.ExtensionRegistry.newInstance();\n");
+    for (int i = 0; i < extensions.size(); i++) {
+      ExtensionGenerator(extensions[i]).GenerateRegistrationCode(printer);
     }
     printer->Print(
       "return registry;\n");
@@ -375,7 +435,9 @@
 
   printer.Print(
     "// Generated by the protocol buffer compiler.  DO NOT EDIT!\n"
-    "\n");
+    "// source: $filename$\n"
+    "\n",
+    "filename", descriptor->file()->name());
   if (!java_package.empty()) {
     printer.Print(
       "package $package$;\n"
diff --git a/third_party/protobuf/src/google/protobuf/compiler/java/java_helpers.cc b/third_party/protobuf/src/google/protobuf/compiler/java/java_helpers.cc
index 1b6f165..cf241b8 100644
--- a/third_party/protobuf/src/google/protobuf/compiler/java/java_helpers.cc
+++ b/third_party/protobuf/src/google/protobuf/compiler/java/java_helpers.cc
@@ -177,6 +177,18 @@
   return result;
 }
 
+string ClassName(const Descriptor* descriptor) {
+  return ToJavaName(descriptor->full_name(), descriptor->file());
+}
+
+string ClassName(const EnumDescriptor* descriptor) {
+  return ToJavaName(descriptor->full_name(), descriptor->file());
+}
+
+string ClassName(const ServiceDescriptor* descriptor) {
+  return ToJavaName(descriptor->full_name(), descriptor->file());
+}
+
 string ClassName(const FileDescriptor* descriptor) {
   string result = FileJavaPackage(descriptor);
   if (!result.empty()) result += '.';
@@ -326,14 +338,14 @@
         } else {
           // See comments in Internal.java for gory details.
           return strings::Substitute(
-            "com.google.protobuf.Internal.stringDefaultValue(\"$0\")",
-            CEscape(field->default_value_string()));
+              "com.google.protobuf.Internal.stringDefaultValue(\"$0\")",
+              CEscape(field->default_value_string()));
         }
       }
 
     case FieldDescriptor::CPPTYPE_ENUM:
       return ClassName(field->enum_type()) + "." +
-             field->default_value_enum()->name();
+          field->default_value_enum()->name();
 
     case FieldDescriptor::CPPTYPE_MESSAGE:
       return ClassName(field->message_type()) + ".getDefaultInstance()";
@@ -427,8 +439,10 @@
   return GetBitFieldName(bitIndex / 32);
 }
 
-string GenerateGetBit(int bitIndex) {
-  string varName = GetBitFieldNameForBit(bitIndex);
+namespace {
+
+string GenerateGetBitInternal(const string& prefix, int bitIndex) {
+  string varName = prefix + GetBitFieldNameForBit(bitIndex);
   int bitInVarIndex = bitIndex % 32;
 
   string mask = bit_masks[bitInVarIndex];
@@ -436,8 +450,8 @@
   return result;
 }
 
-string GenerateSetBit(int bitIndex) {
-  string varName = GetBitFieldNameForBit(bitIndex);
+string GenerateSetBitInternal(const string& prefix, int bitIndex) {
+  string varName = prefix + GetBitFieldNameForBit(bitIndex);
   int bitInVarIndex = bitIndex % 32;
 
   string mask = bit_masks[bitInVarIndex];
@@ -445,6 +459,16 @@
   return result;
 }
 
+}  // namespace
+
+string GenerateGetBit(int bitIndex) {
+  return GenerateGetBitInternal("", bitIndex);
+}
+
+string GenerateSetBit(int bitIndex) {
+  return GenerateSetBitInternal("", bitIndex);
+}
+
 string GenerateClearBit(int bitIndex) {
   string varName = GetBitFieldNameForBit(bitIndex);
   int bitInVarIndex = bitIndex % 32;
@@ -455,21 +479,19 @@
 }
 
 string GenerateGetBitFromLocal(int bitIndex) {
-  string varName = "from_" + GetBitFieldNameForBit(bitIndex);
-  int bitInVarIndex = bitIndex % 32;
-
-  string mask = bit_masks[bitInVarIndex];
-  string result = "((" + varName + " & " + mask + ") == " + mask + ")";
-  return result;
+  return GenerateGetBitInternal("from_", bitIndex);
 }
 
 string GenerateSetBitToLocal(int bitIndex) {
-  string varName = "to_" + GetBitFieldNameForBit(bitIndex);
-  int bitInVarIndex = bitIndex % 32;
+  return GenerateSetBitInternal("to_", bitIndex);
+}
 
-  string mask = bit_masks[bitInVarIndex];
-  string result = varName + " |= " + mask;
-  return result;
+string GenerateGetBitMutableLocal(int bitIndex) {
+  return GenerateGetBitInternal("mutable_", bitIndex);
+}
+
+string GenerateSetBitMutableLocal(int bitIndex) {
+  return GenerateSetBitInternal("mutable_", bitIndex);
 }
 
 }  // namespace java
diff --git a/third_party/protobuf/src/google/protobuf/compiler/java/java_helpers.h b/third_party/protobuf/src/google/protobuf/compiler/java/java_helpers.h
index 88efd45..3ef7149 100644
--- a/third_party/protobuf/src/google/protobuf/compiler/java/java_helpers.h
+++ b/third_party/protobuf/src/google/protobuf/compiler/java/java_helpers.h
@@ -78,19 +78,14 @@
 
 // These return the fully-qualified class name corresponding to the given
 // descriptor.
-inline string ClassName(const Descriptor* descriptor) {
-  return ToJavaName(descriptor->full_name(), descriptor->file());
-}
-inline string ClassName(const EnumDescriptor* descriptor) {
-  return ToJavaName(descriptor->full_name(), descriptor->file());
-}
-inline string ClassName(const ServiceDescriptor* descriptor) {
-  return ToJavaName(descriptor->full_name(), descriptor->file());
-}
+string ClassName(const Descriptor* descriptor);
+string ClassName(const EnumDescriptor* descriptor);
+string ClassName(const ServiceDescriptor* descriptor);
+string ClassName(const FileDescriptor* descriptor);
+
 inline string ExtensionIdentifierName(const FieldDescriptor* descriptor) {
   return ToJavaName(descriptor->full_name(), descriptor->file());
 }
-string ClassName(const FileDescriptor* descriptor);
 
 // Get the unqualified name that should be used for a field's field
 // number constant.
@@ -206,6 +201,18 @@
 // Example: "to_bitField1_ = (to_bitField1_ | 0x04)"
 string GenerateSetBitToLocal(int bitIndex);
 
+// Does the same as GenerateGetBit but operates on the bit field on a local
+// variable. This is used by the parsing constructor to record if a repeated
+// field is mutable.
+// Example: "((mutable_bitField1_ & 0x04) == 0x04)"
+string GenerateGetBitMutableLocal(int bitIndex);
+
+// Does the same as GenerateSetBit but operates on the bit field on a local
+// variable. This is used by the parsing constructor to record if a repeated
+// field is mutable.
+// Example: "mutable_bitField1_ = (mutable_bitField1_ | 0x04)"
+string GenerateSetBitMutableLocal(int bitIndex);
+
 }  // namespace java
 }  // namespace compiler
 }  // namespace protobuf
diff --git a/third_party/protobuf/src/google/protobuf/compiler/java/java_message.cc b/third_party/protobuf/src/google/protobuf/compiler/java/java_message.cc
index 4c087db..9322e24 100644
--- a/third_party/protobuf/src/google/protobuf/compiler/java/java_message.cc
+++ b/third_party/protobuf/src/google/protobuf/compiler/java/java_message.cc
@@ -32,17 +32,23 @@
 //  Based on original Protocol Buffers design by
 //  Sanjay Ghemawat, Jeff Dean, and others.
 
+#include <google/protobuf/compiler/java/java_message.h>
+
 #include <algorithm>
 #include <google/protobuf/stubs/hash.h>
-#include <google/protobuf/compiler/java/java_message.h>
+#include <map>
+#include <vector>
+
+#include <google/protobuf/compiler/java/java_doc_comment.h>
 #include <google/protobuf/compiler/java/java_enum.h>
 #include <google/protobuf/compiler/java/java_extension.h>
 #include <google/protobuf/compiler/java/java_helpers.h>
-#include <google/protobuf/stubs/strutil.h>
-#include <google/protobuf/io/printer.h>
 #include <google/protobuf/io/coded_stream.h>
-#include <google/protobuf/wire_format.h>
+#include <google/protobuf/io/printer.h>
 #include <google/protobuf/descriptor.pb.h>
+#include <google/protobuf/wire_format.h>
+#include <google/protobuf/stubs/strutil.h>
+#include <google/protobuf/stubs/substitute.h>
 
 namespace google {
 namespace protobuf {
@@ -233,10 +239,8 @@
         "field_name",
           UnderscoresToCapitalizedCamelCase(descriptor_->field(i)));
     }
-    printer->Print("},\n"
-      "    $classname$.class,\n"
-      "    $classname$.Builder.class);\n",
-      "classname", ClassName(descriptor_));
+    printer->Print(
+        "});\n");
   }
 
   // Generate static member initializers for all nested types.
@@ -250,7 +254,6 @@
 // ===================================================================
 
 void MessageGenerator::GenerateInterface(io::Printer* printer) {
-
   if (descriptor_->extension_range_count() > 0) {
     if (HasDescriptorMethods(descriptor_)) {
       printer->Print(
@@ -298,6 +301,10 @@
     descriptor_->containing_type() == NULL &&
     descriptor_->file()->options().java_multiple_files();
 
+  WriteMessageDocComment(printer, descriptor_);
+
+  // The builder_type stores the super type name of the nested Builder class.
+  string builder_type;
   if (descriptor_->extension_range_count() > 0) {
     if (HasDescriptorMethods(descriptor_)) {
       printer->Print(
@@ -306,6 +313,9 @@
         "      $classname$> implements $classname$OrBuilder {\n",
         "static", is_own_file ? "" : "static",
         "classname", descriptor_->name());
+      builder_type = strings::Substitute(
+          "com.google.protobuf.GeneratedMessage.ExtendableBuilder<$0, ?>",
+          ClassName(descriptor_));
     } else {
       printer->Print(
         "public $static$ final class $classname$ extends\n"
@@ -313,6 +323,9 @@
         "      $classname$> implements $classname$OrBuilder {\n",
         "static", is_own_file ? "" : "static",
         "classname", descriptor_->name());
+      builder_type = strings::Substitute(
+          "com.google.protobuf.GeneratedMessageLite.ExtendableBuilder<$0, ?>",
+          ClassName(descriptor_));
     }
   } else {
     if (HasDescriptorMethods(descriptor_)) {
@@ -322,6 +335,7 @@
         "    implements $classname$OrBuilder {\n",
         "static", is_own_file ? "" : "static",
         "classname", descriptor_->name());
+      builder_type = "com.google.protobuf.GeneratedMessage.Builder<?>";
     } else {
       printer->Print(
         "public $static$ final class $classname$ extends\n"
@@ -329,17 +343,28 @@
         "    implements $classname$OrBuilder {\n",
         "static", is_own_file ? "" : "static",
         "classname", descriptor_->name());
+      builder_type = "com.google.protobuf.GeneratedMessageLite.Builder";
     }
   }
   printer->Indent();
+  // Using builder_type, instead of Builder, prevents the Builder class from
+  // being loaded into PermGen space when the default instance is created.
+  // This optimizes the PermGen space usage for clients that do not modify
+  // messages.
   printer->Print(
     "// Use $classname$.newBuilder() to construct.\n"
-    "private $classname$(Builder builder) {\n"
+    "private $classname$($buildertype$ builder) {\n"
     "  super(builder);\n"
-    "}\n"
+    "$set_unknown_fields$\n"
+    "}\n",
+    "classname", descriptor_->name(),
+    "buildertype", builder_type,
+    "set_unknown_fields", HasUnknownFields(descriptor_)
+        ? "  this.unknownFields = builder.getUnknownFields();" : "");
+  printer->Print(
     // Used when constructing the default instance, which cannot be initialized
     // immediately because it may cyclically refer to other default instances.
-    "private $classname$(boolean noInit) {}\n"
+    "private $classname$(boolean noInit) {$set_default_unknown_fields$}\n"
     "\n"
     "private static final $classname$ defaultInstance;\n"
     "public static $classname$ getDefaultInstance() {\n"
@@ -350,9 +375,28 @@
     "  return defaultInstance;\n"
     "}\n"
     "\n",
-    "classname", descriptor_->name());
+    "classname", descriptor_->name(),
+    "set_default_unknown_fields", HasUnknownFields(descriptor_)
+        ? " this.unknownFields ="
+          " com.google.protobuf.UnknownFieldSet.getDefaultInstance(); " : "");
+
+  if (HasUnknownFields(descriptor_)) {
+    printer->Print(
+        "private final com.google.protobuf.UnknownFieldSet unknownFields;\n"
+        ""
+        "@java.lang.Override\n"
+        "public final com.google.protobuf.UnknownFieldSet\n"
+        "    getUnknownFields() {\n"
+        "  return this.unknownFields;\n"
+        "}\n");
+  }
+
+  if (HasGeneratedMethods(descriptor_)) {
+    GenerateParsingConstructor(printer);
+  }
 
   GenerateDescriptorMethods(printer);
+  GenerateParser(printer);
 
   // Nested types
   for (int i = 0; i < descriptor_->enum_type_count(); i++) {
@@ -567,68 +611,54 @@
     "public static $classname$ parseFrom(\n"
     "    com.google.protobuf.ByteString data)\n"
     "    throws com.google.protobuf.InvalidProtocolBufferException {\n"
-    "  return newBuilder().mergeFrom(data).buildParsed();\n"
+    "  return PARSER.parseFrom(data);\n"
     "}\n"
     "public static $classname$ parseFrom(\n"
     "    com.google.protobuf.ByteString data,\n"
     "    com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n"
     "    throws com.google.protobuf.InvalidProtocolBufferException {\n"
-    "  return newBuilder().mergeFrom(data, extensionRegistry)\n"
-    "           .buildParsed();\n"
+    "  return PARSER.parseFrom(data, extensionRegistry);\n"
     "}\n"
     "public static $classname$ parseFrom(byte[] data)\n"
     "    throws com.google.protobuf.InvalidProtocolBufferException {\n"
-    "  return newBuilder().mergeFrom(data).buildParsed();\n"
+    "  return PARSER.parseFrom(data);\n"
     "}\n"
     "public static $classname$ parseFrom(\n"
     "    byte[] data,\n"
     "    com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n"
     "    throws com.google.protobuf.InvalidProtocolBufferException {\n"
-    "  return newBuilder().mergeFrom(data, extensionRegistry)\n"
-    "           .buildParsed();\n"
+    "  return PARSER.parseFrom(data, extensionRegistry);\n"
     "}\n"
     "public static $classname$ parseFrom(java.io.InputStream input)\n"
     "    throws java.io.IOException {\n"
-    "  return newBuilder().mergeFrom(input).buildParsed();\n"
+    "  return PARSER.parseFrom(input);\n"
     "}\n"
     "public static $classname$ parseFrom(\n"
     "    java.io.InputStream input,\n"
     "    com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n"
     "    throws java.io.IOException {\n"
-    "  return newBuilder().mergeFrom(input, extensionRegistry)\n"
-    "           .buildParsed();\n"
+    "  return PARSER.parseFrom(input, extensionRegistry);\n"
     "}\n"
     "public static $classname$ parseDelimitedFrom(java.io.InputStream input)\n"
     "    throws java.io.IOException {\n"
-    "  Builder builder = newBuilder();\n"
-    "  if (builder.mergeDelimitedFrom(input)) {\n"
-    "    return builder.buildParsed();\n"
-    "  } else {\n"
-    "    return null;\n"
-    "  }\n"
+    "  return PARSER.parseDelimitedFrom(input);\n"
     "}\n"
     "public static $classname$ parseDelimitedFrom(\n"
     "    java.io.InputStream input,\n"
     "    com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n"
     "    throws java.io.IOException {\n"
-    "  Builder builder = newBuilder();\n"
-    "  if (builder.mergeDelimitedFrom(input, extensionRegistry)) {\n"
-    "    return builder.buildParsed();\n"
-    "  } else {\n"
-    "    return null;\n"
-    "  }\n"
+    "  return PARSER.parseDelimitedFrom(input, extensionRegistry);\n"
     "}\n"
     "public static $classname$ parseFrom(\n"
     "    com.google.protobuf.CodedInputStream input)\n"
     "    throws java.io.IOException {\n"
-    "  return newBuilder().mergeFrom(input).buildParsed();\n"
+    "  return PARSER.parseFrom(input);\n"
     "}\n"
     "public static $classname$ parseFrom(\n"
     "    com.google.protobuf.CodedInputStream input,\n"
     "    com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n"
     "    throws java.io.IOException {\n"
-    "  return newBuilder().mergeFrom(input, extensionRegistry)\n"
-    "           .buildParsed();\n"
+    "  return PARSER.parseFrom(input, extensionRegistry);\n"
     "}\n"
     "\n",
     "classname", ClassName(descriptor_));
@@ -669,6 +699,8 @@
       "}\n");
   }
 
+  WriteMessageDocComment(printer, descriptor_);
+
   if (descriptor_->extension_range_count() > 0) {
     if (HasDescriptorMethods(descriptor_)) {
       printer->Print(
@@ -739,17 +771,25 @@
 
 void MessageGenerator::GenerateDescriptorMethods(io::Printer* printer) {
   if (HasDescriptorMethods(descriptor_)) {
+    if (!descriptor_->options().no_standard_descriptor_accessor()) {
+      printer->Print(
+        "public static final com.google.protobuf.Descriptors.Descriptor\n"
+        "    getDescriptor() {\n"
+        "  return $fileclass$.internal_$identifier$_descriptor;\n"
+        "}\n"
+        "\n",
+        "fileclass", ClassName(descriptor_->file()),
+        "identifier", UniqueFileScopeIdentifier(descriptor_));
+    }
     printer->Print(
-      "public static final com.google.protobuf.Descriptors.Descriptor\n"
-      "    getDescriptor() {\n"
-      "  return $fileclass$.internal_$identifier$_descriptor;\n"
-      "}\n"
-      "\n"
       "protected com.google.protobuf.GeneratedMessage.FieldAccessorTable\n"
       "    internalGetFieldAccessorTable() {\n"
-      "  return $fileclass$.internal_$identifier$_fieldAccessorTable;\n"
+      "  return $fileclass$.internal_$identifier$_fieldAccessorTable\n"
+      "      .ensureFieldAccessorsInitialized(\n"
+      "          $classname$.class, $classname$.Builder.class);\n"
       "}\n"
       "\n",
+      "classname", ClassName(descriptor_),
       "fileclass", ClassName(descriptor_->file()),
       "identifier", UniqueFileScopeIdentifier(descriptor_));
   }
@@ -768,7 +808,8 @@
 
   if (HasDescriptorMethods(descriptor_)) {
     printer->Print(
-      "private Builder(BuilderParent parent) {\n"
+      "private Builder(\n"
+      "    com.google.protobuf.GeneratedMessage.BuilderParent parent) {\n"
       "  super(parent);\n"
       "  maybeForceBuilderInitialization();\n"
       "}\n",
@@ -830,10 +871,11 @@
     printer->Print(
       "public com.google.protobuf.Descriptors.Descriptor\n"
       "    getDescriptorForType() {\n"
-      "  return $classname$.getDescriptor();\n"
+      "  return $fileclass$.internal_$identifier$_descriptor;\n"
       "}\n"
       "\n",
-      "classname", ClassName(descriptor_));
+      "fileclass", ClassName(descriptor_->file()),
+      "identifier", UniqueFileScopeIdentifier(descriptor_));
   }
   printer->Print(
     "public $classname$ getDefaultInstanceForType() {\n"
@@ -853,16 +895,6 @@
     "  return result;\n"
     "}\n"
     "\n"
-    "private $classname$ buildParsed()\n"
-    "    throws com.google.protobuf.InvalidProtocolBufferException {\n"
-    "  $classname$ result = buildPartial();\n"
-    "  if (!result.isInitialized()) {\n"
-    "    throw newUninitializedMessageException(\n"
-    "      result).asInvalidProtocolBufferException();\n"
-    "  }\n"
-    "  return result;\n"
-    "}\n"
-    "\n"
     "public $classname$ buildPartial() {\n"
     "  $classname$ result = new $classname$(this);\n",
     "classname", ClassName(descriptor_));
@@ -969,108 +1001,25 @@
 // ===================================================================
 
 void MessageGenerator::GenerateBuilderParsingMethods(io::Printer* printer) {
-  scoped_array<const FieldDescriptor*> sorted_fields(
-    SortFieldsByNumber(descriptor_));
-
   printer->Print(
     "public Builder mergeFrom(\n"
     "    com.google.protobuf.CodedInputStream input,\n"
     "    com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n"
-    "    throws java.io.IOException {\n");
-  printer->Indent();
-
-  if (HasUnknownFields(descriptor_)) {
-    printer->Print(
-      "com.google.protobuf.UnknownFieldSet.Builder unknownFields =\n"
-      "  com.google.protobuf.UnknownFieldSet.newBuilder(\n"
-      "    this.getUnknownFields());\n");
-  }
-
-  printer->Print(
-    "while (true) {\n");
-  printer->Indent();
-
-  printer->Print(
-    "int tag = input.readTag();\n"
-    "switch (tag) {\n");
-  printer->Indent();
-
-  if (HasUnknownFields(descriptor_)) {
-    printer->Print(
-      "case 0:\n"          // zero signals EOF / limit reached
-      "  this.setUnknownFields(unknownFields.build());\n"
-      "  $on_changed$\n"
-      "  return this;\n"
-      "default: {\n"
-      "  if (!parseUnknownField(input, unknownFields,\n"
-      "                         extensionRegistry, tag)) {\n"
-      "    this.setUnknownFields(unknownFields.build());\n"
-      "    $on_changed$\n"
-      "    return this;\n"   // it's an endgroup tag
-      "  }\n"
-      "  break;\n"
-      "}\n",
-      "on_changed", HasDescriptorMethods(descriptor_) ? "onChanged();" : "");
-  } else {
-    printer->Print(
-      "case 0:\n"          // zero signals EOF / limit reached
-      "  $on_changed$\n"
-      "  return this;\n"
-      "default: {\n"
-      "  if (!parseUnknownField(input, extensionRegistry, tag)) {\n"
-      "    $on_changed$\n"
-      "    return this;\n"   // it's an endgroup tag
-      "  }\n"
-      "  break;\n"
-      "}\n",
-      "on_changed", HasDescriptorMethods(descriptor_) ? "onChanged();" : "");
-  }
-
-  for (int i = 0; i < descriptor_->field_count(); i++) {
-    const FieldDescriptor* field = sorted_fields[i];
-    uint32 tag = WireFormatLite::MakeTag(field->number(),
-      WireFormat::WireTypeForFieldType(field->type()));
-
-    printer->Print(
-      "case $tag$: {\n",
-      "tag", SimpleItoa(tag));
-    printer->Indent();
-
-    field_generators_.get(field).GenerateParsingCode(printer);
-
-    printer->Outdent();
-    printer->Print(
-      "  break;\n"
-      "}\n");
-
-    if (field->is_packable()) {
-      // To make packed = true wire compatible, we generate parsing code from a
-      // packed version of this field regardless of field->options().packed().
-      uint32 packed_tag = WireFormatLite::MakeTag(field->number(),
-        WireFormatLite::WIRETYPE_LENGTH_DELIMITED);
-      printer->Print(
-        "case $tag$: {\n",
-        "tag", SimpleItoa(packed_tag));
-      printer->Indent();
-
-      field_generators_.get(field).GenerateParsingCodeFromPacked(printer);
-
-      printer->Outdent();
-      printer->Print(
-        "  break;\n"
-        "}\n");
-    }
-  }
-
-  printer->Outdent();
-  printer->Outdent();
-  printer->Outdent();
-  printer->Print(
-    "    }\n"     // switch (tag)
-    "  }\n"       // while (true)
-    "}\n"
-
-    "\n");
+    "    throws java.io.IOException {\n"
+    "  $classname$ parsedMessage = null;\n"
+    "  try {\n"
+    "    parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);\n"
+    "  } catch (com.google.protobuf.InvalidProtocolBufferException e) {\n"
+    "    parsedMessage = ($classname$) e.getUnfinishedMessage();\n"
+    "    throw e;\n"
+    "  } finally {\n"
+    "    if (parsedMessage != null) {\n"
+    "      mergeFrom(parsedMessage);\n"
+    "    }\n"
+    "  }\n"
+    "  return this;\n"
+    "}\n",
+    "classname", ClassName(descriptor_));
 }
 
 // ===================================================================
@@ -1232,10 +1181,19 @@
     "\n");
 
   printer->Print(
+    "private int memoizedHashCode = 0;\n");
+  printer->Print(
     "@java.lang.Override\n"
     "public int hashCode() {\n");
   printer->Indent();
   printer->Print(
+    "if (memoizedHashCode != 0) {\n");
+  printer->Indent();
+  printer->Print(
+    "return memoizedHashCode;\n");
+  printer->Outdent();
+  printer->Print(
+    "}\n"
     "int hash = 41;\n"
     "hash = (19 * hash) + getDescriptorForType().hashCode();\n");
   for (int i = 0; i < descriptor_->field_count(); i++) {
@@ -1260,6 +1218,7 @@
   }
   printer->Print(
     "hash = (29 * hash) + getUnknownFields().hashCode();\n"
+    "memoizedHashCode = hash;\n"
     "return hash;\n");
   printer->Outdent();
   printer->Print(
@@ -1281,6 +1240,195 @@
   }
 }
 
+// ===================================================================
+void MessageGenerator::GenerateParsingConstructor(io::Printer* printer) {
+  scoped_array<const FieldDescriptor*> sorted_fields(
+      SortFieldsByNumber(descriptor_));
+
+  printer->Print(
+      "private $classname$(\n"
+      "    com.google.protobuf.CodedInputStream input,\n"
+      "    com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n"
+      "    throws com.google.protobuf.InvalidProtocolBufferException {\n",
+      "classname", descriptor_->name());
+  printer->Indent();
+
+  // Initialize all fields to default.
+  printer->Print(
+      "initFields();\n");
+
+  // Use builder bits to track mutable repeated fields.
+  int totalBuilderBits = 0;
+  for (int i = 0; i < descriptor_->field_count(); i++) {
+    const FieldGenerator& field = field_generators_.get(descriptor_->field(i));
+    totalBuilderBits += field.GetNumBitsForBuilder();
+  }
+  int totalBuilderInts = (totalBuilderBits + 31) / 32;
+  for (int i = 0; i < totalBuilderInts; i++) {
+    printer->Print("int mutable_$bit_field_name$ = 0;\n",
+      "bit_field_name", GetBitFieldName(i));
+  }
+
+  if (HasUnknownFields(descriptor_)) {
+    printer->Print(
+      "com.google.protobuf.UnknownFieldSet.Builder unknownFields =\n"
+      "    com.google.protobuf.UnknownFieldSet.newBuilder();\n");
+  }
+
+  printer->Print(
+      "try {\n");
+  printer->Indent();
+
+  printer->Print(
+    "boolean done = false;\n"
+    "while (!done) {\n");
+  printer->Indent();
+
+  printer->Print(
+    "int tag = input.readTag();\n"
+    "switch (tag) {\n");
+  printer->Indent();
+
+  printer->Print(
+    "case 0:\n"          // zero signals EOF / limit reached
+    "  done = true;\n"
+    "  break;\n"
+    "default: {\n"
+    "  if (!parseUnknownField(input,$unknown_fields$\n"
+    "                         extensionRegistry, tag)) {\n"
+    "    done = true;\n"  // it's an endgroup tag
+    "  }\n"
+    "  break;\n"
+    "}\n",
+    "unknown_fields", HasUnknownFields(descriptor_)
+        ? " unknownFields," : "");
+
+  for (int i = 0; i < descriptor_->field_count(); i++) {
+    const FieldDescriptor* field = sorted_fields[i];
+    uint32 tag = WireFormatLite::MakeTag(field->number(),
+      WireFormat::WireTypeForFieldType(field->type()));
+
+    printer->Print(
+      "case $tag$: {\n",
+      "tag", SimpleItoa(tag));
+    printer->Indent();
+
+    field_generators_.get(field).GenerateParsingCode(printer);
+
+    printer->Outdent();
+    printer->Print(
+      "  break;\n"
+      "}\n");
+
+    if (field->is_packable()) {
+      // To make packed = true wire compatible, we generate parsing code from a
+      // packed version of this field regardless of field->options().packed().
+      uint32 packed_tag = WireFormatLite::MakeTag(field->number(),
+        WireFormatLite::WIRETYPE_LENGTH_DELIMITED);
+      printer->Print(
+        "case $tag$: {\n",
+        "tag", SimpleItoa(packed_tag));
+      printer->Indent();
+
+      field_generators_.get(field).GenerateParsingCodeFromPacked(printer);
+
+      printer->Outdent();
+      printer->Print(
+        "  break;\n"
+        "}\n");
+    }
+  }
+
+  printer->Outdent();
+  printer->Outdent();
+  printer->Print(
+      "  }\n"     // switch (tag)
+      "}\n");     // while (!done)
+
+  printer->Outdent();
+  printer->Print(
+      "} catch (com.google.protobuf.InvalidProtocolBufferException e) {\n"
+      "  throw e.setUnfinishedMessage(this);\n"
+      "} catch (java.io.IOException e) {\n"
+      "  throw new com.google.protobuf.InvalidProtocolBufferException(\n"
+      "      e.getMessage()).setUnfinishedMessage(this);\n"
+      "} finally {\n");
+  printer->Indent();
+
+  // Make repeated field list immutable.
+  for (int i = 0; i < descriptor_->field_count(); i++) {
+    const FieldDescriptor* field = sorted_fields[i];
+    field_generators_.get(field).GenerateParsingDoneCode(printer);
+  }
+
+  // Make unknown fields immutable.
+  if (HasUnknownFields(descriptor_)) {
+    printer->Print(
+        "this.unknownFields = unknownFields.build();\n");
+  }
+
+  // Make extensions immutable.
+  printer->Print(
+      "makeExtensionsImmutable();\n");
+
+  printer->Outdent();
+  printer->Outdent();
+  printer->Print(
+      "  }\n"     // finally
+      "}\n");
+}
+
+// ===================================================================
+void MessageGenerator::GenerateParser(io::Printer* printer) {
+  printer->Print(
+      "public static com.google.protobuf.Parser<$classname$> PARSER =\n"
+      "    new com.google.protobuf.AbstractParser<$classname$>() {\n",
+      "classname", descriptor_->name());
+  printer->Indent();
+  printer->Print(
+      "public $classname$ parsePartialFrom(\n"
+      "    com.google.protobuf.CodedInputStream input,\n"
+      "    com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n"
+      "    throws com.google.protobuf.InvalidProtocolBufferException {\n",
+      "classname", descriptor_->name());
+  if (HasGeneratedMethods(descriptor_)) {
+    printer->Print(
+        "  return new $classname$(input, extensionRegistry);\n",
+        "classname", descriptor_->name());
+  } else {
+    // When parsing constructor isn't generated, use builder to parse messages.
+    // Note, will fallback to use reflection based mergeFieldFrom() in
+    // AbstractMessage.Builder.
+    printer->Indent();
+    printer->Print(
+        "Builder builder = newBuilder();\n"
+        "try {\n"
+        "  builder.mergeFrom(input, extensionRegistry);\n"
+        "} catch (com.google.protobuf.InvalidProtocolBufferException e) {\n"
+        "  throw e.setUnfinishedMessage(builder.buildPartial());\n"
+        "} catch (java.io.IOException e) {\n"
+        "  throw new com.google.protobuf.InvalidProtocolBufferException(\n"
+        "      e.getMessage()).setUnfinishedMessage(builder.buildPartial());\n"
+        "}\n"
+        "return builder.buildPartial();\n");
+    printer->Outdent();
+  }
+  printer->Print(
+        "}\n");
+  printer->Outdent();
+  printer->Print(
+      "};\n"
+      "\n");
+
+  printer->Print(
+      "@java.lang.Override\n"
+      "public com.google.protobuf.Parser<$classname$> getParserForType() {\n"
+      "  return PARSER;\n"
+      "}\n"
+      "\n",
+      "classname", descriptor_->name());
+}
+
 }  // namespace java
 }  // namespace compiler
 }  // namespace protobuf
diff --git a/third_party/protobuf/src/google/protobuf/compiler/java/java_message.h b/third_party/protobuf/src/google/protobuf/compiler/java/java_message.h
index 4c6fbbe..a30f020 100644
--- a/third_party/protobuf/src/google/protobuf/compiler/java/java_message.h
+++ b/third_party/protobuf/src/google/protobuf/compiler/java/java_message.h
@@ -95,6 +95,9 @@
       UseMemoization useMemoization);
   void GenerateEqualsAndHashCode(io::Printer* printer);
 
+  void GenerateParser(io::Printer* printer);
+  void GenerateParsingConstructor(io::Printer* printer);
+
   const Descriptor* descriptor_;
   FieldGeneratorMap field_generators_;
 
diff --git a/third_party/protobuf/src/google/protobuf/compiler/java/java_message_field.cc b/third_party/protobuf/src/google/protobuf/compiler/java/java_message_field.cc
index 251945a..b0b284f 100644
--- a/third_party/protobuf/src/google/protobuf/compiler/java/java_message_field.cc
+++ b/third_party/protobuf/src/google/protobuf/compiler/java/java_message_field.cc
@@ -36,6 +36,7 @@
 #include <string>
 
 #include <google/protobuf/compiler/java/java_message_field.h>
+#include <google/protobuf/compiler/java/java_doc_comment.h>
 #include <google/protobuf/compiler/java/java_helpers.h>
 #include <google/protobuf/io/printer.h>
 #include <google/protobuf/wire_format.h>
@@ -73,6 +74,7 @@
 
   // For singular messages and builders, one bit is used for the hasField bit.
   (*variables)["get_has_field_bit_message"] = GenerateGetBit(messageBitIndex);
+  (*variables)["set_has_field_bit_message"] = GenerateSetBit(messageBitIndex);
 
   (*variables)["get_has_field_bit_builder"] = GenerateGetBit(builderBitIndex);
   (*variables)["set_has_field_bit_builder"] = GenerateSetBit(builderBitIndex);
@@ -84,6 +86,13 @@
   (*variables)["set_mutable_bit_builder"] = GenerateSetBit(builderBitIndex);
   (*variables)["clear_mutable_bit_builder"] = GenerateClearBit(builderBitIndex);
 
+  // For repeated fields, one bit is used for whether the array is immutable
+  // in the parsing constructor.
+  (*variables)["get_mutable_bit_parser"] =
+      GenerateGetBitMutableLocal(builderBitIndex);
+  (*variables)["set_mutable_bit_parser"] =
+      GenerateSetBitMutableLocal(builderBitIndex);
+
   (*variables)["get_has_field_bit_from_local"] =
       GenerateGetBitFromLocal(builderBitIndex);
   (*variables)["set_has_field_bit_to_local"] =
@@ -120,11 +129,15 @@
   // interface so that builders can choose dynamically to either return a
   // message or a nested builder, so that asking for the interface doesn't
   // cause a message to ever be built.
+  WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$boolean has$capitalized_name$();\n"
+    "$deprecation$boolean has$capitalized_name$();\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
     "$deprecation$$type$ get$capitalized_name$();\n");
 
   if (HasNestedBuilders(descriptor_->containing_type())) {
+    WriteFieldDocComment(printer, descriptor_);
     printer->Print(variables_,
       "$deprecation$$type$OrBuilder get$capitalized_name$OrBuilder();\n");
   }
@@ -133,15 +146,20 @@
 void MessageFieldGenerator::
 GenerateMembers(io::Printer* printer) const {
   printer->Print(variables_,
-    "private $type$ $name$_;\n"
+    "private $type$ $name$_;\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
     "$deprecation$public boolean has$capitalized_name$() {\n"
     "  return $get_has_field_bit_message$;\n"
-    "}\n"
+    "}\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
     "$deprecation$public $type$ get$capitalized_name$() {\n"
     "  return $name$_;\n"
     "}\n");
 
   if (HasNestedBuilders(descriptor_->containing_type())) {
+    WriteFieldDocComment(printer, descriptor_);
     printer->Print(variables_,
       "$deprecation$public $type$OrBuilder get$capitalized_name$OrBuilder() {\n"
       "  return $name$_;\n"
@@ -208,12 +226,14 @@
   // field of type "Field" called "Field".
 
   // boolean hasField()
+  WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
     "$deprecation$public boolean has$capitalized_name$() {\n"
     "  return $get_has_field_bit_builder$;\n"
     "}\n");
 
   // Field getField()
+  WriteFieldDocComment(printer, descriptor_);
   PrintNestedBuilderFunction(printer,
     "$deprecation$public $type$ get$capitalized_name$()",
 
@@ -224,6 +244,7 @@
     NULL);
 
   // Field.Builder setField(Field value)
+  WriteFieldDocComment(printer, descriptor_);
   PrintNestedBuilderFunction(printer,
     "$deprecation$public Builder set$capitalized_name$($type$ value)",
 
@@ -239,6 +260,7 @@
     "return this;\n");
 
   // Field.Builder setField(Field.Builder builderForValue)
+  WriteFieldDocComment(printer, descriptor_);
   PrintNestedBuilderFunction(printer,
     "$deprecation$public Builder set$capitalized_name$(\n"
     "    $type$.Builder builderForValue)",
@@ -252,6 +274,7 @@
     "return this;\n");
 
   // Field.Builder mergeField(Field value)
+  WriteFieldDocComment(printer, descriptor_);
   PrintNestedBuilderFunction(printer,
     "$deprecation$public Builder merge$capitalized_name$($type$ value)",
 
@@ -270,6 +293,7 @@
     "return this;\n");
 
   // Field.Builder clearField()
+  WriteFieldDocComment(printer, descriptor_);
   PrintNestedBuilderFunction(printer,
     "$deprecation$public Builder clear$capitalized_name$()",
 
@@ -282,19 +306,24 @@
     "return this;\n");
 
   if (HasNestedBuilders(descriptor_->containing_type())) {
+    WriteFieldDocComment(printer, descriptor_);
     printer->Print(variables_,
       "$deprecation$public $type$.Builder get$capitalized_name$Builder() {\n"
       "  $set_has_field_bit_builder$;\n"
       "  $on_changed$\n"
       "  return get$capitalized_name$FieldBuilder().getBuilder();\n"
-      "}\n"
+      "}\n");
+    WriteFieldDocComment(printer, descriptor_);
+    printer->Print(variables_,
       "$deprecation$public $type$OrBuilder get$capitalized_name$OrBuilder() {\n"
       "  if ($name$Builder_ != null) {\n"
       "    return $name$Builder_.getMessageOrBuilder();\n"
       "  } else {\n"
       "    return $name$_;\n"
       "  }\n"
-      "}\n"
+      "}\n");
+    WriteFieldDocComment(printer, descriptor_);
+    printer->Print(variables_,
       "private com.google.protobuf.SingleFieldBuilder<\n"
       "    $type$, $type$.Builder, $type$OrBuilder> \n"
       "    get$capitalized_name$FieldBuilder() {\n"
@@ -357,21 +386,32 @@
 void MessageFieldGenerator::
 GenerateParsingCode(io::Printer* printer) const {
   printer->Print(variables_,
-    "$type$.Builder subBuilder = $type$.newBuilder();\n"
-    "if (has$capitalized_name$()) {\n"
-    "  subBuilder.mergeFrom(get$capitalized_name$());\n"
+    "$type$.Builder subBuilder = null;\n"
+    "if ($get_has_field_bit_message$) {\n"
+    "  subBuilder = $name$_.toBuilder();\n"
     "}\n");
 
   if (GetType(descriptor_) == FieldDescriptor::TYPE_GROUP) {
     printer->Print(variables_,
-      "input.readGroup($number$, subBuilder, extensionRegistry);\n");
+      "$name$_ = input.readGroup($number$, $type$.PARSER,\n"
+      "    extensionRegistry);\n");
   } else {
     printer->Print(variables_,
-      "input.readMessage(subBuilder, extensionRegistry);\n");
+      "$name$_ = input.readMessage($type$.PARSER, extensionRegistry);\n");
   }
 
   printer->Print(variables_,
-    "set$capitalized_name$(subBuilder.buildPartial());\n");
+    "if (subBuilder != null) {\n"
+    "  subBuilder.mergeFrom($name$_);\n"
+    "  $name$_ = subBuilder.buildPartial();\n"
+    "}\n");
+  printer->Print(variables_,
+    "$set_has_field_bit_message$;\n");
+}
+
+void MessageFieldGenerator::
+GenerateParsingDoneCode(io::Printer* printer) const {
+  // noop for messages.
 }
 
 void MessageFieldGenerator::
@@ -437,15 +477,23 @@
   // interface so that builders can choose dynamically to either return a
   // message or a nested builder, so that asking for the interface doesn't
   // cause a message to ever be built.
+  WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
     "$deprecation$java.util.List<$type$> \n"
-    "    get$capitalized_name$List();\n"
-    "$deprecation$$type$ get$capitalized_name$(int index);\n"
+    "    get$capitalized_name$List();\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$$type$ get$capitalized_name$(int index);\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
     "$deprecation$int get$capitalized_name$Count();\n");
   if (HasNestedBuilders(descriptor_->containing_type())) {
+    WriteFieldDocComment(printer, descriptor_);
     printer->Print(variables_,
       "$deprecation$java.util.List<? extends $type$OrBuilder> \n"
-      "    get$capitalized_name$OrBuilderList();\n"
+      "    get$capitalized_name$OrBuilderList();\n");
+    WriteFieldDocComment(printer, descriptor_);
+    printer->Print(variables_,
       "$deprecation$$type$OrBuilder get$capitalized_name$OrBuilder(\n"
       "    int index);\n");
   }
@@ -454,20 +502,30 @@
 void RepeatedMessageFieldGenerator::
 GenerateMembers(io::Printer* printer) const {
   printer->Print(variables_,
-    "private java.util.List<$type$> $name$_;\n"
+    "private java.util.List<$type$> $name$_;\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
     "$deprecation$public java.util.List<$type$> get$capitalized_name$List() {\n"
     "  return $name$_;\n"   // note:  unmodifiable list
-    "}\n"
+    "}\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
     "$deprecation$public java.util.List<? extends $type$OrBuilder> \n"
     "    get$capitalized_name$OrBuilderList() {\n"
     "  return $name$_;\n"
-    "}\n"
+    "}\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
     "$deprecation$public int get$capitalized_name$Count() {\n"
     "  return $name$_.size();\n"
-    "}\n"
+    "}\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
     "$deprecation$public $type$ get$capitalized_name$(int index) {\n"
     "  return $name$_.get(index);\n"
-    "}\n"
+    "}\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
     "$deprecation$public $type$OrBuilder get$capitalized_name$OrBuilder(\n"
     "    int index) {\n"
     "  return $name$_.get(index);\n"
@@ -552,6 +610,7 @@
   // repeated field of type "Field" called "RepeatedField".
 
   // List<Field> getRepeatedFieldList()
+  WriteFieldDocComment(printer, descriptor_);
   PrintNestedBuilderFunction(printer,
     "$deprecation$public java.util.List<$type$> get$capitalized_name$List()",
 
@@ -561,6 +620,7 @@
     NULL);
 
   // int getRepeatedFieldCount()
+  WriteFieldDocComment(printer, descriptor_);
   PrintNestedBuilderFunction(printer,
     "$deprecation$public int get$capitalized_name$Count()",
 
@@ -570,6 +630,7 @@
     NULL);
 
   // Field getRepeatedField(int index)
+  WriteFieldDocComment(printer, descriptor_);
   PrintNestedBuilderFunction(printer,
     "$deprecation$public $type$ get$capitalized_name$(int index)",
 
@@ -580,6 +641,7 @@
     NULL);
 
   // Builder setRepeatedField(int index, Field value)
+  WriteFieldDocComment(printer, descriptor_);
   PrintNestedBuilderFunction(printer,
     "$deprecation$public Builder set$capitalized_name$(\n"
     "    int index, $type$ value)",
@@ -593,6 +655,7 @@
     "return this;\n");
 
   // Builder setRepeatedField(int index, Field.Builder builderForValue)
+  WriteFieldDocComment(printer, descriptor_);
   PrintNestedBuilderFunction(printer,
     "$deprecation$public Builder set$capitalized_name$(\n"
     "    int index, $type$.Builder builderForValue)",
@@ -606,6 +669,7 @@
     "return this;\n");
 
   // Builder addRepeatedField(Field value)
+  WriteFieldDocComment(printer, descriptor_);
   PrintNestedBuilderFunction(printer,
     "$deprecation$public Builder add$capitalized_name$($type$ value)",
 
@@ -622,6 +686,7 @@
     "return this;\n");
 
   // Builder addRepeatedField(int index, Field value)
+  WriteFieldDocComment(printer, descriptor_);
   PrintNestedBuilderFunction(printer,
     "$deprecation$public Builder add$capitalized_name$(\n"
     "    int index, $type$ value)",
@@ -638,6 +703,7 @@
     "return this;\n");
 
   // Builder addRepeatedField(Field.Builder builderForValue)
+  WriteFieldDocComment(printer, descriptor_);
   PrintNestedBuilderFunction(printer,
     "$deprecation$public Builder add$capitalized_name$(\n"
     "    $type$.Builder builderForValue)",
@@ -651,6 +717,7 @@
     "return this;\n");
 
   // Builder addRepeatedField(int index, Field.Builder builderForValue)
+  WriteFieldDocComment(printer, descriptor_);
   PrintNestedBuilderFunction(printer,
     "$deprecation$public Builder add$capitalized_name$(\n"
     "    int index, $type$.Builder builderForValue)",
@@ -664,6 +731,7 @@
     "return this;\n");
 
   // Builder addAllRepeatedField(Iterable<Field> values)
+  WriteFieldDocComment(printer, descriptor_);
   PrintNestedBuilderFunction(printer,
     "$deprecation$public Builder addAll$capitalized_name$(\n"
     "    java.lang.Iterable<? extends $type$> values)",
@@ -677,6 +745,7 @@
     "return this;\n");
 
   // Builder clearAllRepeatedField()
+  WriteFieldDocComment(printer, descriptor_);
   PrintNestedBuilderFunction(printer,
     "$deprecation$public Builder clear$capitalized_name$()",
 
@@ -689,6 +758,7 @@
     "return this;\n");
 
   // Builder removeRepeatedField(int index)
+  WriteFieldDocComment(printer, descriptor_);
   PrintNestedBuilderFunction(printer,
     "$deprecation$public Builder remove$capitalized_name$(int index)",
 
@@ -701,12 +771,15 @@
     "return this;\n");
 
   if (HasNestedBuilders(descriptor_->containing_type())) {
+    WriteFieldDocComment(printer, descriptor_);
     printer->Print(variables_,
       "$deprecation$public $type$.Builder get$capitalized_name$Builder(\n"
       "    int index) {\n"
       "  return get$capitalized_name$FieldBuilder().getBuilder(index);\n"
-      "}\n"
+      "}\n");
 
+    WriteFieldDocComment(printer, descriptor_);
+        printer->Print(variables_,
       "$deprecation$public $type$OrBuilder get$capitalized_name$OrBuilder(\n"
       "    int index) {\n"
       "  if ($name$Builder_ == null) {\n"
@@ -714,8 +787,10 @@
       "  } else {\n"
       "    return $name$Builder_.getMessageOrBuilder(index);\n"
       "  }\n"
-      "}\n"
+      "}\n");
 
+    WriteFieldDocComment(printer, descriptor_);
+        printer->Print(variables_,
       "$deprecation$public java.util.List<? extends $type$OrBuilder> \n"
       "     get$capitalized_name$OrBuilderList() {\n"
       "  if ($name$Builder_ != null) {\n"
@@ -723,17 +798,23 @@
       "  } else {\n"
       "    return java.util.Collections.unmodifiableList($name$_);\n"
       "  }\n"
-      "}\n"
+      "}\n");
 
+    WriteFieldDocComment(printer, descriptor_);
+        printer->Print(variables_,
       "$deprecation$public $type$.Builder add$capitalized_name$Builder() {\n"
       "  return get$capitalized_name$FieldBuilder().addBuilder(\n"
       "      $type$.getDefaultInstance());\n"
-      "}\n"
+      "}\n");
+    WriteFieldDocComment(printer, descriptor_);
+        printer->Print(variables_,
       "$deprecation$public $type$.Builder add$capitalized_name$Builder(\n"
       "    int index) {\n"
       "  return get$capitalized_name$FieldBuilder().addBuilder(\n"
       "      index, $type$.getDefaultInstance());\n"
-      "}\n"
+      "}\n");
+    WriteFieldDocComment(printer, descriptor_);
+        printer->Print(variables_,
       "$deprecation$public java.util.List<$type$.Builder> \n"
       "     get$capitalized_name$BuilderList() {\n"
       "  return get$capitalized_name$FieldBuilder().getBuilderList();\n"
@@ -827,18 +908,27 @@
 void RepeatedMessageFieldGenerator::
 GenerateParsingCode(io::Printer* printer) const {
   printer->Print(variables_,
-    "$type$.Builder subBuilder = $type$.newBuilder();\n");
+    "if (!$get_mutable_bit_parser$) {\n"
+    "  $name$_ = new java.util.ArrayList<$type$>();\n"
+    "  $set_mutable_bit_parser$;\n"
+    "}\n");
 
   if (GetType(descriptor_) == FieldDescriptor::TYPE_GROUP) {
     printer->Print(variables_,
-      "input.readGroup($number$, subBuilder, extensionRegistry);\n");
+      "$name$_.add(input.readGroup($number$, $type$.PARSER,\n"
+      "    extensionRegistry));\n");
   } else {
     printer->Print(variables_,
-      "input.readMessage(subBuilder, extensionRegistry);\n");
+      "$name$_.add(input.readMessage($type$.PARSER, extensionRegistry));\n");
   }
+}
 
+void RepeatedMessageFieldGenerator::
+GenerateParsingDoneCode(io::Printer* printer) const {
   printer->Print(variables_,
-    "add$capitalized_name$(subBuilder.buildPartial());\n");
+    "if ($get_mutable_bit_parser$) {\n"
+    "  $name$_ = java.util.Collections.unmodifiableList($name$_);\n"
+    "}\n");
 }
 
 void RepeatedMessageFieldGenerator::
diff --git a/third_party/protobuf/src/google/protobuf/compiler/java/java_message_field.h b/third_party/protobuf/src/google/protobuf/compiler/java/java_message_field.h
index 2efbcd9..5c8078a 100644
--- a/third_party/protobuf/src/google/protobuf/compiler/java/java_message_field.h
+++ b/third_party/protobuf/src/google/protobuf/compiler/java/java_message_field.h
@@ -61,6 +61,7 @@
   void GenerateMergingCode(io::Printer* printer) const;
   void GenerateBuildingCode(io::Printer* printer) const;
   void GenerateParsingCode(io::Printer* printer) const;
+  void GenerateParsingDoneCode(io::Printer* printer) const;
   void GenerateSerializationCode(io::Printer* printer) const;
   void GenerateSerializedSizeCode(io::Printer* printer) const;
   void GenerateFieldBuilderInitializationCode(io::Printer* printer) const;
@@ -102,6 +103,7 @@
   void GenerateMergingCode(io::Printer* printer) const;
   void GenerateBuildingCode(io::Printer* printer) const;
   void GenerateParsingCode(io::Printer* printer) const;
+  void GenerateParsingDoneCode(io::Printer* printer) const;
   void GenerateSerializationCode(io::Printer* printer) const;
   void GenerateSerializedSizeCode(io::Printer* printer) const;
   void GenerateFieldBuilderInitializationCode(io::Printer* printer) const;
diff --git a/third_party/protobuf/src/google/protobuf/compiler/java/java_primitive_field.cc b/third_party/protobuf/src/google/protobuf/compiler/java/java_primitive_field.cc
index 712e047..0140e23 100644
--- a/third_party/protobuf/src/google/protobuf/compiler/java/java_primitive_field.cc
+++ b/third_party/protobuf/src/google/protobuf/compiler/java/java_primitive_field.cc
@@ -36,6 +36,7 @@
 #include <string>
 
 #include <google/protobuf/compiler/java/java_primitive_field.h>
+#include <google/protobuf/compiler/java/java_doc_comment.h>
 #include <google/protobuf/stubs/common.h>
 #include <google/protobuf/compiler/java/java_helpers.h>
 #include <google/protobuf/io/printer.h>
@@ -197,6 +198,7 @@
 
   // For singular messages and builders, one bit is used for the hasField bit.
   (*variables)["get_has_field_bit_message"] = GenerateGetBit(messageBitIndex);
+  (*variables)["set_has_field_bit_message"] = GenerateSetBit(messageBitIndex);
 
   (*variables)["get_has_field_bit_builder"] = GenerateGetBit(builderBitIndex);
   (*variables)["set_has_field_bit_builder"] = GenerateSetBit(builderBitIndex);
@@ -208,6 +210,13 @@
   (*variables)["set_mutable_bit_builder"] = GenerateSetBit(builderBitIndex);
   (*variables)["clear_mutable_bit_builder"] = GenerateClearBit(builderBitIndex);
 
+  // For repeated fields, one bit is used for whether the array is immutable
+  // in the parsing constructor.
+  (*variables)["get_mutable_bit_parser"] =
+      GenerateGetBitMutableLocal(builderBitIndex);
+  (*variables)["set_mutable_bit_parser"] =
+      GenerateSetBitMutableLocal(builderBitIndex);
+
   (*variables)["get_has_field_bit_from_local"] =
       GenerateGetBitFromLocal(builderBitIndex);
   (*variables)["set_has_field_bit_to_local"] =
@@ -240,19 +249,26 @@
 
 void PrimitiveFieldGenerator::
 GenerateInterfaceMembers(io::Printer* printer) const {
+  WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$boolean has$capitalized_name$();\n"
+    "$deprecation$boolean has$capitalized_name$();\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
     "$deprecation$$type$ get$capitalized_name$();\n");
 }
 
 void PrimitiveFieldGenerator::
 GenerateMembers(io::Printer* printer) const {
   printer->Print(variables_,
-    "private $field_type$ $name$_;\n"
+    "private $field_type$ $name$_;\n");
+
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
     "$deprecation$public boolean has$capitalized_name$() {\n"
     "  return $get_has_field_bit_message$;\n"
     "}\n");
 
+  WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
     "$deprecation$public $type$ get$capitalized_name$() {\n"
     "  return $name$_;\n"
@@ -262,16 +278,21 @@
 void PrimitiveFieldGenerator::
 GenerateBuilderMembers(io::Printer* printer) const {
   printer->Print(variables_,
-    "private $field_type$ $name$_ $default_init$;\n"
+    "private $field_type$ $name$_ $default_init$;\n");
+
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
     "$deprecation$public boolean has$capitalized_name$() {\n"
     "  return $get_has_field_bit_builder$;\n"
     "}\n");
 
+  WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
     "$deprecation$public $type$ get$capitalized_name$() {\n"
     "  return $name$_;\n"
     "}\n");
 
+  WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
     "$deprecation$public Builder set$capitalized_name$($type$ value) {\n"
     "$null_check$"
@@ -279,7 +300,10 @@
     "  $name$_ = value;\n"
     "  $on_changed$\n"
     "  return this;\n"
-    "}\n"
+    "}\n");
+
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
     "$deprecation$public Builder clear$capitalized_name$() {\n"
     "  $clear_has_field_bit_builder$;\n");
   JavaType type = GetJavaType(descriptor_);
@@ -335,11 +359,16 @@
 void PrimitiveFieldGenerator::
 GenerateParsingCode(io::Printer* printer) const {
   printer->Print(variables_,
-    "$set_has_field_bit_builder$;\n"
+    "$set_has_field_bit_message$;\n"
     "$name$_ = input.read$capitalized_type$();\n");
 }
 
 void PrimitiveFieldGenerator::
+GenerateParsingDoneCode(io::Printer* printer) const {
+  // noop for primitives.
+}
+
+void PrimitiveFieldGenerator::
 GenerateSerializationCode(io::Printer* printer) const {
   printer->Print(variables_,
     "if ($get_has_field_bit_message$) {\n"
@@ -468,9 +497,14 @@
 
 void RepeatedPrimitiveFieldGenerator::
 GenerateInterfaceMembers(io::Printer* printer) const {
+  WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$java.util.List<$boxed_type$> get$capitalized_name$List();\n"
-    "$deprecation$int get$capitalized_name$Count();\n"
+    "$deprecation$java.util.List<$boxed_type$> get$capitalized_name$List();\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$int get$capitalized_name$Count();\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
     "$deprecation$$type$ get$capitalized_name$(int index);\n");
 }
 
@@ -478,14 +512,20 @@
 void RepeatedPrimitiveFieldGenerator::
 GenerateMembers(io::Printer* printer) const {
   printer->Print(variables_,
-    "private $field_list_type$ $name$_;\n"
+    "private $field_list_type$ $name$_;\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
     "$deprecation$public java.util.List<$boxed_type$>\n"
     "    get$capitalized_name$List() {\n"
     "  return $name$_;\n"   // note:  unmodifiable list
-    "}\n"
+    "}\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
     "$deprecation$public int get$capitalized_name$Count() {\n"
     "  return $name$_.size();\n"
-    "}\n"
+    "}\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
     "$deprecation$public $type$ get$capitalized_name$(int index) {\n"
     "  return $name$_.get(index);\n"
     "}\n");
@@ -523,17 +563,24 @@
     //   could hold on to the returned list and modify it after the message
     //   has been built, thus mutating the message which is supposed to be
     //   immutable.
+  WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
     "$deprecation$public java.util.List<$boxed_type$>\n"
     "    get$capitalized_name$List() {\n"
     "  return java.util.Collections.unmodifiableList($name$_);\n"
-    "}\n"
+    "}\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
     "$deprecation$public int get$capitalized_name$Count() {\n"
     "  return $name$_.size();\n"
-    "}\n"
+    "}\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
     "$deprecation$public $type$ get$capitalized_name$(int index) {\n"
     "  return $name$_.get(index);\n"
-    "}\n"
+    "}\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
     "$deprecation$public Builder set$capitalized_name$(\n"
     "    int index, $type$ value) {\n"
     "$null_check$"
@@ -541,21 +588,27 @@
     "  $name$_.set(index, value);\n"
     "  $on_changed$\n"
     "  return this;\n"
-    "}\n"
+    "}\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
     "$deprecation$public Builder add$capitalized_name$($type$ value) {\n"
     "$null_check$"
     "  ensure$capitalized_name$IsMutable();\n"
     "  $name$_.add(value);\n"
     "  $on_changed$\n"
     "  return this;\n"
-    "}\n"
+    "}\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
     "$deprecation$public Builder addAll$capitalized_name$(\n"
     "    java.lang.Iterable<? extends $boxed_type$> values) {\n"
     "  ensure$capitalized_name$IsMutable();\n"
     "  super.addAll(values, $name$_);\n"
     "  $on_changed$\n"
     "  return this;\n"
-    "}\n"
+    "}\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
     "$deprecation$public Builder clear$capitalized_name$() {\n"
     "  $name$_ = $empty_list$;\n"
     "  $clear_mutable_bit_builder$;\n"
@@ -616,7 +669,10 @@
 void RepeatedPrimitiveFieldGenerator::
 GenerateParsingCode(io::Printer* printer) const {
   printer->Print(variables_,
-    "ensure$capitalized_name$IsMutable();\n"
+    "if (!$get_mutable_bit_parser$) {\n"
+    "  $name$_ = new java.util.ArrayList<$boxed_type$>();\n"
+    "  $set_mutable_bit_parser$;\n"
+    "}\n"
     "$name$_.add(input.read$capitalized_type$());\n");
 }
 
@@ -625,13 +681,25 @@
   printer->Print(variables_,
     "int length = input.readRawVarint32();\n"
     "int limit = input.pushLimit(length);\n"
+    "if (!$get_mutable_bit_parser$ && input.getBytesUntilLimit() > 0) {\n"
+    "  $name$_ = new java.util.ArrayList<$boxed_type$>();\n"
+    "  $set_mutable_bit_parser$;\n"
+    "}\n"
     "while (input.getBytesUntilLimit() > 0) {\n"
-    "  add$capitalized_name$(input.read$capitalized_type$());\n"
+    "  $name$_.add(input.read$capitalized_type$());\n"
     "}\n"
     "input.popLimit(limit);\n");
 }
 
 void RepeatedPrimitiveFieldGenerator::
+GenerateParsingDoneCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "if ($get_mutable_bit_parser$) {\n"
+    "  $name$_ = java.util.Collections.unmodifiableList($name$_);\n"
+    "}\n");
+}
+
+void RepeatedPrimitiveFieldGenerator::
 GenerateSerializationCode(io::Printer* printer) const {
   if (descriptor_->options().packed()) {
     printer->Print(variables_,
diff --git a/third_party/protobuf/src/google/protobuf/compiler/java/java_primitive_field.h b/third_party/protobuf/src/google/protobuf/compiler/java/java_primitive_field.h
index 7900fac..1b5b6d9 100644
--- a/third_party/protobuf/src/google/protobuf/compiler/java/java_primitive_field.h
+++ b/third_party/protobuf/src/google/protobuf/compiler/java/java_primitive_field.h
@@ -61,6 +61,7 @@
   void GenerateMergingCode(io::Printer* printer) const;
   void GenerateBuildingCode(io::Printer* printer) const;
   void GenerateParsingCode(io::Printer* printer) const;
+  void GenerateParsingDoneCode(io::Printer* printer) const;
   void GenerateSerializationCode(io::Printer* printer) const;
   void GenerateSerializedSizeCode(io::Printer* printer) const;
   void GenerateFieldBuilderInitializationCode(io::Printer* printer) const;
@@ -96,6 +97,7 @@
   void GenerateBuildingCode(io::Printer* printer) const;
   void GenerateParsingCode(io::Printer* printer) const;
   void GenerateParsingCodeFromPacked(io::Printer* printer) const;
+  void GenerateParsingDoneCode(io::Printer* printer) const;
   void GenerateSerializationCode(io::Printer* printer) const;
   void GenerateSerializedSizeCode(io::Printer* printer) const;
   void GenerateFieldBuilderInitializationCode(io::Printer* printer) const;
diff --git a/third_party/protobuf/src/google/protobuf/compiler/java/java_service.cc b/third_party/protobuf/src/google/protobuf/compiler/java/java_service.cc
index 2d85b7a..bcd8035 100644
--- a/third_party/protobuf/src/google/protobuf/compiler/java/java_service.cc
+++ b/third_party/protobuf/src/google/protobuf/compiler/java/java_service.cc
@@ -33,6 +33,7 @@
 //  Sanjay Ghemawat, Jeff Dean, and others.
 
 #include <google/protobuf/compiler/java/java_service.h>
+#include <google/protobuf/compiler/java/java_doc_comment.h>
 #include <google/protobuf/compiler/java/java_helpers.h>
 #include <google/protobuf/io/printer.h>
 #include <google/protobuf/descriptor.pb.h>
@@ -50,6 +51,7 @@
 
 void ServiceGenerator::Generate(io::Printer* printer) {
   bool is_own_file = descriptor_->file()->options().java_multiple_files();
+  WriteServiceDocComment(printer, descriptor_);
   printer->Print(
     "public $static$ abstract class $classname$\n"
     "    implements com.google.protobuf.Service {\n",
@@ -163,6 +165,7 @@
 void ServiceGenerator::GenerateAbstractMethods(io::Printer* printer) {
   for (int i = 0; i < descriptor_->method_count(); i++) {
     const MethodDescriptor* method = descriptor_->method(i);
+    WriteMethodDocComment(printer, method);
     GenerateMethodSignature(printer, method, IS_ABSTRACT);
     printer->Print(";\n\n");
   }
diff --git a/third_party/protobuf/src/google/protobuf/compiler/java/java_string_field.cc b/third_party/protobuf/src/google/protobuf/compiler/java/java_string_field.cc
index 222285b..4815663 100644
--- a/third_party/protobuf/src/google/protobuf/compiler/java/java_string_field.cc
+++ b/third_party/protobuf/src/google/protobuf/compiler/java/java_string_field.cc
@@ -37,6 +37,7 @@
 #include <string>
 
 #include <google/protobuf/compiler/java/java_string_field.h>
+#include <google/protobuf/compiler/java/java_doc_comment.h>
 #include <google/protobuf/stubs/common.h>
 #include <google/protobuf/compiler/java/java_helpers.h>
 #include <google/protobuf/io/printer.h>
@@ -85,6 +86,7 @@
 
   // For singular messages and builders, one bit is used for the hasField bit.
   (*variables)["get_has_field_bit_message"] = GenerateGetBit(messageBitIndex);
+  (*variables)["set_has_field_bit_message"] = GenerateSetBit(messageBitIndex);
 
   (*variables)["get_has_field_bit_builder"] = GenerateGetBit(builderBitIndex);
   (*variables)["set_has_field_bit_builder"] = GenerateSetBit(builderBitIndex);
@@ -96,6 +98,13 @@
   (*variables)["set_mutable_bit_builder"] = GenerateSetBit(builderBitIndex);
   (*variables)["clear_mutable_bit_builder"] = GenerateClearBit(builderBitIndex);
 
+  // For repeated fields, one bit is used for whether the array is immutable
+  // in the parsing constructor.
+  (*variables)["get_mutable_bit_parser"] =
+      GenerateGetBitMutableLocal(builderBitIndex);
+  (*variables)["set_mutable_bit_parser"] =
+      GenerateSetBitMutableLocal(builderBitIndex);
+
   (*variables)["get_has_field_bit_from_local"] =
       GenerateGetBitFromLocal(builderBitIndex);
   (*variables)["set_has_field_bit_to_local"] =
@@ -160,19 +169,29 @@
 // UnmodifiableLazyStringList.
 void StringFieldGenerator::
 GenerateInterfaceMembers(io::Printer* printer) const {
+  WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$boolean has$capitalized_name$();\n"
+    "$deprecation$boolean has$capitalized_name$();\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
     "$deprecation$java.lang.String get$capitalized_name$();\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$com.google.protobuf.ByteString\n"
+    "    get$capitalized_name$Bytes();\n");
 }
 
 void StringFieldGenerator::
 GenerateMembers(io::Printer* printer) const {
   printer->Print(variables_,
-    "private java.lang.Object $name$_;\n"
+    "private java.lang.Object $name$_;\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
     "$deprecation$public boolean has$capitalized_name$() {\n"
     "  return $get_has_field_bit_message$;\n"
     "}\n");
 
+  WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
     "$deprecation$public java.lang.String get$capitalized_name$() {\n"
     "  java.lang.Object ref = $name$_;\n"
@@ -182,13 +201,16 @@
     "    com.google.protobuf.ByteString bs = \n"
     "        (com.google.protobuf.ByteString) ref;\n"
     "    java.lang.String s = bs.toStringUtf8();\n"
-    "    if (com.google.protobuf.Internal.isValidUtf8(bs)) {\n"
+    "    if (bs.isValidUtf8()) {\n"
     "      $name$_ = s;\n"
     "    }\n"
     "    return s;\n"
     "  }\n"
-    "}\n"
-    "private com.google.protobuf.ByteString get$capitalized_name$Bytes() {\n"
+    "}\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public com.google.protobuf.ByteString\n"
+    "    get$capitalized_name$Bytes() {\n"
     "  java.lang.Object ref = $name$_;\n"
     "  if (ref instanceof java.lang.String) {\n"
     "    com.google.protobuf.ByteString b = \n"
@@ -205,11 +227,14 @@
 void StringFieldGenerator::
 GenerateBuilderMembers(io::Printer* printer) const {
   printer->Print(variables_,
-    "private java.lang.Object $name$_ $default_init$;\n"
+    "private java.lang.Object $name$_ $default_init$;\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
     "$deprecation$public boolean has$capitalized_name$() {\n"
     "  return $get_has_field_bit_builder$;\n"
     "}\n");
 
+  WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
     "$deprecation$public java.lang.String get$capitalized_name$() {\n"
     "  java.lang.Object ref = $name$_;\n"
@@ -223,6 +248,23 @@
     "  }\n"
     "}\n");
 
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public com.google.protobuf.ByteString\n"
+    "    get$capitalized_name$Bytes() {\n"
+    "  java.lang.Object ref = $name$_;\n"
+    "  if (ref instanceof String) {\n"
+    "    com.google.protobuf.ByteString b = \n"
+    "        com.google.protobuf.ByteString.copyFromUtf8(\n"
+    "            (java.lang.String) ref);\n"
+    "    $name$_ = b;\n"
+    "    return b;\n"
+    "  } else {\n"
+    "    return (com.google.protobuf.ByteString) ref;\n"
+    "  }\n"
+    "}\n");
+
+  WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
     "$deprecation$public Builder set$capitalized_name$(\n"
     "    java.lang.String value) {\n"
@@ -231,7 +273,9 @@
     "  $name$_ = value;\n"
     "  $on_changed$\n"
     "  return this;\n"
-    "}\n"
+    "}\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
     "$deprecation$public Builder clear$capitalized_name$() {\n"
     "  $clear_has_field_bit_builder$;\n");
   // The default value is not a simple literal so we want to avoid executing
@@ -243,11 +287,15 @@
     "  return this;\n"
     "}\n");
 
+  WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "void set$capitalized_name$(com.google.protobuf.ByteString value) {\n"
+    "$deprecation$public Builder set$capitalized_name$Bytes(\n"
+    "    com.google.protobuf.ByteString value) {\n"
+    "$null_check$"
     "  $set_has_field_bit_builder$;\n"
     "  $name$_ = value;\n"
     "  $on_changed$\n"
+    "  return this;\n"
     "}\n");
 }
 
@@ -270,9 +318,13 @@
 
 void StringFieldGenerator::
 GenerateMergingCode(io::Printer* printer) const {
+  // Allow a slight breach of abstraction here in order to avoid forcing
+  // all string fields to Strings when copying fields from a Message.
   printer->Print(variables_,
     "if (other.has$capitalized_name$()) {\n"
-    "  set$capitalized_name$(other.get$capitalized_name$());\n"
+    "  $set_has_field_bit_builder$;\n"
+    "  $name$_ = other.$name$_;\n"
+    "  $on_changed$\n"
     "}\n");
 }
 
@@ -288,11 +340,16 @@
 void StringFieldGenerator::
 GenerateParsingCode(io::Printer* printer) const {
   printer->Print(variables_,
-    "$set_has_field_bit_builder$;\n"
+    "$set_has_field_bit_message$;\n"
     "$name$_ = input.readBytes();\n");
 }
 
 void StringFieldGenerator::
+GenerateParsingDoneCode(io::Printer* printer) const {
+  // noop for strings.
+}
+
+void StringFieldGenerator::
 GenerateSerializationCode(io::Printer* printer) const {
   printer->Print(variables_,
     "if ($get_has_field_bit_message$) {\n"
@@ -353,28 +410,49 @@
 
 void RepeatedStringFieldGenerator::
 GenerateInterfaceMembers(io::Printer* printer) const {
+  WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
     "$deprecation$java.util.List<java.lang.String>\n"
-    "    get$capitalized_name$List();\n"
-    "$deprecation$int get$capitalized_name$Count();\n"
+    "get$capitalized_name$List();\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$int get$capitalized_name$Count();\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
     "$deprecation$java.lang.String get$capitalized_name$(int index);\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$com.google.protobuf.ByteString\n"
+    "    get$capitalized_name$Bytes(int index);\n");
 }
 
 
 void RepeatedStringFieldGenerator::
 GenerateMembers(io::Printer* printer) const {
   printer->Print(variables_,
-    "private com.google.protobuf.LazyStringList $name$_;\n"
+    "private com.google.protobuf.LazyStringList $name$_;\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
     "$deprecation$public java.util.List<java.lang.String>\n"
     "    get$capitalized_name$List() {\n"
     "  return $name$_;\n"   // note:  unmodifiable list
-    "}\n"
+    "}\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
     "$deprecation$public int get$capitalized_name$Count() {\n"
     "  return $name$_.size();\n"
-    "}\n"
+    "}\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
     "$deprecation$public java.lang.String get$capitalized_name$(int index) {\n"
     "  return $name$_.get(index);\n"
     "}\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public com.google.protobuf.ByteString\n"
+    "    get$capitalized_name$Bytes(int index) {\n"
+    "  return $name$_.getByteString(index);\n"
+    "}\n");
 
   if (descriptor_->options().packed() &&
       HasGeneratedMethods(descriptor_->containing_type())) {
@@ -409,17 +487,30 @@
     //   could hold on to the returned list and modify it after the message
     //   has been built, thus mutating the message which is supposed to be
     //   immutable.
+  WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
     "$deprecation$public java.util.List<java.lang.String>\n"
     "    get$capitalized_name$List() {\n"
     "  return java.util.Collections.unmodifiableList($name$_);\n"
-    "}\n"
+    "}\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
     "$deprecation$public int get$capitalized_name$Count() {\n"
     "  return $name$_.size();\n"
-    "}\n"
+    "}\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
     "$deprecation$public java.lang.String get$capitalized_name$(int index) {\n"
     "  return $name$_.get(index);\n"
-    "}\n"
+    "}\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public com.google.protobuf.ByteString\n"
+    "    get$capitalized_name$Bytes(int index) {\n"
+    "  return $name$_.getByteString(index);\n"
+    "}\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
     "$deprecation$public Builder set$capitalized_name$(\n"
     "    int index, java.lang.String value) {\n"
     "$null_check$"
@@ -427,7 +518,9 @@
     "  $name$_.set(index, value);\n"
     "  $on_changed$\n"
     "  return this;\n"
-    "}\n"
+    "}\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
     "$deprecation$public Builder add$capitalized_name$(\n"
     "    java.lang.String value) {\n"
     "$null_check$"
@@ -435,14 +528,18 @@
     "  $name$_.add(value);\n"
     "  $on_changed$\n"
     "  return this;\n"
-    "}\n"
+    "}\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
     "$deprecation$public Builder addAll$capitalized_name$(\n"
     "    java.lang.Iterable<java.lang.String> values) {\n"
     "  ensure$capitalized_name$IsMutable();\n"
     "  super.addAll(values, $name$_);\n"
     "  $on_changed$\n"
     "  return this;\n"
-    "}\n"
+    "}\n");
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
     "$deprecation$public Builder clear$capitalized_name$() {\n"
     "  $name$_ = $empty_list$;\n"
     "  $clear_mutable_bit_builder$;\n"
@@ -450,11 +547,15 @@
     "  return this;\n"
     "}\n");
 
+  WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "void add$capitalized_name$(com.google.protobuf.ByteString value) {\n"
+    "$deprecation$public Builder add$capitalized_name$Bytes(\n"
+    "    com.google.protobuf.ByteString value) {\n"
+    "$null_check$"
     "  ensure$capitalized_name$IsMutable();\n"
     "  $name$_.add(value);\n"
     "  $on_changed$\n"
+    "  return this;\n"
     "}\n");
 }
 
@@ -512,7 +613,10 @@
 void RepeatedStringFieldGenerator::
 GenerateParsingCode(io::Printer* printer) const {
   printer->Print(variables_,
-    "ensure$capitalized_name$IsMutable();\n"
+    "if (!$get_mutable_bit_parser$) {\n"
+    "  $name$_ = new com.google.protobuf.LazyStringArrayList();\n"
+    "  $set_mutable_bit_parser$;\n"
+    "}\n"
     "$name$_.add(input.readBytes());\n");
 }
 
@@ -521,13 +625,25 @@
   printer->Print(variables_,
     "int length = input.readRawVarint32();\n"
     "int limit = input.pushLimit(length);\n"
+    "if (!$get_mutable_bit_parser$ && input.getBytesUntilLimit() > 0) {\n"
+    "  $name$_ = new com.google.protobuf.LazyStringArrayList();\n"
+    "  $set_mutable_bit_parser$;\n"
+    "}\n"
     "while (input.getBytesUntilLimit() > 0) {\n"
-    "  add$capitalized_name$(input.read$capitalized_type$());\n"
+    "  $name$.add(input.read$capitalized_type$());\n"
     "}\n"
     "input.popLimit(limit);\n");
 }
 
 void RepeatedStringFieldGenerator::
+GenerateParsingDoneCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "if ($get_mutable_bit_parser$) {\n"
+    "  $name$_ = new com.google.protobuf.UnmodifiableLazyStringList($name$_);\n"
+    "}\n");
+}
+
+void RepeatedStringFieldGenerator::
 GenerateSerializationCode(io::Printer* printer) const {
   if (descriptor_->options().packed()) {
     printer->Print(variables_,
diff --git a/third_party/protobuf/src/google/protobuf/compiler/java/java_string_field.h b/third_party/protobuf/src/google/protobuf/compiler/java/java_string_field.h
index 8cb4146..4f7532f 100644
--- a/third_party/protobuf/src/google/protobuf/compiler/java/java_string_field.h
+++ b/third_party/protobuf/src/google/protobuf/compiler/java/java_string_field.h
@@ -62,6 +62,7 @@
   void GenerateMergingCode(io::Printer* printer) const;
   void GenerateBuildingCode(io::Printer* printer) const;
   void GenerateParsingCode(io::Printer* printer) const;
+  void GenerateParsingDoneCode(io::Printer* printer) const;
   void GenerateSerializationCode(io::Printer* printer) const;
   void GenerateSerializedSizeCode(io::Printer* printer) const;
   void GenerateFieldBuilderInitializationCode(io::Printer* printer) const;
@@ -96,6 +97,7 @@
   void GenerateBuildingCode(io::Printer* printer) const;
   void GenerateParsingCode(io::Printer* printer) const;
   void GenerateParsingCodeFromPacked(io::Printer* printer) const;
+  void GenerateParsingDoneCode(io::Printer* printer) const;
   void GenerateSerializationCode(io::Printer* printer) const;
   void GenerateSerializedSizeCode(io::Printer* printer) const;
   void GenerateFieldBuilderInitializationCode(io::Printer* printer) const;
diff --git a/third_party/protobuf/src/google/protobuf/compiler/main.cc b/third_party/protobuf/src/google/protobuf/compiler/main.cc
index d9b0c3f..1afc5d6 100644
--- a/third_party/protobuf/src/google/protobuf/compiler/main.cc
+++ b/third_party/protobuf/src/google/protobuf/compiler/main.cc
@@ -43,7 +43,7 @@
 
   // Proto2 C++
   google::protobuf::compiler::cpp::CppGenerator cpp_generator;
-  cli.RegisterGenerator("--cpp_out", &cpp_generator,
+  cli.RegisterGenerator("--cpp_out", "--cpp_opt", &cpp_generator,
                         "Generate C++ header and source.");
 
   // Proto2 Java
diff --git a/third_party/protobuf/src/google/protobuf/compiler/mock_code_generator.cc b/third_party/protobuf/src/google/protobuf/compiler/mock_code_generator.cc
index 5b76af2..0e35ed1 100644
--- a/third_party/protobuf/src/google/protobuf/compiler/mock_code_generator.cc
+++ b/third_party/protobuf/src/google/protobuf/compiler/mock_code_generator.cc
@@ -33,13 +33,14 @@
 #include <google/protobuf/compiler/mock_code_generator.h>
 
 #include <google/protobuf/testing/file.h>
+#include <google/protobuf/descriptor.pb.h>
 #include <google/protobuf/descriptor.h>
 #include <google/protobuf/io/zero_copy_stream.h>
 #include <google/protobuf/io/printer.h>
 #include <google/protobuf/stubs/strutil.h>
 #include <google/protobuf/stubs/substitute.h>
 #include <gtest/gtest.h>
-#include <google/protobuf/stubs/stl_util-inl.h>
+#include <google/protobuf/stubs/stl_util.h>
 
 namespace google {
 namespace protobuf {
@@ -132,6 +133,15 @@
       } else if (command == "Abort") {
         cerr << "Saw message type MockCodeGenerator_Abort." << endl;
         abort();
+      } else if (command == "HasSourceCodeInfo") {
+        FileDescriptorProto file_descriptor_proto;
+        file->CopySourceCodeInfoTo(&file_descriptor_proto);
+        bool has_source_code_info =
+            file_descriptor_proto.has_source_code_info() &&
+            file_descriptor_proto.source_code_info().location_size() > 0;
+        cerr << "Saw message type MockCodeGenerator_HasSourceCodeInfo: "
+             << has_source_code_info << "." << endl;
+        abort();
       } else {
         GOOGLE_LOG(FATAL) << "Unknown MockCodeGenerator command: " << command;
       }
diff --git a/third_party/protobuf/src/google/protobuf/compiler/mock_code_generator.h b/third_party/protobuf/src/google/protobuf/compiler/mock_code_generator.h
index 5c7942b..506fd20 100644
--- a/third_party/protobuf/src/google/protobuf/compiler/mock_code_generator.h
+++ b/third_party/protobuf/src/google/protobuf/compiler/mock_code_generator.h
@@ -59,6 +59,10 @@
 //     MockCodeGenerator_Exit." to stderr and then calls exit(123).
 //   MockCodeGenerator_Abort:  Generate() prints "Saw message type
 //     MockCodeGenerator_Abort." to stderr and then calls abort().
+//   MockCodeGenerator_HasSourceCodeInfo:  Causes Generate() to abort after
+//     printing "Saw message type MockCodeGenerator_HasSourceCodeInfo: FOO." to
+//     stderr, where FOO is "1" if the supplied FileDescriptorProto has source
+//     code info, and "0" otherwise.
 class MockCodeGenerator : public CodeGenerator {
  public:
   MockCodeGenerator(const string& name);
diff --git a/third_party/protobuf/src/google/protobuf/compiler/parser.cc b/third_party/protobuf/src/google/protobuf/compiler/parser.cc
index 34317b1..23aa01c 100644
--- a/third_party/protobuf/src/google/protobuf/compiler/parser.cc
+++ b/third_party/protobuf/src/google/protobuf/compiler/parser.cc
@@ -174,6 +174,20 @@
   }
 }
 
+bool Parser::ConsumeSignedInteger(int* output, const char* error) {
+  bool is_negative = false;
+  uint64 max_value = kint32max;
+  if (TryConsume("-")) {
+    is_negative = true;
+    max_value += 1;
+  }
+  uint64 value = 0;
+  DO(ConsumeInteger64(max_value, &value, error));
+  if (is_negative) value *= -1;
+  *output = value;
+  return true;
+}
+
 bool Parser::ConsumeInteger64(uint64 max_value, uint64* output,
                               const char* error) {
   if (LookingAtType(io::Tokenizer::TYPE_INTEGER)) {
@@ -237,6 +251,35 @@
   }
 }
 
+bool Parser::TryConsumeEndOfDeclaration(const char* text,
+                                        const LocationRecorder* location) {
+  if (LookingAt(text)) {
+    string leading, trailing;
+    input_->NextWithComments(&trailing, NULL, &leading);
+
+    // Save the leading comments for next time, and recall the leading comments
+    // from last time.
+    leading.swap(upcoming_doc_comments_);
+
+    if (location != NULL) {
+      location->AttachComments(&leading, &trailing);
+    }
+    return true;
+  } else {
+    return false;
+  }
+}
+
+bool Parser::ConsumeEndOfDeclaration(const char* text,
+                                     const LocationRecorder* location) {
+  if (TryConsumeEndOfDeclaration(text, location)) {
+    return true;
+  } else {
+    AddError("Expected \"" + string(text) + "\".");
+    return false;
+  }
+}
+
 // -------------------------------------------------------------------
 
 void Parser::AddError(int line, int column, const string& error) {
@@ -315,6 +358,19 @@
   }
 }
 
+void Parser::LocationRecorder::AttachComments(
+    string* leading, string* trailing) const {
+  GOOGLE_CHECK(!location_->has_leading_comments());
+  GOOGLE_CHECK(!location_->has_trailing_comments());
+
+  if (!leading->empty()) {
+    location_->mutable_leading_comments()->swap(*leading);
+  }
+  if (!trailing->empty()) {
+    location_->mutable_trailing_comments()->swap(*trailing);
+  }
+}
+
 // -------------------------------------------------------------------
 
 void Parser::SkipStatement() {
@@ -322,7 +378,7 @@
     if (AtEnd()) {
       return;
     } else if (LookingAtType(io::Tokenizer::TYPE_SYMBOL)) {
-      if (TryConsume(";")) {
+      if (TryConsumeEndOfDeclaration(";", NULL)) {
         return;
       } else if (TryConsume("{")) {
         SkipRestOfBlock();
@@ -340,7 +396,7 @@
     if (AtEnd()) {
       return;
     } else if (LookingAtType(io::Tokenizer::TYPE_SYMBOL)) {
-      if (TryConsume("}")) {
+      if (TryConsumeEndOfDeclaration("}", NULL)) {
         return;
       } else if (TryConsume("{")) {
         SkipRestOfBlock();
@@ -366,7 +422,7 @@
 
   if (LookingAtType(io::Tokenizer::TYPE_START)) {
     // Advance to first token.
-    input_->Next();
+    input_->NextWithComments(NULL, NULL, &upcoming_doc_comments_);
   }
 
   {
@@ -393,7 +449,7 @@
 
         if (LookingAt("}")) {
           AddError("Unmatched \"}\".");
-          input_->Next();
+          input_->NextWithComments(NULL, NULL, &upcoming_doc_comments_);
         }
       }
     }
@@ -411,7 +467,7 @@
   io::Tokenizer::Token syntax_token = input_->current();
   string syntax;
   DO(ConsumeString(&syntax, "Expected syntax identifier."));
-  DO(Consume(";"));
+  DO(ConsumeEndOfDeclaration(";", NULL));
 
   syntax_identifier_ = syntax;
 
@@ -427,7 +483,7 @@
 
 bool Parser::ParseTopLevelStatement(FileDescriptorProto* file,
                                     const LocationRecorder& root_location) {
-  if (TryConsume(";")) {
+  if (TryConsumeEndOfDeclaration(";", NULL)) {
     // empty statement; ignore
     return true;
   } else if (LookingAt("message")) {
@@ -451,14 +507,16 @@
                        FileDescriptorProto::kMessageTypeFieldNumber,
                        location);
   } else if (LookingAt("import")) {
-    int index = file->dependency_size();
-    return ParseImport(file->add_dependency(), root_location, index);
+    return ParseImport(file->mutable_dependency(),
+                       file->mutable_public_dependency(),
+                       file->mutable_weak_dependency(),
+                       root_location);
   } else if (LookingAt("package")) {
     return ParsePackage(file, root_location);
   } else if (LookingAt("option")) {
     LocationRecorder location(root_location,
         FileDescriptorProto::kOptionsFieldNumber);
-    return ParseOption(file->mutable_options(), location);
+    return ParseOption(file->mutable_options(), location, OPTION_STATEMENT);
   } else {
     AddError("Expected top-level statement (e.g. \"message\").");
     return false;
@@ -482,11 +540,45 @@
   return true;
 }
 
+namespace {
+
+const int kMaxExtensionRangeSentinel = -1;
+
+bool IsMessageSetWireFormatMessage(const DescriptorProto& message) {
+  const MessageOptions& options = message.options();
+  for (int i = 0; i < options.uninterpreted_option_size(); ++i) {
+    const UninterpretedOption& uninterpreted = options.uninterpreted_option(i);
+    if (uninterpreted.name_size() == 1 &&
+        uninterpreted.name(0).name_part() == "message_set_wire_format" &&
+        uninterpreted.identifier_value() == "true") {
+      return true;
+    }
+  }
+  return false;
+}
+
+// Modifies any extension ranges that specified 'max' as the end of the
+// extension range, and sets them to the type-specific maximum. The actual max
+// tag number can only be determined after all options have been parsed.
+void AdjustExtensionRangesWithMaxEndNumber(DescriptorProto* message) {
+  const bool is_message_set = IsMessageSetWireFormatMessage(*message);
+  const int max_extension_number = is_message_set ?
+      kint32max :
+      FieldDescriptor::kMaxNumber + 1;
+  for (int i = 0; i < message->extension_range_size(); ++i) {
+    if (message->extension_range(i).end() == kMaxExtensionRangeSentinel) {
+      message->mutable_extension_range(i)->set_end(max_extension_number);
+    }
+  }
+}
+
+}  // namespace
+
 bool Parser::ParseMessageBlock(DescriptorProto* message,
                                const LocationRecorder& message_location) {
-  DO(Consume("{"));
+  DO(ConsumeEndOfDeclaration("{", &message_location));
 
-  while (!TryConsume("}")) {
+  while (!TryConsumeEndOfDeclaration("}", NULL)) {
     if (AtEnd()) {
       AddError("Reached end of input in message definition (missing '}').");
       return false;
@@ -499,12 +591,15 @@
     }
   }
 
+  if (message->extension_range_size() > 0) {
+    AdjustExtensionRangesWithMaxEndNumber(message);
+  }
   return true;
 }
 
 bool Parser::ParseMessageStatement(DescriptorProto* message,
                                    const LocationRecorder& message_location) {
-  if (TryConsume(";")) {
+  if (TryConsumeEndOfDeclaration(";", NULL)) {
     // empty statement; ignore
     return true;
   } else if (LookingAt("message")) {
@@ -532,7 +627,7 @@
   } else if (LookingAt("option")) {
     LocationRecorder location(message_location,
                               DescriptorProto::kOptionsFieldNumber);
-    return ParseOption(message->mutable_options(), location);
+    return ParseOption(message->mutable_options(), location, OPTION_STATEMENT);
   } else {
     LocationRecorder location(message_location,
                               DescriptorProto::kFieldFieldNumber,
@@ -647,7 +742,7 @@
       return false;
     }
   } else {
-    DO(Consume(";"));
+    DO(ConsumeEndOfDeclaration(";", &field_location));
   }
 
   return true;
@@ -669,7 +764,7 @@
       // the default value is not actually an option.
       DO(ParseDefaultAssignment(field, field_location));
     } else {
-      DO(ParseOptionAssignment(field->mutable_options(), location));
+      DO(ParseOption(field->mutable_options(), location, OPTION_ASSIGNMENT));
     }
   } while (TryConsume(","));
 
@@ -835,6 +930,8 @@
 
 bool Parser::ParseUninterpretedBlock(string* value) {
   // Note that enclosing braces are not added to *value.
+  // We do NOT use ConsumeEndOfStatement for this brace because it's delimiting
+  // an expression, not a block of statements.
   DO(Consume("{"));
   int brace_depth = 1;
   while (!AtEnd()) {
@@ -858,8 +955,9 @@
 
 // We don't interpret the option here. Instead we store it in an
 // UninterpretedOption, to be interpreted later.
-bool Parser::ParseOptionAssignment(Message* options,
-                                   const LocationRecorder& options_location) {
+bool Parser::ParseOption(Message* options,
+                         const LocationRecorder& options_location,
+                         OptionStyle style) {
   // Create an entry in the uninterpreted_option field.
   const FieldDescriptor* uninterpreted_option_field = options->GetDescriptor()->
       FindFieldByName("uninterpreted_option");
@@ -872,6 +970,10 @@
       options_location, uninterpreted_option_field->number(),
       reflection->FieldSize(*options, uninterpreted_option_field));
 
+  if (style == OPTION_STATEMENT) {
+    DO(Consume("option"));
+  }
+
   UninterpretedOption* uninterpreted_option = down_cast<UninterpretedOption*>(
       options->GetReflection()->AddMessage(options,
                                            uninterpreted_option_field));
@@ -899,82 +1001,91 @@
 
   DO(Consume("="));
 
-  LocationRecorder value_location(location);
-  value_location.RecordLegacyLocation(
-      uninterpreted_option, DescriptorPool::ErrorCollector::OPTION_VALUE);
+  {
+    LocationRecorder value_location(location);
+    value_location.RecordLegacyLocation(
+        uninterpreted_option, DescriptorPool::ErrorCollector::OPTION_VALUE);
 
-  // All values are a single token, except for negative numbers, which consist
-  // of a single '-' symbol, followed by a positive number.
-  bool is_negative = TryConsume("-");
+    // All values are a single token, except for negative numbers, which consist
+    // of a single '-' symbol, followed by a positive number.
+    bool is_negative = TryConsume("-");
 
-  switch (input_->current().type) {
-    case io::Tokenizer::TYPE_START:
-      GOOGLE_LOG(FATAL) << "Trying to read value before any tokens have been read.";
-      return false;
-
-    case io::Tokenizer::TYPE_END:
-      AddError("Unexpected end of stream while parsing option value.");
-      return false;
-
-    case io::Tokenizer::TYPE_IDENTIFIER: {
-      value_location.AddPath(UninterpretedOption::kIdentifierValueFieldNumber);
-      if (is_negative) {
-        AddError("Invalid '-' symbol before identifier.");
+    switch (input_->current().type) {
+      case io::Tokenizer::TYPE_START:
+        GOOGLE_LOG(FATAL) << "Trying to read value before any tokens have been read.";
         return false;
-      }
-      string value;
-      DO(ConsumeIdentifier(&value, "Expected identifier."));
-      uninterpreted_option->set_identifier_value(value);
-      break;
-    }
 
-    case io::Tokenizer::TYPE_INTEGER: {
-      uint64 value;
-      uint64 max_value =
-          is_negative ? static_cast<uint64>(kint64max) + 1 : kuint64max;
-      DO(ConsumeInteger64(max_value, &value, "Expected integer."));
-      if (is_negative) {
+      case io::Tokenizer::TYPE_END:
+        AddError("Unexpected end of stream while parsing option value.");
+        return false;
+
+      case io::Tokenizer::TYPE_IDENTIFIER: {
         value_location.AddPath(
-            UninterpretedOption::kNegativeIntValueFieldNumber);
-        uninterpreted_option->set_negative_int_value(-static_cast<int64>(value));
-      } else {
-        value_location.AddPath(
-            UninterpretedOption::kPositiveIntValueFieldNumber);
-        uninterpreted_option->set_positive_int_value(value);
+            UninterpretedOption::kIdentifierValueFieldNumber);
+        if (is_negative) {
+          AddError("Invalid '-' symbol before identifier.");
+          return false;
+        }
+        string value;
+        DO(ConsumeIdentifier(&value, "Expected identifier."));
+        uninterpreted_option->set_identifier_value(value);
+        break;
       }
-      break;
-    }
 
-    case io::Tokenizer::TYPE_FLOAT: {
-      value_location.AddPath(UninterpretedOption::kDoubleValueFieldNumber);
-      double value;
-      DO(ConsumeNumber(&value, "Expected number."));
-      uninterpreted_option->set_double_value(is_negative ? -value : value);
-      break;
-    }
-
-    case io::Tokenizer::TYPE_STRING: {
-      value_location.AddPath(UninterpretedOption::kStringValueFieldNumber);
-      if (is_negative) {
-        AddError("Invalid '-' symbol before string.");
-        return false;
+      case io::Tokenizer::TYPE_INTEGER: {
+        uint64 value;
+        uint64 max_value =
+            is_negative ? static_cast<uint64>(kint64max) + 1 : kuint64max;
+        DO(ConsumeInteger64(max_value, &value, "Expected integer."));
+        if (is_negative) {
+          value_location.AddPath(
+              UninterpretedOption::kNegativeIntValueFieldNumber);
+          uninterpreted_option->set_negative_int_value(
+              -static_cast<int64>(value));
+        } else {
+          value_location.AddPath(
+              UninterpretedOption::kPositiveIntValueFieldNumber);
+          uninterpreted_option->set_positive_int_value(value);
+        }
+        break;
       }
-      string value;
-      DO(ConsumeString(&value, "Expected string."));
-      uninterpreted_option->set_string_value(value);
-      break;
-    }
 
-    case io::Tokenizer::TYPE_SYMBOL:
-      if (LookingAt("{")) {
-        value_location.AddPath(UninterpretedOption::kAggregateValueFieldNumber);
-        DO(ParseUninterpretedBlock(
-            uninterpreted_option->mutable_aggregate_value()));
-      } else {
-        AddError("Expected option value.");
-        return false;
+      case io::Tokenizer::TYPE_FLOAT: {
+        value_location.AddPath(UninterpretedOption::kDoubleValueFieldNumber);
+        double value;
+        DO(ConsumeNumber(&value, "Expected number."));
+        uninterpreted_option->set_double_value(is_negative ? -value : value);
+        break;
       }
-      break;
+
+      case io::Tokenizer::TYPE_STRING: {
+        value_location.AddPath(UninterpretedOption::kStringValueFieldNumber);
+        if (is_negative) {
+          AddError("Invalid '-' symbol before string.");
+          return false;
+        }
+        string value;
+        DO(ConsumeString(&value, "Expected string."));
+        uninterpreted_option->set_string_value(value);
+        break;
+      }
+
+      case io::Tokenizer::TYPE_SYMBOL:
+        if (LookingAt("{")) {
+          value_location.AddPath(
+              UninterpretedOption::kAggregateValueFieldNumber);
+          DO(ParseUninterpretedBlock(
+              uninterpreted_option->mutable_aggregate_value()));
+        } else {
+          AddError("Expected option value.");
+          return false;
+        }
+        break;
+    }
+  }
+
+  if (style == OPTION_STATEMENT) {
+    DO(ConsumeEndOfDeclaration(";", &location));
   }
 
   return true;
@@ -1008,7 +1119,10 @@
       LocationRecorder end_location(
           location, DescriptorProto::ExtensionRange::kEndFieldNumber);
       if (TryConsume("max")) {
-        end = FieldDescriptor::kMaxNumber;
+        // Set to the sentinel value - 1 since we increment the value below.
+        // The actual value of the end of the range should be set with
+        // AdjustExtensionRangesWithMaxEndNumber.
+        end = kMaxExtensionRangeSentinel - 1;
       } else {
         DO(ConsumeInteger(&end, "Expected integer."));
       }
@@ -1028,7 +1142,7 @@
     range->set_end(end);
   } while (TryConsume(","));
 
-  DO(Consume(";"));
+  DO(ConsumeEndOfDeclaration(";", &extensions_location));
   return true;
 }
 
@@ -1046,7 +1160,7 @@
   io::Tokenizer::Token extendee_end = input_->previous();
 
   // Parse the block.
-  DO(Consume("{"));
+  DO(ConsumeEndOfDeclaration("{", &extend_location));
 
   bool is_first = true;
 
@@ -1083,7 +1197,7 @@
       // other statements.
       SkipStatement();
     }
-  } while(!TryConsume("}"));
+  } while (!TryConsumeEndOfDeclaration("}", NULL));
 
   return true;
 }
@@ -1109,9 +1223,9 @@
 
 bool Parser::ParseEnumBlock(EnumDescriptorProto* enum_type,
                             const LocationRecorder& enum_location) {
-  DO(Consume("{"));
+  DO(ConsumeEndOfDeclaration("{", &enum_location));
 
-  while (!TryConsume("}")) {
+  while (!TryConsumeEndOfDeclaration("}", NULL)) {
     if (AtEnd()) {
       AddError("Reached end of input in enum definition (missing '}').");
       return false;
@@ -1129,13 +1243,14 @@
 
 bool Parser::ParseEnumStatement(EnumDescriptorProto* enum_type,
                                 const LocationRecorder& enum_location) {
-  if (TryConsume(";")) {
+  if (TryConsumeEndOfDeclaration(";", NULL)) {
     // empty statement; ignore
     return true;
   } else if (LookingAt("option")) {
     LocationRecorder location(enum_location,
                               EnumDescriptorProto::kOptionsFieldNumber);
-    return ParseOption(enum_type->mutable_options(), location);
+    return ParseOption(enum_type->mutable_options(), location,
+                       OPTION_STATEMENT);
   } else {
     LocationRecorder location(enum_location,
         EnumDescriptorProto::kValueFieldNumber, enum_type->value_size());
@@ -1164,16 +1279,14 @@
     location.RecordLegacyLocation(
         enum_value, DescriptorPool::ErrorCollector::NUMBER);
 
-    bool is_negative = TryConsume("-");
     int number;
-    DO(ConsumeInteger(&number, "Expected integer."));
-    if (is_negative) number *= -1;
+    DO(ConsumeSignedInteger(&number, "Expected integer."));
     enum_value->set_number(number);
   }
 
   DO(ParseEnumConstantOptions(enum_value, enum_value_location));
 
-  DO(Consume(";"));
+  DO(ConsumeEndOfDeclaration(";", &enum_value_location));
 
   return true;
 }
@@ -1189,7 +1302,7 @@
   DO(Consume("["));
 
   do {
-    DO(ParseOptionAssignment(value->mutable_options(), location));
+    DO(ParseOption(value->mutable_options(), location, OPTION_ASSIGNMENT));
   } while (TryConsume(","));
 
   DO(Consume("]"));
@@ -1217,9 +1330,9 @@
 
 bool Parser::ParseServiceBlock(ServiceDescriptorProto* service,
                                const LocationRecorder& service_location) {
-  DO(Consume("{"));
+  DO(ConsumeEndOfDeclaration("{", &service_location));
 
-  while (!TryConsume("}")) {
+  while (!TryConsumeEndOfDeclaration("}", NULL)) {
     if (AtEnd()) {
       AddError("Reached end of input in service definition (missing '}').");
       return false;
@@ -1237,13 +1350,13 @@
 
 bool Parser::ParseServiceStatement(ServiceDescriptorProto* service,
                                    const LocationRecorder& service_location) {
-  if (TryConsume(";")) {
+  if (TryConsumeEndOfDeclaration(";", NULL)) {
     // empty statement; ignore
     return true;
   } else if (LookingAt("option")) {
     LocationRecorder location(
         service_location, ServiceDescriptorProto::kOptionsFieldNumber);
-    return ParseOption(service->mutable_options(), location);
+    return ParseOption(service->mutable_options(), location, OPTION_STATEMENT);
   } else {
     LocationRecorder location(service_location,
         ServiceDescriptorProto::kMethodFieldNumber, service->method_size());
@@ -1286,28 +1399,41 @@
   }
   DO(Consume(")"));
 
-  if (TryConsume("{")) {
+  if (LookingAt("{")) {
     // Options!
-    while (!TryConsume("}")) {
-      if (AtEnd()) {
-        AddError("Reached end of input in method options (missing '}').");
-        return false;
-      }
+    DO(ParseOptions(method_location,
+                    MethodDescriptorProto::kOptionsFieldNumber,
+                    method->mutable_options()));
+  } else {
+    DO(ConsumeEndOfDeclaration(";", &method_location));
+  }
 
-      if (TryConsume(";")) {
-        // empty statement; ignore
-      } else {
-        LocationRecorder location(method_location,
-                                  MethodDescriptorProto::kOptionsFieldNumber);
-        if (!ParseOption(method->mutable_options(), location)) {
-          // This statement failed to parse.  Skip it, but keep looping to
-          // parse other statements.
-          SkipStatement();
-        }
+  return true;
+}
+
+
+bool Parser::ParseOptions(const LocationRecorder& parent_location,
+                          const int optionsFieldNumber,
+                          Message* mutable_options) {
+  // Options!
+  ConsumeEndOfDeclaration("{", &parent_location);
+  while (!TryConsumeEndOfDeclaration("}", NULL)) {
+    if (AtEnd()) {
+      AddError("Reached end of input in method options (missing '}').");
+      return false;
+    }
+
+    if (TryConsumeEndOfDeclaration(";", NULL)) {
+      // empty statement; ignore
+    } else {
+      LocationRecorder location(parent_location,
+                                optionsFieldNumber);
+      if (!ParseOption(mutable_options, location, OPTION_STATEMENT)) {
+        // This statement failed to parse.  Skip it, but keep looping to
+        // parse other statements.
+        SkipStatement();
       }
     }
-  } else {
-    DO(Consume(";"));
   }
 
   return true;
@@ -1406,32 +1532,44 @@
       if (!TryConsume(".")) break;
       file->mutable_package()->append(".");
     }
+
+    location.EndAt(input_->previous());
+
+    DO(ConsumeEndOfDeclaration(";", &location));
   }
 
-  DO(Consume(";"));
   return true;
 }
 
-bool Parser::ParseImport(string* import_filename,
-                         const LocationRecorder& root_location,
-                         int index) {
+bool Parser::ParseImport(RepeatedPtrField<string>* dependency,
+                         RepeatedField<int32>* public_dependency,
+                         RepeatedField<int32>* weak_dependency,
+                         const LocationRecorder& root_location) {
   DO(Consume("import"));
+  if (LookingAt("public")) {
+    LocationRecorder location(
+        root_location, FileDescriptorProto::kPublicDependencyFieldNumber,
+        public_dependency->size());
+    DO(Consume("public"));
+    *public_dependency->Add() = dependency->size();
+  } else if (LookingAt("weak")) {
+    LocationRecorder location(
+        root_location, FileDescriptorProto::kWeakDependencyFieldNumber,
+        weak_dependency->size());
+    DO(Consume("weak"));
+    *weak_dependency->Add() = dependency->size();
+  }
   {
     LocationRecorder location(root_location,
                               FileDescriptorProto::kDependencyFieldNumber,
-                              index);
-    DO(ConsumeString(import_filename,
+                              dependency->size());
+    DO(ConsumeString(dependency->Add(),
       "Expected a string naming the file to import."));
-  }
-  DO(Consume(";"));
-  return true;
-}
 
-bool Parser::ParseOption(Message* options,
-                         const LocationRecorder& options_location) {
-  DO(Consume("option"));
-  DO(ParseOptionAssignment(options, options_location));
-  DO(Consume(";"));
+    location.EndAt(input_->previous());
+
+    DO(ConsumeEndOfDeclaration(";", &location));
+  }
   return true;
 }
 
diff --git a/third_party/protobuf/src/google/protobuf/compiler/parser.h b/third_party/protobuf/src/google/protobuf/compiler/parser.h
index 4cc90a2..cfd3649 100644
--- a/third_party/protobuf/src/google/protobuf/compiler/parser.h
+++ b/third_party/protobuf/src/google/protobuf/compiler/parser.h
@@ -116,6 +116,8 @@
   }
 
  private:
+  class LocationRecorder;
+
   // =================================================================
   // Error recovery helpers
 
@@ -164,6 +166,8 @@
   bool ConsumeIdentifier(string* output, const char* error);
   // Consume an integer and store its value in "output".
   bool ConsumeInteger(int* output, const char* error);
+  // Consume a signed integer and store its value in "output".
+  bool ConsumeSignedInteger(int* output, const char* error);
   // Consume a 64-bit integer and store its value in "output".  If the value
   // is greater than max_value, an error will be reported.
   bool ConsumeInteger64(uint64 max_value, uint64* output, const char* error);
@@ -173,6 +177,20 @@
   // Consume a string literal and store its (unescaped) value in "output".
   bool ConsumeString(string* output, const char* error);
 
+  // Consume a token representing the end of the statement.  Comments between
+  // this token and the next will be harvested for documentation.  The given
+  // LocationRecorder should refer to the declaration that was just parsed;
+  // it will be populated with these comments.
+  //
+  // TODO(kenton):  The LocationRecorder is const because historically locations
+  //   have been passed around by const reference, for no particularly good
+  //   reason.  We should probably go through and change them all to mutable
+  //   pointer to make this more intuitive.
+  bool TryConsumeEndOfDeclaration(const char* text,
+                                  const LocationRecorder* location);
+  bool ConsumeEndOfDeclaration(const char* text,
+                               const LocationRecorder* location);
+
   // -----------------------------------------------------------------
   // Error logging helpers
 
@@ -227,6 +245,14 @@
     void RecordLegacyLocation(const Message* descriptor,
         DescriptorPool::ErrorCollector::ErrorLocation location);
 
+    // Attaches leading and trailing comments to the location.  The two strings
+    // will be swapped into place, so after this is called *leading and
+    // *trailing will be empty.
+    //
+    // TODO(kenton):  See comment on TryConsumeEndOfDeclaration(), above, for
+    //   why this is const.
+    void AttachComments(string* leading, string* trailing) const;
+
    private:
     Parser* parser_;
     SourceCodeInfo::Location* location_;
@@ -265,9 +291,10 @@
                               const LocationRecorder& service_location);
   bool ParsePackage(FileDescriptorProto* file,
                     const LocationRecorder& root_location);
-  bool ParseImport(string* import_filename,
-                   const LocationRecorder& root_location,
-                   int index);
+  bool ParseImport(RepeatedPtrField<string>* dependency,
+                   RepeatedField<int32>* public_dependency,
+                   RepeatedField<int32>* weak_dependency,
+                   const LocationRecorder& root_location);
   bool ParseOption(Message* options,
                    const LocationRecorder& options_location);
 
@@ -329,6 +356,12 @@
   bool ParseServiceMethod(MethodDescriptorProto* method,
                           const LocationRecorder& method_location);
 
+
+  // Parse options of a single method or stream.
+  bool ParseOptions(const LocationRecorder& parent_location,
+                    const int optionsFieldNumber,
+                    Message* mutable_options);
+
   // Parse "required", "optional", or "repeated" and fill in "label"
   // with the value.
   bool ParseLabel(FieldDescriptorProto::Label* label);
@@ -351,11 +384,17 @@
   bool ParseDefaultAssignment(FieldDescriptorProto* field,
                               const LocationRecorder& field_location);
 
+  enum OptionStyle {
+    OPTION_ASSIGNMENT,  // just "name = value"
+    OPTION_STATEMENT    // "option name = value;"
+  };
+
   // Parse a single option name/value pair, e.g. "ctype = CORD".  The name
   // identifies a field of the given Message, and the value of that field
   // is set to the parsed value.
-  bool ParseOptionAssignment(Message* options,
-                             const LocationRecorder& options_location);
+  bool ParseOption(Message* options,
+                   const LocationRecorder& options_location,
+                   OptionStyle style);
 
   // Parses a single part of a multipart option name. A multipart name consists
   // of names separated by dots. Each name is either an identifier or a series
@@ -387,6 +426,10 @@
   bool stop_after_syntax_identifier_;
   string syntax_identifier_;
 
+  // Leading doc comments for the next declaration.  These are not complete
+  // yet; use ConsumeEndOfDeclaration() to get the complete comments.
+  string upcoming_doc_comments_;
+
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Parser);
 };
 
diff --git a/third_party/protobuf/src/google/protobuf/compiler/parser_unittest.cc b/third_party/protobuf/src/google/protobuf/compiler/parser_unittest.cc
index 156c0dc..c61ac60 100644
--- a/third_party/protobuf/src/google/protobuf/compiler/parser_unittest.cc
+++ b/third_party/protobuf/src/google/protobuf/compiler/parser_unittest.cc
@@ -44,6 +44,7 @@
 #include <google/protobuf/wire_format.h>
 #include <google/protobuf/text_format.h>
 #include <google/protobuf/unittest.pb.h>
+#include <google/protobuf/unittest_custom_options.pb.h>
 #include <google/protobuf/stubs/strutil.h>
 #include <google/protobuf/stubs/substitute.h>
 #include <google/protobuf/stubs/map-util.h>
@@ -509,6 +510,31 @@
     "}");
 }
 
+TEST_F(ParseMessageTest, LargerMaxForMessageSetWireFormatMessages) {
+  // Messages using the message_set_wire_format option can accept larger
+  // extension numbers, as the numbers are not encoded as int32 field values
+  // rather than tags.
+  ExpectParsesTo(
+    "message TestMessage {\n"
+    "  extensions 4 to max;\n"
+    "  option message_set_wire_format = true;\n"
+    "}\n",
+
+    "message_type {"
+    "  name: \"TestMessage\""
+    "    extension_range { start:4 end: 0x7fffffff }"
+    "  options {\n"
+    "    uninterpreted_option { \n"
+    "      name {\n"
+    "        name_part: \"message_set_wire_format\"\n"
+    "        is_extension: false\n"
+    "      }\n"
+    "      identifier_value: \"true\"\n"
+    "    }\n"
+    "  }\n"
+    "}");
+}
+
 TEST_F(ParseMessageTest, Extensions) {
   ExpectParsesTo(
     "extend Extendee1 { optional int32 foo = 12; }\n"
@@ -571,6 +597,10 @@
     "  FOO = 13;\n"
     "  BAR = -10;\n"
     "  BAZ = 500;\n"
+    "  HEX_MAX = 0x7FFFFFFF;\n"
+    "  HEX_MIN = -0x80000000;\n"
+    "  INT_MAX = 2147483647;\n"
+    "  INT_MIN = -2147483648;\n"
     "}\n",
 
     "enum_type {"
@@ -578,6 +608,10 @@
     "  value { name:\"FOO\" number:13 }"
     "  value { name:\"BAR\" number:-10 }"
     "  value { name:\"BAZ\" number:500 }"
+    "  value { name:\"HEX_MAX\" number:2147483647 }"
+    "  value { name:\"HEX_MIN\" number:-2147483648 }"
+    "  value { name:\"INT_MAX\" number:2147483647 }"
+    "  value { name:\"INT_MIN\" number:-2147483648 }"
     "}");
 }
 
@@ -631,7 +665,7 @@
     "}");
 }
 
-TEST_F(ParseServiceTest, Methods) {
+TEST_F(ParseServiceTest, MethodsAndStreams) {
   ExpectParsesTo(
     "service TestService {\n"
     "  rpc Foo(In1) returns (Out1);\n"
@@ -668,6 +702,20 @@
     "dependency: \"baz.proto\"");
 }
 
+TEST_F(ParseMiscTest, ParsePublicImports) {
+  ExpectParsesTo(
+    "import \"foo.proto\";\n"
+    "import public \"bar.proto\";\n"
+    "import \"baz.proto\";\n"
+    "import public \"qux.proto\";\n",
+    "dependency: \"foo.proto\""
+    "dependency: \"bar.proto\""
+    "dependency: \"baz.proto\""
+    "dependency: \"qux.proto\""
+    "public_dependency: 1 "
+    "public_dependency: 3 ");
+}
+
 TEST_F(ParseMiscTest, ParsePackage) {
   ExpectParsesTo(
     "package foo.bar.baz;\n",
@@ -867,6 +915,20 @@
     "6:36: Integer out of range.\n");
 }
 
+TEST_F(ParseErrorTest, EnumValueOutOfRange) {
+  ExpectHasErrors(
+    "enum TestEnum {\n"
+    "  HEX_TOO_BIG   =  0x80000000;\n"
+    "  HEX_TOO_SMALL = -0x80000001;\n"
+    "  INT_TOO_BIG   =  2147483648;\n"
+    "  INT_TOO_SMALL = -2147483649;\n"
+    "}\n",
+    "1:19: Integer out of range.\n"
+    "2:19: Integer out of range.\n"
+    "3:19: Integer out of range.\n"
+    "4:19: Integer out of range.\n");
+}
+
 TEST_F(ParseErrorTest, DefaultValueMissing) {
   ExpectHasErrors(
     "message TestMessage {\n"
@@ -976,6 +1038,7 @@
     "1:26: Expected message type.\n");
 }
 
+
 TEST_F(ParseErrorTest, EofInMethodOptions) {
   ExpectHasErrors(
     "service TestService {\n"
@@ -984,6 +1047,7 @@
     "1:29: Reached end of input in service definition (missing '}').\n");
 }
 
+
 TEST_F(ParseErrorTest, PrimitiveMethodInput) {
   ExpectHasErrors(
     "service TestService {\n"
@@ -992,6 +1056,7 @@
     "1:10: Expected message type.\n");
 }
 
+
 TEST_F(ParseErrorTest, MethodOptionTypeError) {
   // This used to cause an infinite loop.
   ExpectHasErrors(
@@ -1002,6 +1067,7 @@
     "2:45: Expected \"=\".\n");
 }
 
+
 // -------------------------------------------------------------------
 // Import and package errors
 
@@ -1157,6 +1223,7 @@
     "3:6: \"Bar\" is already defined in \"Foo\".\n");
 }
 
+
 TEST_F(ParserValidationErrorTest, MethodInputTypeError) {
   ExpectHasValidationErrors(
     "message Baz {}\n"
@@ -1166,6 +1233,7 @@
     "2:10: \"Qux\" is not defined.\n");
 }
 
+
 TEST_F(ParserValidationErrorTest, MethodOutputTypeError) {
   ExpectHasValidationErrors(
     "message Baz {}\n"
@@ -1175,6 +1243,7 @@
     "2:23: \"Qux\" is not defined.\n");
 }
 
+
 // ===================================================================
 // Test that the output from FileDescriptor::DebugString() (and all other
 // descriptor types) is parseable, and results in the same Descriptor
@@ -1236,6 +1305,11 @@
   // also need to give it the same name as the original.
   parsed.set_name("google/protobuf/unittest.proto");
   // We need the imported dependency before we can build our parsed proto
+  const FileDescriptor* public_import =
+      protobuf_unittest_import::PublicImportMessage::descriptor()->file();
+  FileDescriptorProto public_import_proto;
+  public_import->CopyTo(&public_import_proto);
+  ASSERT_TRUE(pool_.BuildFile(public_import_proto) != NULL);
   const FileDescriptor* import =
        protobuf_unittest_import::ImportMessage::descriptor()->file();
   FileDescriptorProto import_proto;
@@ -1258,6 +1332,45 @@
   EXPECT_EQ(expected.DebugString(), parsed.DebugString());
 }
 
+TEST_F(ParseDecriptorDebugTest, TestCustomOptions) {
+  const FileDescriptor* original_file =
+     protobuf_unittest::AggregateMessage::descriptor()->file();
+  FileDescriptorProto expected;
+  original_file->CopyTo(&expected);
+
+  string debug_string = original_file->DebugString();
+
+  // Parse the debug string
+  SetupParser(debug_string.c_str());
+  FileDescriptorProto parsed;
+  parser_->Parse(input_.get(), &parsed);
+  EXPECT_EQ(io::Tokenizer::TYPE_END, input_->current().type);
+  ASSERT_EQ("", error_collector_.text_);
+
+  // We now have a FileDescriptorProto, but to compare with the expected we
+  // need to link to a FileDecriptor, then output back to a proto. We'll
+  // also need to give it the same name as the original.
+  parsed.set_name(original_file->name());
+
+  // unittest_custom_options.proto depends on descriptor.proto.
+  const FileDescriptor* import = FileDescriptorProto::descriptor()->file();
+  FileDescriptorProto import_proto;
+  import->CopyTo(&import_proto);
+  ASSERT_TRUE(pool_.BuildFile(import_proto) != NULL);
+  const FileDescriptor* actual = pool_.BuildFile(parsed);
+  ASSERT_TRUE(actual != NULL);
+  parsed.Clear();
+  actual->CopyTo(&parsed);
+
+  // The messages might be in different orders, making them hard to compare.
+  // So, sort the messages in the descriptor protos (including nested messages,
+  // recursively).
+  SortMessages(&expected);
+  SortMessages(&parsed);
+
+  EXPECT_EQ(expected.DebugString(), parsed.DebugString());
+}
+
 // ===================================================================
 // SourceCodeInfo tests.
 
@@ -1353,67 +1466,6 @@
   }
 }
 
-// Split some text on line breaks.  The line breaks are retained in the output,
-// so each line (except the last) ends with a '\n', and the lines can be
-// concatenated to produce the original text.
-//
-// I couldn't find the proper string utility function for this.  Our
-// split-on-delimiter functions don't include the delimiter in the output.
-void SplitLines(const string& text, vector<string>* lines) {
-  string::size_type pos = 0;
-
-  while (pos != string::npos) {
-    string::size_type last_pos = pos;
-    pos = text.find_first_of('\n', pos);
-    if (pos != string::npos) ++pos;
-    lines->push_back(text.substr(last_pos, pos - last_pos));
-  }
-}
-
-// Look for the given tags in the given text and construct a span (as defined
-// by SourceCodeInfo.Location.span) from them.  E.g. for text like:
-//   /*a*/message /*b*/Foo/*c*/ {}/*d*/
-// There are four tags:  "a", "b", "c", and "d".  The constructed span starts
-// immediately after the start tag's trailing '/' and ends immediately before
-// the end tags leading '/'.
-void MakeExpectedSpan(const vector<string>& lines,
-                      const string& start_tag, const string& end_tag,
-                      RepeatedField<int>* output) {
-  string start_comment = "/*" + start_tag + "*/";
-  string end_comment = "/*" + end_tag + "*/";
-
-  int start_line = -1;
-  int start_column = -1;
-  for (int i = 0; i < lines.size(); i++) {
-    string::size_type pos = lines[i].find(start_comment);
-    if (pos != string::npos) {
-      start_line = i;
-      start_column = pos + start_comment.size();
-      break;
-    }
-  }
-  ASSERT_NE(start_line, -1)
-      << "Tag \"" << start_comment << "\" not found in text.";
-
-  int end_line = -1;
-  int end_column = -1;
-  for (int i = start_line; i < lines.size(); i++) {
-    string::size_type pos = lines[i].find(end_comment);
-    if (pos != string::npos) {
-      end_line = i;
-      end_column = pos;
-      break;
-    }
-  }
-  ASSERT_NE(end_line, -1)
-      << "Tag \"" << end_comment << "\" not found in text.";
-
-  output->Add(start_line);
-  output->Add(start_column);
-  if (end_line != start_line) output->Add(end_line);
-  output->Add(end_column);
-}
-
 // Check if two spans are equal.
 bool CompareSpans(const RepeatedField<int>& span1,
                   const RepeatedField<int>& span2) {
@@ -1434,8 +1486,8 @@
   // Parse the given text as a .proto file and populate the spans_ map with
   // all the source location spans in its SourceCodeInfo table.
   bool Parse(const char* text) {
-    SetupParser(text);
-    SplitLines(text, &lines_);
+    ExtractMarkers(text);
+    SetupParser(text_without_markers_.c_str());
     if (!parser_->Parse(input_.get(), &file_)) {
       return false;
     }
@@ -1470,19 +1522,38 @@
   // part of the FileDescriptorProto.  (If unclear, look at the actual tests;
   // it should quickly become obvious.)
 
-  bool HasSpan(const char* start_tag, const char* end_tag,
+  bool HasSpan(char start_marker, char end_marker,
                const Message& descriptor_proto) {
-    return HasSpan(start_tag, end_tag, descriptor_proto, NULL, -1);
+    return HasSpanWithComment(
+        start_marker, end_marker, descriptor_proto, NULL, -1, NULL, NULL);
   }
 
-  bool HasSpan(const char* start_tag, const char* end_tag,
+  bool HasSpanWithComment(char start_marker, char end_marker,
+                          const Message& descriptor_proto,
+                          const char* expected_leading_comments,
+                          const char* expected_trailing_comments) {
+    return HasSpanWithComment(
+        start_marker, end_marker, descriptor_proto, NULL, -1,
+        expected_leading_comments, expected_trailing_comments);
+  }
+
+  bool HasSpan(char start_marker, char end_marker,
                const Message& descriptor_proto, const string& field_name) {
-    return HasSpan(start_tag, end_tag, descriptor_proto, field_name, -1);
+    return HasSpan(start_marker, end_marker, descriptor_proto, field_name, -1);
   }
 
-  bool HasSpan(const char* start_tag, const char* end_tag,
+  bool HasSpan(char start_marker, char end_marker,
                const Message& descriptor_proto, const string& field_name,
                int index) {
+    return HasSpan(start_marker, end_marker, descriptor_proto,
+                   field_name, index, NULL, NULL);
+  }
+
+  bool HasSpan(char start_marker, char end_marker,
+               const Message& descriptor_proto,
+               const string& field_name, int index,
+               const char* expected_leading_comments,
+               const char* expected_trailing_comments) {
     const FieldDescriptor* field =
         descriptor_proto.GetDescriptor()->FindFieldByName(field_name);
     if (field == NULL) {
@@ -1491,29 +1562,34 @@
       return false;
     }
 
-    return HasSpan(start_tag, end_tag, descriptor_proto, field, index);
+    return HasSpanWithComment(
+        start_marker, end_marker, descriptor_proto, field, index,
+        expected_leading_comments, expected_trailing_comments);
   }
 
   bool HasSpan(const Message& descriptor_proto) {
-    return HasSpan(NULL, NULL, descriptor_proto, NULL, -1);
+    return HasSpanWithComment(
+        '\0', '\0', descriptor_proto, NULL, -1, NULL, NULL);
   }
 
   bool HasSpan(const Message& descriptor_proto, const string& field_name) {
-    return HasSpan(NULL, NULL, descriptor_proto, field_name, -1);
+    return HasSpan('\0', '\0', descriptor_proto, field_name, -1);
   }
 
   bool HasSpan(const Message& descriptor_proto, const string& field_name,
                int index) {
-    return HasSpan(NULL, NULL, descriptor_proto, field_name, index);
+    return HasSpan('\0', '\0', descriptor_proto, field_name, index);
   }
 
-  bool HasSpan(const char* start_tag, const char* end_tag,
-               const Message& descriptor_proto, const FieldDescriptor* field,
-               int index) {
+  bool HasSpanWithComment(char start_marker, char end_marker,
+                          const Message& descriptor_proto,
+                          const FieldDescriptor* field, int index,
+                          const char* expected_leading_comments,
+                          const char* expected_trailing_comments) {
     pair<SpanMap::iterator, SpanMap::iterator> range =
         spans_.equal_range(SpanKey(descriptor_proto, field, index));
 
-    if (start_tag == NULL) {
+    if (start_marker == '\0') {
       if (range.first == range.second) {
         return false;
       } else {
@@ -1521,11 +1597,34 @@
         return true;
       }
     } else {
+      pair<int, int> start_pos = FindOrDie(markers_, start_marker);
+      pair<int, int> end_pos = FindOrDie(markers_, end_marker);
+
       RepeatedField<int> expected_span;
-      MakeExpectedSpan(lines_, start_tag, end_tag, &expected_span);
+      expected_span.Add(start_pos.first);
+      expected_span.Add(start_pos.second);
+      if (end_pos.first != start_pos.first) {
+        expected_span.Add(end_pos.first);
+      }
+      expected_span.Add(end_pos.second);
 
       for (SpanMap::iterator iter = range.first; iter != range.second; ++iter) {
         if (CompareSpans(expected_span, iter->second->span())) {
+          if (expected_leading_comments == NULL) {
+            EXPECT_FALSE(iter->second->has_leading_comments());
+          } else {
+            EXPECT_TRUE(iter->second->has_leading_comments());
+            EXPECT_EQ(expected_leading_comments,
+                      iter->second->leading_comments());
+          }
+          if (expected_trailing_comments == NULL) {
+            EXPECT_FALSE(iter->second->has_trailing_comments());
+          } else {
+            EXPECT_TRUE(iter->second->has_trailing_comments());
+            EXPECT_EQ(expected_trailing_comments,
+                      iter->second->trailing_comments());
+          }
+
           spans_.erase(iter);
           return true;
         }
@@ -1542,10 +1641,11 @@
     int index;
 
     inline SpanKey() {}
-    inline SpanKey(const Message& descriptor_proto,
-                   const FieldDescriptor* field,
-                   int index)
-        : descriptor_proto(&descriptor_proto), field(field), index(index) {}
+    inline SpanKey(const Message& descriptor_proto_param,
+                   const FieldDescriptor* field_param,
+                   int index_param)
+        : descriptor_proto(&descriptor_proto_param), field(field_param),
+          index(index_param) {}
 
     inline bool operator<(const SpanKey& other) const {
       if (descriptor_proto < other.descriptor_proto) return true;
@@ -1558,32 +1658,63 @@
 
   typedef multimap<SpanKey, const SourceCodeInfo::Location*> SpanMap;
   SpanMap spans_;
-  vector<string> lines_;
+  map<char, pair<int, int> > markers_;
+  string text_without_markers_;
+
+  void ExtractMarkers(const char* text) {
+    markers_.clear();
+    text_without_markers_.clear();
+    int line = 0;
+    int column = 0;
+    while (*text != '\0') {
+      if (*text == '$') {
+        ++text;
+        GOOGLE_CHECK_NE('\0', *text);
+        if (*text == '$') {
+          text_without_markers_ += '$';
+          ++column;
+        } else {
+          markers_[*text] = make_pair(line, column);
+          ++text;
+          GOOGLE_CHECK_EQ('$', *text);
+        }
+      } else if (*text == '\n') {
+        ++line;
+        column = 0;
+        text_without_markers_ += *text;
+      } else {
+        text_without_markers_ += *text;
+        ++column;
+      }
+      ++text;
+    }
+  }
 };
 
 TEST_F(SourceInfoTest, BasicFileDecls) {
   EXPECT_TRUE(Parse(
-      "/*a*/syntax = \"proto2\";\n"
-      "package /*b*/foo.bar/*c*/;\n"
-      "import /*d*/\"baz.proto\"/*e*/;\n"
-      "import /*f*/\"qux.proto\"/*g*/;/*h*/\n"
+      "$a$syntax = \"proto2\";\n"
+      "package $b$foo.bar$c$;\n"
+      "import $d$\"baz.proto\"$e$;\n"
+      "import $f$\"qux.proto\"$g$;$h$\n"
+      "\n"
       "// comment ignored\n"));
 
-  EXPECT_TRUE(HasSpan("a", "h", file_));
-  EXPECT_TRUE(HasSpan("b", "c", file_, "package"));
-  EXPECT_TRUE(HasSpan("d", "e", file_, "dependency", 0));
-  EXPECT_TRUE(HasSpan("f", "g", file_, "dependency", 1));
+  EXPECT_TRUE(HasSpan('a', 'h', file_));
+  EXPECT_TRUE(HasSpan('b', 'c', file_, "package"));
+  EXPECT_TRUE(HasSpan('d', 'e', file_, "dependency", 0));
+  EXPECT_TRUE(HasSpan('f', 'g', file_, "dependency", 1));
 }
 
 TEST_F(SourceInfoTest, Messages) {
   EXPECT_TRUE(Parse(
-      "/*a*/message /*b*/Foo/*c*/ {}/*d*/\n"
-      "/*e*/message /*f*/Bar/*g*/ {}/*h*/\n"));
+      "$a$message $b$Foo$c$ {}$d$\n"
+      "$e$message $f$Bar$g$ {}$h$\n"));
 
-  EXPECT_TRUE(HasSpan("a", "d", file_.message_type(0)));
-  EXPECT_TRUE(HasSpan("b", "c", file_.message_type(0), "name"));
-  EXPECT_TRUE(HasSpan("e", "h", file_.message_type(1)));
-  EXPECT_TRUE(HasSpan("f", "g", file_.message_type(1), "name"));
+  EXPECT_TRUE(HasSpan('a', 'd', file_.message_type(0)));
+  EXPECT_TRUE(HasSpan('b', 'c', file_.message_type(0), "name"));
+  EXPECT_TRUE(HasSpan('e', 'h', file_.message_type(1)));
+  EXPECT_TRUE(HasSpan('f', 'g', file_.message_type(1), "name"));
 
   // Ignore these.
   EXPECT_TRUE(HasSpan(file_));
@@ -1592,24 +1723,24 @@
 TEST_F(SourceInfoTest, Fields) {
   EXPECT_TRUE(Parse(
       "message Foo {\n"
-      "  /*a*/optional/*b*/ /*c*/int32/*d*/ /*e*/bar/*f*/ = /*g*/1/*h*/;/*i*/\n"
-      "  /*j*/repeated/*k*/ /*l*/X.Y/*m*/ /*n*/baz/*o*/ = /*p*/2/*q*/;/*r*/\n"
+      "  $a$optional$b$ $c$int32$d$ $e$bar$f$ = $g$1$h$;$i$\n"
+      "  $j$repeated$k$ $l$X.Y$m$ $n$baz$o$ = $p$2$q$;$r$\n"
       "}\n"));
 
   const FieldDescriptorProto& field1 = file_.message_type(0).field(0);
   const FieldDescriptorProto& field2 = file_.message_type(0).field(1);
 
-  EXPECT_TRUE(HasSpan("a", "i", field1));
-  EXPECT_TRUE(HasSpan("a", "b", field1, "label"));
-  EXPECT_TRUE(HasSpan("c", "d", field1, "type"));
-  EXPECT_TRUE(HasSpan("e", "f", field1, "name"));
-  EXPECT_TRUE(HasSpan("g", "h", field1, "number"));
+  EXPECT_TRUE(HasSpan('a', 'i', field1));
+  EXPECT_TRUE(HasSpan('a', 'b', field1, "label"));
+  EXPECT_TRUE(HasSpan('c', 'd', field1, "type"));
+  EXPECT_TRUE(HasSpan('e', 'f', field1, "name"));
+  EXPECT_TRUE(HasSpan('g', 'h', field1, "number"));
 
-  EXPECT_TRUE(HasSpan("j", "r", field2));
-  EXPECT_TRUE(HasSpan("j", "k", field2, "label"));
-  EXPECT_TRUE(HasSpan("l", "m", field2, "type_name"));
-  EXPECT_TRUE(HasSpan("n", "o", field2, "name"));
-  EXPECT_TRUE(HasSpan("p", "q", field2, "number"));
+  EXPECT_TRUE(HasSpan('j', 'r', field2));
+  EXPECT_TRUE(HasSpan('j', 'k', field2, "label"));
+  EXPECT_TRUE(HasSpan('l', 'm', field2, "type_name"));
+  EXPECT_TRUE(HasSpan('n', 'o', field2, "name"));
+  EXPECT_TRUE(HasSpan('p', 'q', field2, "number"));
 
   // Ignore these.
   EXPECT_TRUE(HasSpan(file_));
@@ -1619,31 +1750,31 @@
 
 TEST_F(SourceInfoTest, Extensions) {
   EXPECT_TRUE(Parse(
-      "/*a*/extend /*b*/Foo/*c*/ {\n"
-      "  /*d*/optional/*e*/ int32 bar = 1;/*f*/\n"
-      "  /*g*/repeated/*h*/ X.Y baz = 2;/*i*/\n"
-      "}/*j*/\n"
-      "/*k*/extend /*l*/Bar/*m*/ {\n"
-      "  /*n*/optional int32 qux = 1;/*o*/\n"
-      "}/*p*/\n"));
+      "$a$extend $b$Foo$c$ {\n"
+      "  $d$optional$e$ int32 bar = 1;$f$\n"
+      "  $g$repeated$h$ X.Y baz = 2;$i$\n"
+      "}$j$\n"
+      "$k$extend $l$Bar$m$ {\n"
+      "  $n$optional int32 qux = 1;$o$\n"
+      "}$p$\n"));
 
   const FieldDescriptorProto& field1 = file_.extension(0);
   const FieldDescriptorProto& field2 = file_.extension(1);
   const FieldDescriptorProto& field3 = file_.extension(2);
 
-  EXPECT_TRUE(HasSpan("a", "j", file_, "extension"));
-  EXPECT_TRUE(HasSpan("k", "p", file_, "extension"));
+  EXPECT_TRUE(HasSpan('a', 'j', file_, "extension"));
+  EXPECT_TRUE(HasSpan('k', 'p', file_, "extension"));
 
-  EXPECT_TRUE(HasSpan("d", "f", field1));
-  EXPECT_TRUE(HasSpan("d", "e", field1, "label"));
-  EXPECT_TRUE(HasSpan("b", "c", field1, "extendee"));
+  EXPECT_TRUE(HasSpan('d', 'f', field1));
+  EXPECT_TRUE(HasSpan('d', 'e', field1, "label"));
+  EXPECT_TRUE(HasSpan('b', 'c', field1, "extendee"));
 
-  EXPECT_TRUE(HasSpan("g", "i", field2));
-  EXPECT_TRUE(HasSpan("g", "h", field2, "label"));
-  EXPECT_TRUE(HasSpan("b", "c", field2, "extendee"));
+  EXPECT_TRUE(HasSpan('g', 'i', field2));
+  EXPECT_TRUE(HasSpan('g', 'h', field2, "label"));
+  EXPECT_TRUE(HasSpan('b', 'c', field2, "extendee"));
 
-  EXPECT_TRUE(HasSpan("n", "o", field3));
-  EXPECT_TRUE(HasSpan("l", "m", field3, "extendee"));
+  EXPECT_TRUE(HasSpan('n', 'o', field3));
+  EXPECT_TRUE(HasSpan('l', 'm', field3, "extendee"));
 
   // Ignore these.
   EXPECT_TRUE(HasSpan(file_));
@@ -1662,32 +1793,32 @@
 TEST_F(SourceInfoTest, NestedExtensions) {
   EXPECT_TRUE(Parse(
       "message Message {\n"
-      "  /*a*/extend /*b*/Foo/*c*/ {\n"
-      "    /*d*/optional/*e*/ int32 bar = 1;/*f*/\n"
-      "    /*g*/repeated/*h*/ X.Y baz = 2;/*i*/\n"
-      "  }/*j*/\n"
-      "  /*k*/extend /*l*/Bar/*m*/ {\n"
-      "    /*n*/optional int32 qux = 1;/*o*/\n"
-      "  }/*p*/\n"
+      "  $a$extend $b$Foo$c$ {\n"
+      "    $d$optional$e$ int32 bar = 1;$f$\n"
+      "    $g$repeated$h$ X.Y baz = 2;$i$\n"
+      "  }$j$\n"
+      "  $k$extend $l$Bar$m$ {\n"
+      "    $n$optional int32 qux = 1;$o$\n"
+      "  }$p$\n"
       "}\n"));
 
   const FieldDescriptorProto& field1 = file_.message_type(0).extension(0);
   const FieldDescriptorProto& field2 = file_.message_type(0).extension(1);
   const FieldDescriptorProto& field3 = file_.message_type(0).extension(2);
 
-  EXPECT_TRUE(HasSpan("a", "j", file_.message_type(0), "extension"));
-  EXPECT_TRUE(HasSpan("k", "p", file_.message_type(0), "extension"));
+  EXPECT_TRUE(HasSpan('a', 'j', file_.message_type(0), "extension"));
+  EXPECT_TRUE(HasSpan('k', 'p', file_.message_type(0), "extension"));
 
-  EXPECT_TRUE(HasSpan("d", "f", field1));
-  EXPECT_TRUE(HasSpan("d", "e", field1, "label"));
-  EXPECT_TRUE(HasSpan("b", "c", field1, "extendee"));
+  EXPECT_TRUE(HasSpan('d', 'f', field1));
+  EXPECT_TRUE(HasSpan('d', 'e', field1, "label"));
+  EXPECT_TRUE(HasSpan('b', 'c', field1, "extendee"));
 
-  EXPECT_TRUE(HasSpan("g", "i", field2));
-  EXPECT_TRUE(HasSpan("g", "h", field2, "label"));
-  EXPECT_TRUE(HasSpan("b", "c", field2, "extendee"));
+  EXPECT_TRUE(HasSpan('g', 'i', field2));
+  EXPECT_TRUE(HasSpan('g', 'h', field2, "label"));
+  EXPECT_TRUE(HasSpan('b', 'c', field2, "extendee"));
 
-  EXPECT_TRUE(HasSpan("n", "o", field3));
-  EXPECT_TRUE(HasSpan("l", "m", field3, "extendee"));
+  EXPECT_TRUE(HasSpan('n', 'o', field3));
+  EXPECT_TRUE(HasSpan('l', 'm', field3, "extendee"));
 
   // Ignore these.
   EXPECT_TRUE(HasSpan(file_));
@@ -1708,8 +1839,8 @@
 TEST_F(SourceInfoTest, ExtensionRanges) {
   EXPECT_TRUE(Parse(
       "message Message {\n"
-      "  /*a*/extensions /*b*/1/*c*/ to /*d*/4/*e*/, /*f*/6/*g*/;/*h*/\n"
-      "  /*i*/extensions /*j*/8/*k*/ to /*l*/max/*m*/;/*n*/\n"
+      "  $a$extensions $b$1$c$ to $d$4$e$, $f$6$g$;$h$\n"
+      "  $i$extensions $j$8$k$ to $l$max$m$;$n$\n"
       "}\n"));
 
   const DescriptorProto::ExtensionRange& range1 =
@@ -1719,20 +1850,20 @@
   const DescriptorProto::ExtensionRange& range3 =
       file_.message_type(0).extension_range(2);
 
-  EXPECT_TRUE(HasSpan("a", "h", file_.message_type(0), "extension_range"));
-  EXPECT_TRUE(HasSpan("i", "n", file_.message_type(0), "extension_range"));
+  EXPECT_TRUE(HasSpan('a', 'h', file_.message_type(0), "extension_range"));
+  EXPECT_TRUE(HasSpan('i', 'n', file_.message_type(0), "extension_range"));
 
-  EXPECT_TRUE(HasSpan("b", "e", range1));
-  EXPECT_TRUE(HasSpan("b", "c", range1, "start"));
-  EXPECT_TRUE(HasSpan("d", "e", range1, "end"));
+  EXPECT_TRUE(HasSpan('b', 'e', range1));
+  EXPECT_TRUE(HasSpan('b', 'c', range1, "start"));
+  EXPECT_TRUE(HasSpan('d', 'e', range1, "end"));
 
-  EXPECT_TRUE(HasSpan("f", "g", range2));
-  EXPECT_TRUE(HasSpan("f", "g", range2, "start"));
-  EXPECT_TRUE(HasSpan("f", "g", range2, "end"));
+  EXPECT_TRUE(HasSpan('f', 'g', range2));
+  EXPECT_TRUE(HasSpan('f', 'g', range2, "start"));
+  EXPECT_TRUE(HasSpan('f', 'g', range2, "end"));
 
-  EXPECT_TRUE(HasSpan("j", "m", range3));
-  EXPECT_TRUE(HasSpan("j", "k", range3, "start"));
-  EXPECT_TRUE(HasSpan("l", "m", range3, "end"));
+  EXPECT_TRUE(HasSpan('j', 'm', range3));
+  EXPECT_TRUE(HasSpan('j', 'k', range3, "start"));
+  EXPECT_TRUE(HasSpan('l', 'm', range3, "end"));
 
   // Ignore these.
   EXPECT_TRUE(HasSpan(file_));
@@ -1743,22 +1874,22 @@
 TEST_F(SourceInfoTest, NestedMessages) {
   EXPECT_TRUE(Parse(
       "message Foo {\n"
-      "  /*a*/message /*b*/Bar/*c*/ {\n"
-      "    /*d*/message /*e*/Baz/*f*/ {}/*g*/\n"
-      "  }/*h*/\n"
-      "  /*i*/message /*j*/Qux/*k*/ {}/*l*/\n"
+      "  $a$message $b$Bar$c$ {\n"
+      "    $d$message $e$Baz$f$ {}$g$\n"
+      "  }$h$\n"
+      "  $i$message $j$Qux$k$ {}$l$\n"
       "}\n"));
 
   const DescriptorProto& bar = file_.message_type(0).nested_type(0);
   const DescriptorProto& baz = bar.nested_type(0);
   const DescriptorProto& qux = file_.message_type(0).nested_type(1);
 
-  EXPECT_TRUE(HasSpan("a", "h", bar));
-  EXPECT_TRUE(HasSpan("b", "c", bar, "name"));
-  EXPECT_TRUE(HasSpan("d", "g", baz));
-  EXPECT_TRUE(HasSpan("e", "f", baz, "name"));
-  EXPECT_TRUE(HasSpan("i", "l", qux));
-  EXPECT_TRUE(HasSpan("j", "k", qux, "name"));
+  EXPECT_TRUE(HasSpan('a', 'h', bar));
+  EXPECT_TRUE(HasSpan('b', 'c', bar, "name"));
+  EXPECT_TRUE(HasSpan('d', 'g', baz));
+  EXPECT_TRUE(HasSpan('e', 'f', baz, "name"));
+  EXPECT_TRUE(HasSpan('i', 'l', qux));
+  EXPECT_TRUE(HasSpan('j', 'k', qux, "name"));
 
   // Ignore these.
   EXPECT_TRUE(HasSpan(file_));
@@ -1770,9 +1901,9 @@
   EXPECT_TRUE(Parse(
       "message Foo {\n"
       "  message Bar {}\n"
-      "  /*a*/optional/*b*/ /*c*/group/*d*/ /*e*/Baz/*f*/ = /*g*/1/*h*/ {\n"
-      "    /*i*/message Qux {}/*j*/\n"
-      "  }/*k*/\n"
+      "  $a$optional$b$ $c$group$d$ $e$Baz$f$ = $g$1$h$ {\n"
+      "    $i$message Qux {}$j$\n"
+      "  }$k$\n"
       "}\n"));
 
   const DescriptorProto& bar = file_.message_type(0).nested_type(0);
@@ -1780,16 +1911,16 @@
   const DescriptorProto& qux = baz.nested_type(0);
   const FieldDescriptorProto& field = file_.message_type(0).field(0);
 
-  EXPECT_TRUE(HasSpan("a", "k", field));
-  EXPECT_TRUE(HasSpan("a", "b", field, "label"));
-  EXPECT_TRUE(HasSpan("c", "d", field, "type"));
-  EXPECT_TRUE(HasSpan("e", "f", field, "name"));
-  EXPECT_TRUE(HasSpan("e", "f", field, "type_name"));
-  EXPECT_TRUE(HasSpan("g", "h", field, "number"));
+  EXPECT_TRUE(HasSpan('a', 'k', field));
+  EXPECT_TRUE(HasSpan('a', 'b', field, "label"));
+  EXPECT_TRUE(HasSpan('c', 'd', field, "type"));
+  EXPECT_TRUE(HasSpan('e', 'f', field, "name"));
+  EXPECT_TRUE(HasSpan('e', 'f', field, "type_name"));
+  EXPECT_TRUE(HasSpan('g', 'h', field, "number"));
 
-  EXPECT_TRUE(HasSpan("a", "k", baz));
-  EXPECT_TRUE(HasSpan("e", "f", baz, "name"));
-  EXPECT_TRUE(HasSpan("i", "j", qux));
+  EXPECT_TRUE(HasSpan('a', 'k', baz));
+  EXPECT_TRUE(HasSpan('e', 'f', baz, "name"));
+  EXPECT_TRUE(HasSpan('i', 'j', qux));
 
   // Ignore these.
   EXPECT_TRUE(HasSpan(file_));
@@ -1802,13 +1933,13 @@
 
 TEST_F(SourceInfoTest, Enums) {
   EXPECT_TRUE(Parse(
-      "/*a*/enum /*b*/Foo/*c*/ {}/*d*/\n"
-      "/*e*/enum /*f*/Bar/*g*/ {}/*h*/\n"));
+      "$a$enum $b$Foo$c$ {}$d$\n"
+      "$e$enum $f$Bar$g$ {}$h$\n"));
 
-  EXPECT_TRUE(HasSpan("a", "d", file_.enum_type(0)));
-  EXPECT_TRUE(HasSpan("b", "c", file_.enum_type(0), "name"));
-  EXPECT_TRUE(HasSpan("e", "h", file_.enum_type(1)));
-  EXPECT_TRUE(HasSpan("f", "g", file_.enum_type(1), "name"));
+  EXPECT_TRUE(HasSpan('a', 'd', file_.enum_type(0)));
+  EXPECT_TRUE(HasSpan('b', 'c', file_.enum_type(0), "name"));
+  EXPECT_TRUE(HasSpan('e', 'h', file_.enum_type(1)));
+  EXPECT_TRUE(HasSpan('f', 'g', file_.enum_type(1), "name"));
 
   // Ignore these.
   EXPECT_TRUE(HasSpan(file_));
@@ -1817,19 +1948,19 @@
 TEST_F(SourceInfoTest, EnumValues) {
   EXPECT_TRUE(Parse(
       "enum Foo {\n"
-      "  /*a*/BAR/*b*/ = /*c*/1/*d*/;/*e*/\n"
-      "  /*f*/BAZ/*g*/ = /*h*/2/*i*/;/*j*/\n"
+      "  $a$BAR$b$ = $c$1$d$;$e$\n"
+      "  $f$BAZ$g$ = $h$2$i$;$j$\n"
       "}"));
 
   const EnumValueDescriptorProto& bar = file_.enum_type(0).value(0);
   const EnumValueDescriptorProto& baz = file_.enum_type(0).value(1);
 
-  EXPECT_TRUE(HasSpan("a", "e", bar));
-  EXPECT_TRUE(HasSpan("a", "b", bar, "name"));
-  EXPECT_TRUE(HasSpan("c", "d", bar, "number"));
-  EXPECT_TRUE(HasSpan("f", "j", baz));
-  EXPECT_TRUE(HasSpan("f", "g", baz, "name"));
-  EXPECT_TRUE(HasSpan("h", "i", baz, "number"));
+  EXPECT_TRUE(HasSpan('a', 'e', bar));
+  EXPECT_TRUE(HasSpan('a', 'b', bar, "name"));
+  EXPECT_TRUE(HasSpan('c', 'd', bar, "number"));
+  EXPECT_TRUE(HasSpan('f', 'j', baz));
+  EXPECT_TRUE(HasSpan('f', 'g', baz, "name"));
+  EXPECT_TRUE(HasSpan('h', 'i', baz, "number"));
 
   // Ignore these.
   EXPECT_TRUE(HasSpan(file_));
@@ -1840,17 +1971,17 @@
 TEST_F(SourceInfoTest, NestedEnums) {
   EXPECT_TRUE(Parse(
       "message Foo {\n"
-      "  /*a*/enum /*b*/Bar/*c*/ {}/*d*/\n"
-      "  /*e*/enum /*f*/Baz/*g*/ {}/*h*/\n"
+      "  $a$enum $b$Bar$c$ {}$d$\n"
+      "  $e$enum $f$Baz$g$ {}$h$\n"
       "}\n"));
 
   const EnumDescriptorProto& bar = file_.message_type(0).enum_type(0);
   const EnumDescriptorProto& baz = file_.message_type(0).enum_type(1);
 
-  EXPECT_TRUE(HasSpan("a", "d", bar));
-  EXPECT_TRUE(HasSpan("b", "c", bar, "name"));
-  EXPECT_TRUE(HasSpan("e", "h", baz));
-  EXPECT_TRUE(HasSpan("f", "g", baz, "name"));
+  EXPECT_TRUE(HasSpan('a', 'd', bar));
+  EXPECT_TRUE(HasSpan('b', 'c', bar, "name"));
+  EXPECT_TRUE(HasSpan('e', 'h', baz));
+  EXPECT_TRUE(HasSpan('f', 'g', baz, "name"));
 
   // Ignore these.
   EXPECT_TRUE(HasSpan(file_));
@@ -1860,37 +1991,37 @@
 
 TEST_F(SourceInfoTest, Services) {
   EXPECT_TRUE(Parse(
-      "/*a*/service /*b*/Foo/*c*/ {}/*d*/\n"
-      "/*e*/service /*f*/Bar/*g*/ {}/*h*/\n"));
+      "$a$service $b$Foo$c$ {}$d$\n"
+      "$e$service $f$Bar$g$ {}$h$\n"));
 
-  EXPECT_TRUE(HasSpan("a", "d", file_.service(0)));
-  EXPECT_TRUE(HasSpan("b", "c", file_.service(0), "name"));
-  EXPECT_TRUE(HasSpan("e", "h", file_.service(1)));
-  EXPECT_TRUE(HasSpan("f", "g", file_.service(1), "name"));
+  EXPECT_TRUE(HasSpan('a', 'd', file_.service(0)));
+  EXPECT_TRUE(HasSpan('b', 'c', file_.service(0), "name"));
+  EXPECT_TRUE(HasSpan('e', 'h', file_.service(1)));
+  EXPECT_TRUE(HasSpan('f', 'g', file_.service(1), "name"));
 
   // Ignore these.
   EXPECT_TRUE(HasSpan(file_));
 }
 
-TEST_F(SourceInfoTest, Methods) {
+TEST_F(SourceInfoTest, MethodsAndStreams) {
   EXPECT_TRUE(Parse(
       "service Foo {\n"
-      "  /*a*/rpc /*b*/Bar/*c*/(/*d*/X/*e*/) returns(/*f*/Y/*g*/);/*h*/"
-      "  /*i*/rpc /*j*/Baz/*k*/(/*l*/Z/*m*/) returns(/*n*/W/*o*/);/*p*/"
+      "  $a$rpc $b$Bar$c$($d$X$e$) returns($f$Y$g$);$h$"
+      "  $i$rpc $j$Baz$k$($l$Z$m$) returns($n$W$o$);$p$"
       "}"));
 
   const MethodDescriptorProto& bar = file_.service(0).method(0);
   const MethodDescriptorProto& baz = file_.service(0).method(1);
 
-  EXPECT_TRUE(HasSpan("a", "h", bar));
-  EXPECT_TRUE(HasSpan("b", "c", bar, "name"));
-  EXPECT_TRUE(HasSpan("d", "e", bar, "input_type"));
-  EXPECT_TRUE(HasSpan("f", "g", bar, "output_type"));
+  EXPECT_TRUE(HasSpan('a', 'h', bar));
+  EXPECT_TRUE(HasSpan('b', 'c', bar, "name"));
+  EXPECT_TRUE(HasSpan('d', 'e', bar, "input_type"));
+  EXPECT_TRUE(HasSpan('f', 'g', bar, "output_type"));
 
-  EXPECT_TRUE(HasSpan("i", "p", baz));
-  EXPECT_TRUE(HasSpan("j", "k", baz, "name"));
-  EXPECT_TRUE(HasSpan("l", "m", baz, "input_type"));
-  EXPECT_TRUE(HasSpan("n", "o", baz, "output_type"));
+  EXPECT_TRUE(HasSpan('i', 'p', baz));
+  EXPECT_TRUE(HasSpan('j', 'k', baz, "name"));
+  EXPECT_TRUE(HasSpan('l', 'm', baz, "input_type"));
+  EXPECT_TRUE(HasSpan('n', 'o', baz, "output_type"));
 
   // Ignore these.
   EXPECT_TRUE(HasSpan(file_));
@@ -1900,13 +2031,13 @@
 
 TEST_F(SourceInfoTest, Options) {
   EXPECT_TRUE(Parse(
-      "/*a*/option /*b*/foo/*c*/./*d*/(/*e*/bar.baz/*f*/)/*g*/ = "
-          "/*h*/123/*i*/;/*j*/\n"
-      "/*k*/option qux = /*l*/-123/*m*/;/*n*/\n"
-      "/*o*/option corge = /*p*/abc/*q*/;/*r*/\n"
-      "/*s*/option grault = /*t*/'blah'/*u*/;/*v*/\n"
-      "/*w*/option garply = /*x*/{ yadda yadda }/*y*/;/*z*/\n"
-      "/*0*/option waldo = /*1*/123.0/*2*/;/*3*/\n"
+      "$a$option $b$foo$c$.$d$($e$bar.baz$f$)$g$ = "
+          "$h$123$i$;$j$\n"
+      "$k$option qux = $l$-123$m$;$n$\n"
+      "$o$option corge = $p$abc$q$;$r$\n"
+      "$s$option grault = $t$'blah'$u$;$v$\n"
+      "$w$option garply = $x${ yadda yadda }$y$;$z$\n"
+      "$0$option waldo = $1$123.0$2$;$3$\n"
   ));
 
   const UninterpretedOption& option1 = file_.options().uninterpreted_option(0);
@@ -1916,29 +2047,29 @@
   const UninterpretedOption& option5 = file_.options().uninterpreted_option(4);
   const UninterpretedOption& option6 = file_.options().uninterpreted_option(5);
 
-  EXPECT_TRUE(HasSpan("a", "j", file_.options()));
-  EXPECT_TRUE(HasSpan("b", "i", option1));
-  EXPECT_TRUE(HasSpan("b", "g", option1, "name"));
-  EXPECT_TRUE(HasSpan("b", "c", option1.name(0)));
-  EXPECT_TRUE(HasSpan("b", "c", option1.name(0), "name_part"));
-  EXPECT_TRUE(HasSpan("d", "g", option1.name(1)));
-  EXPECT_TRUE(HasSpan("e", "f", option1.name(1), "name_part"));
-  EXPECT_TRUE(HasSpan("h", "i", option1, "positive_int_value"));
+  EXPECT_TRUE(HasSpan('a', 'j', file_.options()));
+  EXPECT_TRUE(HasSpan('a', 'j', option1));
+  EXPECT_TRUE(HasSpan('b', 'g', option1, "name"));
+  EXPECT_TRUE(HasSpan('b', 'c', option1.name(0)));
+  EXPECT_TRUE(HasSpan('b', 'c', option1.name(0), "name_part"));
+  EXPECT_TRUE(HasSpan('d', 'g', option1.name(1)));
+  EXPECT_TRUE(HasSpan('e', 'f', option1.name(1), "name_part"));
+  EXPECT_TRUE(HasSpan('h', 'i', option1, "positive_int_value"));
 
-  EXPECT_TRUE(HasSpan("k", "n", file_.options()));
-  EXPECT_TRUE(HasSpan("l", "m", option2, "negative_int_value"));
+  EXPECT_TRUE(HasSpan('k', 'n', file_.options()));
+  EXPECT_TRUE(HasSpan('l', 'm', option2, "negative_int_value"));
 
-  EXPECT_TRUE(HasSpan("o", "r", file_.options()));
-  EXPECT_TRUE(HasSpan("p", "q", option3, "identifier_value"));
+  EXPECT_TRUE(HasSpan('o', 'r', file_.options()));
+  EXPECT_TRUE(HasSpan('p', 'q', option3, "identifier_value"));
 
-  EXPECT_TRUE(HasSpan("s", "v", file_.options()));
-  EXPECT_TRUE(HasSpan("t", "u", option4, "string_value"));
+  EXPECT_TRUE(HasSpan('s', 'v', file_.options()));
+  EXPECT_TRUE(HasSpan('t', 'u', option4, "string_value"));
 
-  EXPECT_TRUE(HasSpan("w", "z", file_.options()));
-  EXPECT_TRUE(HasSpan("x", "y", option5, "aggregate_value"));
+  EXPECT_TRUE(HasSpan('w', 'z', file_.options()));
+  EXPECT_TRUE(HasSpan('x', 'y', option5, "aggregate_value"));
 
-  EXPECT_TRUE(HasSpan("0", "3", file_.options()));
-  EXPECT_TRUE(HasSpan("1", "2", option6, "double_value"));
+  EXPECT_TRUE(HasSpan('0', '3', file_.options()));
+  EXPECT_TRUE(HasSpan('1', '2', option6, "double_value"));
 
   // Ignore these.
   EXPECT_TRUE(HasSpan(file_));
@@ -1967,22 +2098,22 @@
 TEST_F(SourceInfoTest, ScopedOptions) {
   EXPECT_TRUE(Parse(
     "message Foo {\n"
-    "  /*a*/option mopt = 1;/*b*/\n"
+    "  $a$option mopt = 1;$b$\n"
     "}\n"
     "enum Bar {\n"
-    "  /*c*/option eopt = 1;/*d*/\n"
+    "  $c$option eopt = 1;$d$\n"
     "}\n"
     "service Baz {\n"
-    "  /*e*/option sopt = 1;/*f*/\n"
+    "  $e$option sopt = 1;$f$\n"
     "  rpc M(X) returns(Y) {\n"
-    "    /*g*/option mopt = 1;/*h*/\n"
+    "    $g$option mopt = 1;$h$\n"
     "  }\n"
     "}\n"));
 
-  EXPECT_TRUE(HasSpan("a", "b", file_.message_type(0).options()));
-  EXPECT_TRUE(HasSpan("c", "d", file_.enum_type(0).options()));
-  EXPECT_TRUE(HasSpan("e", "f", file_.service(0).options()));
-  EXPECT_TRUE(HasSpan("g", "h", file_.service(0).method(0).options()));
+  EXPECT_TRUE(HasSpan('a', 'b', file_.message_type(0).options()));
+  EXPECT_TRUE(HasSpan('c', 'd', file_.enum_type(0).options()));
+  EXPECT_TRUE(HasSpan('e', 'f', file_.service(0).options()));
+  EXPECT_TRUE(HasSpan('g', 'h', file_.service(0).method(0).options()));
 
   // Ignore these.
   EXPECT_TRUE(HasSpan(file_));
@@ -2045,8 +2176,8 @@
   EXPECT_TRUE(Parse(
       "message Foo {"
       "  optional int32 bar = 1 "
-          "/*a*/[default=/*b*/123/*c*/,/*d*/opt1=123/*e*/,"
-          "/*f*/opt2='hi'/*g*/]/*h*/;"
+          "$a$[default=$b$123$c$,$d$opt1=123$e$,"
+          "$f$opt2='hi'$g$]$h$;"
       "}\n"
   ));
 
@@ -2054,10 +2185,10 @@
   const UninterpretedOption& option1 = field.options().uninterpreted_option(0);
   const UninterpretedOption& option2 = field.options().uninterpreted_option(1);
 
-  EXPECT_TRUE(HasSpan("a", "h", field.options()));
-  EXPECT_TRUE(HasSpan("b", "c", field, "default_value"));
-  EXPECT_TRUE(HasSpan("d", "e", option1));
-  EXPECT_TRUE(HasSpan("f", "g", option2));
+  EXPECT_TRUE(HasSpan('a', 'h', field.options()));
+  EXPECT_TRUE(HasSpan('b', 'c', field, "default_value"));
+  EXPECT_TRUE(HasSpan('d', 'e', option1));
+  EXPECT_TRUE(HasSpan('f', 'g', option2));
 
   // Ignore these.
   EXPECT_TRUE(HasSpan(file_));
@@ -2084,7 +2215,7 @@
   // syntax used for enum options is understood.
   EXPECT_TRUE(Parse(
       "enum Foo {"
-      "  BAR = 1 /*a*/[/*b*/opt1=123/*c*/,/*d*/opt2='hi'/*e*/]/*f*/;"
+      "  BAR = 1 $a$[$b$opt1=123$c$,$d$opt2='hi'$e$]$f$;"
       "}\n"
   ));
 
@@ -2092,9 +2223,9 @@
   const UninterpretedOption& option1 = value.options().uninterpreted_option(0);
   const UninterpretedOption& option2 = value.options().uninterpreted_option(1);
 
-  EXPECT_TRUE(HasSpan("a", "f", value.options()));
-  EXPECT_TRUE(HasSpan("b", "c", option1));
-  EXPECT_TRUE(HasSpan("d", "e", option2));
+  EXPECT_TRUE(HasSpan('a', 'f', value.options()));
+  EXPECT_TRUE(HasSpan('b', 'c', option1));
+  EXPECT_TRUE(HasSpan('d', 'e', option2));
 
   // Ignore these.
   EXPECT_TRUE(HasSpan(file_));
@@ -2113,6 +2244,127 @@
   EXPECT_TRUE(HasSpan(option2, "string_value"));
 }
 
+TEST_F(SourceInfoTest, DocComments) {
+  EXPECT_TRUE(Parse(
+      "// Foo leading\n"
+      "// line 2\n"
+      "$a$message Foo {\n"
+      "  // Foo trailing\n"
+      "  // line 2\n"
+      "\n"
+      "  // ignored\n"
+      "\n"
+      "  // bar leading\n"
+      "  $b$optional int32 bar = 1;$c$\n"
+      "  // bar trailing\n"
+      "}$d$\n"
+      "// ignored\n"
+  ));
+
+  const DescriptorProto& foo = file_.message_type(0);
+  const FieldDescriptorProto& bar = foo.field(0);
+
+  EXPECT_TRUE(HasSpanWithComment('a', 'd', foo,
+      " Foo leading\n line 2\n",
+      " Foo trailing\n line 2\n"));
+  EXPECT_TRUE(HasSpanWithComment('b', 'c', bar,
+      " bar leading\n",
+      " bar trailing\n"));
+
+  // Ignore these.
+  EXPECT_TRUE(HasSpan(file_));
+  EXPECT_TRUE(HasSpan(foo, "name"));
+  EXPECT_TRUE(HasSpan(bar, "label"));
+  EXPECT_TRUE(HasSpan(bar, "type"));
+  EXPECT_TRUE(HasSpan(bar, "name"));
+  EXPECT_TRUE(HasSpan(bar, "number"));
+}
+
+TEST_F(SourceInfoTest, DocComments2) {
+  EXPECT_TRUE(Parse(
+      "// ignored\n"
+      "syntax = \"proto2\";\n"
+      "// Foo leading\n"
+      "// line 2\n"
+      "$a$message Foo {\n"
+      "  /* Foo trailing\n"
+      "   * line 2 */\n"
+      "  // ignored\n"
+      "  /* bar leading\n"
+      "   */"
+      "  $b$optional int32 bar = 1;$c$  // bar trailing\n"
+      "  // ignored\n"
+      "}$d$\n"
+      "// ignored\n"
+      "\n"
+      "// option leading\n"
+      "$e$option baz = 123;$f$\n"
+      "// option trailing\n"
+  ));
+
+  const DescriptorProto& foo = file_.message_type(0);
+  const FieldDescriptorProto& bar = foo.field(0);
+  const UninterpretedOption& baz = file_.options().uninterpreted_option(0);
+
+  EXPECT_TRUE(HasSpanWithComment('a', 'd', foo,
+      " Foo leading\n line 2\n",
+      " Foo trailing\n line 2 "));
+  EXPECT_TRUE(HasSpanWithComment('b', 'c', bar,
+      " bar leading\n",
+      " bar trailing\n"));
+  EXPECT_TRUE(HasSpanWithComment('e', 'f', baz,
+      " option leading\n",
+      " option trailing\n"));
+
+  // Ignore these.
+  EXPECT_TRUE(HasSpan(file_));
+  EXPECT_TRUE(HasSpan(foo, "name"));
+  EXPECT_TRUE(HasSpan(bar, "label"));
+  EXPECT_TRUE(HasSpan(bar, "type"));
+  EXPECT_TRUE(HasSpan(bar, "name"));
+  EXPECT_TRUE(HasSpan(bar, "number"));
+  EXPECT_TRUE(HasSpan(file_.options()));
+  EXPECT_TRUE(HasSpan(baz, "name"));
+  EXPECT_TRUE(HasSpan(baz.name(0)));
+  EXPECT_TRUE(HasSpan(baz.name(0), "name_part"));
+  EXPECT_TRUE(HasSpan(baz, "positive_int_value"));
+}
+
+TEST_F(SourceInfoTest, DocComments3) {
+  EXPECT_TRUE(Parse(
+      "$a$message Foo {\n"
+      "  // bar leading\n"
+      "  $b$optional int32 bar = 1 [(baz.qux) = {}];$c$\n"
+      "  // bar trailing\n"
+      "}$d$\n"
+      "// ignored\n"
+  ));
+
+  const DescriptorProto& foo = file_.message_type(0);
+  const FieldDescriptorProto& bar = foo.field(0);
+
+  EXPECT_TRUE(HasSpanWithComment('b', 'c', bar,
+      " bar leading\n",
+      " bar trailing\n"));
+
+  // Ignore these.
+  EXPECT_TRUE(HasSpan(file_));
+  EXPECT_TRUE(HasSpan(foo));
+  EXPECT_TRUE(HasSpan(foo, "name"));
+  EXPECT_TRUE(HasSpan(bar, "label"));
+  EXPECT_TRUE(HasSpan(bar, "type"));
+  EXPECT_TRUE(HasSpan(bar, "name"));
+  EXPECT_TRUE(HasSpan(bar, "number"));
+  EXPECT_TRUE(HasSpan(bar.options()));
+  EXPECT_TRUE(HasSpan(bar.options().uninterpreted_option(0)));
+  EXPECT_TRUE(HasSpan(bar.options().uninterpreted_option(0), "name"));
+  EXPECT_TRUE(HasSpan(bar.options().uninterpreted_option(0).name(0)));
+  EXPECT_TRUE(HasSpan(
+      bar.options().uninterpreted_option(0).name(0), "name_part"));
+  EXPECT_TRUE(HasSpan(
+      bar.options().uninterpreted_option(0), "aggregate_value"));
+}
+
 // ===================================================================
 
 }  // anonymous namespace
diff --git a/third_party/protobuf/src/google/protobuf/compiler/plugin.h b/third_party/protobuf/src/google/protobuf/compiler/plugin.h
index 7c40333..6fa2de1 100644
--- a/third_party/protobuf/src/google/protobuf/compiler/plugin.h
+++ b/third_party/protobuf/src/google/protobuf/compiler/plugin.h
@@ -56,7 +56,6 @@
 #define GOOGLE_PROTOBUF_COMPILER_PLUGIN_H__
 
 #include <google/protobuf/stubs/common.h>
-
 namespace google {
 namespace protobuf {
 namespace compiler {
diff --git a/third_party/protobuf/src/google/protobuf/compiler/plugin.pb.cc b/third_party/protobuf/src/google/protobuf/compiler/plugin.pb.cc
index c956188..7b0b1f9 100644
--- a/third_party/protobuf/src/google/protobuf/compiler/plugin.pb.cc
+++ b/third_party/protobuf/src/google/protobuf/compiler/plugin.pb.cc
@@ -1,14 +1,17 @@
 // Generated by the protocol buffer compiler.  DO NOT EDIT!
+// source: google/protobuf/compiler/plugin.proto
 
 #define INTERNAL_SUPPRESS_PROTOBUF_FIELD_DEPRECATION
 #include "google/protobuf/compiler/plugin.pb.h"
 
 #include <algorithm>
 
+#include <google/protobuf/stubs/common.h>
 #include <google/protobuf/stubs/once.h>
 #include <google/protobuf/io/coded_stream.h>
 #include <google/protobuf/wire_format_lite_inl.h>
 #include <google/protobuf/descriptor.h>
+#include <google/protobuf/generated_message_reflection.h>
 #include <google/protobuf/reflection_ops.h>
 #include <google/protobuf/wire_format.h>
 // @@protoc_insertion_point(includes)
@@ -124,6 +127,7 @@
   if (already_here) return;
   already_here = true;
   GOOGLE_PROTOBUF_VERIFY_VERSION;
+
   ::google::protobuf::protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
   ::google::protobuf::DescriptorPool::InternalAddGeneratedFile(
     "\n%google/protobuf/compiler/plugin.proto\022"
@@ -253,7 +257,7 @@
         if (input->ExpectTag(18)) goto parse_parameter;
         break;
       }
-      
+
       // optional string parameter = 2;
       case 2: {
         if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
@@ -270,7 +274,7 @@
         if (input->ExpectTag(122)) goto parse_proto_file;
         break;
       }
-      
+
       // repeated .google.protobuf.FileDescriptorProto proto_file = 15;
       case 15: {
         if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
@@ -285,14 +289,15 @@
         if (input->ExpectAtEnd()) return true;
         break;
       }
-      
+
       default: {
       handle_uninterpreted:
         if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
             ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
           return true;
         }
-        DO_(::google::protobuf::internal::WireFormatLite::SkipField(input, tag, mutable_unknown_fields()));
+        DO_(::google::protobuf::internal::WireFormatLite::SkipField(
+              input, tag, mutable_unknown_fields()));
         break;
       }
     }
@@ -311,7 +316,7 @@
     ::google::protobuf::internal::WireFormatLite::WriteString(
       1, this->file_to_generate(i), output);
   }
-  
+
   // optional string parameter = 2;
   if (has_parameter()) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8String(
@@ -320,13 +325,13 @@
     ::google::protobuf::internal::WireFormatLite::WriteString(
       2, this->parameter(), output);
   }
-  
+
   // repeated .google.protobuf.FileDescriptorProto proto_file = 15;
   for (int i = 0; i < this->proto_file_size(); i++) {
     ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
       15, this->proto_file(i), output);
   }
-  
+
   if (!unknown_fields().empty()) {
     ::google::protobuf::internal::WireFormatLite::SerializeUnknownFields(
         unknown_fields(), output);
@@ -343,7 +348,7 @@
     target = ::google::protobuf::internal::WireFormatLite::
       WriteStringToArray(1, this->file_to_generate(i), target);
   }
-  
+
   // optional string parameter = 2;
   if (has_parameter()) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8String(
@@ -353,14 +358,14 @@
       ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
         2, this->parameter(), target);
   }
-  
+
   // repeated .google.protobuf.FileDescriptorProto proto_file = 15;
   for (int i = 0; i < this->proto_file_size(); i++) {
     target = ::google::protobuf::internal::WireFormatLite::
       WriteMessageNoVirtualToArray(
         15, this->proto_file(i), target);
   }
-  
+
   if (!unknown_fields().empty()) {
     target = ::google::protobuf::internal::WireFormatLite::SerializeUnknownFieldsToArray(
         unknown_fields(), target);
@@ -370,7 +375,7 @@
 
 int CodeGeneratorRequest::ByteSize() const {
   int total_size = 0;
-  
+
   if (_has_bits_[1 / 32] & (0xffu << (1 % 32))) {
     // optional string parameter = 2;
     if (has_parameter()) {
@@ -378,7 +383,7 @@
         ::google::protobuf::internal::WireFormatLite::StringSize(
           this->parameter());
     }
-    
+
   }
   // repeated string file_to_generate = 1;
   total_size += 1 * this->file_to_generate_size();
@@ -386,7 +391,7 @@
     total_size += ::google::protobuf::internal::WireFormatLite::StringSize(
       this->file_to_generate(i));
   }
-  
+
   // repeated .google.protobuf.FileDescriptorProto proto_file = 15;
   total_size += 1 * this->proto_file_size();
   for (int i = 0; i < this->proto_file_size(); i++) {
@@ -394,7 +399,7 @@
       ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
         this->proto_file(i));
   }
-  
+
   if (!unknown_fields().empty()) {
     total_size +=
       ::google::protobuf::internal::WireFormatLite::ComputeUnknownFieldsSize(
@@ -443,7 +448,7 @@
 }
 
 bool CodeGeneratorRequest::IsInitialized() const {
-  
+
   for (int i = 0; i < proto_file_size(); i++) {
     if (!this->proto_file(i).IsInitialized()) return false;
   }
@@ -582,7 +587,7 @@
         if (input->ExpectTag(18)) goto parse_insertion_point;
         break;
       }
-      
+
       // optional string insertion_point = 2;
       case 2: {
         if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
@@ -599,7 +604,7 @@
         if (input->ExpectTag(122)) goto parse_content;
         break;
       }
-      
+
       // optional string content = 15;
       case 15: {
         if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
@@ -616,14 +621,15 @@
         if (input->ExpectAtEnd()) return true;
         break;
       }
-      
+
       default: {
       handle_uninterpreted:
         if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
             ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
           return true;
         }
-        DO_(::google::protobuf::internal::WireFormatLite::SkipField(input, tag, mutable_unknown_fields()));
+        DO_(::google::protobuf::internal::WireFormatLite::SkipField(
+              input, tag, mutable_unknown_fields()));
         break;
       }
     }
@@ -642,7 +648,7 @@
     ::google::protobuf::internal::WireFormatLite::WriteString(
       1, this->name(), output);
   }
-  
+
   // optional string insertion_point = 2;
   if (has_insertion_point()) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8String(
@@ -651,7 +657,7 @@
     ::google::protobuf::internal::WireFormatLite::WriteString(
       2, this->insertion_point(), output);
   }
-  
+
   // optional string content = 15;
   if (has_content()) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8String(
@@ -660,7 +666,7 @@
     ::google::protobuf::internal::WireFormatLite::WriteString(
       15, this->content(), output);
   }
-  
+
   if (!unknown_fields().empty()) {
     ::google::protobuf::internal::WireFormatLite::SerializeUnknownFields(
         unknown_fields(), output);
@@ -678,7 +684,7 @@
       ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
         1, this->name(), target);
   }
-  
+
   // optional string insertion_point = 2;
   if (has_insertion_point()) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8String(
@@ -688,7 +694,7 @@
       ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
         2, this->insertion_point(), target);
   }
-  
+
   // optional string content = 15;
   if (has_content()) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8String(
@@ -698,7 +704,7 @@
       ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
         15, this->content(), target);
   }
-  
+
   if (!unknown_fields().empty()) {
     target = ::google::protobuf::internal::WireFormatLite::SerializeUnknownFieldsToArray(
         unknown_fields(), target);
@@ -708,7 +714,7 @@
 
 int CodeGeneratorResponse_File::ByteSize() const {
   int total_size = 0;
-  
+
   if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) {
     // optional string name = 1;
     if (has_name()) {
@@ -716,21 +722,21 @@
         ::google::protobuf::internal::WireFormatLite::StringSize(
           this->name());
     }
-    
+
     // optional string insertion_point = 2;
     if (has_insertion_point()) {
       total_size += 1 +
         ::google::protobuf::internal::WireFormatLite::StringSize(
           this->insertion_point());
     }
-    
+
     // optional string content = 15;
     if (has_content()) {
       total_size += 1 +
         ::google::protobuf::internal::WireFormatLite::StringSize(
           this->content());
     }
-    
+
   }
   if (!unknown_fields().empty()) {
     total_size +=
@@ -784,7 +790,7 @@
 }
 
 bool CodeGeneratorResponse_File::IsInitialized() const {
-  
+
   return true;
 }
 
@@ -902,7 +908,7 @@
         if (input->ExpectTag(122)) goto parse_file;
         break;
       }
-      
+
       // repeated .google.protobuf.compiler.CodeGeneratorResponse.File file = 15;
       case 15: {
         if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
@@ -917,14 +923,15 @@
         if (input->ExpectAtEnd()) return true;
         break;
       }
-      
+
       default: {
       handle_uninterpreted:
         if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
             ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
           return true;
         }
-        DO_(::google::protobuf::internal::WireFormatLite::SkipField(input, tag, mutable_unknown_fields()));
+        DO_(::google::protobuf::internal::WireFormatLite::SkipField(
+              input, tag, mutable_unknown_fields()));
         break;
       }
     }
@@ -943,13 +950,13 @@
     ::google::protobuf::internal::WireFormatLite::WriteString(
       1, this->error(), output);
   }
-  
+
   // repeated .google.protobuf.compiler.CodeGeneratorResponse.File file = 15;
   for (int i = 0; i < this->file_size(); i++) {
     ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
       15, this->file(i), output);
   }
-  
+
   if (!unknown_fields().empty()) {
     ::google::protobuf::internal::WireFormatLite::SerializeUnknownFields(
         unknown_fields(), output);
@@ -967,14 +974,14 @@
       ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
         1, this->error(), target);
   }
-  
+
   // repeated .google.protobuf.compiler.CodeGeneratorResponse.File file = 15;
   for (int i = 0; i < this->file_size(); i++) {
     target = ::google::protobuf::internal::WireFormatLite::
       WriteMessageNoVirtualToArray(
         15, this->file(i), target);
   }
-  
+
   if (!unknown_fields().empty()) {
     target = ::google::protobuf::internal::WireFormatLite::SerializeUnknownFieldsToArray(
         unknown_fields(), target);
@@ -984,7 +991,7 @@
 
 int CodeGeneratorResponse::ByteSize() const {
   int total_size = 0;
-  
+
   if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) {
     // optional string error = 1;
     if (has_error()) {
@@ -992,7 +999,7 @@
         ::google::protobuf::internal::WireFormatLite::StringSize(
           this->error());
     }
-    
+
   }
   // repeated .google.protobuf.compiler.CodeGeneratorResponse.File file = 15;
   total_size += 1 * this->file_size();
@@ -1001,7 +1008,7 @@
       ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
         this->file(i));
   }
-  
+
   if (!unknown_fields().empty()) {
     total_size +=
       ::google::protobuf::internal::WireFormatLite::ComputeUnknownFieldsSize(
@@ -1049,7 +1056,7 @@
 }
 
 bool CodeGeneratorResponse::IsInitialized() const {
-  
+
   return true;
 }
 
diff --git a/third_party/protobuf/src/google/protobuf/compiler/plugin.pb.h b/third_party/protobuf/src/google/protobuf/compiler/plugin.pb.h
index 64246fc..46478c7 100644
--- a/third_party/protobuf/src/google/protobuf/compiler/plugin.pb.h
+++ b/third_party/protobuf/src/google/protobuf/compiler/plugin.pb.h
@@ -20,10 +20,10 @@
 #endif
 
 #include <google/protobuf/generated_message_util.h>
+#include <google/protobuf/message.h>
 #include <google/protobuf/repeated_field.h>
 #include <google/protobuf/extension_set.h>
 #include <google/protobuf/unknown_field_set.h>
-#include <google/protobuf/generated_message_reflection.h>
 #include "google/protobuf/descriptor.pb.h"
 // @@protoc_insertion_point(includes)
 
@@ -46,29 +46,29 @@
  public:
   CodeGeneratorRequest();
   virtual ~CodeGeneratorRequest();
-  
+
   CodeGeneratorRequest(const CodeGeneratorRequest& from);
-  
+
   inline CodeGeneratorRequest& operator=(const CodeGeneratorRequest& from) {
     CopyFrom(from);
     return *this;
   }
-  
+
   inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
     return _unknown_fields_;
   }
-  
+
   inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
     return &_unknown_fields_;
   }
-  
+
   static const ::google::protobuf::Descriptor* descriptor();
   static const CodeGeneratorRequest& default_instance();
-  
+
   void Swap(CodeGeneratorRequest* other);
-  
+
   // implements Message ----------------------------------------------
-  
+
   CodeGeneratorRequest* New() const;
   void CopyFrom(const ::google::protobuf::Message& from);
   void MergeFrom(const ::google::protobuf::Message& from);
@@ -76,7 +76,7 @@
   void MergeFrom(const CodeGeneratorRequest& from);
   void Clear();
   bool IsInitialized() const;
-  
+
   int ByteSize() const;
   bool MergePartialFromCodedStream(
       ::google::protobuf::io::CodedInputStream* input);
@@ -89,13 +89,13 @@
   void SharedDtor();
   void SetCachedSize(int size) const;
   public:
-  
+
   ::google::protobuf::Metadata GetMetadata() const;
-  
+
   // nested types ----------------------------------------------------
-  
+
   // accessors -------------------------------------------------------
-  
+
   // repeated string file_to_generate = 1;
   inline int file_to_generate_size() const;
   inline void clear_file_to_generate();
@@ -111,7 +111,7 @@
   inline void add_file_to_generate(const char* value, size_t size);
   inline const ::google::protobuf::RepeatedPtrField< ::std::string>& file_to_generate() const;
   inline ::google::protobuf::RepeatedPtrField< ::std::string>* mutable_file_to_generate();
-  
+
   // optional string parameter = 2;
   inline bool has_parameter() const;
   inline void clear_parameter();
@@ -122,7 +122,8 @@
   inline void set_parameter(const char* value, size_t size);
   inline ::std::string* mutable_parameter();
   inline ::std::string* release_parameter();
-  
+  inline void set_allocated_parameter(::std::string* parameter);
+
   // repeated .google.protobuf.FileDescriptorProto proto_file = 15;
   inline int proto_file_size() const;
   inline void clear_proto_file();
@@ -134,25 +135,25 @@
       proto_file() const;
   inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >*
       mutable_proto_file();
-  
+
   // @@protoc_insertion_point(class_scope:google.protobuf.compiler.CodeGeneratorRequest)
  private:
   inline void set_has_parameter();
   inline void clear_has_parameter();
-  
+
   ::google::protobuf::UnknownFieldSet _unknown_fields_;
-  
+
   ::google::protobuf::RepeatedPtrField< ::std::string> file_to_generate_;
   ::std::string* parameter_;
   ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto > proto_file_;
-  
+
   mutable int _cached_size_;
   ::google::protobuf::uint32 _has_bits_[(3 + 31) / 32];
-  
+
   friend void LIBPROTOC_EXPORT protobuf_AddDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto();
   friend void protobuf_AssignDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto();
   friend void protobuf_ShutdownFile_google_2fprotobuf_2fcompiler_2fplugin_2eproto();
-  
+
   void InitAsDefaultInstance();
   static CodeGeneratorRequest* default_instance_;
 };
@@ -162,29 +163,29 @@
  public:
   CodeGeneratorResponse_File();
   virtual ~CodeGeneratorResponse_File();
-  
+
   CodeGeneratorResponse_File(const CodeGeneratorResponse_File& from);
-  
+
   inline CodeGeneratorResponse_File& operator=(const CodeGeneratorResponse_File& from) {
     CopyFrom(from);
     return *this;
   }
-  
+
   inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
     return _unknown_fields_;
   }
-  
+
   inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
     return &_unknown_fields_;
   }
-  
+
   static const ::google::protobuf::Descriptor* descriptor();
   static const CodeGeneratorResponse_File& default_instance();
-  
+
   void Swap(CodeGeneratorResponse_File* other);
-  
+
   // implements Message ----------------------------------------------
-  
+
   CodeGeneratorResponse_File* New() const;
   void CopyFrom(const ::google::protobuf::Message& from);
   void MergeFrom(const ::google::protobuf::Message& from);
@@ -192,7 +193,7 @@
   void MergeFrom(const CodeGeneratorResponse_File& from);
   void Clear();
   bool IsInitialized() const;
-  
+
   int ByteSize() const;
   bool MergePartialFromCodedStream(
       ::google::protobuf::io::CodedInputStream* input);
@@ -205,13 +206,13 @@
   void SharedDtor();
   void SetCachedSize(int size) const;
   public:
-  
+
   ::google::protobuf::Metadata GetMetadata() const;
-  
+
   // nested types ----------------------------------------------------
-  
+
   // accessors -------------------------------------------------------
-  
+
   // optional string name = 1;
   inline bool has_name() const;
   inline void clear_name();
@@ -222,7 +223,8 @@
   inline void set_name(const char* value, size_t size);
   inline ::std::string* mutable_name();
   inline ::std::string* release_name();
-  
+  inline void set_allocated_name(::std::string* name);
+
   // optional string insertion_point = 2;
   inline bool has_insertion_point() const;
   inline void clear_insertion_point();
@@ -233,7 +235,8 @@
   inline void set_insertion_point(const char* value, size_t size);
   inline ::std::string* mutable_insertion_point();
   inline ::std::string* release_insertion_point();
-  
+  inline void set_allocated_insertion_point(::std::string* insertion_point);
+
   // optional string content = 15;
   inline bool has_content() const;
   inline void clear_content();
@@ -244,7 +247,8 @@
   inline void set_content(const char* value, size_t size);
   inline ::std::string* mutable_content();
   inline ::std::string* release_content();
-  
+  inline void set_allocated_content(::std::string* content);
+
   // @@protoc_insertion_point(class_scope:google.protobuf.compiler.CodeGeneratorResponse.File)
  private:
   inline void set_has_name();
@@ -253,20 +257,20 @@
   inline void clear_has_insertion_point();
   inline void set_has_content();
   inline void clear_has_content();
-  
+
   ::google::protobuf::UnknownFieldSet _unknown_fields_;
-  
+
   ::std::string* name_;
   ::std::string* insertion_point_;
   ::std::string* content_;
-  
+
   mutable int _cached_size_;
   ::google::protobuf::uint32 _has_bits_[(3 + 31) / 32];
-  
+
   friend void LIBPROTOC_EXPORT protobuf_AddDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto();
   friend void protobuf_AssignDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto();
   friend void protobuf_ShutdownFile_google_2fprotobuf_2fcompiler_2fplugin_2eproto();
-  
+
   void InitAsDefaultInstance();
   static CodeGeneratorResponse_File* default_instance_;
 };
@@ -276,29 +280,29 @@
  public:
   CodeGeneratorResponse();
   virtual ~CodeGeneratorResponse();
-  
+
   CodeGeneratorResponse(const CodeGeneratorResponse& from);
-  
+
   inline CodeGeneratorResponse& operator=(const CodeGeneratorResponse& from) {
     CopyFrom(from);
     return *this;
   }
-  
+
   inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
     return _unknown_fields_;
   }
-  
+
   inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
     return &_unknown_fields_;
   }
-  
+
   static const ::google::protobuf::Descriptor* descriptor();
   static const CodeGeneratorResponse& default_instance();
-  
+
   void Swap(CodeGeneratorResponse* other);
-  
+
   // implements Message ----------------------------------------------
-  
+
   CodeGeneratorResponse* New() const;
   void CopyFrom(const ::google::protobuf::Message& from);
   void MergeFrom(const ::google::protobuf::Message& from);
@@ -306,7 +310,7 @@
   void MergeFrom(const CodeGeneratorResponse& from);
   void Clear();
   bool IsInitialized() const;
-  
+
   int ByteSize() const;
   bool MergePartialFromCodedStream(
       ::google::protobuf::io::CodedInputStream* input);
@@ -319,15 +323,15 @@
   void SharedDtor();
   void SetCachedSize(int size) const;
   public:
-  
+
   ::google::protobuf::Metadata GetMetadata() const;
-  
+
   // nested types ----------------------------------------------------
-  
+
   typedef CodeGeneratorResponse_File File;
-  
+
   // accessors -------------------------------------------------------
-  
+
   // optional string error = 1;
   inline bool has_error() const;
   inline void clear_error();
@@ -338,7 +342,8 @@
   inline void set_error(const char* value, size_t size);
   inline ::std::string* mutable_error();
   inline ::std::string* release_error();
-  
+  inline void set_allocated_error(::std::string* error);
+
   // repeated .google.protobuf.compiler.CodeGeneratorResponse.File file = 15;
   inline int file_size() const;
   inline void clear_file();
@@ -350,24 +355,24 @@
       file() const;
   inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::compiler::CodeGeneratorResponse_File >*
       mutable_file();
-  
+
   // @@protoc_insertion_point(class_scope:google.protobuf.compiler.CodeGeneratorResponse)
  private:
   inline void set_has_error();
   inline void clear_has_error();
-  
+
   ::google::protobuf::UnknownFieldSet _unknown_fields_;
-  
+
   ::std::string* error_;
   ::google::protobuf::RepeatedPtrField< ::google::protobuf::compiler::CodeGeneratorResponse_File > file_;
-  
+
   mutable int _cached_size_;
   ::google::protobuf::uint32 _has_bits_[(2 + 31) / 32];
-  
+
   friend void LIBPROTOC_EXPORT protobuf_AddDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto();
   friend void protobuf_AssignDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto();
   friend void protobuf_ShutdownFile_google_2fprotobuf_2fcompiler_2fplugin_2eproto();
-  
+
   void InitAsDefaultInstance();
   static CodeGeneratorResponse* default_instance_;
 };
@@ -479,6 +484,18 @@
     return temp;
   }
 }
+inline void CodeGeneratorRequest::set_allocated_parameter(::std::string* parameter) {
+  if (parameter_ != &::google::protobuf::internal::kEmptyString) {
+    delete parameter_;
+  }
+  if (parameter) {
+    set_has_parameter();
+    parameter_ = parameter;
+  } else {
+    clear_has_parameter();
+    parameter_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
+  }
+}
 
 // repeated .google.protobuf.FileDescriptorProto proto_file = 15;
 inline int CodeGeneratorRequest::proto_file_size() const {
@@ -566,6 +583,18 @@
     return temp;
   }
 }
+inline void CodeGeneratorResponse_File::set_allocated_name(::std::string* name) {
+  if (name_ != &::google::protobuf::internal::kEmptyString) {
+    delete name_;
+  }
+  if (name) {
+    set_has_name();
+    name_ = name;
+  } else {
+    clear_has_name();
+    name_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
+  }
+}
 
 // optional string insertion_point = 2;
 inline bool CodeGeneratorResponse_File::has_insertion_point() const {
@@ -624,6 +653,18 @@
     return temp;
   }
 }
+inline void CodeGeneratorResponse_File::set_allocated_insertion_point(::std::string* insertion_point) {
+  if (insertion_point_ != &::google::protobuf::internal::kEmptyString) {
+    delete insertion_point_;
+  }
+  if (insertion_point) {
+    set_has_insertion_point();
+    insertion_point_ = insertion_point;
+  } else {
+    clear_has_insertion_point();
+    insertion_point_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
+  }
+}
 
 // optional string content = 15;
 inline bool CodeGeneratorResponse_File::has_content() const {
@@ -682,6 +723,18 @@
     return temp;
   }
 }
+inline void CodeGeneratorResponse_File::set_allocated_content(::std::string* content) {
+  if (content_ != &::google::protobuf::internal::kEmptyString) {
+    delete content_;
+  }
+  if (content) {
+    set_has_content();
+    content_ = content;
+  } else {
+    clear_has_content();
+    content_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
+  }
+}
 
 // -------------------------------------------------------------------
 
@@ -744,6 +797,18 @@
     return temp;
   }
 }
+inline void CodeGeneratorResponse::set_allocated_error(::std::string* error) {
+  if (error_ != &::google::protobuf::internal::kEmptyString) {
+    delete error_;
+  }
+  if (error) {
+    set_has_error();
+    error_ = error;
+  } else {
+    clear_has_error();
+    error_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
+  }
+}
 
 // repeated .google.protobuf.compiler.CodeGeneratorResponse.File file = 15;
 inline int CodeGeneratorResponse::file_size() const {
diff --git a/third_party/protobuf/src/google/protobuf/compiler/python/python_generator.cc b/third_party/protobuf/src/google/protobuf/compiler/python/python_generator.cc
index 9b10937..211ac70 100644
--- a/third_party/protobuf/src/google/protobuf/compiler/python/python_generator.cc
+++ b/third_party/protobuf/src/google/protobuf/compiler/python/python_generator.cc
@@ -52,6 +52,7 @@
 #include <google/protobuf/descriptor.pb.h>
 
 #include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/stringprintf.h>
 #include <google/protobuf/io/printer.h>
 #include <google/protobuf/descriptor.h>
 #include <google/protobuf/io/zero_copy_stream.h>
@@ -106,6 +107,12 @@
 const char kDescriptorKey[] = "DESCRIPTOR";
 
 
+// Does the file have top-level enums?
+inline bool HasTopLevelEnums(const FileDescriptor *file) {
+  return file->enum_type_count() > 0;
+}
+
+
 // Should we generate generic services for this file?
 inline bool HasGenericServices(const FileDescriptor *file) {
   return file->service_count() > 0 &&
@@ -120,13 +127,21 @@
   // TODO(robinson): Allow parameterization of Python version?
   printer->Print(
       "# Generated by the protocol buffer compiler.  DO NOT EDIT!\n"
-      "\n"
-      "from google.protobuf import descriptor\n"
-      "from google.protobuf import message\n"
-      "from google.protobuf import reflection\n");
+      "# source: $filename$\n"
+      "\n",
+      "filename", file->name());
+  if (HasTopLevelEnums(file)) {
+    printer->Print(
+        "from google.protobuf.internal import enum_type_wrapper\n");
+  }
+  printer->Print(
+      "from google.protobuf import descriptor as _descriptor\n"
+      "from google.protobuf import message as _message\n"
+      "from google.protobuf import reflection as _reflection\n"
+      );
   if (HasGenericServices(file)) {
     printer->Print(
-        "from google.protobuf import service\n"
+        "from google.protobuf import service as _service\n"
         "from google.protobuf import service_reflection\n");
   }
 
@@ -204,12 +219,12 @@
     case FieldDescriptor::CPPTYPE_STRING:
       if (field.type() == FieldDescriptor::TYPE_STRING) {
         return "unicode(\"" + CEscape(field.default_value_string()) +
-            "\", \"utf-8\")";
+                        "\", \"utf-8\")";
       } else {
         return "\"" + CEscape(field.default_value_string()) + "\"";
       }
-    case FieldDescriptor::CPPTYPE_MESSAGE:
-      return "None";
+      case FieldDescriptor::CPPTYPE_MESSAGE:
+          return "None";
   }
   // (We could add a default case above but then we wouldn't get the nice
   // compiler warning when a new type is added.)
@@ -270,6 +285,11 @@
   // since they need to call static RegisterExtension() methods on these
   // classes.
   FixForeignFieldsInExtensions();
+  // Descriptor options may have custom extensions. These custom options
+  // can only be successfully parsed after we register corresponding
+  // extensions. Therefore we parse all options again here to recognize
+  // custom options that may be unknown when we define the descriptors.
+  FixAllDescriptorOptions();
   if (HasGenericServices(file)) {
     PrintServices();
   }
@@ -288,6 +308,13 @@
                     module_name);
   }
   printer_->Print("\n");
+
+  // Print public imports.
+  for (int i = 0; i < file_->public_dependency_count(); ++i) {
+    string module_name = ModuleName(file_->public_dependency(i)->name());
+    printer_->Print("from $module$ import *\n", "module", module_name);
+  }
+  printer_->Print("\n");
 }
 
 // Prints the single file descriptor for this file.
@@ -297,7 +324,7 @@
   m["name"] = file_->name();
   m["package"] = file_->package();
   const char file_descriptor_template[] =
-      "$descriptor_name$ = descriptor.FileDescriptor(\n"
+      "$descriptor_name$ = _descriptor.FileDescriptor(\n"
       "  name='$name$',\n"
       "  package='$package$',\n";
   printer_->Print(m, file_descriptor_template);
@@ -321,6 +348,11 @@
   for (int i = 0; i < file_->enum_type_count(); ++i) {
     const EnumDescriptor& enum_descriptor = *file_->enum_type(i);
     PrintEnum(enum_descriptor);
+    printer_->Print("$name$ = "
+                    "enum_type_wrapper.EnumTypeWrapper($descriptor_name$)",
+                    "name", enum_descriptor.name(),
+                    "descriptor_name",
+                    ModuleLevelDescriptorName(enum_descriptor));
     printer_->Print("\n");
 
     for (int j = 0; j < enum_descriptor.value_count(); ++j) {
@@ -355,7 +387,7 @@
   m["full_name"] = enum_descriptor.full_name();
   m["file"] = kDescriptorKey;
   const char enum_descriptor_template[] =
-      "$descriptor_name$ = descriptor.EnumDescriptor(\n"
+      "$descriptor_name$ = _descriptor.EnumDescriptor(\n"
       "  name='$name$',\n"
       "  full_name='$full_name$',\n"
       "  filename=None,\n"
@@ -436,7 +468,7 @@
   descriptor.options().SerializeToString(&options_string);
 
   printer_->Print(
-      "$service_name$ = descriptor.ServiceDescriptor(\n",
+      "$service_name$ = _descriptor.ServiceDescriptor(\n",
       "service_name", service_name);
   printer_->Indent();
   map<string, string> m;
@@ -459,7 +491,6 @@
   printer_->Print("methods=[\n");
   for (int i = 0; i < descriptor.method_count(); ++i) {
     const MethodDescriptor* method = descriptor.method(i);
-    string options_string;
     method->options().SerializeToString(&options_string);
 
     m.clear();
@@ -470,7 +501,7 @@
     m["input_type"] = ModuleLevelDescriptorName(*(method->input_type()));
     m["output_type"] = ModuleLevelDescriptorName(*(method->output_type()));
     m["options_value"] = OptionsValue("MethodOptions", options_string);
-    printer_->Print("descriptor.MethodDescriptor(\n");
+    printer_->Print("_descriptor.MethodDescriptor(\n");
     printer_->Indent();
     printer_->Print(
         m,
@@ -491,7 +522,7 @@
 
 void Generator::PrintServiceClass(const ServiceDescriptor& descriptor) const {
   // Print the service.
-  printer_->Print("class $class_name$(service.Service):\n",
+  printer_->Print("class $class_name$(_service.Service):\n",
                   "class_name", descriptor.name());
   printer_->Indent();
   printer_->Print(
@@ -523,7 +554,7 @@
   PrintNestedDescriptors(message_descriptor);
 
   printer_->Print("\n");
-  printer_->Print("$descriptor_name$ = descriptor.Descriptor(\n",
+  printer_->Print("$descriptor_name$ = _descriptor.Descriptor(\n",
                   "descriptor_name",
                   ModuleLevelDescriptorName(message_descriptor));
   printer_->Indent();
@@ -618,10 +649,10 @@
 // Mutually recursive with PrintNestedMessages().
 void Generator::PrintMessage(
     const Descriptor& message_descriptor) const {
-  printer_->Print("class $name$(message.Message):\n", "name",
+  printer_->Print("class $name$(_message.Message):\n", "name",
                   message_descriptor.name());
   printer_->Indent();
-  printer_->Print("__metaclass__ = reflection.GeneratedProtocolMessageType\n");
+  printer_->Print("__metaclass__ = _reflection.GeneratedProtocolMessageType\n");
   PrintNestedMessages(message_descriptor);
   map<string, string> m;
   m["descriptor_key"] = kDescriptorKey;
@@ -779,6 +810,7 @@
   for (int i = 0; i < file_->message_type_count(); ++i) {
     FixForeignFieldsInNestedExtensions(*file_->message_type(i));
   }
+  printer_->Print("\n");
 }
 
 void Generator::FixForeignFieldsInExtension(
@@ -829,7 +861,7 @@
   m["options"] = OptionsValue("EnumValueOptions", options_string);
   printer_->Print(
       m,
-      "descriptor.EnumValueDescriptor(\n"
+      "_descriptor.EnumValueDescriptor(\n"
       "  name='$name$', index=$index$, number=$number$,\n"
       "  options=$options$,\n"
       "  type=None)");
@@ -843,7 +875,7 @@
     return "None";
   } else {
     string full_class_name = "descriptor_pb2." + class_name;
-    return "descriptor._ParseOptions(" + full_class_name + "(), '"
+    return "_descriptor._ParseOptions(" + full_class_name + "(), '"
         + CEscape(serialized_options)+ "')";
   }
 }
@@ -869,7 +901,7 @@
   // these fields in correctly after all referenced descriptors have been
   // defined and/or imported (see FixForeignFieldsInDescriptors()).
   const char field_descriptor_decl[] =
-    "descriptor.FieldDescriptor(\n"
+    "_descriptor.FieldDescriptor(\n"
     "  name='$name$', full_name='$full_name$', index=$index$,\n"
     "  number=$number$, type=$type$, cpp_type=$cpp_type$, label=$label$,\n"
     "  has_default_value=$has_default_value$, default_value=$default_value$,\n"
@@ -1000,6 +1032,125 @@
                   "serialized_end", SimpleItoa(offset + sp.size()));
 }
 
+namespace {
+void PrintDescriptorOptionsFixingCode(const string& descriptor,
+                                      const string& options,
+                                      io::Printer* printer) {
+  // TODO(xiaofeng): I have added a method _SetOptions() to DescriptorBase
+  // in proto2 python runtime but it couldn't be used here because appengine
+  // uses a snapshot version of the library in which the new method is not
+  // yet present. After appengine has synced their runtime library, the code
+  // below should be cleaned up to use _SetOptions().
+  printer->Print(
+      "$descriptor$.has_options = True\n"
+      "$descriptor$._options = $options$\n",
+      "descriptor", descriptor, "options", options);
+}
+}  // namespace
+
+// Prints expressions that set the options field of all descriptors.
+void Generator::FixAllDescriptorOptions() const {
+  // Prints an expression that sets the file descriptor's options.
+  string file_options = OptionsValue(
+      "FileOptions", file_->options().SerializeAsString());
+  if (file_options != "None") {
+    PrintDescriptorOptionsFixingCode(kDescriptorKey, file_options, printer_);
+  }
+  // Prints expressions that set the options for all top level enums.
+  for (int i = 0; i < file_->enum_type_count(); ++i) {
+    const EnumDescriptor& enum_descriptor = *file_->enum_type(i);
+    FixOptionsForEnum(enum_descriptor);
+  }
+  // Prints expressions that set the options for all top level extensions.
+  for (int i = 0; i < file_->extension_count(); ++i) {
+    const FieldDescriptor& field = *file_->extension(i);
+    FixOptionsForField(field);
+  }
+  // Prints expressions that set the options for all messages, nested enums,
+  // nested extensions and message fields.
+  for (int i = 0; i < file_->message_type_count(); ++i) {
+    FixOptionsForMessage(*file_->message_type(i));
+  }
+}
+
+// Prints expressions that set the options for an enum descriptor and its
+// value descriptors.
+void Generator::FixOptionsForEnum(const EnumDescriptor& enum_descriptor) const {
+  string descriptor_name = ModuleLevelDescriptorName(enum_descriptor);
+  string enum_options = OptionsValue(
+      "EnumOptions", enum_descriptor.options().SerializeAsString());
+  if (enum_options != "None") {
+    PrintDescriptorOptionsFixingCode(descriptor_name, enum_options, printer_);
+  }
+  for (int i = 0; i < enum_descriptor.value_count(); ++i) {
+    const EnumValueDescriptor& value_descriptor = *enum_descriptor.value(i);
+    string value_options = OptionsValue(
+        "EnumValueOptions", value_descriptor.options().SerializeAsString());
+    if (value_options != "None") {
+      PrintDescriptorOptionsFixingCode(
+          StringPrintf("%s.values_by_name[\"%s\"]", descriptor_name.c_str(),
+                       value_descriptor.name().c_str()),
+          value_options, printer_);
+    }
+  }
+}
+
+// Prints expressions that set the options for field descriptors (including
+// extensions).
+void Generator::FixOptionsForField(
+    const FieldDescriptor& field) const {
+  string field_options = OptionsValue(
+      "FieldOptions", field.options().SerializeAsString());
+  if (field_options != "None") {
+    string field_name;
+    if (field.is_extension()) {
+      if (field.extension_scope() == NULL) {
+        // Top level extensions.
+        field_name = field.name();
+      } else {
+        field_name = FieldReferencingExpression(
+            field.extension_scope(), field, "extensions_by_name");
+      }
+    } else {
+      field_name = FieldReferencingExpression(
+          field.containing_type(), field, "fields_by_name");
+    }
+    PrintDescriptorOptionsFixingCode(field_name, field_options, printer_);
+  }
+}
+
+// Prints expressions that set the options for a message and all its inner
+// types (nested messages, nested enums, extensions, fields).
+void Generator::FixOptionsForMessage(const Descriptor& descriptor) const {
+  // Nested messages.
+  for (int i = 0; i < descriptor.nested_type_count(); ++i) {
+    FixOptionsForMessage(*descriptor.nested_type(i));
+  }
+  // Enums.
+  for (int i = 0; i < descriptor.enum_type_count(); ++i) {
+    FixOptionsForEnum(*descriptor.enum_type(i));
+  }
+  // Fields.
+  for (int i = 0; i < descriptor.field_count(); ++i) {
+    const FieldDescriptor& field = *descriptor.field(i);
+    FixOptionsForField(field);
+  }
+  // Extensions.
+  for (int i = 0; i < descriptor.extension_count(); ++i) {
+    const FieldDescriptor& field = *descriptor.extension(i);
+    FixOptionsForField(field);
+  }
+  // Message option for this message.
+  string message_options = OptionsValue(
+      "MessageOptions", descriptor.options().SerializeAsString());
+  if (message_options != "None") {
+    string descriptor_name = ModuleLevelDescriptorName(descriptor);
+    PrintDescriptorOptionsFixingCode(descriptor_name,
+                                     message_options,
+                                     printer_);
+  }
+}
+
 }  // namespace python
 }  // namespace compiler
 }  // namespace protobuf
diff --git a/third_party/protobuf/src/google/protobuf/compiler/python/python_generator.h b/third_party/protobuf/src/google/protobuf/compiler/python/python_generator.h
index 84eaf8a..a3f22ce 100644
--- a/third_party/protobuf/src/google/protobuf/compiler/python/python_generator.h
+++ b/third_party/protobuf/src/google/protobuf/compiler/python/python_generator.h
@@ -138,6 +138,11 @@
   void PrintSerializedPbInterval(
       const DescriptorT& descriptor, DescriptorProtoT& proto) const;
 
+  void FixAllDescriptorOptions() const;
+  void FixOptionsForField(const FieldDescriptor& field) const;
+  void FixOptionsForEnum(const EnumDescriptor& descriptor) const;
+  void FixOptionsForMessage(const Descriptor& descriptor) const;
+
   // Very coarse-grained lock to ensure that Generate() is reentrant.
   // Guards file_, printer_ and file_descriptor_serialized_.
   mutable Mutex mutex_;
diff --git a/third_party/protobuf/src/google/protobuf/compiler/subprocess.cc b/third_party/protobuf/src/google/protobuf/compiler/subprocess.cc
index 5fb5d5c..860fc87 100644
--- a/third_party/protobuf/src/google/protobuf/compiler/subprocess.cc
+++ b/third_party/protobuf/src/google/protobuf/compiler/subprocess.cc
@@ -33,6 +33,7 @@
 #include <google/protobuf/compiler/subprocess.h>
 
 #include <algorithm>
+#include <iostream>
 
 #ifndef _WIN32
 #include <errno.h>
diff --git a/third_party/protobuf/src/google/protobuf/compiler/subprocess.h b/third_party/protobuf/src/google/protobuf/compiler/subprocess.h
index 0056496..de9fce9 100644
--- a/third_party/protobuf/src/google/protobuf/compiler/subprocess.h
+++ b/third_party/protobuf/src/google/protobuf/compiler/subprocess.h
@@ -53,7 +53,7 @@
 namespace compiler {
 
 // Utility class for launching sub-processes.
-class LIBPROTOC_EXPORT Subprocess {
+class Subprocess {
  public:
   Subprocess();
   ~Subprocess();
diff --git a/third_party/protobuf/src/google/protobuf/descriptor.cc b/third_party/protobuf/src/google/protobuf/descriptor.cc
index 5bdd565..45293fe 100644
--- a/third_party/protobuf/src/google/protobuf/descriptor.cc
+++ b/third_party/protobuf/src/google/protobuf/descriptor.cc
@@ -54,7 +54,7 @@
 #include <google/protobuf/stubs/strutil.h>
 #include <google/protobuf/stubs/substitute.h>
 #include <google/protobuf/stubs/map-util.h>
-#include <google/protobuf/stubs/stl_util-inl.h>
+#include <google/protobuf/stubs/stl_util.h>
 
 #undef PACKAGE  // autoheader #defines this.  :(
 
@@ -108,6 +108,21 @@
   "sint64",    // TYPE_SINT64
 };
 
+const char * const FieldDescriptor::kCppTypeToName[MAX_CPPTYPE + 1] = {
+  "ERROR",     // 0 is reserved for errors
+
+  "int32",     // CPPTYPE_INT32
+  "int64",     // CPPTYPE_INT64
+  "uint32",    // CPPTYPE_UINT32
+  "uint64",    // CPPTYPE_UINT64
+  "double",    // CPPTYPE_DOUBLE
+  "float",     // CPPTYPE_FLOAT
+  "bool",      // CPPTYPE_BOOL
+  "enum",      // CPPTYPE_ENUM
+  "string",    // CPPTYPE_STRING
+  "message",   // CPPTYPE_MESSAGE
+};
+
 const char * const FieldDescriptor::kLabelToName[MAX_LABEL + 1] = {
   "ERROR",     // 0 is reserved for errors
 
@@ -221,7 +236,8 @@
 
 struct Symbol {
   enum Type {
-    NULL_SYMBOL, MESSAGE, FIELD, ENUM, ENUM_VALUE, SERVICE, METHOD, PACKAGE
+    NULL_SYMBOL, MESSAGE, FIELD, ENUM, ENUM_VALUE, SERVICE, METHOD,
+    PACKAGE
   };
   Type type;
   union {
@@ -311,17 +327,42 @@
   Tables();
   ~Tables();
 
-  // Checkpoint the state of the tables.  Future calls to Rollback() will
-  // return the Tables to this state.  This is used when building files, since
-  // some kinds of validation errors cannot be detected until the file's
-  // descriptors have already been added to the tables.  BuildFile() calls
-  // Checkpoint() before it starts building and Rollback() if it encounters
-  // an error.
-  void Checkpoint();
+  // Record the current state of the tables to the stack of checkpoints.
+  // Each call to AddCheckpoint() must be paired with exactly one call to either
+  // ClearLastCheckpoint() or RollbackToLastCheckpoint().
+  //
+  // This is used when building files, since some kinds of validation errors
+  // cannot be detected until the file's descriptors have already been added to
+  // the tables.
+  //
+  // This supports recursive checkpoints, since building a file may trigger
+  // recursive building of other files. Note that recursive checkpoints are not
+  // normally necessary; explicit dependencies are built prior to checkpointing.
+  // So although we recursively build transitive imports, there is at most one
+  // checkpoint in the stack during dependency building.
+  //
+  // Recursive checkpoints only arise during cross-linking of the descriptors.
+  // Symbol references must be resolved, via DescriptorBuilder::FindSymbol and
+  // friends. If the pending file references an unknown symbol
+  // (e.g., it is not defined in the pending file's explicit dependencies), and
+  // the pool is using a fallback database, and that database contains a file
+  // defining that symbol, and that file has not yet been built by the pool,
+  // the pool builds the file during cross-linking, leading to another
+  // checkpoint.
+  void AddCheckpoint();
 
-  // Roll back the Tables to the state of the last Checkpoint(), removing
-  // everything that was added after that point.
-  void Rollback();
+  // Mark the last checkpoint as having cleared successfully, removing it from
+  // the stack. If the stack is empty, all pending symbols will be committed.
+  //
+  // Note that this does not guarantee that the symbols added since the last
+  // checkpoint won't be rolled back: if a checkpoint gets rolled back,
+  // everything past that point gets rolled back, including symbols added after
+  // checkpoints that were pushed onto the stack after it and marked as cleared.
+  void ClearLastCheckpoint();
+
+  // Roll back the Tables to the state of the checkpoint at the top of the
+  // stack, removing everything that was added after that point.
+  void RollbackToLastCheckpoint();
 
   // The stack of files which are currently being built.  Used to detect
   // cyclic dependencies when loading files from a DescriptorDatabase.  Not
@@ -405,10 +446,28 @@
   FilesByNameMap        files_by_name_;
   ExtensionsGroupedByDescriptorMap extensions_;
 
-  int strings_before_checkpoint_;
-  int messages_before_checkpoint_;
-  int file_tables_before_checkpoint_;
-  int allocations_before_checkpoint_;
+  struct CheckPoint {
+    explicit CheckPoint(const Tables* tables)
+      : strings_before_checkpoint(tables->strings_.size()),
+        messages_before_checkpoint(tables->messages_.size()),
+        file_tables_before_checkpoint(tables->file_tables_.size()),
+        allocations_before_checkpoint(tables->allocations_.size()),
+        pending_symbols_before_checkpoint(
+            tables->symbols_after_checkpoint_.size()),
+        pending_files_before_checkpoint(
+            tables->files_after_checkpoint_.size()),
+        pending_extensions_before_checkpoint(
+            tables->extensions_after_checkpoint_.size()) {
+    }
+    int strings_before_checkpoint;
+    int messages_before_checkpoint;
+    int file_tables_before_checkpoint;
+    int allocations_before_checkpoint;
+    int pending_symbols_before_checkpoint;
+    int pending_files_before_checkpoint;
+    int pending_extensions_before_checkpoint;
+  };
+  vector<CheckPoint> checkpoints_;
   vector<const char*      > symbols_after_checkpoint_;
   vector<const char*      > files_after_checkpoint_;
   vector<DescriptorIntPair> extensions_after_checkpoint_;
@@ -481,11 +540,15 @@
 };
 
 DescriptorPool::Tables::Tables()
-  : strings_before_checkpoint_(0),
-    messages_before_checkpoint_(0),
-    allocations_before_checkpoint_(0) {}
+    // Start some hash_map and hash_set objects with a small # of buckets
+    : known_bad_files_(3),
+      extensions_loaded_from_db_(3),
+      symbols_by_name_(3),
+      files_by_name_(3) {}
+
 
 DescriptorPool::Tables::~Tables() {
+  GOOGLE_DCHECK(checkpoints_.empty());
   // Note that the deletion order is important, since the destructors of some
   // messages may refer to objects in allocations_.
   STLDeleteElements(&messages_);
@@ -496,51 +559,80 @@
   STLDeleteElements(&file_tables_);
 }
 
-FileDescriptorTables::FileDescriptorTables() {}
+FileDescriptorTables::FileDescriptorTables()
+    // Initialize all the hash tables to start out with a small # of buckets
+    : symbols_by_parent_(3),
+      fields_by_lowercase_name_(3),
+      fields_by_camelcase_name_(3),
+      fields_by_number_(3),
+      enum_values_by_number_(3) {
+}
+
 FileDescriptorTables::~FileDescriptorTables() {}
 
 const FileDescriptorTables FileDescriptorTables::kEmpty;
 
-void DescriptorPool::Tables::Checkpoint() {
-  strings_before_checkpoint_ = strings_.size();
-  messages_before_checkpoint_ = messages_.size();
-  file_tables_before_checkpoint_ = file_tables_.size();
-  allocations_before_checkpoint_ = allocations_.size();
-
-  symbols_after_checkpoint_.clear();
-  files_after_checkpoint_.clear();
-  extensions_after_checkpoint_.clear();
+void DescriptorPool::Tables::AddCheckpoint() {
+  checkpoints_.push_back(CheckPoint(this));
 }
 
-void DescriptorPool::Tables::Rollback() {
-  for (int i = 0; i < symbols_after_checkpoint_.size(); i++) {
+void DescriptorPool::Tables::ClearLastCheckpoint() {
+  GOOGLE_DCHECK(!checkpoints_.empty());
+  checkpoints_.pop_back();
+  if (checkpoints_.empty()) {
+    // All checkpoints have been cleared: we can now commit all of the pending
+    // data.
+    symbols_after_checkpoint_.clear();
+    files_after_checkpoint_.clear();
+    extensions_after_checkpoint_.clear();
+  }
+}
+
+void DescriptorPool::Tables::RollbackToLastCheckpoint() {
+  GOOGLE_DCHECK(!checkpoints_.empty());
+  const CheckPoint& checkpoint = checkpoints_.back();
+
+  for (int i = checkpoint.pending_symbols_before_checkpoint;
+       i < symbols_after_checkpoint_.size();
+       i++) {
     symbols_by_name_.erase(symbols_after_checkpoint_[i]);
   }
-  for (int i = 0; i < files_after_checkpoint_.size(); i++) {
+  for (int i = checkpoint.pending_files_before_checkpoint;
+       i < files_after_checkpoint_.size();
+       i++) {
     files_by_name_.erase(files_after_checkpoint_[i]);
   }
-  for (int i = 0; i < extensions_after_checkpoint_.size(); i++) {
+  for (int i = checkpoint.pending_extensions_before_checkpoint;
+       i < extensions_after_checkpoint_.size();
+       i++) {
     extensions_.erase(extensions_after_checkpoint_[i]);
   }
 
-  symbols_after_checkpoint_.clear();
-  files_after_checkpoint_.clear();
-  extensions_after_checkpoint_.clear();
+  symbols_after_checkpoint_.resize(
+      checkpoint.pending_symbols_before_checkpoint);
+  files_after_checkpoint_.resize(checkpoint.pending_files_before_checkpoint);
+  extensions_after_checkpoint_.resize(
+      checkpoint.pending_extensions_before_checkpoint);
 
   STLDeleteContainerPointers(
-    strings_.begin() + strings_before_checkpoint_, strings_.end());
+      strings_.begin() + checkpoint.strings_before_checkpoint, strings_.end());
   STLDeleteContainerPointers(
-    messages_.begin() + messages_before_checkpoint_, messages_.end());
+      messages_.begin() + checkpoint.messages_before_checkpoint,
+      messages_.end());
   STLDeleteContainerPointers(
-    file_tables_.begin() + file_tables_before_checkpoint_, file_tables_.end());
-  for (int i = allocations_before_checkpoint_; i < allocations_.size(); i++) {
+      file_tables_.begin() + checkpoint.file_tables_before_checkpoint,
+      file_tables_.end());
+  for (int i = checkpoint.allocations_before_checkpoint;
+       i < allocations_.size();
+       i++) {
     operator delete(allocations_[i]);
   }
 
-  strings_.resize(strings_before_checkpoint_);
-  messages_.resize(messages_before_checkpoint_);
-  file_tables_.resize(file_tables_before_checkpoint_);
-  allocations_.resize(allocations_before_checkpoint_);
+  strings_.resize(checkpoint.strings_before_checkpoint);
+  messages_.resize(checkpoint.messages_before_checkpoint);
+  file_tables_.resize(checkpoint.file_tables_before_checkpoint);
+  allocations_.resize(checkpoint.allocations_before_checkpoint);
+  checkpoints_.pop_back();
 }
 
 // -------------------------------------------------------------------
@@ -811,7 +903,7 @@
   generated_pool_ = NULL;
 }
 
-void InitGeneratedPool() {
+static void InitGeneratedPool() {
   generated_database_ = new EncodedDescriptorDatabase;
   generated_pool_ = new DescriptorPool(generated_database_);
 
@@ -874,11 +966,11 @@
   const FileDescriptor* result = tables_->FindFile(name);
   if (result != NULL) return result;
   if (underlay_ != NULL) {
-    const FileDescriptor* result = underlay_->FindFileByName(name);
+    result = underlay_->FindFileByName(name);
     if (result != NULL) return result;
   }
   if (TryFindFileInFallbackDatabase(name)) {
-    const FileDescriptor* result = tables_->FindFile(name);
+    result = tables_->FindFile(name);
     if (result != NULL) return result;
   }
   return NULL;
@@ -890,12 +982,12 @@
   Symbol result = tables_->FindSymbol(symbol_name);
   if (!result.IsNull()) return result.GetFile();
   if (underlay_ != NULL) {
-    const FileDescriptor* result =
+    const FileDescriptor* file_result =
       underlay_->FindFileContainingSymbol(symbol_name);
-    if (result != NULL) return result;
+    if (file_result != NULL) return file_result;
   }
   if (TryFindSymbolInFallbackDatabase(symbol_name)) {
-    Symbol result = tables_->FindSymbol(symbol_name);
+    result = tables_->FindSymbol(symbol_name);
     if (!result.IsNull()) return result.GetFile();
   }
   return NULL;
@@ -962,12 +1054,11 @@
     return result;
   }
   if (underlay_ != NULL) {
-    const FieldDescriptor* result =
-      underlay_->FindExtensionByNumber(extendee, number);
+    result = underlay_->FindExtensionByNumber(extendee, number);
     if (result != NULL) return result;
   }
   if (TryFindExtensionInFallbackDatabase(extendee, number)) {
-    const FieldDescriptor* result = tables_->FindExtension(extendee, number);
+    result = tables_->FindExtension(extendee, number);
     if (result != NULL) {
       return result;
     }
@@ -1241,9 +1332,48 @@
   return true;
 }
 
+bool DescriptorPool::IsSubSymbolOfBuiltType(const string& name) const {
+  string prefix = name;
+  for (;;) {
+    string::size_type dot_pos = prefix.find_last_of('.');
+    if (dot_pos == string::npos) {
+      break;
+    }
+    prefix = prefix.substr(0, dot_pos);
+    Symbol symbol = tables_->FindSymbol(prefix);
+    // If the symbol type is anything other than PACKAGE, then its complete
+    // definition is already known.
+    if (!symbol.IsNull() && symbol.type != Symbol::PACKAGE) {
+      return true;
+    }
+  }
+  if (underlay_ != NULL) {
+    // Check to see if any prefix of this symbol exists in the underlay.
+    return underlay_->IsSubSymbolOfBuiltType(name);
+  }
+  return false;
+}
+
 bool DescriptorPool::TryFindSymbolInFallbackDatabase(const string& name) const {
   if (fallback_database_ == NULL) return false;
 
+  // We skip looking in the fallback database if the name is a sub-symbol of
+  // any descriptor that already exists in the descriptor pool (except for
+  // package descriptors).  This is valid because all symbols except for
+  // packages are defined in a single file, so if the symbol exists then we
+  // should already have its definition.
+  //
+  // The other reason to do this is to support "overriding" type definitions
+  // by merging two databases that define the same type.  (Yes, people do
+  // this.)  The main difficulty with making this work is that
+  // FindFileContainingSymbol() is allowed to return both false positives
+  // (e.g., SimpleDescriptorDatabase, UpgradedDescriptorDatabase) and false
+  // negatives (e.g. ProtoFileParser, SourceTreeDescriptorDatabase).  When two
+  // such databases are merged, looking up a non-existent sub-symbol of a type
+  // that already exists in the descriptor pool can result in an attempt to
+  // load multiple definitions of the same type.  The check below avoids this.
+  if (IsSubSymbolOfBuiltType(name)) return false;
+
   FileDescriptorProto file_proto;
   if (!fallback_database_->FindFileContainingSymbol(name, &file_proto)) {
     return false;
@@ -1345,6 +1475,14 @@
     proto->add_dependency(dependency(i)->name());
   }
 
+  for (int i = 0; i < public_dependency_count(); i++) {
+    proto->add_public_dependency(public_dependencies_[i]);
+  }
+
+  for (int i = 0; i < weak_dependency_count(); i++) {
+    proto->add_weak_dependency(weak_dependencies_[i]);
+  }
+
   for (int i = 0; i < message_type_count(); i++) {
     message_type(i)->CopyTo(proto->add_message_type());
   }
@@ -1363,6 +1501,12 @@
   }
 }
 
+void FileDescriptor::CopySourceCodeInfoTo(FileDescriptorProto* proto) const {
+  if (source_code_info_ != &SourceCodeInfo::default_instance()) {
+    proto->mutable_source_code_info()->CopyFrom(*source_code_info_);
+  }
+}
+
 void Descriptor::CopyTo(DescriptorProto* proto) const {
   proto->set_name(name());
 
@@ -1490,16 +1634,14 @@
 namespace {
 
 // Used by each of the option formatters.
-bool RetrieveOptions(const Message &options, vector<string> *option_entries) {
+bool RetrieveOptions(int depth,
+                     const Message &options,
+                     vector<string> *option_entries) {
   option_entries->clear();
   const Reflection* reflection = options.GetReflection();
   vector<const FieldDescriptor*> fields;
   reflection->ListFields(options, &fields);
   for (int i = 0; i < fields.size(); i++) {
-    // Doesn't make sense to have message type fields here
-    if (fields[i]->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
-      continue;
-    }
     int count = 1;
     bool repeated = false;
     if (fields[i]->is_repeated()) {
@@ -1508,9 +1650,27 @@
     }
     for (int j = 0; j < count; j++) {
       string fieldval;
-      TextFormat::PrintFieldValueToString(options, fields[i],
-                                          repeated ? count : -1, &fieldval);
-      option_entries->push_back(fields[i]->name() + " = " + fieldval);
+      if (fields[i]->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
+        string tmp;
+        TextFormat::Printer printer;
+        printer.SetInitialIndentLevel(depth + 1);
+        printer.PrintFieldValueToString(options, fields[i],
+                                        repeated ? j : -1, &tmp);
+        fieldval.append("{\n");
+        fieldval.append(tmp);
+        fieldval.append(depth * 2, ' ');
+        fieldval.append("}");
+      } else {
+        TextFormat::PrintFieldValueToString(options, fields[i],
+                                            repeated ? j : -1, &fieldval);
+      }
+      string name;
+      if (fields[i]->is_extension()) {
+        name = "(." + fields[i]->full_name() + ")";
+      } else {
+        name = fields[i]->name();
+      }
+      option_entries->push_back(name + " = " + fieldval);
     }
   }
   return !option_entries->empty();
@@ -1518,9 +1678,9 @@
 
 // Formats options that all appear together in brackets. Does not include
 // brackets.
-bool FormatBracketedOptions(const Message &options, string *output) {
+bool FormatBracketedOptions(int depth, const Message &options, string *output) {
   vector<string> all_options;
-  if (RetrieveOptions(options, &all_options)) {
+  if (RetrieveOptions(depth, options, &all_options)) {
     output->append(JoinStrings(all_options, ", "));
   }
   return !all_options.empty();
@@ -1530,7 +1690,7 @@
 bool FormatLineOptions(int depth, const Message &options, string *output) {
   string prefix(depth * 2, ' ');
   vector<string> all_options;
-  if (RetrieveOptions(options, &all_options)) {
+  if (RetrieveOptions(depth, options, &all_options)) {
     for (int i = 0; i < all_options.size(); i++) {
       strings::SubstituteAndAppend(output, "$0option $1;\n",
                                    prefix, all_options[i]);
@@ -1544,9 +1704,24 @@
 string FileDescriptor::DebugString() const {
   string contents = "syntax = \"proto2\";\n\n";
 
+  set<int> public_dependencies;
+  set<int> weak_dependencies;
+  public_dependencies.insert(public_dependencies_,
+                             public_dependencies_ + public_dependency_count_);
+  weak_dependencies.insert(weak_dependencies_,
+                           weak_dependencies_ + weak_dependency_count_);
+
   for (int i = 0; i < dependency_count(); i++) {
-    strings::SubstituteAndAppend(&contents, "import \"$0\";\n",
-                                 dependency(i)->name());
+    if (public_dependencies.count(i) > 0) {
+      strings::SubstituteAndAppend(&contents, "import public \"$0\";\n",
+                                   dependency(i)->name());
+    } else if (weak_dependencies.count(i) > 0) {
+      strings::SubstituteAndAppend(&contents, "import weak \"$0\";\n",
+                                   dependency(i)->name());
+    } else {
+      strings::SubstituteAndAppend(&contents, "import \"$0\";\n",
+                                   dependency(i)->name());
+    }
   }
 
   if (!package().empty()) {
@@ -1712,7 +1887,7 @@
   }
 
   string formatted_options;
-  if (FormatBracketedOptions(options(), &formatted_options)) {
+  if (FormatBracketedOptions(depth, options(), &formatted_options)) {
     contents->append(bracketed ? ", " : " [");
     bracketed = true;
     contents->append(formatted_options);
@@ -1761,7 +1936,7 @@
                                prefix, name(), number());
 
   string formatted_options;
-  if (FormatBracketedOptions(options(), &formatted_options)) {
+  if (FormatBracketedOptions(depth, options(), &formatted_options)) {
     strings::SubstituteAndAppend(contents, " [$0]", formatted_options);
   }
   contents->append(";\n");
@@ -1807,6 +1982,126 @@
     contents->append(";\n");
   }
 }
+
+
+// Location methods ===============================================
+
+static bool PathsEqual(const vector<int>& x, const RepeatedField<int32>& y) {
+  if (x.size() != y.size()) return false;
+  for (int i = 0; i < x.size(); ++i) {
+    if (x[i] != y.Get(i)) return false;
+  }
+  return true;
+}
+
+bool FileDescriptor::GetSourceLocation(const vector<int>& path,
+                                       SourceLocation* out_location) const {
+  GOOGLE_CHECK_NOTNULL(out_location);
+  const SourceCodeInfo* info = source_code_info_;
+  for (int i = 0; info && i < info->location_size(); ++i) {
+    if (PathsEqual(path, info->location(i).path())) {
+      const RepeatedField<int32>& span = info->location(i).span();
+      if (span.size() == 3 || span.size() == 4) {
+        out_location->start_line   = span.Get(0);
+        out_location->start_column = span.Get(1);
+        out_location->end_line     = span.Get(span.size() == 3 ? 0 : 2);
+        out_location->end_column   = span.Get(span.size() - 1);
+
+        out_location->leading_comments = info->location(i).leading_comments();
+        out_location->trailing_comments = info->location(i).trailing_comments();
+        return true;
+      }
+    }
+  }
+  return false;
+}
+
+bool FieldDescriptor::is_packed() const {
+  return is_packable() && (options_ != NULL) && options_->packed();
+}
+
+bool Descriptor::GetSourceLocation(SourceLocation* out_location) const {
+  vector<int> path;
+  GetLocationPath(&path);
+  return file()->GetSourceLocation(path, out_location);
+}
+
+bool FieldDescriptor::GetSourceLocation(SourceLocation* out_location) const {
+  vector<int> path;
+  GetLocationPath(&path);
+  return file()->GetSourceLocation(path, out_location);
+}
+
+bool EnumDescriptor::GetSourceLocation(SourceLocation* out_location) const {
+  vector<int> path;
+  GetLocationPath(&path);
+  return file()->GetSourceLocation(path, out_location);
+}
+
+bool MethodDescriptor::GetSourceLocation(SourceLocation* out_location) const {
+  vector<int> path;
+  GetLocationPath(&path);
+  return service()->file()->GetSourceLocation(path, out_location);
+}
+
+bool ServiceDescriptor::GetSourceLocation(SourceLocation* out_location) const {
+  vector<int> path;
+  GetLocationPath(&path);
+  return file()->GetSourceLocation(path, out_location);
+}
+
+bool EnumValueDescriptor::GetSourceLocation(
+    SourceLocation* out_location) const {
+  vector<int> path;
+  GetLocationPath(&path);
+  return type()->file()->GetSourceLocation(path, out_location);
+}
+
+void Descriptor::GetLocationPath(vector<int>* output) const {
+  if (containing_type()) {
+    containing_type()->GetLocationPath(output);
+    output->push_back(DescriptorProto::kNestedTypeFieldNumber);
+    output->push_back(index());
+  } else {
+    output->push_back(FileDescriptorProto::kMessageTypeFieldNumber);
+    output->push_back(index());
+  }
+}
+
+void FieldDescriptor::GetLocationPath(vector<int>* output) const {
+  containing_type()->GetLocationPath(output);
+  output->push_back(DescriptorProto::kFieldFieldNumber);
+  output->push_back(index());
+}
+
+void EnumDescriptor::GetLocationPath(vector<int>* output) const {
+  if (containing_type()) {
+    containing_type()->GetLocationPath(output);
+    output->push_back(DescriptorProto::kEnumTypeFieldNumber);
+    output->push_back(index());
+  } else {
+    output->push_back(FileDescriptorProto::kEnumTypeFieldNumber);
+    output->push_back(index());
+  }
+}
+
+void EnumValueDescriptor::GetLocationPath(vector<int>* output) const {
+  type()->GetLocationPath(output);
+  output->push_back(EnumDescriptorProto::kValueFieldNumber);
+  output->push_back(index());
+}
+
+void ServiceDescriptor::GetLocationPath(vector<int>* output) const {
+  output->push_back(FileDescriptorProto::kServiceFieldNumber);
+  output->push_back(index());
+}
+
+void MethodDescriptor::GetLocationPath(vector<int>* output) const {
+  service()->GetLocationPath(output);
+  output->push_back(ServiceDescriptorProto::kMethodFieldNumber);
+  output->push_back(index());
+}
+
 // ===================================================================
 
 namespace {
@@ -1859,6 +2154,7 @@
   string filename_;
   FileDescriptor* file_;
   FileDescriptorTables* file_tables_;
+  set<const FileDescriptor*> dependencies_;
 
   // If LookupSymbol() finds a symbol that is in a file which is not a declared
   // dependency of this file, it will fail, but will set
@@ -1888,6 +2184,10 @@
   // nested package within package_name.
   bool IsInPackage(const FileDescriptor* file, const string& package_name);
 
+  // Helper function which finds all public dependencies of the given file, and
+  // stores the them in the dependencies_ set in the builder.
+  void RecordPublicDependencies(const FileDescriptor* file);
+
   // Like tables_->FindSymbol(), but additionally:
   // - Search the pool's underlay if not found in tables_.
   // - Insure that the resulting Symbol is from one of the file's declared
@@ -1898,6 +2198,10 @@
   // file's declared dependencies.
   Symbol FindSymbolNotEnforcingDeps(const string& name);
 
+  // This implements the body of FindSymbolNotEnforcingDeps().
+  Symbol FindSymbolNotEnforcingDepsHelper(const DescriptorPool* pool,
+                                          const string& name);
+
   // Like FindSymbol(), but looks up the name relative to some other symbol
   // name.  This first searches siblings of relative_to, then siblings of its
   // parents, etc.  For example, LookupSymbol("foo.bar", "baz.qux.corge") makes
@@ -2189,6 +2493,7 @@
 
   void ValidateMapKey(FieldDescriptor* field,
                       const FieldDescriptorProto& proto);
+
 };
 
 const FileDescriptor* DescriptorPool::BuildFile(
@@ -2275,31 +2580,48 @@
             file->package()[package_name.size()] == '.');
 }
 
-Symbol DescriptorBuilder::FindSymbolNotEnforcingDeps(const string& name) {
-  Symbol result;
+void DescriptorBuilder::RecordPublicDependencies(const FileDescriptor* file) {
+  if (file == NULL || !dependencies_.insert(file).second) return;
+  for (int i = 0; file != NULL && i < file->public_dependency_count(); i++) {
+    RecordPublicDependencies(file->public_dependency(i));
+  }
+}
 
-  // We need to search our pool and all its underlays.
-  const DescriptorPool* pool = pool_;
-  while (true) {
-    // If we are looking at an underlay, we must lock its mutex_, since we are
-    // accessing the underlay's tables_ dircetly.
-    MutexLockMaybe lock((pool == pool_) ? NULL : pool->mutex_);
+Symbol DescriptorBuilder::FindSymbolNotEnforcingDepsHelper(
+    const DescriptorPool* pool, const string& name) {
+  // If we are looking at an underlay, we must lock its mutex_, since we are
+  // accessing the underlay's tables_ directly.
+  MutexLockMaybe lock((pool == pool_) ? NULL : pool->mutex_);
 
-    // Note that we don't have to check fallback_database_ here because the
-    // symbol has to be in one of its file's direct dependencies, and we have
-    // already loaded those by the time we get here.
-    result = pool->tables_->FindSymbol(name);
-    if (!result.IsNull()) break;
-    if (pool->underlay_ == NULL) return kNullSymbol;
-    pool = pool->underlay_;
+  Symbol result = pool->tables_->FindSymbol(name);
+  if (result.IsNull() && pool->underlay_ != NULL) {
+    // Symbol not found; check the underlay.
+    result = FindSymbolNotEnforcingDepsHelper(pool->underlay_, name);
+  }
+
+  if (result.IsNull()) {
+    // In theory, we shouldn't need to check fallback_database_ because the
+    // symbol should be in one of its file's direct dependencies, and we have
+    // already loaded those by the time we get here.  But we check anyway so
+    // that we can generate better error message when dependencies are missing
+    // (i.e., "missing dependency" rather than "type is not defined").
+    if (pool->TryFindSymbolInFallbackDatabase(name)) {
+      result = pool->tables_->FindSymbol(name);
+    }
   }
 
   return result;
 }
 
+Symbol DescriptorBuilder::FindSymbolNotEnforcingDeps(const string& name) {
+  return FindSymbolNotEnforcingDepsHelper(pool_, name);
+}
+
 Symbol DescriptorBuilder::FindSymbol(const string& name) {
   Symbol result = FindSymbolNotEnforcingDeps(name);
 
+  if (result.IsNull()) return result;
+
   if (!pool_->enforce_dependencies_) {
     // Hack for CompilerUpgrader.
     return result;
@@ -2308,10 +2630,7 @@
   // Only find symbols which were defined in this file or one of its
   // dependencies.
   const FileDescriptor* file = result.GetFile();
-  if (file == file_) return result;
-  for (int i = 0; i < file_->dependency_count(); i++) {
-    if (file == file_->dependency(i)) return result;
-  }
+  if (file == file_ || dependencies_.count(file) > 0) return result;
 
   if (result.type == Symbol::PACKAGE) {
     // Arg, this is overcomplicated.  The symbol is a package name.  It could
@@ -2322,12 +2641,10 @@
     // dependency also defines the same package.  We can't really rule out this
     // symbol unless none of the dependencies define it.
     if (IsInPackage(file_, name)) return result;
-    for (int i = 0; i < file_->dependency_count(); i++) {
+    for (set<const FileDescriptor*>::const_iterator it = dependencies_.begin();
+         it != dependencies_.end(); ++it) {
       // Note:  A dependency may be NULL if it was not found or had errors.
-      if (file_->dependency(i) != NULL &&
-          IsInPackage(file_->dependency(i), name)) {
-        return result;
-      }
+      if (*it != NULL && IsInPackage(*it, name)) return result;
     }
   }
 
@@ -2448,6 +2765,8 @@
   FileDescriptor* placeholder_file = tables_->Allocate<FileDescriptor>();
   memset(placeholder_file, 0, sizeof(*placeholder_file));
 
+  placeholder_file->source_code_info_ = &SourceCodeInfo::default_instance();
+
   placeholder_file->name_ =
     tables_->AllocateString(*placeholder_full_name + ".placeholder.proto");
   placeholder_file->package_ = placeholder_package;
@@ -2757,11 +3076,19 @@
   }
 
   // Checkpoint the tables so that we can roll back if something goes wrong.
-  tables_->Checkpoint();
+  tables_->AddCheckpoint();
 
   FileDescriptor* result = tables_->Allocate<FileDescriptor>();
   file_ = result;
 
+  if (proto.has_source_code_info()) {
+    SourceCodeInfo *info = tables_->AllocateMessage<SourceCodeInfo>();
+    info->CopyFrom(proto.source_code_info());
+    result->source_code_info_ = info;
+  } else {
+    result->source_code_info_ = &SourceCodeInfo::default_instance();
+  }
+
   file_tables_ = tables_->AllocateFileTables();
   file_->tables_ = file_tables_;
 
@@ -2788,7 +3115,7 @@
              "A file with this name is already in the pool.");
     // Bail out early so that if this is actually the exact same file, we
     // don't end up reporting that every single symbol is already defined.
-    tables_->Rollback();
+    tables_->RollbackToLastCheckpoint();
     return NULL;
   }
   if (!result->package().empty()) {
@@ -2833,6 +3160,45 @@
     result->dependencies_[i] = dependency;
   }
 
+  // Check public dependencies.
+  int public_dependency_count = 0;
+  result->public_dependencies_ = tables_->AllocateArray<int>(
+      proto.public_dependency_size());
+  for (int i = 0; i < proto.public_dependency_size(); i++) {
+    // Only put valid public dependency indexes.
+    int index = proto.public_dependency(i);
+    if (index >= 0 && index < proto.dependency_size()) {
+      result->public_dependencies_[public_dependency_count++] = index;
+    } else {
+      AddError(proto.name(), proto,
+               DescriptorPool::ErrorCollector::OTHER,
+               "Invalid public dependency index.");
+    }
+  }
+  result->public_dependency_count_ = public_dependency_count;
+
+  // Build dependency set
+  dependencies_.clear();
+  for (int i = 0; i < result->dependency_count(); i++) {
+    RecordPublicDependencies(result->dependency(i));
+  }
+
+  // Check weak dependencies.
+  int weak_dependency_count = 0;
+  result->weak_dependencies_ = tables_->AllocateArray<int>(
+      proto.weak_dependency_size());
+  for (int i = 0; i < proto.weak_dependency_size(); i++) {
+    int index = proto.weak_dependency(i);
+    if (index >= 0 && index < proto.dependency_size()) {
+      result->weak_dependencies_[weak_dependency_count++] = index;
+    } else {
+      AddError(proto.name(), proto,
+               DescriptorPool::ErrorCollector::OTHER,
+               "Invalid weak dependency index.");
+    }
+  }
+  result->weak_dependency_count_ = weak_dependency_count;
+
   // Convert children.
   BUILD_ARRAY(proto, result, message_type, BuildMessage  , NULL);
   BUILD_ARRAY(proto, result, enum_type   , BuildEnum     , NULL);
@@ -2870,10 +3236,10 @@
   }
 
   if (had_errors_) {
-    tables_->Rollback();
+    tables_->RollbackToLastCheckpoint();
     return NULL;
   } else {
-    tables_->Checkpoint();
+    tables_->ClearLastCheckpoint();
     return result;
   }
 }
@@ -3065,7 +3431,7 @@
               UnescapeCEscapeString(proto.default_value()));
           } else {
             result->default_value_string_ =
-              tables_->AllocateString(proto.default_value());
+                tables_->AllocateString(proto.default_value());
           }
           break;
         case FieldDescriptor::CPPTYPE_MESSAGE:
@@ -3126,7 +3492,15 @@
   if (result->number() <= 0) {
     AddError(result->full_name(), proto, DescriptorPool::ErrorCollector::NUMBER,
              "Field numbers must be positive integers.");
-  } else if (result->number() > FieldDescriptor::kMaxNumber) {
+  } else if (!is_extension && result->number() > FieldDescriptor::kMaxNumber) {
+    // Only validate that the number is within the valid field range if it is
+    // not an extension. Since extension numbers are validated with the
+    // extendee's valid set of extension numbers, and those are in turn
+    // validated against the max allowed number, the check is unnecessary for
+    // extension fields.
+    // This avoids cross-linking issues that arise when attempting to check if
+    // the extendee is a message_set_wire_format message, which has a higher max
+    // on extension numbers.
     AddError(result->full_name(), proto, DescriptorPool::ErrorCollector::NUMBER,
              strings::Substitute("Field numbers cannot be greater than $0.",
                                  FieldDescriptor::kMaxNumber));
@@ -3181,12 +3555,10 @@
              "Extension numbers must be positive integers.");
   }
 
-  if (result->end > FieldDescriptor::kMaxNumber + 1) {
-    AddError(parent->full_name(), proto,
-             DescriptorPool::ErrorCollector::NUMBER,
-             strings::Substitute("Extension numbers cannot be greater than $0.",
-                                 FieldDescriptor::kMaxNumber));
-  }
+  // Checking of the upper bound of the extension range is deferred until after
+  // options interpreting. This allows messages with message_set_wire_format to
+  // have extensions beyond FieldDescriptor::kMaxNumber, since the extension
+  // numbers are actually used as int32s in the message_set_wire_format.
 
   if (result->start >= result->end) {
     AddError(parent->full_name(), proto,
@@ -3681,6 +4053,20 @@
   VALIDATE_OPTIONS_FROM_ARRAY(message, nested_type, Message);
   VALIDATE_OPTIONS_FROM_ARRAY(message, enum_type, Enum);
   VALIDATE_OPTIONS_FROM_ARRAY(message, extension, Field);
+
+  const int64 max_extension_range =
+      static_cast<int64>(message->options().message_set_wire_format() ?
+                         kint32max :
+                         FieldDescriptor::kMaxNumber);
+  for (int i = 0; i < message->extension_range_count(); ++i) {
+    if (message->extension_range(i)->end > max_extension_range + 1) {
+      AddError(
+          message->full_name(), proto.extension_range(i),
+          DescriptorPool::ErrorCollector::NUMBER,
+          strings::Substitute("Extension numbers cannot be greater than $0.",
+                              max_extension_range));
+    }
+  }
 }
 
 void DescriptorBuilder::ValidateFieldOptions(FieldDescriptor* field,
@@ -3689,6 +4075,15 @@
     ValidateMapKey(field, proto);
   }
 
+  // Only message type fields may be lazy.
+  if (field->options().lazy()) {
+    if (field->type() != FieldDescriptor::TYPE_MESSAGE) {
+      AddError(field->full_name(), proto,
+               DescriptorPool::ErrorCollector::TYPE,
+               "[lazy = true] can only be specified for submessage fields.");
+    }
+  }
+
   // Only repeated primitive fields may be packed.
   if (field->options().packed() && !field->is_packable()) {
     AddError(
@@ -3727,11 +4122,27 @@
              "files.  Note that you cannot extend a non-lite type to contain "
              "a lite type, but the reverse is allowed.");
   }
+
 }
 
 void DescriptorBuilder::ValidateEnumOptions(EnumDescriptor* enm,
                                             const EnumDescriptorProto& proto) {
   VALIDATE_OPTIONS_FROM_ARRAY(enm, value, EnumValue);
+  if (!enm->options().allow_alias()) {
+    map<int, string> used_values;
+    for (int i = 0; i < enm->value_count(); ++i) {
+      const EnumValueDescriptor* enum_value = enm->value(i);
+      if (used_values.find(enum_value->number()) != used_values.end()) {
+        AddError(enm->full_name(), proto,
+                 DescriptorPool::ErrorCollector::NUMBER,
+                 "\"" + enum_value->full_name() +
+                 "\" uses the same enum value as \"" +
+                 used_values[enum_value->number()] + "\"");
+      } else {
+        used_values[enum_value->number()] = enum_value->full_name();
+      }
+    }
+  }
 }
 
 void DescriptorBuilder::ValidateEnumValueOptions(
@@ -3811,6 +4222,7 @@
   field->experimental_map_key_ = key_field;
 }
 
+
 #undef VALIDATE_OPTIONS_FROM_ARRAY
 
 // -------------------------------------------------------------------
@@ -3901,9 +4313,11 @@
   // file we're currently building. The descriptor should be there as long as
   // the file we're building imported "google/protobuf/descriptors.proto".
 
-  // Note that we use DescriptorBuilder::FindSymbol(), not
+  // Note that we use DescriptorBuilder::FindSymbolNotEnforcingDeps(), not
   // DescriptorPool::FindMessageTypeByName() because we're already holding the
-  // pool's mutex, and the latter method locks it again.
+  // pool's mutex, and the latter method locks it again.  We don't use
+  // FindSymbol() because files that use custom options only need to depend on
+  // the file that defines the option, not descriptor.proto itself.
   Symbol symbol = builder_->FindSymbolNotEnforcingDeps(
     options->GetDescriptor()->full_name());
   if (!symbol.IsNull() && symbol.type == Symbol::MESSAGE) {
@@ -3939,8 +4353,8 @@
       // DescriptorPool::FindExtensionByName(), for two reasons: 1) It allows
       // relative lookups, and 2) because we're already holding the pool's
       // mutex, and the latter method locks it again.
-      Symbol symbol = builder_->LookupSymbol(name_part,
-                                             options_to_interpret_->name_scope);
+      symbol = builder_->LookupSymbol(name_part,
+                                      options_to_interpret_->name_scope);
       if (!symbol.IsNull() && symbol.type == Symbol::FIELD) {
         field = symbol.field_descriptor;
       }
@@ -4344,14 +4758,32 @@
   virtual const FieldDescriptor* FindExtension(
       Message* message, const string& name) const {
     assert_mutex_held(builder_->pool_);
+    const Descriptor* descriptor = message->GetDescriptor();
     Symbol result = builder_->LookupSymbolNoPlaceholder(
-        name, message->GetDescriptor()->full_name());
+        name, descriptor->full_name());
     if (result.type == Symbol::FIELD &&
         result.field_descriptor->is_extension()) {
       return result.field_descriptor;
-    } else {
-      return NULL;
+    } else if (result.type == Symbol::MESSAGE &&
+               descriptor->options().message_set_wire_format()) {
+      const Descriptor* foreign_type = result.descriptor;
+      // The text format allows MessageSet items to be specified using
+      // the type name, rather than the extension identifier. If the symbol
+      // lookup returned a Message, and the enclosing Message has
+      // message_set_wire_format = true, then return the message set
+      // extension, if one exists.
+      for (int i = 0; i < foreign_type->extension_count(); i++) {
+        const FieldDescriptor* extension = foreign_type->extension(i);
+        if (extension->containing_type() == descriptor &&
+            extension->type() == FieldDescriptor::TYPE_MESSAGE &&
+            extension->is_optional() &&
+            extension->message_type() == foreign_type) {
+          // Found it.
+          return extension;
+        }
+      }
     }
+    return NULL;
   }
 };
 
@@ -4409,7 +4841,13 @@
   } else {
     string serial;
     dynamic->SerializeToString(&serial);  // Never fails
-    unknown_fields->AddLengthDelimited(option_field->number(), serial);
+    if (option_field->type() == FieldDescriptor::TYPE_MESSAGE) {
+      unknown_fields->AddLengthDelimited(option_field->number(), serial);
+    } else {
+      GOOGLE_CHECK_EQ(option_field->type(),  FieldDescriptor::TYPE_GROUP);
+      UnknownFieldSet* group = unknown_fields->AddGroup(option_field->number());
+      group->ParseFromString(serial);
+    }
     return true;
   }
 }
diff --git a/third_party/protobuf/src/google/protobuf/descriptor.h b/third_party/protobuf/src/google/protobuf/descriptor.h
index 7f87dd8..410d3ed 100644
--- a/third_party/protobuf/src/google/protobuf/descriptor.h
+++ b/third_party/protobuf/src/google/protobuf/descriptor.h
@@ -89,6 +89,7 @@
 class MethodOptions;
 class FileOptions;
 class UninterpretedOption;
+class SourceCodeInfo;
 
 // Defined in message.h
 class Message;
@@ -100,6 +101,20 @@
 // Defined in unknown_field_set.h.
 class UnknownField;
 
+// NB, all indices are zero-based.
+struct SourceLocation {
+  int start_line;
+  int end_line;
+  int start_column;
+  int end_column;
+
+  // Doc comments found at the source location.
+  // TODO(kenton):  Maybe this struct should have been named SourceInfo or
+  //   something instead.  Oh well.
+  string leading_comments;
+  string trailing_comments;
+};
+
 // Describes a type of protocol message, or a particular group within a
 // message.  To obtain the Descriptor for a given message object, call
 // Message::GetDescriptor().  Generated message classes also have a
@@ -236,6 +251,13 @@
   // this message type's scope.
   const FieldDescriptor* FindExtensionByCamelcaseName(const string& name) const;
 
+  // Source Location ---------------------------------------------------
+
+  // Updates |*out_location| to the source location of the complete
+  // extent of this message declaration.  Returns false and leaves
+  // |*out_location| unchanged iff location information was not available.
+  bool GetSourceLocation(SourceLocation* out_location) const;
+
  private:
   typedef MessageOptions OptionsType;
 
@@ -243,6 +265,10 @@
   // correct depth
   void DebugString(int depth, string *contents) const;
 
+  // Walks up the descriptor tree to generate the source location path
+  // to this descriptor from the file root.
+  void GetLocationPath(vector<int>* output) const;
+
   const string* name_;
   const string* full_name_;
   const FileDescriptor* file_;
@@ -388,15 +414,19 @@
   // when parsing formats which prefer to use camel-case naming style.
   const string& camelcase_name() const;
 
-  Type type() const;                 // Declared type of this field.
-  CppType cpp_type() const;          // C++ type of this field.
-  Label label() const;               // optional/required/repeated
+  Type type() const;                  // Declared type of this field.
+  const char* type_name() const;      // Name of the declared type.
+  CppType cpp_type() const;           // C++ type of this field.
+  const char* cpp_type_name() const;  // Name of the C++ type.
+  Label label() const;                // optional/required/repeated
 
   bool is_required() const;      // shorthand for label() == LABEL_REQUIRED
   bool is_optional() const;      // shorthand for label() == LABEL_OPTIONAL
   bool is_repeated() const;      // shorthand for label() == LABEL_REPEATED
   bool is_packable() const;      // shorthand for is_repeated() &&
                                  //               IsTypePackable(type())
+  bool is_packed() const;        // shorthand for is_packable() &&
+                                 //               options().packed()
 
   // Index of this field within the message's field array, or the file or
   // extension scope's extensions array.
@@ -479,6 +509,13 @@
   // Return true iff [packed = true] is valid for fields of this type.
   static inline bool IsTypePackable(Type field_type);
 
+  // Source Location ---------------------------------------------------
+
+  // Updates |*out_location| to the source location of the complete
+  // extent of this field declaration.  Returns false and leaves
+  // |*out_location| unchanged iff location information was not available.
+  bool GetSourceLocation(SourceLocation* out_location) const;
+
  private:
   typedef FieldOptions OptionsType;
 
@@ -490,6 +527,10 @@
   // types of CPPTYPE_STRING whill be surrounded by quotes and CEscaped.
   string DefaultValueAsString(bool quote_string_type) const;
 
+  // Walks up the descriptor tree to generate the source location path
+  // to this descriptor from the file root.
+  void GetLocationPath(vector<int>* output) const;
+
   const string* name_;
   const string* full_name_;
   const string* lowercase_name_;
@@ -527,6 +568,8 @@
 
   static const char * const kTypeToName[MAX_TYPE + 1];
 
+  static const char * const kCppTypeToName[MAX_CPPTYPE + 1];
+
   static const char * const kLabelToName[MAX_LABEL + 1];
 
   // Must be constructed using DescriptorPool.
@@ -583,12 +626,23 @@
   // See Descriptor::DebugString().
   string DebugString() const;
 
+  // Source Location ---------------------------------------------------
+
+  // Updates |*out_location| to the source location of the complete
+  // extent of this enum declaration.  Returns false and leaves
+  // |*out_location| unchanged iff location information was not available.
+  bool GetSourceLocation(SourceLocation* out_location) const;
+
  private:
   typedef EnumOptions OptionsType;
 
   // See Descriptor::DebugString().
   void DebugString(int depth, string *contents) const;
 
+  // Walks up the descriptor tree to generate the source location path
+  // to this descriptor from the file root.
+  void GetLocationPath(vector<int>* output) const;
+
   const string* name_;
   const string* full_name_;
   const FileDescriptor* file_;
@@ -650,12 +704,23 @@
   // See Descriptor::DebugString().
   string DebugString() const;
 
+  // Source Location ---------------------------------------------------
+
+  // Updates |*out_location| to the source location of the complete
+  // extent of this enum value declaration.  Returns false and leaves
+  // |*out_location| unchanged iff location information was not available.
+  bool GetSourceLocation(SourceLocation* out_location) const;
+
  private:
   typedef EnumValueOptions OptionsType;
 
   // See Descriptor::DebugString().
   void DebugString(int depth, string *contents) const;
 
+  // Walks up the descriptor tree to generate the source location path
+  // to this descriptor from the file root.
+  void GetLocationPath(vector<int>* output) const;
+
   const string* name_;
   const string* full_name_;
   int number_;
@@ -703,19 +768,29 @@
 
   // Look up a MethodDescriptor by name.
   const MethodDescriptor* FindMethodByName(const string& name) const;
-
   // See Descriptor::CopyTo().
   void CopyTo(ServiceDescriptorProto* proto) const;
 
   // See Descriptor::DebugString().
   string DebugString() const;
 
+  // Source Location ---------------------------------------------------
+
+  // Updates |*out_location| to the source location of the complete
+  // extent of this service declaration.  Returns false and leaves
+  // |*out_location| unchanged iff location information was not available.
+  bool GetSourceLocation(SourceLocation* out_location) const;
+
  private:
   typedef ServiceOptions OptionsType;
 
   // See Descriptor::DebugString().
   void DebugString(string *contents) const;
 
+  // Walks up the descriptor tree to generate the source location path
+  // to this descriptor from the file root.
+  void GetLocationPath(vector<int>* output) const;
+
   const string* name_;
   const string* full_name_;
   const FileDescriptor* file_;
@@ -768,12 +843,23 @@
   // See Descriptor::DebugString().
   string DebugString() const;
 
+  // Source Location ---------------------------------------------------
+
+  // Updates |*out_location| to the source location of the complete
+  // extent of this method declaration.  Returns false and leaves
+  // |*out_location| unchanged iff location information was not available.
+  bool GetSourceLocation(SourceLocation* out_location) const;
+
  private:
   typedef MethodOptions OptionsType;
 
   // See Descriptor::DebugString().
   void DebugString(int depth, string *contents) const;
 
+  // Walks up the descriptor tree to generate the source location path
+  // to this descriptor from the file root.
+  void GetLocationPath(vector<int>* output) const;
+
   const string* name_;
   const string* full_name_;
   const ServiceDescriptor* service_;
@@ -791,6 +877,7 @@
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MethodDescriptor);
 };
 
+
 // Describes a whole .proto file.  To get the FileDescriptor for a compiled-in
 // file, get the descriptor for something defined in that file and call
 // descriptor->file().  Use DescriptorPool to construct your own descriptors.
@@ -813,6 +900,22 @@
   // These are returned in the order they were defined in the .proto file.
   const FileDescriptor* dependency(int index) const;
 
+  // The number of files public imported by this one.
+  // The public dependency list is a subset of the dependency list.
+  int public_dependency_count() const;
+  // Gets a public imported file by index, where 0 <= index <
+  // public_dependency_count().
+  // These are returned in the order they were defined in the .proto file.
+  const FileDescriptor* public_dependency(int index) const;
+
+  // The number of files that are imported for weak fields.
+  // The weak dependency list is a subset of the dependency list.
+  int weak_dependency_count() const;
+  // Gets a weak imported file by index, where 0 <= index <
+  // weak_dependency_count().
+  // These are returned in the order they were defined in the .proto file.
+  const FileDescriptor* weak_dependency(int index) const;
+
   // Number of top-level message types defined in this file.  (This does not
   // include nested types.)
   int message_type_count() const;
@@ -866,12 +969,28 @@
   const FieldDescriptor* FindExtensionByCamelcaseName(const string& name) const;
 
   // See Descriptor::CopyTo().
+  // Notes:
+  // - This method does NOT copy source code information since it is relatively
+  //   large and rarely needed.  See CopySourceCodeInfoTo() below.
   void CopyTo(FileDescriptorProto* proto) const;
+  // Write the source code information of this FileDescriptor into the given
+  // FileDescriptorProto.  See CopyTo() above.
+  void CopySourceCodeInfoTo(FileDescriptorProto* proto) const;
 
   // See Descriptor::DebugString().
   string DebugString() const;
 
  private:
+  // Source Location ---------------------------------------------------
+
+  // Updates |*out_location| to the source location of the complete
+  // extent of the declaration or declaration-part denoted by |path|.
+  // Returns false and leaves |*out_location| unchanged iff location
+  // information was not available.  (See SourceCodeInfo for
+  // description of path encoding.)
+  bool GetSourceLocation(const vector<int>& path,
+                         SourceLocation* out_location) const;
+
   typedef FileOptions OptionsType;
 
   const string* name_;
@@ -879,6 +998,10 @@
   const DescriptorPool* pool_;
   int dependency_count_;
   const FileDescriptor** dependencies_;
+  int public_dependency_count_;
+  int* public_dependencies_;
+  int weak_dependency_count_;
+  int* weak_dependencies_;
   int message_type_count_;
   Descriptor* message_types_;
   int enum_type_count_;
@@ -890,6 +1013,7 @@
   const FileOptions* options_;
 
   const FileDescriptorTables* tables_;
+  const SourceCodeInfo* source_code_info_;
   // IMPORTANT:  If you add a new field, make sure to search for all instances
   // of Allocate<FileDescriptor>() and AllocateArray<FileDescriptor>() in
   // descriptor.cc and update them to initialize the field.
@@ -899,6 +1023,8 @@
   friend class Descriptor;
   friend class FieldDescriptor;
   friend class EnumDescriptor;
+  friend class EnumValueDescriptor;
+  friend class MethodDescriptor;
   friend class ServiceDescriptor;
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FileDescriptor);
 };
@@ -1106,7 +1232,7 @@
   // For internal use only:  Gets a non-const pointer to the generated pool.
   // This is called at static-initialization time only, so thread-safety is
   // not a concern.  If both an underlay and a fallback database are present,
-  // the fallback database takes precedence.
+  // the underlay takes precedence.
   static DescriptorPool* internal_generated_pool();
 
   // For internal use only:  Changes the behavior of BuildFile() such that it
@@ -1132,6 +1258,11 @@
   friend class FileDescriptor;
   friend class DescriptorBuilder;
 
+  // Return true if the given name is a sub-symbol of any non-package
+  // descriptor that already exists in the descriptor pool.  (The full
+  // definition of such types is already known.)
+  bool IsSubSymbolOfBuiltType(const string& name) const;
+
   // Tries to find something in the fallback database and link in the
   // corresponding proto file.  Returns true if successful, in which case
   // the caller should search for the thing again.  These are declared
@@ -1262,11 +1393,12 @@
 PROTOBUF_DEFINE_ACCESSOR(MethodDescriptor, input_type, const Descriptor*)
 PROTOBUF_DEFINE_ACCESSOR(MethodDescriptor, output_type, const Descriptor*)
 PROTOBUF_DEFINE_OPTIONS_ACCESSOR(MethodDescriptor, MethodOptions);
-
 PROTOBUF_DEFINE_STRING_ACCESSOR(FileDescriptor, name)
 PROTOBUF_DEFINE_STRING_ACCESSOR(FileDescriptor, package)
 PROTOBUF_DEFINE_ACCESSOR(FileDescriptor, pool, const DescriptorPool*)
 PROTOBUF_DEFINE_ACCESSOR(FileDescriptor, dependency_count, int)
+PROTOBUF_DEFINE_ACCESSOR(FileDescriptor, public_dependency_count, int)
+PROTOBUF_DEFINE_ACCESSOR(FileDescriptor, weak_dependency_count, int)
 PROTOBUF_DEFINE_ACCESSOR(FileDescriptor, message_type_count, int)
 PROTOBUF_DEFINE_ACCESSOR(FileDescriptor, enum_type_count, int)
 PROTOBUF_DEFINE_ACCESSOR(FileDescriptor, service_count, int)
@@ -1342,10 +1474,18 @@
   return this - service_->methods_;
 }
 
+inline const char* FieldDescriptor::type_name() const {
+  return kTypeToName[type_];
+}
+
 inline FieldDescriptor::CppType FieldDescriptor::cpp_type() const {
   return kTypeToCppTypeMap[type_];
 }
 
+inline const char* FieldDescriptor::cpp_type_name() const {
+  return kCppTypeToName[kTypeToCppTypeMap[type_]];
+}
+
 inline FieldDescriptor::CppType FieldDescriptor::TypeToCppType(Type type) {
   return kTypeToCppTypeMap[type];
 }
@@ -1361,6 +1501,16 @@
   return dependencies_[index];
 }
 
+inline const FileDescriptor* FileDescriptor::public_dependency(
+    int index) const {
+  return dependencies_[public_dependencies_[index]];
+}
+
+inline const FileDescriptor* FileDescriptor::weak_dependency(
+    int index) const {
+  return dependencies_[weak_dependencies_[index]];
+}
+
 }  // namespace protobuf
 
 }  // namespace google
diff --git a/third_party/protobuf/src/google/protobuf/descriptor.pb.cc b/third_party/protobuf/src/google/protobuf/descriptor.pb.cc
index 7d16080..a05414a 100644
--- a/third_party/protobuf/src/google/protobuf/descriptor.pb.cc
+++ b/third_party/protobuf/src/google/protobuf/descriptor.pb.cc
@@ -1,14 +1,17 @@
 // Generated by the protocol buffer compiler.  DO NOT EDIT!
+// source: google/protobuf/descriptor.proto
 
 #define INTERNAL_SUPPRESS_PROTOBUF_FIELD_DEPRECATION
 #include "google/protobuf/descriptor.pb.h"
 
 #include <algorithm>
 
+#include <google/protobuf/stubs/common.h>
 #include <google/protobuf/stubs/once.h>
 #include <google/protobuf/io/coded_stream.h>
 #include <google/protobuf/wire_format_lite_inl.h>
 #include <google/protobuf/descriptor.h>
+#include <google/protobuf/generated_message_reflection.h>
 #include <google/protobuf/reflection_ops.h>
 #include <google/protobuf/wire_format.h>
 // @@protoc_insertion_point(includes)
@@ -108,10 +111,12 @@
       ::google::protobuf::MessageFactory::generated_factory(),
       sizeof(FileDescriptorSet));
   FileDescriptorProto_descriptor_ = file->message_type(1);
-  static const int FileDescriptorProto_offsets_[9] = {
+  static const int FileDescriptorProto_offsets_[11] = {
     GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileDescriptorProto, name_),
     GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileDescriptorProto, package_),
     GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileDescriptorProto, dependency_),
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileDescriptorProto, public_dependency_),
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileDescriptorProto, weak_dependency_),
     GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileDescriptorProto, message_type_),
     GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileDescriptorProto, enum_type_),
     GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileDescriptorProto, service_),
@@ -261,13 +266,14 @@
       ::google::protobuf::MessageFactory::generated_factory(),
       sizeof(MethodDescriptorProto));
   FileOptions_descriptor_ = file->message_type(8);
-  static const int FileOptions_offsets_[10] = {
+  static const int FileOptions_offsets_[11] = {
     GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, java_package_),
     GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, java_outer_classname_),
     GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, java_multiple_files_),
     GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, retain_unknown_fields_),
     GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, java_generate_equals_and_hash_),
     GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, optimize_for_),
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, go_package_),
     GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, cc_generic_services_),
     GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, java_generic_services_),
     GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, py_generic_services_),
@@ -303,11 +309,13 @@
       ::google::protobuf::MessageFactory::generated_factory(),
       sizeof(MessageOptions));
   FieldOptions_descriptor_ = file->message_type(10);
-  static const int FieldOptions_offsets_[5] = {
+  static const int FieldOptions_offsets_[7] = {
     GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldOptions, ctype_),
     GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldOptions, packed_),
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldOptions, lazy_),
     GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldOptions, deprecated_),
     GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldOptions, experimental_map_key_),
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldOptions, weak_),
     GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldOptions, uninterpreted_option_),
   };
   FieldOptions_reflection_ =
@@ -323,7 +331,8 @@
       sizeof(FieldOptions));
   FieldOptions_CType_descriptor_ = FieldOptions_descriptor_->enum_type(0);
   EnumOptions_descriptor_ = file->message_type(11);
-  static const int EnumOptions_offsets_[1] = {
+  static const int EnumOptions_offsets_[2] = {
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(EnumOptions, allow_alias_),
     GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(EnumOptions, uninterpreted_option_),
   };
   EnumOptions_reflection_ =
@@ -435,9 +444,11 @@
       ::google::protobuf::MessageFactory::generated_factory(),
       sizeof(SourceCodeInfo));
   SourceCodeInfo_Location_descriptor_ = SourceCodeInfo_descriptor_->nested_type(0);
-  static const int SourceCodeInfo_Location_offsets_[2] = {
+  static const int SourceCodeInfo_Location_offsets_[4] = {
     GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(SourceCodeInfo_Location, path_),
     GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(SourceCodeInfo_Location, span_),
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(SourceCodeInfo_Location, leading_comments_),
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(SourceCodeInfo_Location, trailing_comments_),
   };
   SourceCodeInfo_Location_reflection_ =
     new ::google::protobuf::internal::GeneratedMessageReflection(
@@ -554,107 +565,113 @@
   if (already_here) return;
   already_here = true;
   GOOGLE_PROTOBUF_VERIFY_VERSION;
+
   ::google::protobuf::DescriptorPool::InternalAddGeneratedFile(
     "\n google/protobuf/descriptor.proto\022\017goog"
     "le.protobuf\"G\n\021FileDescriptorSet\0222\n\004file"
     "\030\001 \003(\0132$.google.protobuf.FileDescriptorP"
-    "roto\"\227\003\n\023FileDescriptorProto\022\014\n\004name\030\001 \001"
+    "roto\"\313\003\n\023FileDescriptorProto\022\014\n\004name\030\001 \001"
     "(\t\022\017\n\007package\030\002 \001(\t\022\022\n\ndependency\030\003 \003(\t\022"
-    "6\n\014message_type\030\004 \003(\0132 .google.protobuf."
-    "DescriptorProto\0227\n\tenum_type\030\005 \003(\0132$.goo"
-    "gle.protobuf.EnumDescriptorProto\0228\n\007serv"
-    "ice\030\006 \003(\0132\'.google.protobuf.ServiceDescr"
-    "iptorProto\0228\n\textension\030\007 \003(\0132%.google.p"
-    "rotobuf.FieldDescriptorProto\022-\n\007options\030"
-    "\010 \001(\0132\034.google.protobuf.FileOptions\0229\n\020s"
-    "ource_code_info\030\t \001(\0132\037.google.protobuf."
-    "SourceCodeInfo\"\251\003\n\017DescriptorProto\022\014\n\004na"
-    "me\030\001 \001(\t\0224\n\005field\030\002 \003(\0132%.google.protobu"
-    "f.FieldDescriptorProto\0228\n\textension\030\006 \003("
+    "\031\n\021public_dependency\030\n \003(\005\022\027\n\017weak_depen"
+    "dency\030\013 \003(\005\0226\n\014message_type\030\004 \003(\0132 .goog"
+    "le.protobuf.DescriptorProto\0227\n\tenum_type"
+    "\030\005 \003(\0132$.google.protobuf.EnumDescriptorP"
+    "roto\0228\n\007service\030\006 \003(\0132\'.google.protobuf."
+    "ServiceDescriptorProto\0228\n\textension\030\007 \003("
     "\0132%.google.protobuf.FieldDescriptorProto"
-    "\0225\n\013nested_type\030\003 \003(\0132 .google.protobuf."
-    "DescriptorProto\0227\n\tenum_type\030\004 \003(\0132$.goo"
-    "gle.protobuf.EnumDescriptorProto\022H\n\017exte"
-    "nsion_range\030\005 \003(\0132/.google.protobuf.Desc"
-    "riptorProto.ExtensionRange\0220\n\007options\030\007 "
-    "\001(\0132\037.google.protobuf.MessageOptions\032,\n\016"
-    "ExtensionRange\022\r\n\005start\030\001 \001(\005\022\013\n\003end\030\002 \001"
-    "(\005\"\224\005\n\024FieldDescriptorProto\022\014\n\004name\030\001 \001("
-    "\t\022\016\n\006number\030\003 \001(\005\022:\n\005label\030\004 \001(\0162+.googl"
-    "e.protobuf.FieldDescriptorProto.Label\0228\n"
-    "\004type\030\005 \001(\0162*.google.protobuf.FieldDescr"
-    "iptorProto.Type\022\021\n\ttype_name\030\006 \001(\t\022\020\n\010ex"
-    "tendee\030\002 \001(\t\022\025\n\rdefault_value\030\007 \001(\t\022.\n\007o"
-    "ptions\030\010 \001(\0132\035.google.protobuf.FieldOpti"
-    "ons\"\266\002\n\004Type\022\017\n\013TYPE_DOUBLE\020\001\022\016\n\nTYPE_FL"
-    "OAT\020\002\022\016\n\nTYPE_INT64\020\003\022\017\n\013TYPE_UINT64\020\004\022\016"
-    "\n\nTYPE_INT32\020\005\022\020\n\014TYPE_FIXED64\020\006\022\020\n\014TYPE"
-    "_FIXED32\020\007\022\r\n\tTYPE_BOOL\020\010\022\017\n\013TYPE_STRING"
-    "\020\t\022\016\n\nTYPE_GROUP\020\n\022\020\n\014TYPE_MESSAGE\020\013\022\016\n\n"
-    "TYPE_BYTES\020\014\022\017\n\013TYPE_UINT32\020\r\022\r\n\tTYPE_EN"
-    "UM\020\016\022\021\n\rTYPE_SFIXED32\020\017\022\021\n\rTYPE_SFIXED64"
-    "\020\020\022\017\n\013TYPE_SINT32\020\021\022\017\n\013TYPE_SINT64\020\022\"C\n\005"
-    "Label\022\022\n\016LABEL_OPTIONAL\020\001\022\022\n\016LABEL_REQUI"
-    "RED\020\002\022\022\n\016LABEL_REPEATED\020\003\"\214\001\n\023EnumDescri"
-    "ptorProto\022\014\n\004name\030\001 \001(\t\0228\n\005value\030\002 \003(\0132)"
-    ".google.protobuf.EnumValueDescriptorProt"
-    "o\022-\n\007options\030\003 \001(\0132\034.google.protobuf.Enu"
-    "mOptions\"l\n\030EnumValueDescriptorProto\022\014\n\004"
-    "name\030\001 \001(\t\022\016\n\006number\030\002 \001(\005\0222\n\007options\030\003 "
-    "\001(\0132!.google.protobuf.EnumValueOptions\"\220"
-    "\001\n\026ServiceDescriptorProto\022\014\n\004name\030\001 \001(\t\022"
-    "6\n\006method\030\002 \003(\0132&.google.protobuf.Method"
-    "DescriptorProto\0220\n\007options\030\003 \001(\0132\037.googl"
-    "e.protobuf.ServiceOptions\"\177\n\025MethodDescr"
-    "iptorProto\022\014\n\004name\030\001 \001(\t\022\022\n\ninput_type\030\002"
-    " \001(\t\022\023\n\013output_type\030\003 \001(\t\022/\n\007options\030\004 \001"
-    "(\0132\036.google.protobuf.MethodOptions\"\373\003\n\013F"
-    "ileOptions\022\024\n\014java_package\030\001 \001(\t\022\034\n\024java"
-    "_outer_classname\030\010 \001(\t\022\"\n\023java_multiple_"
-    "files\030\n \001(\010:\005false\022$\n\025retain_unknown_fie"
-    "lds\030\013 \001(\010:\005false\022,\n\035java_generate_equals"
-    "_and_hash\030\024 \001(\010:\005false\022F\n\014optimize_for\030\t"
-    " \001(\0162).google.protobuf.FileOptions.Optim"
-    "izeMode:\005SPEED\022\"\n\023cc_generic_services\030\020 "
-    "\001(\010:\005false\022$\n\025java_generic_services\030\021 \001("
-    "\010:\005false\022\"\n\023py_generic_services\030\022 \001(\010:\005f"
-    "alse\022C\n\024uninterpreted_option\030\347\007 \003(\0132$.go"
-    "ogle.protobuf.UninterpretedOption\":\n\014Opt"
-    "imizeMode\022\t\n\005SPEED\020\001\022\r\n\tCODE_SIZE\020\002\022\020\n\014L"
-    "ITE_RUNTIME\020\003*\t\010\350\007\020\200\200\200\200\002\"\270\001\n\016MessageOpti"
-    "ons\022&\n\027message_set_wire_format\030\001 \001(\010:\005fa"
-    "lse\022.\n\037no_standard_descriptor_accessor\030\002"
-    " \001(\010:\005false\022C\n\024uninterpreted_option\030\347\007 \003"
-    "(\0132$.google.protobuf.UninterpretedOption"
-    "*\t\010\350\007\020\200\200\200\200\002\"\224\002\n\014FieldOptions\022:\n\005ctype\030\001 "
-    "\001(\0162#.google.protobuf.FieldOptions.CType"
-    ":\006STRING\022\016\n\006packed\030\002 \001(\010\022\031\n\ndeprecated\030\003"
-    " \001(\010:\005false\022\034\n\024experimental_map_key\030\t \001("
-    "\t\022C\n\024uninterpreted_option\030\347\007 \003(\0132$.googl"
-    "e.protobuf.UninterpretedOption\"/\n\005CType\022"
-    "\n\n\006STRING\020\000\022\010\n\004CORD\020\001\022\020\n\014STRING_PIECE\020\002*"
-    "\t\010\350\007\020\200\200\200\200\002\"]\n\013EnumOptions\022C\n\024uninterpret"
-    "ed_option\030\347\007 \003(\0132$.google.protobuf.Unint"
-    "erpretedOption*\t\010\350\007\020\200\200\200\200\002\"b\n\020EnumValueOp"
-    "tions\022C\n\024uninterpreted_option\030\347\007 \003(\0132$.g"
-    "oogle.protobuf.UninterpretedOption*\t\010\350\007\020"
-    "\200\200\200\200\002\"`\n\016ServiceOptions\022C\n\024uninterpreted"
-    "_option\030\347\007 \003(\0132$.google.protobuf.Uninter"
-    "pretedOption*\t\010\350\007\020\200\200\200\200\002\"_\n\rMethodOptions"
-    "\022C\n\024uninterpreted_option\030\347\007 \003(\0132$.google"
-    ".protobuf.UninterpretedOption*\t\010\350\007\020\200\200\200\200\002"
-    "\"\236\002\n\023UninterpretedOption\022;\n\004name\030\002 \003(\0132-"
-    ".google.protobuf.UninterpretedOption.Nam"
-    "ePart\022\030\n\020identifier_value\030\003 \001(\t\022\032\n\022posit"
-    "ive_int_value\030\004 \001(\004\022\032\n\022negative_int_valu"
-    "e\030\005 \001(\003\022\024\n\014double_value\030\006 \001(\001\022\024\n\014string_"
-    "value\030\007 \001(\014\022\027\n\017aggregate_value\030\010 \001(\t\0323\n\010"
-    "NamePart\022\021\n\tname_part\030\001 \002(\t\022\024\n\014is_extens"
-    "ion\030\002 \002(\010\"|\n\016SourceCodeInfo\022:\n\010location\030"
-    "\001 \003(\0132(.google.protobuf.SourceCodeInfo.L"
-    "ocation\032.\n\010Location\022\020\n\004path\030\001 \003(\005B\002\020\001\022\020\n"
-    "\004span\030\002 \003(\005B\002\020\001B)\n\023com.google.protobufB\020"
-    "DescriptorProtosH\001", 3978);
+    "\022-\n\007options\030\010 \001(\0132\034.google.protobuf.File"
+    "Options\0229\n\020source_code_info\030\t \001(\0132\037.goog"
+    "le.protobuf.SourceCodeInfo\"\251\003\n\017Descripto"
+    "rProto\022\014\n\004name\030\001 \001(\t\0224\n\005field\030\002 \003(\0132%.go"
+    "ogle.protobuf.FieldDescriptorProto\0228\n\tex"
+    "tension\030\006 \003(\0132%.google.protobuf.FieldDes"
+    "criptorProto\0225\n\013nested_type\030\003 \003(\0132 .goog"
+    "le.protobuf.DescriptorProto\0227\n\tenum_type"
+    "\030\004 \003(\0132$.google.protobuf.EnumDescriptorP"
+    "roto\022H\n\017extension_range\030\005 \003(\0132/.google.p"
+    "rotobuf.DescriptorProto.ExtensionRange\0220"
+    "\n\007options\030\007 \001(\0132\037.google.protobuf.Messag"
+    "eOptions\032,\n\016ExtensionRange\022\r\n\005start\030\001 \001("
+    "\005\022\013\n\003end\030\002 \001(\005\"\224\005\n\024FieldDescriptorProto\022"
+    "\014\n\004name\030\001 \001(\t\022\016\n\006number\030\003 \001(\005\022:\n\005label\030\004"
+    " \001(\0162+.google.protobuf.FieldDescriptorPr"
+    "oto.Label\0228\n\004type\030\005 \001(\0162*.google.protobu"
+    "f.FieldDescriptorProto.Type\022\021\n\ttype_name"
+    "\030\006 \001(\t\022\020\n\010extendee\030\002 \001(\t\022\025\n\rdefault_valu"
+    "e\030\007 \001(\t\022.\n\007options\030\010 \001(\0132\035.google.protob"
+    "uf.FieldOptions\"\266\002\n\004Type\022\017\n\013TYPE_DOUBLE\020"
+    "\001\022\016\n\nTYPE_FLOAT\020\002\022\016\n\nTYPE_INT64\020\003\022\017\n\013TYP"
+    "E_UINT64\020\004\022\016\n\nTYPE_INT32\020\005\022\020\n\014TYPE_FIXED"
+    "64\020\006\022\020\n\014TYPE_FIXED32\020\007\022\r\n\tTYPE_BOOL\020\010\022\017\n"
+    "\013TYPE_STRING\020\t\022\016\n\nTYPE_GROUP\020\n\022\020\n\014TYPE_M"
+    "ESSAGE\020\013\022\016\n\nTYPE_BYTES\020\014\022\017\n\013TYPE_UINT32\020"
+    "\r\022\r\n\tTYPE_ENUM\020\016\022\021\n\rTYPE_SFIXED32\020\017\022\021\n\rT"
+    "YPE_SFIXED64\020\020\022\017\n\013TYPE_SINT32\020\021\022\017\n\013TYPE_"
+    "SINT64\020\022\"C\n\005Label\022\022\n\016LABEL_OPTIONAL\020\001\022\022\n"
+    "\016LABEL_REQUIRED\020\002\022\022\n\016LABEL_REPEATED\020\003\"\214\001"
+    "\n\023EnumDescriptorProto\022\014\n\004name\030\001 \001(\t\0228\n\005v"
+    "alue\030\002 \003(\0132).google.protobuf.EnumValueDe"
+    "scriptorProto\022-\n\007options\030\003 \001(\0132\034.google."
+    "protobuf.EnumOptions\"l\n\030EnumValueDescrip"
+    "torProto\022\014\n\004name\030\001 \001(\t\022\016\n\006number\030\002 \001(\005\0222"
+    "\n\007options\030\003 \001(\0132!.google.protobuf.EnumVa"
+    "lueOptions\"\220\001\n\026ServiceDescriptorProto\022\014\n"
+    "\004name\030\001 \001(\t\0226\n\006method\030\002 \003(\0132&.google.pro"
+    "tobuf.MethodDescriptorProto\0220\n\007options\030\003"
+    " \001(\0132\037.google.protobuf.ServiceOptions\"\177\n"
+    "\025MethodDescriptorProto\022\014\n\004name\030\001 \001(\t\022\022\n\n"
+    "input_type\030\002 \001(\t\022\023\n\013output_type\030\003 \001(\t\022/\n"
+    "\007options\030\004 \001(\0132\036.google.protobuf.MethodO"
+    "ptions\"\217\004\n\013FileOptions\022\024\n\014java_package\030\001"
+    " \001(\t\022\034\n\024java_outer_classname\030\010 \001(\t\022\"\n\023ja"
+    "va_multiple_files\030\n \001(\010:\005false\022$\n\025retain"
+    "_unknown_fields\030\014 \001(\010:\005false\022,\n\035java_gen"
+    "erate_equals_and_hash\030\024 \001(\010:\005false\022F\n\014op"
+    "timize_for\030\t \001(\0162).google.protobuf.FileO"
+    "ptions.OptimizeMode:\005SPEED\022\022\n\ngo_package"
+    "\030\013 \001(\t\022\"\n\023cc_generic_services\030\020 \001(\010:\005fal"
+    "se\022$\n\025java_generic_services\030\021 \001(\010:\005false"
+    "\022\"\n\023py_generic_services\030\022 \001(\010:\005false\022C\n\024"
+    "uninterpreted_option\030\347\007 \003(\0132$.google.pro"
+    "tobuf.UninterpretedOption\":\n\014OptimizeMod"
+    "e\022\t\n\005SPEED\020\001\022\r\n\tCODE_SIZE\020\002\022\020\n\014LITE_RUNT"
+    "IME\020\003*\t\010\350\007\020\200\200\200\200\002\"\270\001\n\016MessageOptions\022&\n\027m"
+    "essage_set_wire_format\030\001 \001(\010:\005false\022.\n\037n"
+    "o_standard_descriptor_accessor\030\002 \001(\010:\005fa"
+    "lse\022C\n\024uninterpreted_option\030\347\007 \003(\0132$.goo"
+    "gle.protobuf.UninterpretedOption*\t\010\350\007\020\200\200"
+    "\200\200\002\"\276\002\n\014FieldOptions\022:\n\005ctype\030\001 \001(\0162#.go"
+    "ogle.protobuf.FieldOptions.CType:\006STRING"
+    "\022\016\n\006packed\030\002 \001(\010\022\023\n\004lazy\030\005 \001(\010:\005false\022\031\n"
+    "\ndeprecated\030\003 \001(\010:\005false\022\034\n\024experimental"
+    "_map_key\030\t \001(\t\022\023\n\004weak\030\n \001(\010:\005false\022C\n\024u"
+    "ninterpreted_option\030\347\007 \003(\0132$.google.prot"
+    "obuf.UninterpretedOption\"/\n\005CType\022\n\n\006STR"
+    "ING\020\000\022\010\n\004CORD\020\001\022\020\n\014STRING_PIECE\020\002*\t\010\350\007\020\200"
+    "\200\200\200\002\"x\n\013EnumOptions\022\031\n\013allow_alias\030\002 \001(\010"
+    ":\004true\022C\n\024uninterpreted_option\030\347\007 \003(\0132$."
+    "google.protobuf.UninterpretedOption*\t\010\350\007"
+    "\020\200\200\200\200\002\"b\n\020EnumValueOptions\022C\n\024uninterpre"
+    "ted_option\030\347\007 \003(\0132$.google.protobuf.Unin"
+    "terpretedOption*\t\010\350\007\020\200\200\200\200\002\"`\n\016ServiceOpt"
+    "ions\022C\n\024uninterpreted_option\030\347\007 \003(\0132$.go"
+    "ogle.protobuf.UninterpretedOption*\t\010\350\007\020\200"
+    "\200\200\200\002\"_\n\rMethodOptions\022C\n\024uninterpreted_o"
+    "ption\030\347\007 \003(\0132$.google.protobuf.Uninterpr"
+    "etedOption*\t\010\350\007\020\200\200\200\200\002\"\236\002\n\023UninterpretedO"
+    "ption\022;\n\004name\030\002 \003(\0132-.google.protobuf.Un"
+    "interpretedOption.NamePart\022\030\n\020identifier"
+    "_value\030\003 \001(\t\022\032\n\022positive_int_value\030\004 \001(\004"
+    "\022\032\n\022negative_int_value\030\005 \001(\003\022\024\n\014double_v"
+    "alue\030\006 \001(\001\022\024\n\014string_value\030\007 \001(\014\022\027\n\017aggr"
+    "egate_value\030\010 \001(\t\0323\n\010NamePart\022\021\n\tname_pa"
+    "rt\030\001 \002(\t\022\024\n\014is_extension\030\002 \002(\010\"\261\001\n\016Sourc"
+    "eCodeInfo\022:\n\010location\030\001 \003(\0132(.google.pro"
+    "tobuf.SourceCodeInfo.Location\032c\n\010Locatio"
+    "n\022\020\n\004path\030\001 \003(\005B\002\020\001\022\020\n\004span\030\002 \003(\005B\002\020\001\022\030\n"
+    "\020leading_comments\030\003 \001(\t\022\031\n\021trailing_comm"
+    "ents\030\004 \001(\tB)\n\023com.google.protobufB\020Descr"
+    "iptorProtosH\001", 4173);
   ::google::protobuf::MessageFactory::InternalRegisterGeneratedFile(
     "google/protobuf/descriptor.proto", &protobuf_RegisterTypes);
   FileDescriptorSet::default_instance_ = new FileDescriptorSet();
@@ -788,14 +805,15 @@
         if (input->ExpectAtEnd()) return true;
         break;
       }
-      
+
       default: {
       handle_uninterpreted:
         if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
             ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
           return true;
         }
-        DO_(::google::protobuf::internal::WireFormatLite::SkipField(input, tag, mutable_unknown_fields()));
+        DO_(::google::protobuf::internal::WireFormatLite::SkipField(
+              input, tag, mutable_unknown_fields()));
         break;
       }
     }
@@ -811,7 +829,7 @@
     ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
       1, this->file(i), output);
   }
-  
+
   if (!unknown_fields().empty()) {
     ::google::protobuf::internal::WireFormatLite::SerializeUnknownFields(
         unknown_fields(), output);
@@ -826,7 +844,7 @@
       WriteMessageNoVirtualToArray(
         1, this->file(i), target);
   }
-  
+
   if (!unknown_fields().empty()) {
     target = ::google::protobuf::internal::WireFormatLite::SerializeUnknownFieldsToArray(
         unknown_fields(), target);
@@ -836,7 +854,7 @@
 
 int FileDescriptorSet::ByteSize() const {
   int total_size = 0;
-  
+
   // repeated .google.protobuf.FileDescriptorProto file = 1;
   total_size += 1 * this->file_size();
   for (int i = 0; i < this->file_size(); i++) {
@@ -844,7 +862,7 @@
       ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
         this->file(i));
   }
-  
+
   if (!unknown_fields().empty()) {
     total_size +=
       ::google::protobuf::internal::WireFormatLite::ComputeUnknownFieldsSize(
@@ -887,7 +905,7 @@
 }
 
 bool FileDescriptorSet::IsInitialized() const {
-  
+
   for (int i = 0; i < file_size(); i++) {
     if (!this->file(i).IsInitialized()) return false;
   }
@@ -918,6 +936,8 @@
 const int FileDescriptorProto::kNameFieldNumber;
 const int FileDescriptorProto::kPackageFieldNumber;
 const int FileDescriptorProto::kDependencyFieldNumber;
+const int FileDescriptorProto::kPublicDependencyFieldNumber;
+const int FileDescriptorProto::kWeakDependencyFieldNumber;
 const int FileDescriptorProto::kMessageTypeFieldNumber;
 const int FileDescriptorProto::kEnumTypeFieldNumber;
 const int FileDescriptorProto::kServiceFieldNumber;
@@ -1001,16 +1021,18 @@
         package_->clear();
       }
     }
+  }
+  if (_has_bits_[9 / 32] & (0xffu << (9 % 32))) {
     if (has_options()) {
       if (options_ != NULL) options_->::google::protobuf::FileOptions::Clear();
     }
-  }
-  if (_has_bits_[8 / 32] & (0xffu << (8 % 32))) {
     if (has_source_code_info()) {
       if (source_code_info_ != NULL) source_code_info_->::google::protobuf::SourceCodeInfo::Clear();
     }
   }
   dependency_.Clear();
+  public_dependency_.Clear();
+  weak_dependency_.Clear();
   message_type_.Clear();
   enum_type_.Clear();
   service_.Clear();
@@ -1040,7 +1062,7 @@
         if (input->ExpectTag(18)) goto parse_package;
         break;
       }
-      
+
       // optional string package = 2;
       case 2: {
         if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
@@ -1057,7 +1079,7 @@
         if (input->ExpectTag(26)) goto parse_dependency;
         break;
       }
-      
+
       // repeated string dependency = 3;
       case 3: {
         if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
@@ -1076,7 +1098,7 @@
         if (input->ExpectTag(34)) goto parse_message_type;
         break;
       }
-      
+
       // repeated .google.protobuf.DescriptorProto message_type = 4;
       case 4: {
         if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
@@ -1091,7 +1113,7 @@
         if (input->ExpectTag(42)) goto parse_enum_type;
         break;
       }
-      
+
       // repeated .google.protobuf.EnumDescriptorProto enum_type = 5;
       case 5: {
         if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
@@ -1106,7 +1128,7 @@
         if (input->ExpectTag(50)) goto parse_service;
         break;
       }
-      
+
       // repeated .google.protobuf.ServiceDescriptorProto service = 6;
       case 6: {
         if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
@@ -1121,7 +1143,7 @@
         if (input->ExpectTag(58)) goto parse_extension;
         break;
       }
-      
+
       // repeated .google.protobuf.FieldDescriptorProto extension = 7;
       case 7: {
         if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
@@ -1136,7 +1158,7 @@
         if (input->ExpectTag(66)) goto parse_options;
         break;
       }
-      
+
       // optional .google.protobuf.FileOptions options = 8;
       case 8: {
         if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
@@ -1150,7 +1172,7 @@
         if (input->ExpectTag(74)) goto parse_source_code_info;
         break;
       }
-      
+
       // optional .google.protobuf.SourceCodeInfo source_code_info = 9;
       case 9: {
         if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
@@ -1161,17 +1183,62 @@
         } else {
           goto handle_uninterpreted;
         }
+        if (input->ExpectTag(80)) goto parse_public_dependency;
+        break;
+      }
+
+      // repeated int32 public_dependency = 10;
+      case 10: {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) {
+         parse_public_dependency:
+          DO_((::google::protobuf::internal::WireFormatLite::ReadRepeatedPrimitive<
+                   ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>(
+                 1, 80, input, this->mutable_public_dependency())));
+        } else if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag)
+                   == ::google::protobuf::internal::WireFormatLite::
+                      WIRETYPE_LENGTH_DELIMITED) {
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPackedPrimitiveNoInline<
+                   ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>(
+                 input, this->mutable_public_dependency())));
+        } else {
+          goto handle_uninterpreted;
+        }
+        if (input->ExpectTag(80)) goto parse_public_dependency;
+        if (input->ExpectTag(88)) goto parse_weak_dependency;
+        break;
+      }
+
+      // repeated int32 weak_dependency = 11;
+      case 11: {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) {
+         parse_weak_dependency:
+          DO_((::google::protobuf::internal::WireFormatLite::ReadRepeatedPrimitive<
+                   ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>(
+                 1, 88, input, this->mutable_weak_dependency())));
+        } else if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag)
+                   == ::google::protobuf::internal::WireFormatLite::
+                      WIRETYPE_LENGTH_DELIMITED) {
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPackedPrimitiveNoInline<
+                   ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>(
+                 input, this->mutable_weak_dependency())));
+        } else {
+          goto handle_uninterpreted;
+        }
+        if (input->ExpectTag(88)) goto parse_weak_dependency;
         if (input->ExpectAtEnd()) return true;
         break;
       }
-      
+
       default: {
       handle_uninterpreted:
         if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
             ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
           return true;
         }
-        DO_(::google::protobuf::internal::WireFormatLite::SkipField(input, tag, mutable_unknown_fields()));
+        DO_(::google::protobuf::internal::WireFormatLite::SkipField(
+              input, tag, mutable_unknown_fields()));
         break;
       }
     }
@@ -1190,7 +1257,7 @@
     ::google::protobuf::internal::WireFormatLite::WriteString(
       1, this->name(), output);
   }
-  
+
   // optional string package = 2;
   if (has_package()) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8String(
@@ -1199,7 +1266,7 @@
     ::google::protobuf::internal::WireFormatLite::WriteString(
       2, this->package(), output);
   }
-  
+
   // repeated string dependency = 3;
   for (int i = 0; i < this->dependency_size(); i++) {
   ::google::protobuf::internal::WireFormat::VerifyUTF8String(
@@ -1208,43 +1275,55 @@
     ::google::protobuf::internal::WireFormatLite::WriteString(
       3, this->dependency(i), output);
   }
-  
+
   // repeated .google.protobuf.DescriptorProto message_type = 4;
   for (int i = 0; i < this->message_type_size(); i++) {
     ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
       4, this->message_type(i), output);
   }
-  
+
   // repeated .google.protobuf.EnumDescriptorProto enum_type = 5;
   for (int i = 0; i < this->enum_type_size(); i++) {
     ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
       5, this->enum_type(i), output);
   }
-  
+
   // repeated .google.protobuf.ServiceDescriptorProto service = 6;
   for (int i = 0; i < this->service_size(); i++) {
     ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
       6, this->service(i), output);
   }
-  
+
   // repeated .google.protobuf.FieldDescriptorProto extension = 7;
   for (int i = 0; i < this->extension_size(); i++) {
     ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
       7, this->extension(i), output);
   }
-  
+
   // optional .google.protobuf.FileOptions options = 8;
   if (has_options()) {
     ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
       8, this->options(), output);
   }
-  
+
   // optional .google.protobuf.SourceCodeInfo source_code_info = 9;
   if (has_source_code_info()) {
     ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
       9, this->source_code_info(), output);
   }
-  
+
+  // repeated int32 public_dependency = 10;
+  for (int i = 0; i < this->public_dependency_size(); i++) {
+    ::google::protobuf::internal::WireFormatLite::WriteInt32(
+      10, this->public_dependency(i), output);
+  }
+
+  // repeated int32 weak_dependency = 11;
+  for (int i = 0; i < this->weak_dependency_size(); i++) {
+    ::google::protobuf::internal::WireFormatLite::WriteInt32(
+      11, this->weak_dependency(i), output);
+  }
+
   if (!unknown_fields().empty()) {
     ::google::protobuf::internal::WireFormatLite::SerializeUnknownFields(
         unknown_fields(), output);
@@ -1262,7 +1341,7 @@
       ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
         1, this->name(), target);
   }
-  
+
   // optional string package = 2;
   if (has_package()) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8String(
@@ -1272,7 +1351,7 @@
       ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
         2, this->package(), target);
   }
-  
+
   // repeated string dependency = 3;
   for (int i = 0; i < this->dependency_size(); i++) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8String(
@@ -1281,49 +1360,61 @@
     target = ::google::protobuf::internal::WireFormatLite::
       WriteStringToArray(3, this->dependency(i), target);
   }
-  
+
   // repeated .google.protobuf.DescriptorProto message_type = 4;
   for (int i = 0; i < this->message_type_size(); i++) {
     target = ::google::protobuf::internal::WireFormatLite::
       WriteMessageNoVirtualToArray(
         4, this->message_type(i), target);
   }
-  
+
   // repeated .google.protobuf.EnumDescriptorProto enum_type = 5;
   for (int i = 0; i < this->enum_type_size(); i++) {
     target = ::google::protobuf::internal::WireFormatLite::
       WriteMessageNoVirtualToArray(
         5, this->enum_type(i), target);
   }
-  
+
   // repeated .google.protobuf.ServiceDescriptorProto service = 6;
   for (int i = 0; i < this->service_size(); i++) {
     target = ::google::protobuf::internal::WireFormatLite::
       WriteMessageNoVirtualToArray(
         6, this->service(i), target);
   }
-  
+
   // repeated .google.protobuf.FieldDescriptorProto extension = 7;
   for (int i = 0; i < this->extension_size(); i++) {
     target = ::google::protobuf::internal::WireFormatLite::
       WriteMessageNoVirtualToArray(
         7, this->extension(i), target);
   }
-  
+
   // optional .google.protobuf.FileOptions options = 8;
   if (has_options()) {
     target = ::google::protobuf::internal::WireFormatLite::
       WriteMessageNoVirtualToArray(
         8, this->options(), target);
   }
-  
+
   // optional .google.protobuf.SourceCodeInfo source_code_info = 9;
   if (has_source_code_info()) {
     target = ::google::protobuf::internal::WireFormatLite::
       WriteMessageNoVirtualToArray(
         9, this->source_code_info(), target);
   }
-  
+
+  // repeated int32 public_dependency = 10;
+  for (int i = 0; i < this->public_dependency_size(); i++) {
+    target = ::google::protobuf::internal::WireFormatLite::
+      WriteInt32ToArray(10, this->public_dependency(i), target);
+  }
+
+  // repeated int32 weak_dependency = 11;
+  for (int i = 0; i < this->weak_dependency_size(); i++) {
+    target = ::google::protobuf::internal::WireFormatLite::
+      WriteInt32ToArray(11, this->weak_dependency(i), target);
+  }
+
   if (!unknown_fields().empty()) {
     target = ::google::protobuf::internal::WireFormatLite::SerializeUnknownFieldsToArray(
         unknown_fields(), target);
@@ -1333,7 +1424,7 @@
 
 int FileDescriptorProto::ByteSize() const {
   int total_size = 0;
-  
+
   if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) {
     // optional string name = 1;
     if (has_name()) {
@@ -1341,30 +1432,30 @@
         ::google::protobuf::internal::WireFormatLite::StringSize(
           this->name());
     }
-    
+
     // optional string package = 2;
     if (has_package()) {
       total_size += 1 +
         ::google::protobuf::internal::WireFormatLite::StringSize(
           this->package());
     }
-    
+
+  }
+  if (_has_bits_[9 / 32] & (0xffu << (9 % 32))) {
     // optional .google.protobuf.FileOptions options = 8;
     if (has_options()) {
       total_size += 1 +
         ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
           this->options());
     }
-    
-  }
-  if (_has_bits_[8 / 32] & (0xffu << (8 % 32))) {
+
     // optional .google.protobuf.SourceCodeInfo source_code_info = 9;
     if (has_source_code_info()) {
       total_size += 1 +
         ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
           this->source_code_info());
     }
-    
+
   }
   // repeated string dependency = 3;
   total_size += 1 * this->dependency_size();
@@ -1372,7 +1463,27 @@
     total_size += ::google::protobuf::internal::WireFormatLite::StringSize(
       this->dependency(i));
   }
-  
+
+  // repeated int32 public_dependency = 10;
+  {
+    int data_size = 0;
+    for (int i = 0; i < this->public_dependency_size(); i++) {
+      data_size += ::google::protobuf::internal::WireFormatLite::
+        Int32Size(this->public_dependency(i));
+    }
+    total_size += 1 * this->public_dependency_size() + data_size;
+  }
+
+  // repeated int32 weak_dependency = 11;
+  {
+    int data_size = 0;
+    for (int i = 0; i < this->weak_dependency_size(); i++) {
+      data_size += ::google::protobuf::internal::WireFormatLite::
+        Int32Size(this->weak_dependency(i));
+    }
+    total_size += 1 * this->weak_dependency_size() + data_size;
+  }
+
   // repeated .google.protobuf.DescriptorProto message_type = 4;
   total_size += 1 * this->message_type_size();
   for (int i = 0; i < this->message_type_size(); i++) {
@@ -1380,7 +1491,7 @@
       ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
         this->message_type(i));
   }
-  
+
   // repeated .google.protobuf.EnumDescriptorProto enum_type = 5;
   total_size += 1 * this->enum_type_size();
   for (int i = 0; i < this->enum_type_size(); i++) {
@@ -1388,7 +1499,7 @@
       ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
         this->enum_type(i));
   }
-  
+
   // repeated .google.protobuf.ServiceDescriptorProto service = 6;
   total_size += 1 * this->service_size();
   for (int i = 0; i < this->service_size(); i++) {
@@ -1396,7 +1507,7 @@
       ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
         this->service(i));
   }
-  
+
   // repeated .google.protobuf.FieldDescriptorProto extension = 7;
   total_size += 1 * this->extension_size();
   for (int i = 0; i < this->extension_size(); i++) {
@@ -1404,7 +1515,7 @@
       ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
         this->extension(i));
   }
-  
+
   if (!unknown_fields().empty()) {
     total_size +=
       ::google::protobuf::internal::WireFormatLite::ComputeUnknownFieldsSize(
@@ -1431,6 +1542,8 @@
 void FileDescriptorProto::MergeFrom(const FileDescriptorProto& from) {
   GOOGLE_CHECK_NE(&from, this);
   dependency_.MergeFrom(from.dependency_);
+  public_dependency_.MergeFrom(from.public_dependency_);
+  weak_dependency_.MergeFrom(from.weak_dependency_);
   message_type_.MergeFrom(from.message_type_);
   enum_type_.MergeFrom(from.enum_type_);
   service_.MergeFrom(from.service_);
@@ -1442,11 +1555,11 @@
     if (from.has_package()) {
       set_package(from.package());
     }
+  }
+  if (from._has_bits_[9 / 32] & (0xffu << (9 % 32))) {
     if (from.has_options()) {
       mutable_options()->::google::protobuf::FileOptions::MergeFrom(from.options());
     }
-  }
-  if (from._has_bits_[8 / 32] & (0xffu << (8 % 32))) {
     if (from.has_source_code_info()) {
       mutable_source_code_info()->::google::protobuf::SourceCodeInfo::MergeFrom(from.source_code_info());
     }
@@ -1467,7 +1580,7 @@
 }
 
 bool FileDescriptorProto::IsInitialized() const {
-  
+
   for (int i = 0; i < message_type_size(); i++) {
     if (!this->message_type(i).IsInitialized()) return false;
   }
@@ -1491,6 +1604,8 @@
     std::swap(name_, other->name_);
     std::swap(package_, other->package_);
     dependency_.Swap(&other->dependency_);
+    public_dependency_.Swap(&other->public_dependency_);
+    weak_dependency_.Swap(&other->weak_dependency_);
     message_type_.Swap(&other->message_type_);
     enum_type_.Swap(&other->enum_type_);
     service_.Swap(&other->service_);
@@ -1599,7 +1714,7 @@
         if (input->ExpectTag(16)) goto parse_end;
         break;
       }
-      
+
       // optional int32 end = 2;
       case 2: {
         if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
@@ -1615,14 +1730,15 @@
         if (input->ExpectAtEnd()) return true;
         break;
       }
-      
+
       default: {
       handle_uninterpreted:
         if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
             ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
           return true;
         }
-        DO_(::google::protobuf::internal::WireFormatLite::SkipField(input, tag, mutable_unknown_fields()));
+        DO_(::google::protobuf::internal::WireFormatLite::SkipField(
+              input, tag, mutable_unknown_fields()));
         break;
       }
     }
@@ -1637,12 +1753,12 @@
   if (has_start()) {
     ::google::protobuf::internal::WireFormatLite::WriteInt32(1, this->start(), output);
   }
-  
+
   // optional int32 end = 2;
   if (has_end()) {
     ::google::protobuf::internal::WireFormatLite::WriteInt32(2, this->end(), output);
   }
-  
+
   if (!unknown_fields().empty()) {
     ::google::protobuf::internal::WireFormatLite::SerializeUnknownFields(
         unknown_fields(), output);
@@ -1655,12 +1771,12 @@
   if (has_start()) {
     target = ::google::protobuf::internal::WireFormatLite::WriteInt32ToArray(1, this->start(), target);
   }
-  
+
   // optional int32 end = 2;
   if (has_end()) {
     target = ::google::protobuf::internal::WireFormatLite::WriteInt32ToArray(2, this->end(), target);
   }
-  
+
   if (!unknown_fields().empty()) {
     target = ::google::protobuf::internal::WireFormatLite::SerializeUnknownFieldsToArray(
         unknown_fields(), target);
@@ -1670,7 +1786,7 @@
 
 int DescriptorProto_ExtensionRange::ByteSize() const {
   int total_size = 0;
-  
+
   if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) {
     // optional int32 start = 1;
     if (has_start()) {
@@ -1678,14 +1794,14 @@
         ::google::protobuf::internal::WireFormatLite::Int32Size(
           this->start());
     }
-    
+
     // optional int32 end = 2;
     if (has_end()) {
       total_size += 1 +
         ::google::protobuf::internal::WireFormatLite::Int32Size(
           this->end());
     }
-    
+
   }
   if (!unknown_fields().empty()) {
     total_size +=
@@ -1736,7 +1852,7 @@
 }
 
 bool DescriptorProto_ExtensionRange::IsInitialized() const {
-  
+
   return true;
 }
 
@@ -1868,7 +1984,7 @@
         if (input->ExpectTag(18)) goto parse_field;
         break;
       }
-      
+
       // repeated .google.protobuf.FieldDescriptorProto field = 2;
       case 2: {
         if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
@@ -1883,7 +1999,7 @@
         if (input->ExpectTag(26)) goto parse_nested_type;
         break;
       }
-      
+
       // repeated .google.protobuf.DescriptorProto nested_type = 3;
       case 3: {
         if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
@@ -1898,7 +2014,7 @@
         if (input->ExpectTag(34)) goto parse_enum_type;
         break;
       }
-      
+
       // repeated .google.protobuf.EnumDescriptorProto enum_type = 4;
       case 4: {
         if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
@@ -1913,7 +2029,7 @@
         if (input->ExpectTag(42)) goto parse_extension_range;
         break;
       }
-      
+
       // repeated .google.protobuf.DescriptorProto.ExtensionRange extension_range = 5;
       case 5: {
         if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
@@ -1928,7 +2044,7 @@
         if (input->ExpectTag(50)) goto parse_extension;
         break;
       }
-      
+
       // repeated .google.protobuf.FieldDescriptorProto extension = 6;
       case 6: {
         if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
@@ -1943,7 +2059,7 @@
         if (input->ExpectTag(58)) goto parse_options;
         break;
       }
-      
+
       // optional .google.protobuf.MessageOptions options = 7;
       case 7: {
         if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
@@ -1957,14 +2073,15 @@
         if (input->ExpectAtEnd()) return true;
         break;
       }
-      
+
       default: {
       handle_uninterpreted:
         if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
             ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
           return true;
         }
-        DO_(::google::protobuf::internal::WireFormatLite::SkipField(input, tag, mutable_unknown_fields()));
+        DO_(::google::protobuf::internal::WireFormatLite::SkipField(
+              input, tag, mutable_unknown_fields()));
         break;
       }
     }
@@ -1983,43 +2100,43 @@
     ::google::protobuf::internal::WireFormatLite::WriteString(
       1, this->name(), output);
   }
-  
+
   // repeated .google.protobuf.FieldDescriptorProto field = 2;
   for (int i = 0; i < this->field_size(); i++) {
     ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
       2, this->field(i), output);
   }
-  
+
   // repeated .google.protobuf.DescriptorProto nested_type = 3;
   for (int i = 0; i < this->nested_type_size(); i++) {
     ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
       3, this->nested_type(i), output);
   }
-  
+
   // repeated .google.protobuf.EnumDescriptorProto enum_type = 4;
   for (int i = 0; i < this->enum_type_size(); i++) {
     ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
       4, this->enum_type(i), output);
   }
-  
+
   // repeated .google.protobuf.DescriptorProto.ExtensionRange extension_range = 5;
   for (int i = 0; i < this->extension_range_size(); i++) {
     ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
       5, this->extension_range(i), output);
   }
-  
+
   // repeated .google.protobuf.FieldDescriptorProto extension = 6;
   for (int i = 0; i < this->extension_size(); i++) {
     ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
       6, this->extension(i), output);
   }
-  
+
   // optional .google.protobuf.MessageOptions options = 7;
   if (has_options()) {
     ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
       7, this->options(), output);
   }
-  
+
   if (!unknown_fields().empty()) {
     ::google::protobuf::internal::WireFormatLite::SerializeUnknownFields(
         unknown_fields(), output);
@@ -2037,49 +2154,49 @@
       ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
         1, this->name(), target);
   }
-  
+
   // repeated .google.protobuf.FieldDescriptorProto field = 2;
   for (int i = 0; i < this->field_size(); i++) {
     target = ::google::protobuf::internal::WireFormatLite::
       WriteMessageNoVirtualToArray(
         2, this->field(i), target);
   }
-  
+
   // repeated .google.protobuf.DescriptorProto nested_type = 3;
   for (int i = 0; i < this->nested_type_size(); i++) {
     target = ::google::protobuf::internal::WireFormatLite::
       WriteMessageNoVirtualToArray(
         3, this->nested_type(i), target);
   }
-  
+
   // repeated .google.protobuf.EnumDescriptorProto enum_type = 4;
   for (int i = 0; i < this->enum_type_size(); i++) {
     target = ::google::protobuf::internal::WireFormatLite::
       WriteMessageNoVirtualToArray(
         4, this->enum_type(i), target);
   }
-  
+
   // repeated .google.protobuf.DescriptorProto.ExtensionRange extension_range = 5;
   for (int i = 0; i < this->extension_range_size(); i++) {
     target = ::google::protobuf::internal::WireFormatLite::
       WriteMessageNoVirtualToArray(
         5, this->extension_range(i), target);
   }
-  
+
   // repeated .google.protobuf.FieldDescriptorProto extension = 6;
   for (int i = 0; i < this->extension_size(); i++) {
     target = ::google::protobuf::internal::WireFormatLite::
       WriteMessageNoVirtualToArray(
         6, this->extension(i), target);
   }
-  
+
   // optional .google.protobuf.MessageOptions options = 7;
   if (has_options()) {
     target = ::google::protobuf::internal::WireFormatLite::
       WriteMessageNoVirtualToArray(
         7, this->options(), target);
   }
-  
+
   if (!unknown_fields().empty()) {
     target = ::google::protobuf::internal::WireFormatLite::SerializeUnknownFieldsToArray(
         unknown_fields(), target);
@@ -2089,7 +2206,7 @@
 
 int DescriptorProto::ByteSize() const {
   int total_size = 0;
-  
+
   if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) {
     // optional string name = 1;
     if (has_name()) {
@@ -2097,14 +2214,14 @@
         ::google::protobuf::internal::WireFormatLite::StringSize(
           this->name());
     }
-    
+
     // optional .google.protobuf.MessageOptions options = 7;
     if (has_options()) {
       total_size += 1 +
         ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
           this->options());
     }
-    
+
   }
   // repeated .google.protobuf.FieldDescriptorProto field = 2;
   total_size += 1 * this->field_size();
@@ -2113,7 +2230,7 @@
       ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
         this->field(i));
   }
-  
+
   // repeated .google.protobuf.FieldDescriptorProto extension = 6;
   total_size += 1 * this->extension_size();
   for (int i = 0; i < this->extension_size(); i++) {
@@ -2121,7 +2238,7 @@
       ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
         this->extension(i));
   }
-  
+
   // repeated .google.protobuf.DescriptorProto nested_type = 3;
   total_size += 1 * this->nested_type_size();
   for (int i = 0; i < this->nested_type_size(); i++) {
@@ -2129,7 +2246,7 @@
       ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
         this->nested_type(i));
   }
-  
+
   // repeated .google.protobuf.EnumDescriptorProto enum_type = 4;
   total_size += 1 * this->enum_type_size();
   for (int i = 0; i < this->enum_type_size(); i++) {
@@ -2137,7 +2254,7 @@
       ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
         this->enum_type(i));
   }
-  
+
   // repeated .google.protobuf.DescriptorProto.ExtensionRange extension_range = 5;
   total_size += 1 * this->extension_range_size();
   for (int i = 0; i < this->extension_range_size(); i++) {
@@ -2145,7 +2262,7 @@
       ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
         this->extension_range(i));
   }
-  
+
   if (!unknown_fields().empty()) {
     total_size +=
       ::google::protobuf::internal::WireFormatLite::ComputeUnknownFieldsSize(
@@ -2200,7 +2317,7 @@
 }
 
 bool DescriptorProto::IsInitialized() const {
-  
+
   for (int i = 0; i < field_size(); i++) {
     if (!this->field(i).IsInitialized()) return false;
   }
@@ -2457,7 +2574,7 @@
         if (input->ExpectTag(18)) goto parse_extendee;
         break;
       }
-      
+
       // optional string extendee = 2;
       case 2: {
         if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
@@ -2474,7 +2591,7 @@
         if (input->ExpectTag(24)) goto parse_number;
         break;
       }
-      
+
       // optional int32 number = 3;
       case 3: {
         if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
@@ -2490,7 +2607,7 @@
         if (input->ExpectTag(32)) goto parse_label;
         break;
       }
-      
+
       // optional .google.protobuf.FieldDescriptorProto.Label label = 4;
       case 4: {
         if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
@@ -2511,7 +2628,7 @@
         if (input->ExpectTag(40)) goto parse_type;
         break;
       }
-      
+
       // optional .google.protobuf.FieldDescriptorProto.Type type = 5;
       case 5: {
         if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
@@ -2532,7 +2649,7 @@
         if (input->ExpectTag(50)) goto parse_type_name;
         break;
       }
-      
+
       // optional string type_name = 6;
       case 6: {
         if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
@@ -2549,7 +2666,7 @@
         if (input->ExpectTag(58)) goto parse_default_value;
         break;
       }
-      
+
       // optional string default_value = 7;
       case 7: {
         if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
@@ -2566,7 +2683,7 @@
         if (input->ExpectTag(66)) goto parse_options;
         break;
       }
-      
+
       // optional .google.protobuf.FieldOptions options = 8;
       case 8: {
         if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
@@ -2580,14 +2697,15 @@
         if (input->ExpectAtEnd()) return true;
         break;
       }
-      
+
       default: {
       handle_uninterpreted:
         if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
             ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
           return true;
         }
-        DO_(::google::protobuf::internal::WireFormatLite::SkipField(input, tag, mutable_unknown_fields()));
+        DO_(::google::protobuf::internal::WireFormatLite::SkipField(
+              input, tag, mutable_unknown_fields()));
         break;
       }
     }
@@ -2606,7 +2724,7 @@
     ::google::protobuf::internal::WireFormatLite::WriteString(
       1, this->name(), output);
   }
-  
+
   // optional string extendee = 2;
   if (has_extendee()) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8String(
@@ -2615,24 +2733,24 @@
     ::google::protobuf::internal::WireFormatLite::WriteString(
       2, this->extendee(), output);
   }
-  
+
   // optional int32 number = 3;
   if (has_number()) {
     ::google::protobuf::internal::WireFormatLite::WriteInt32(3, this->number(), output);
   }
-  
+
   // optional .google.protobuf.FieldDescriptorProto.Label label = 4;
   if (has_label()) {
     ::google::protobuf::internal::WireFormatLite::WriteEnum(
       4, this->label(), output);
   }
-  
+
   // optional .google.protobuf.FieldDescriptorProto.Type type = 5;
   if (has_type()) {
     ::google::protobuf::internal::WireFormatLite::WriteEnum(
       5, this->type(), output);
   }
-  
+
   // optional string type_name = 6;
   if (has_type_name()) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8String(
@@ -2641,7 +2759,7 @@
     ::google::protobuf::internal::WireFormatLite::WriteString(
       6, this->type_name(), output);
   }
-  
+
   // optional string default_value = 7;
   if (has_default_value()) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8String(
@@ -2650,13 +2768,13 @@
     ::google::protobuf::internal::WireFormatLite::WriteString(
       7, this->default_value(), output);
   }
-  
+
   // optional .google.protobuf.FieldOptions options = 8;
   if (has_options()) {
     ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
       8, this->options(), output);
   }
-  
+
   if (!unknown_fields().empty()) {
     ::google::protobuf::internal::WireFormatLite::SerializeUnknownFields(
         unknown_fields(), output);
@@ -2674,7 +2792,7 @@
       ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
         1, this->name(), target);
   }
-  
+
   // optional string extendee = 2;
   if (has_extendee()) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8String(
@@ -2684,24 +2802,24 @@
       ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
         2, this->extendee(), target);
   }
-  
+
   // optional int32 number = 3;
   if (has_number()) {
     target = ::google::protobuf::internal::WireFormatLite::WriteInt32ToArray(3, this->number(), target);
   }
-  
+
   // optional .google.protobuf.FieldDescriptorProto.Label label = 4;
   if (has_label()) {
     target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray(
       4, this->label(), target);
   }
-  
+
   // optional .google.protobuf.FieldDescriptorProto.Type type = 5;
   if (has_type()) {
     target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray(
       5, this->type(), target);
   }
-  
+
   // optional string type_name = 6;
   if (has_type_name()) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8String(
@@ -2711,7 +2829,7 @@
       ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
         6, this->type_name(), target);
   }
-  
+
   // optional string default_value = 7;
   if (has_default_value()) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8String(
@@ -2721,14 +2839,14 @@
       ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
         7, this->default_value(), target);
   }
-  
+
   // optional .google.protobuf.FieldOptions options = 8;
   if (has_options()) {
     target = ::google::protobuf::internal::WireFormatLite::
       WriteMessageNoVirtualToArray(
         8, this->options(), target);
   }
-  
+
   if (!unknown_fields().empty()) {
     target = ::google::protobuf::internal::WireFormatLite::SerializeUnknownFieldsToArray(
         unknown_fields(), target);
@@ -2738,7 +2856,7 @@
 
 int FieldDescriptorProto::ByteSize() const {
   int total_size = 0;
-  
+
   if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) {
     // optional string name = 1;
     if (has_name()) {
@@ -2746,54 +2864,54 @@
         ::google::protobuf::internal::WireFormatLite::StringSize(
           this->name());
     }
-    
+
     // optional int32 number = 3;
     if (has_number()) {
       total_size += 1 +
         ::google::protobuf::internal::WireFormatLite::Int32Size(
           this->number());
     }
-    
+
     // optional .google.protobuf.FieldDescriptorProto.Label label = 4;
     if (has_label()) {
       total_size += 1 +
         ::google::protobuf::internal::WireFormatLite::EnumSize(this->label());
     }
-    
+
     // optional .google.protobuf.FieldDescriptorProto.Type type = 5;
     if (has_type()) {
       total_size += 1 +
         ::google::protobuf::internal::WireFormatLite::EnumSize(this->type());
     }
-    
+
     // optional string type_name = 6;
     if (has_type_name()) {
       total_size += 1 +
         ::google::protobuf::internal::WireFormatLite::StringSize(
           this->type_name());
     }
-    
+
     // optional string extendee = 2;
     if (has_extendee()) {
       total_size += 1 +
         ::google::protobuf::internal::WireFormatLite::StringSize(
           this->extendee());
     }
-    
+
     // optional string default_value = 7;
     if (has_default_value()) {
       total_size += 1 +
         ::google::protobuf::internal::WireFormatLite::StringSize(
           this->default_value());
     }
-    
+
     // optional .google.protobuf.FieldOptions options = 8;
     if (has_options()) {
       total_size += 1 +
         ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
           this->options());
     }
-    
+
   }
   if (!unknown_fields().empty()) {
     total_size +=
@@ -2862,7 +2980,7 @@
 }
 
 bool FieldDescriptorProto::IsInitialized() const {
-  
+
   if (has_options()) {
     if (!this->options().IsInitialized()) return false;
   }
@@ -2995,7 +3113,7 @@
         if (input->ExpectTag(18)) goto parse_value;
         break;
       }
-      
+
       // repeated .google.protobuf.EnumValueDescriptorProto value = 2;
       case 2: {
         if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
@@ -3010,7 +3128,7 @@
         if (input->ExpectTag(26)) goto parse_options;
         break;
       }
-      
+
       // optional .google.protobuf.EnumOptions options = 3;
       case 3: {
         if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
@@ -3024,14 +3142,15 @@
         if (input->ExpectAtEnd()) return true;
         break;
       }
-      
+
       default: {
       handle_uninterpreted:
         if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
             ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
           return true;
         }
-        DO_(::google::protobuf::internal::WireFormatLite::SkipField(input, tag, mutable_unknown_fields()));
+        DO_(::google::protobuf::internal::WireFormatLite::SkipField(
+              input, tag, mutable_unknown_fields()));
         break;
       }
     }
@@ -3050,19 +3169,19 @@
     ::google::protobuf::internal::WireFormatLite::WriteString(
       1, this->name(), output);
   }
-  
+
   // repeated .google.protobuf.EnumValueDescriptorProto value = 2;
   for (int i = 0; i < this->value_size(); i++) {
     ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
       2, this->value(i), output);
   }
-  
+
   // optional .google.protobuf.EnumOptions options = 3;
   if (has_options()) {
     ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
       3, this->options(), output);
   }
-  
+
   if (!unknown_fields().empty()) {
     ::google::protobuf::internal::WireFormatLite::SerializeUnknownFields(
         unknown_fields(), output);
@@ -3080,21 +3199,21 @@
       ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
         1, this->name(), target);
   }
-  
+
   // repeated .google.protobuf.EnumValueDescriptorProto value = 2;
   for (int i = 0; i < this->value_size(); i++) {
     target = ::google::protobuf::internal::WireFormatLite::
       WriteMessageNoVirtualToArray(
         2, this->value(i), target);
   }
-  
+
   // optional .google.protobuf.EnumOptions options = 3;
   if (has_options()) {
     target = ::google::protobuf::internal::WireFormatLite::
       WriteMessageNoVirtualToArray(
         3, this->options(), target);
   }
-  
+
   if (!unknown_fields().empty()) {
     target = ::google::protobuf::internal::WireFormatLite::SerializeUnknownFieldsToArray(
         unknown_fields(), target);
@@ -3104,7 +3223,7 @@
 
 int EnumDescriptorProto::ByteSize() const {
   int total_size = 0;
-  
+
   if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) {
     // optional string name = 1;
     if (has_name()) {
@@ -3112,14 +3231,14 @@
         ::google::protobuf::internal::WireFormatLite::StringSize(
           this->name());
     }
-    
+
     // optional .google.protobuf.EnumOptions options = 3;
     if (has_options()) {
       total_size += 1 +
         ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
           this->options());
     }
-    
+
   }
   // repeated .google.protobuf.EnumValueDescriptorProto value = 2;
   total_size += 1 * this->value_size();
@@ -3128,7 +3247,7 @@
       ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
         this->value(i));
   }
-  
+
   if (!unknown_fields().empty()) {
     total_size +=
       ::google::protobuf::internal::WireFormatLite::ComputeUnknownFieldsSize(
@@ -3179,7 +3298,7 @@
 }
 
 bool EnumDescriptorProto::IsInitialized() const {
-  
+
   for (int i = 0; i < value_size(); i++) {
     if (!this->value(i).IsInitialized()) return false;
   }
@@ -3311,7 +3430,7 @@
         if (input->ExpectTag(16)) goto parse_number;
         break;
       }
-      
+
       // optional int32 number = 2;
       case 2: {
         if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
@@ -3327,7 +3446,7 @@
         if (input->ExpectTag(26)) goto parse_options;
         break;
       }
-      
+
       // optional .google.protobuf.EnumValueOptions options = 3;
       case 3: {
         if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
@@ -3341,14 +3460,15 @@
         if (input->ExpectAtEnd()) return true;
         break;
       }
-      
+
       default: {
       handle_uninterpreted:
         if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
             ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
           return true;
         }
-        DO_(::google::protobuf::internal::WireFormatLite::SkipField(input, tag, mutable_unknown_fields()));
+        DO_(::google::protobuf::internal::WireFormatLite::SkipField(
+              input, tag, mutable_unknown_fields()));
         break;
       }
     }
@@ -3367,18 +3487,18 @@
     ::google::protobuf::internal::WireFormatLite::WriteString(
       1, this->name(), output);
   }
-  
+
   // optional int32 number = 2;
   if (has_number()) {
     ::google::protobuf::internal::WireFormatLite::WriteInt32(2, this->number(), output);
   }
-  
+
   // optional .google.protobuf.EnumValueOptions options = 3;
   if (has_options()) {
     ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
       3, this->options(), output);
   }
-  
+
   if (!unknown_fields().empty()) {
     ::google::protobuf::internal::WireFormatLite::SerializeUnknownFields(
         unknown_fields(), output);
@@ -3396,19 +3516,19 @@
       ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
         1, this->name(), target);
   }
-  
+
   // optional int32 number = 2;
   if (has_number()) {
     target = ::google::protobuf::internal::WireFormatLite::WriteInt32ToArray(2, this->number(), target);
   }
-  
+
   // optional .google.protobuf.EnumValueOptions options = 3;
   if (has_options()) {
     target = ::google::protobuf::internal::WireFormatLite::
       WriteMessageNoVirtualToArray(
         3, this->options(), target);
   }
-  
+
   if (!unknown_fields().empty()) {
     target = ::google::protobuf::internal::WireFormatLite::SerializeUnknownFieldsToArray(
         unknown_fields(), target);
@@ -3418,7 +3538,7 @@
 
 int EnumValueDescriptorProto::ByteSize() const {
   int total_size = 0;
-  
+
   if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) {
     // optional string name = 1;
     if (has_name()) {
@@ -3426,21 +3546,21 @@
         ::google::protobuf::internal::WireFormatLite::StringSize(
           this->name());
     }
-    
+
     // optional int32 number = 2;
     if (has_number()) {
       total_size += 1 +
         ::google::protobuf::internal::WireFormatLite::Int32Size(
           this->number());
     }
-    
+
     // optional .google.protobuf.EnumValueOptions options = 3;
     if (has_options()) {
       total_size += 1 +
         ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
           this->options());
     }
-    
+
   }
   if (!unknown_fields().empty()) {
     total_size +=
@@ -3494,7 +3614,7 @@
 }
 
 bool EnumValueDescriptorProto::IsInitialized() const {
-  
+
   if (has_options()) {
     if (!this->options().IsInitialized()) return false;
   }
@@ -3622,7 +3742,7 @@
         if (input->ExpectTag(18)) goto parse_method;
         break;
       }
-      
+
       // repeated .google.protobuf.MethodDescriptorProto method = 2;
       case 2: {
         if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
@@ -3637,7 +3757,7 @@
         if (input->ExpectTag(26)) goto parse_options;
         break;
       }
-      
+
       // optional .google.protobuf.ServiceOptions options = 3;
       case 3: {
         if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
@@ -3651,14 +3771,15 @@
         if (input->ExpectAtEnd()) return true;
         break;
       }
-      
+
       default: {
       handle_uninterpreted:
         if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
             ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
           return true;
         }
-        DO_(::google::protobuf::internal::WireFormatLite::SkipField(input, tag, mutable_unknown_fields()));
+        DO_(::google::protobuf::internal::WireFormatLite::SkipField(
+              input, tag, mutable_unknown_fields()));
         break;
       }
     }
@@ -3677,19 +3798,19 @@
     ::google::protobuf::internal::WireFormatLite::WriteString(
       1, this->name(), output);
   }
-  
+
   // repeated .google.protobuf.MethodDescriptorProto method = 2;
   for (int i = 0; i < this->method_size(); i++) {
     ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
       2, this->method(i), output);
   }
-  
+
   // optional .google.protobuf.ServiceOptions options = 3;
   if (has_options()) {
     ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
       3, this->options(), output);
   }
-  
+
   if (!unknown_fields().empty()) {
     ::google::protobuf::internal::WireFormatLite::SerializeUnknownFields(
         unknown_fields(), output);
@@ -3707,21 +3828,21 @@
       ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
         1, this->name(), target);
   }
-  
+
   // repeated .google.protobuf.MethodDescriptorProto method = 2;
   for (int i = 0; i < this->method_size(); i++) {
     target = ::google::protobuf::internal::WireFormatLite::
       WriteMessageNoVirtualToArray(
         2, this->method(i), target);
   }
-  
+
   // optional .google.protobuf.ServiceOptions options = 3;
   if (has_options()) {
     target = ::google::protobuf::internal::WireFormatLite::
       WriteMessageNoVirtualToArray(
         3, this->options(), target);
   }
-  
+
   if (!unknown_fields().empty()) {
     target = ::google::protobuf::internal::WireFormatLite::SerializeUnknownFieldsToArray(
         unknown_fields(), target);
@@ -3731,7 +3852,7 @@
 
 int ServiceDescriptorProto::ByteSize() const {
   int total_size = 0;
-  
+
   if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) {
     // optional string name = 1;
     if (has_name()) {
@@ -3739,14 +3860,14 @@
         ::google::protobuf::internal::WireFormatLite::StringSize(
           this->name());
     }
-    
+
     // optional .google.protobuf.ServiceOptions options = 3;
     if (has_options()) {
       total_size += 1 +
         ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
           this->options());
     }
-    
+
   }
   // repeated .google.protobuf.MethodDescriptorProto method = 2;
   total_size += 1 * this->method_size();
@@ -3755,7 +3876,7 @@
       ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
         this->method(i));
   }
-  
+
   if (!unknown_fields().empty()) {
     total_size +=
       ::google::protobuf::internal::WireFormatLite::ComputeUnknownFieldsSize(
@@ -3806,7 +3927,7 @@
 }
 
 bool ServiceDescriptorProto::IsInitialized() const {
-  
+
   for (int i = 0; i < method_size(); i++) {
     if (!this->method(i).IsInitialized()) return false;
   }
@@ -3955,7 +4076,7 @@
         if (input->ExpectTag(18)) goto parse_input_type;
         break;
       }
-      
+
       // optional string input_type = 2;
       case 2: {
         if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
@@ -3972,7 +4093,7 @@
         if (input->ExpectTag(26)) goto parse_output_type;
         break;
       }
-      
+
       // optional string output_type = 3;
       case 3: {
         if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
@@ -3989,7 +4110,7 @@
         if (input->ExpectTag(34)) goto parse_options;
         break;
       }
-      
+
       // optional .google.protobuf.MethodOptions options = 4;
       case 4: {
         if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
@@ -4003,14 +4124,15 @@
         if (input->ExpectAtEnd()) return true;
         break;
       }
-      
+
       default: {
       handle_uninterpreted:
         if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
             ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
           return true;
         }
-        DO_(::google::protobuf::internal::WireFormatLite::SkipField(input, tag, mutable_unknown_fields()));
+        DO_(::google::protobuf::internal::WireFormatLite::SkipField(
+              input, tag, mutable_unknown_fields()));
         break;
       }
     }
@@ -4029,7 +4151,7 @@
     ::google::protobuf::internal::WireFormatLite::WriteString(
       1, this->name(), output);
   }
-  
+
   // optional string input_type = 2;
   if (has_input_type()) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8String(
@@ -4038,7 +4160,7 @@
     ::google::protobuf::internal::WireFormatLite::WriteString(
       2, this->input_type(), output);
   }
-  
+
   // optional string output_type = 3;
   if (has_output_type()) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8String(
@@ -4047,13 +4169,13 @@
     ::google::protobuf::internal::WireFormatLite::WriteString(
       3, this->output_type(), output);
   }
-  
+
   // optional .google.protobuf.MethodOptions options = 4;
   if (has_options()) {
     ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
       4, this->options(), output);
   }
-  
+
   if (!unknown_fields().empty()) {
     ::google::protobuf::internal::WireFormatLite::SerializeUnknownFields(
         unknown_fields(), output);
@@ -4071,7 +4193,7 @@
       ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
         1, this->name(), target);
   }
-  
+
   // optional string input_type = 2;
   if (has_input_type()) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8String(
@@ -4081,7 +4203,7 @@
       ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
         2, this->input_type(), target);
   }
-  
+
   // optional string output_type = 3;
   if (has_output_type()) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8String(
@@ -4091,14 +4213,14 @@
       ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
         3, this->output_type(), target);
   }
-  
+
   // optional .google.protobuf.MethodOptions options = 4;
   if (has_options()) {
     target = ::google::protobuf::internal::WireFormatLite::
       WriteMessageNoVirtualToArray(
         4, this->options(), target);
   }
-  
+
   if (!unknown_fields().empty()) {
     target = ::google::protobuf::internal::WireFormatLite::SerializeUnknownFieldsToArray(
         unknown_fields(), target);
@@ -4108,7 +4230,7 @@
 
 int MethodDescriptorProto::ByteSize() const {
   int total_size = 0;
-  
+
   if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) {
     // optional string name = 1;
     if (has_name()) {
@@ -4116,28 +4238,28 @@
         ::google::protobuf::internal::WireFormatLite::StringSize(
           this->name());
     }
-    
+
     // optional string input_type = 2;
     if (has_input_type()) {
       total_size += 1 +
         ::google::protobuf::internal::WireFormatLite::StringSize(
           this->input_type());
     }
-    
+
     // optional string output_type = 3;
     if (has_output_type()) {
       total_size += 1 +
         ::google::protobuf::internal::WireFormatLite::StringSize(
           this->output_type());
     }
-    
+
     // optional .google.protobuf.MethodOptions options = 4;
     if (has_options()) {
       total_size += 1 +
         ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
           this->options());
     }
-    
+
   }
   if (!unknown_fields().empty()) {
     total_size +=
@@ -4194,7 +4316,7 @@
 }
 
 bool MethodDescriptorProto::IsInitialized() const {
-  
+
   if (has_options()) {
     if (!this->options().IsInitialized()) return false;
   }
@@ -4254,6 +4376,7 @@
 const int FileOptions::kRetainUnknownFieldsFieldNumber;
 const int FileOptions::kJavaGenerateEqualsAndHashFieldNumber;
 const int FileOptions::kOptimizeForFieldNumber;
+const int FileOptions::kGoPackageFieldNumber;
 const int FileOptions::kCcGenericServicesFieldNumber;
 const int FileOptions::kJavaGenericServicesFieldNumber;
 const int FileOptions::kPyGenericServicesFieldNumber;
@@ -4282,6 +4405,7 @@
   retain_unknown_fields_ = false;
   java_generate_equals_and_hash_ = false;
   optimize_for_ = 1;
+  go_package_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
   cc_generic_services_ = false;
   java_generic_services_ = false;
   py_generic_services_ = false;
@@ -4299,6 +4423,9 @@
   if (java_outer_classname_ != &::google::protobuf::internal::kEmptyString) {
     delete java_outer_classname_;
   }
+  if (go_package_ != &::google::protobuf::internal::kEmptyString) {
+    delete go_package_;
+  }
   if (this != default_instance_) {
   }
 }
@@ -4341,10 +4468,15 @@
     retain_unknown_fields_ = false;
     java_generate_equals_and_hash_ = false;
     optimize_for_ = 1;
+    if (has_go_package()) {
+      if (go_package_ != &::google::protobuf::internal::kEmptyString) {
+        go_package_->clear();
+      }
+    }
     cc_generic_services_ = false;
-    java_generic_services_ = false;
   }
   if (_has_bits_[8 / 32] & (0xffu << (8 % 32))) {
+    java_generic_services_ = false;
     py_generic_services_ = false;
   }
   uninterpreted_option_.Clear();
@@ -4373,7 +4505,7 @@
         if (input->ExpectTag(66)) goto parse_java_outer_classname;
         break;
       }
-      
+
       // optional string java_outer_classname = 8;
       case 8: {
         if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
@@ -4390,7 +4522,7 @@
         if (input->ExpectTag(72)) goto parse_optimize_for;
         break;
       }
-      
+
       // optional .google.protobuf.FileOptions.OptimizeMode optimize_for = 9 [default = SPEED];
       case 9: {
         if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
@@ -4411,7 +4543,7 @@
         if (input->ExpectTag(80)) goto parse_java_multiple_files;
         break;
       }
-      
+
       // optional bool java_multiple_files = 10 [default = false];
       case 10: {
         if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
@@ -4424,13 +4556,30 @@
         } else {
           goto handle_uninterpreted;
         }
-        if (input->ExpectTag(88)) goto parse_retain_unknown_fields;
+        if (input->ExpectTag(90)) goto parse_go_package;
         break;
       }
-      
-      // optional bool retain_unknown_fields = 11 [default = false];
+
+      // optional string go_package = 11;
       case 11: {
         if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
+         parse_go_package:
+          DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+                input, this->mutable_go_package()));
+          ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+            this->go_package().data(), this->go_package().length(),
+            ::google::protobuf::internal::WireFormat::PARSE);
+        } else {
+          goto handle_uninterpreted;
+        }
+        if (input->ExpectTag(96)) goto parse_retain_unknown_fields;
+        break;
+      }
+
+      // optional bool retain_unknown_fields = 12 [default = false];
+      case 12: {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
             ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) {
          parse_retain_unknown_fields:
           DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
@@ -4443,7 +4592,7 @@
         if (input->ExpectTag(128)) goto parse_cc_generic_services;
         break;
       }
-      
+
       // optional bool cc_generic_services = 16 [default = false];
       case 16: {
         if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
@@ -4459,7 +4608,7 @@
         if (input->ExpectTag(136)) goto parse_java_generic_services;
         break;
       }
-      
+
       // optional bool java_generic_services = 17 [default = false];
       case 17: {
         if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
@@ -4475,7 +4624,7 @@
         if (input->ExpectTag(144)) goto parse_py_generic_services;
         break;
       }
-      
+
       // optional bool py_generic_services = 18 [default = false];
       case 18: {
         if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
@@ -4491,7 +4640,7 @@
         if (input->ExpectTag(160)) goto parse_java_generate_equals_and_hash;
         break;
       }
-      
+
       // optional bool java_generate_equals_and_hash = 20 [default = false];
       case 20: {
         if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
@@ -4507,7 +4656,7 @@
         if (input->ExpectTag(7994)) goto parse_uninterpreted_option;
         break;
       }
-      
+
       // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
       case 999: {
         if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
@@ -4522,7 +4671,7 @@
         if (input->ExpectAtEnd()) return true;
         break;
       }
-      
+
       default: {
       handle_uninterpreted:
         if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
@@ -4534,7 +4683,8 @@
                                       mutable_unknown_fields()));
           continue;
         }
-        DO_(::google::protobuf::internal::WireFormatLite::SkipField(input, tag, mutable_unknown_fields()));
+        DO_(::google::protobuf::internal::WireFormatLite::SkipField(
+              input, tag, mutable_unknown_fields()));
         break;
       }
     }
@@ -4553,7 +4703,7 @@
     ::google::protobuf::internal::WireFormatLite::WriteString(
       1, this->java_package(), output);
   }
-  
+
   // optional string java_outer_classname = 8;
   if (has_java_outer_classname()) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8String(
@@ -4562,53 +4712,62 @@
     ::google::protobuf::internal::WireFormatLite::WriteString(
       8, this->java_outer_classname(), output);
   }
-  
+
   // optional .google.protobuf.FileOptions.OptimizeMode optimize_for = 9 [default = SPEED];
   if (has_optimize_for()) {
     ::google::protobuf::internal::WireFormatLite::WriteEnum(
       9, this->optimize_for(), output);
   }
-  
+
   // optional bool java_multiple_files = 10 [default = false];
   if (has_java_multiple_files()) {
     ::google::protobuf::internal::WireFormatLite::WriteBool(10, this->java_multiple_files(), output);
   }
-  
-  // optional bool retain_unknown_fields = 11 [default = false];
-  if (has_retain_unknown_fields()) {
-    ::google::protobuf::internal::WireFormatLite::WriteBool(11, this->retain_unknown_fields(), output);
+
+  // optional string go_package = 11;
+  if (has_go_package()) {
+    ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+      this->go_package().data(), this->go_package().length(),
+      ::google::protobuf::internal::WireFormat::SERIALIZE);
+    ::google::protobuf::internal::WireFormatLite::WriteString(
+      11, this->go_package(), output);
   }
-  
+
+  // optional bool retain_unknown_fields = 12 [default = false];
+  if (has_retain_unknown_fields()) {
+    ::google::protobuf::internal::WireFormatLite::WriteBool(12, this->retain_unknown_fields(), output);
+  }
+
   // optional bool cc_generic_services = 16 [default = false];
   if (has_cc_generic_services()) {
     ::google::protobuf::internal::WireFormatLite::WriteBool(16, this->cc_generic_services(), output);
   }
-  
+
   // optional bool java_generic_services = 17 [default = false];
   if (has_java_generic_services()) {
     ::google::protobuf::internal::WireFormatLite::WriteBool(17, this->java_generic_services(), output);
   }
-  
+
   // optional bool py_generic_services = 18 [default = false];
   if (has_py_generic_services()) {
     ::google::protobuf::internal::WireFormatLite::WriteBool(18, this->py_generic_services(), output);
   }
-  
+
   // optional bool java_generate_equals_and_hash = 20 [default = false];
   if (has_java_generate_equals_and_hash()) {
     ::google::protobuf::internal::WireFormatLite::WriteBool(20, this->java_generate_equals_and_hash(), output);
   }
-  
+
   // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
   for (int i = 0; i < this->uninterpreted_option_size(); i++) {
     ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
       999, this->uninterpreted_option(i), output);
   }
-  
+
   // Extension range [1000, 536870912)
   _extensions_.SerializeWithCachedSizes(
       1000, 536870912, output);
-  
+
   if (!unknown_fields().empty()) {
     ::google::protobuf::internal::WireFormatLite::SerializeUnknownFields(
         unknown_fields(), output);
@@ -4626,7 +4785,7 @@
       ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
         1, this->java_package(), target);
   }
-  
+
   // optional string java_outer_classname = 8;
   if (has_java_outer_classname()) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8String(
@@ -4636,54 +4795,64 @@
       ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
         8, this->java_outer_classname(), target);
   }
-  
+
   // optional .google.protobuf.FileOptions.OptimizeMode optimize_for = 9 [default = SPEED];
   if (has_optimize_for()) {
     target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray(
       9, this->optimize_for(), target);
   }
-  
+
   // optional bool java_multiple_files = 10 [default = false];
   if (has_java_multiple_files()) {
     target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(10, this->java_multiple_files(), target);
   }
-  
-  // optional bool retain_unknown_fields = 11 [default = false];
-  if (has_retain_unknown_fields()) {
-    target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(11, this->retain_unknown_fields(), target);
+
+  // optional string go_package = 11;
+  if (has_go_package()) {
+    ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+      this->go_package().data(), this->go_package().length(),
+      ::google::protobuf::internal::WireFormat::SERIALIZE);
+    target =
+      ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+        11, this->go_package(), target);
   }
-  
+
+  // optional bool retain_unknown_fields = 12 [default = false];
+  if (has_retain_unknown_fields()) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(12, this->retain_unknown_fields(), target);
+  }
+
   // optional bool cc_generic_services = 16 [default = false];
   if (has_cc_generic_services()) {
     target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(16, this->cc_generic_services(), target);
   }
-  
+
   // optional bool java_generic_services = 17 [default = false];
   if (has_java_generic_services()) {
     target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(17, this->java_generic_services(), target);
   }
-  
+
   // optional bool py_generic_services = 18 [default = false];
   if (has_py_generic_services()) {
     target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(18, this->py_generic_services(), target);
   }
-  
+
   // optional bool java_generate_equals_and_hash = 20 [default = false];
   if (has_java_generate_equals_and_hash()) {
     target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(20, this->java_generate_equals_and_hash(), target);
   }
-  
+
   // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
   for (int i = 0; i < this->uninterpreted_option_size(); i++) {
     target = ::google::protobuf::internal::WireFormatLite::
       WriteMessageNoVirtualToArray(
         999, this->uninterpreted_option(i), target);
   }
-  
+
   // Extension range [1000, 536870912)
   target = _extensions_.SerializeWithCachedSizesToArray(
       1000, 536870912, target);
-  
+
   if (!unknown_fields().empty()) {
     target = ::google::protobuf::internal::WireFormatLite::SerializeUnknownFieldsToArray(
         unknown_fields(), target);
@@ -4693,7 +4862,7 @@
 
 int FileOptions::ByteSize() const {
   int total_size = 0;
-  
+
   if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) {
     // optional string java_package = 1;
     if (has_java_package()) {
@@ -4701,52 +4870,59 @@
         ::google::protobuf::internal::WireFormatLite::StringSize(
           this->java_package());
     }
-    
+
     // optional string java_outer_classname = 8;
     if (has_java_outer_classname()) {
       total_size += 1 +
         ::google::protobuf::internal::WireFormatLite::StringSize(
           this->java_outer_classname());
     }
-    
+
     // optional bool java_multiple_files = 10 [default = false];
     if (has_java_multiple_files()) {
       total_size += 1 + 1;
     }
-    
-    // optional bool retain_unknown_fields = 11 [default = false];
+
+    // optional bool retain_unknown_fields = 12 [default = false];
     if (has_retain_unknown_fields()) {
       total_size += 1 + 1;
     }
-    
+
     // optional bool java_generate_equals_and_hash = 20 [default = false];
     if (has_java_generate_equals_and_hash()) {
       total_size += 2 + 1;
     }
-    
+
     // optional .google.protobuf.FileOptions.OptimizeMode optimize_for = 9 [default = SPEED];
     if (has_optimize_for()) {
       total_size += 1 +
         ::google::protobuf::internal::WireFormatLite::EnumSize(this->optimize_for());
     }
-    
+
+    // optional string go_package = 11;
+    if (has_go_package()) {
+      total_size += 1 +
+        ::google::protobuf::internal::WireFormatLite::StringSize(
+          this->go_package());
+    }
+
     // optional bool cc_generic_services = 16 [default = false];
     if (has_cc_generic_services()) {
       total_size += 2 + 1;
     }
-    
+
+  }
+  if (_has_bits_[8 / 32] & (0xffu << (8 % 32))) {
     // optional bool java_generic_services = 17 [default = false];
     if (has_java_generic_services()) {
       total_size += 2 + 1;
     }
-    
-  }
-  if (_has_bits_[8 / 32] & (0xffu << (8 % 32))) {
+
     // optional bool py_generic_services = 18 [default = false];
     if (has_py_generic_services()) {
       total_size += 2 + 1;
     }
-    
+
   }
   // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
   total_size += 2 * this->uninterpreted_option_size();
@@ -4755,9 +4931,9 @@
       ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
         this->uninterpreted_option(i));
   }
-  
+
   total_size += _extensions_.ByteSize();
-  
+
   if (!unknown_fields().empty()) {
     total_size +=
       ::google::protobuf::internal::WireFormatLite::ComputeUnknownFieldsSize(
@@ -4803,14 +4979,17 @@
     if (from.has_optimize_for()) {
       set_optimize_for(from.optimize_for());
     }
+    if (from.has_go_package()) {
+      set_go_package(from.go_package());
+    }
     if (from.has_cc_generic_services()) {
       set_cc_generic_services(from.cc_generic_services());
     }
+  }
+  if (from._has_bits_[8 / 32] & (0xffu << (8 % 32))) {
     if (from.has_java_generic_services()) {
       set_java_generic_services(from.java_generic_services());
     }
-  }
-  if (from._has_bits_[8 / 32] & (0xffu << (8 % 32))) {
     if (from.has_py_generic_services()) {
       set_py_generic_services(from.py_generic_services());
     }
@@ -4832,11 +5011,11 @@
 }
 
 bool FileOptions::IsInitialized() const {
-  
+
   for (int i = 0; i < uninterpreted_option_size(); i++) {
     if (!this->uninterpreted_option(i).IsInitialized()) return false;
   }
-  
+
   if (!_extensions_.IsInitialized()) return false;  return true;
 }
 
@@ -4848,6 +5027,7 @@
     std::swap(retain_unknown_fields_, other->retain_unknown_fields_);
     std::swap(java_generate_equals_and_hash_, other->java_generate_equals_and_hash_);
     std::swap(optimize_for_, other->optimize_for_);
+    std::swap(go_package_, other->go_package_);
     std::swap(cc_generic_services_, other->cc_generic_services_);
     std::swap(java_generic_services_, other->java_generic_services_);
     std::swap(py_generic_services_, other->py_generic_services_);
@@ -4958,7 +5138,7 @@
         if (input->ExpectTag(16)) goto parse_no_standard_descriptor_accessor;
         break;
       }
-      
+
       // optional bool no_standard_descriptor_accessor = 2 [default = false];
       case 2: {
         if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
@@ -4974,7 +5154,7 @@
         if (input->ExpectTag(7994)) goto parse_uninterpreted_option;
         break;
       }
-      
+
       // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
       case 999: {
         if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
@@ -4989,7 +5169,7 @@
         if (input->ExpectAtEnd()) return true;
         break;
       }
-      
+
       default: {
       handle_uninterpreted:
         if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
@@ -5001,7 +5181,8 @@
                                       mutable_unknown_fields()));
           continue;
         }
-        DO_(::google::protobuf::internal::WireFormatLite::SkipField(input, tag, mutable_unknown_fields()));
+        DO_(::google::protobuf::internal::WireFormatLite::SkipField(
+              input, tag, mutable_unknown_fields()));
         break;
       }
     }
@@ -5016,22 +5197,22 @@
   if (has_message_set_wire_format()) {
     ::google::protobuf::internal::WireFormatLite::WriteBool(1, this->message_set_wire_format(), output);
   }
-  
+
   // optional bool no_standard_descriptor_accessor = 2 [default = false];
   if (has_no_standard_descriptor_accessor()) {
     ::google::protobuf::internal::WireFormatLite::WriteBool(2, this->no_standard_descriptor_accessor(), output);
   }
-  
+
   // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
   for (int i = 0; i < this->uninterpreted_option_size(); i++) {
     ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
       999, this->uninterpreted_option(i), output);
   }
-  
+
   // Extension range [1000, 536870912)
   _extensions_.SerializeWithCachedSizes(
       1000, 536870912, output);
-  
+
   if (!unknown_fields().empty()) {
     ::google::protobuf::internal::WireFormatLite::SerializeUnknownFields(
         unknown_fields(), output);
@@ -5044,23 +5225,23 @@
   if (has_message_set_wire_format()) {
     target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(1, this->message_set_wire_format(), target);
   }
-  
+
   // optional bool no_standard_descriptor_accessor = 2 [default = false];
   if (has_no_standard_descriptor_accessor()) {
     target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(2, this->no_standard_descriptor_accessor(), target);
   }
-  
+
   // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
   for (int i = 0; i < this->uninterpreted_option_size(); i++) {
     target = ::google::protobuf::internal::WireFormatLite::
       WriteMessageNoVirtualToArray(
         999, this->uninterpreted_option(i), target);
   }
-  
+
   // Extension range [1000, 536870912)
   target = _extensions_.SerializeWithCachedSizesToArray(
       1000, 536870912, target);
-  
+
   if (!unknown_fields().empty()) {
     target = ::google::protobuf::internal::WireFormatLite::SerializeUnknownFieldsToArray(
         unknown_fields(), target);
@@ -5070,18 +5251,18 @@
 
 int MessageOptions::ByteSize() const {
   int total_size = 0;
-  
+
   if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) {
     // optional bool message_set_wire_format = 1 [default = false];
     if (has_message_set_wire_format()) {
       total_size += 1 + 1;
     }
-    
+
     // optional bool no_standard_descriptor_accessor = 2 [default = false];
     if (has_no_standard_descriptor_accessor()) {
       total_size += 1 + 1;
     }
-    
+
   }
   // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
   total_size += 2 * this->uninterpreted_option_size();
@@ -5090,9 +5271,9 @@
       ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
         this->uninterpreted_option(i));
   }
-  
+
   total_size += _extensions_.ByteSize();
-  
+
   if (!unknown_fields().empty()) {
     total_size +=
       ::google::protobuf::internal::WireFormatLite::ComputeUnknownFieldsSize(
@@ -5144,11 +5325,11 @@
 }
 
 bool MessageOptions::IsInitialized() const {
-  
+
   for (int i = 0; i < uninterpreted_option_size(); i++) {
     if (!this->uninterpreted_option(i).IsInitialized()) return false;
   }
-  
+
   if (!_extensions_.IsInitialized()) return false;  return true;
 }
 
@@ -5201,8 +5382,10 @@
 #ifndef _MSC_VER
 const int FieldOptions::kCtypeFieldNumber;
 const int FieldOptions::kPackedFieldNumber;
+const int FieldOptions::kLazyFieldNumber;
 const int FieldOptions::kDeprecatedFieldNumber;
 const int FieldOptions::kExperimentalMapKeyFieldNumber;
+const int FieldOptions::kWeakFieldNumber;
 const int FieldOptions::kUninterpretedOptionFieldNumber;
 #endif  // !_MSC_VER
 
@@ -5224,8 +5407,10 @@
   _cached_size_ = 0;
   ctype_ = 0;
   packed_ = false;
+  lazy_ = false;
   deprecated_ = false;
   experimental_map_key_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
+  weak_ = false;
   ::memset(_has_bits_, 0, sizeof(_has_bits_));
 }
 
@@ -5267,12 +5452,14 @@
   if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) {
     ctype_ = 0;
     packed_ = false;
+    lazy_ = false;
     deprecated_ = false;
     if (has_experimental_map_key()) {
       if (experimental_map_key_ != &::google::protobuf::internal::kEmptyString) {
         experimental_map_key_->clear();
       }
     }
+    weak_ = false;
   }
   uninterpreted_option_.Clear();
   ::memset(_has_bits_, 0, sizeof(_has_bits_));
@@ -5304,7 +5491,7 @@
         if (input->ExpectTag(16)) goto parse_packed;
         break;
       }
-      
+
       // optional bool packed = 2;
       case 2: {
         if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
@@ -5320,7 +5507,7 @@
         if (input->ExpectTag(24)) goto parse_deprecated;
         break;
       }
-      
+
       // optional bool deprecated = 3 [default = false];
       case 3: {
         if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
@@ -5333,10 +5520,26 @@
         } else {
           goto handle_uninterpreted;
         }
+        if (input->ExpectTag(40)) goto parse_lazy;
+        break;
+      }
+
+      // optional bool lazy = 5 [default = false];
+      case 5: {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) {
+         parse_lazy:
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>(
+                 input, &lazy_)));
+          set_has_lazy();
+        } else {
+          goto handle_uninterpreted;
+        }
         if (input->ExpectTag(74)) goto parse_experimental_map_key;
         break;
       }
-      
+
       // optional string experimental_map_key = 9;
       case 9: {
         if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
@@ -5350,10 +5553,26 @@
         } else {
           goto handle_uninterpreted;
         }
+        if (input->ExpectTag(80)) goto parse_weak;
+        break;
+      }
+
+      // optional bool weak = 10 [default = false];
+      case 10: {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) {
+         parse_weak:
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>(
+                 input, &weak_)));
+          set_has_weak();
+        } else {
+          goto handle_uninterpreted;
+        }
         if (input->ExpectTag(7994)) goto parse_uninterpreted_option;
         break;
       }
-      
+
       // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
       case 999: {
         if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
@@ -5368,7 +5587,7 @@
         if (input->ExpectAtEnd()) return true;
         break;
       }
-      
+
       default: {
       handle_uninterpreted:
         if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
@@ -5380,7 +5599,8 @@
                                       mutable_unknown_fields()));
           continue;
         }
-        DO_(::google::protobuf::internal::WireFormatLite::SkipField(input, tag, mutable_unknown_fields()));
+        DO_(::google::protobuf::internal::WireFormatLite::SkipField(
+              input, tag, mutable_unknown_fields()));
         break;
       }
     }
@@ -5396,17 +5616,22 @@
     ::google::protobuf::internal::WireFormatLite::WriteEnum(
       1, this->ctype(), output);
   }
-  
+
   // optional bool packed = 2;
   if (has_packed()) {
     ::google::protobuf::internal::WireFormatLite::WriteBool(2, this->packed(), output);
   }
-  
+
   // optional bool deprecated = 3 [default = false];
   if (has_deprecated()) {
     ::google::protobuf::internal::WireFormatLite::WriteBool(3, this->deprecated(), output);
   }
-  
+
+  // optional bool lazy = 5 [default = false];
+  if (has_lazy()) {
+    ::google::protobuf::internal::WireFormatLite::WriteBool(5, this->lazy(), output);
+  }
+
   // optional string experimental_map_key = 9;
   if (has_experimental_map_key()) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8String(
@@ -5415,17 +5640,22 @@
     ::google::protobuf::internal::WireFormatLite::WriteString(
       9, this->experimental_map_key(), output);
   }
-  
+
+  // optional bool weak = 10 [default = false];
+  if (has_weak()) {
+    ::google::protobuf::internal::WireFormatLite::WriteBool(10, this->weak(), output);
+  }
+
   // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
   for (int i = 0; i < this->uninterpreted_option_size(); i++) {
     ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
       999, this->uninterpreted_option(i), output);
   }
-  
+
   // Extension range [1000, 536870912)
   _extensions_.SerializeWithCachedSizes(
       1000, 536870912, output);
-  
+
   if (!unknown_fields().empty()) {
     ::google::protobuf::internal::WireFormatLite::SerializeUnknownFields(
         unknown_fields(), output);
@@ -5439,17 +5669,22 @@
     target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray(
       1, this->ctype(), target);
   }
-  
+
   // optional bool packed = 2;
   if (has_packed()) {
     target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(2, this->packed(), target);
   }
-  
+
   // optional bool deprecated = 3 [default = false];
   if (has_deprecated()) {
     target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(3, this->deprecated(), target);
   }
-  
+
+  // optional bool lazy = 5 [default = false];
+  if (has_lazy()) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(5, this->lazy(), target);
+  }
+
   // optional string experimental_map_key = 9;
   if (has_experimental_map_key()) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8String(
@@ -5459,18 +5694,23 @@
       ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
         9, this->experimental_map_key(), target);
   }
-  
+
+  // optional bool weak = 10 [default = false];
+  if (has_weak()) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(10, this->weak(), target);
+  }
+
   // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
   for (int i = 0; i < this->uninterpreted_option_size(); i++) {
     target = ::google::protobuf::internal::WireFormatLite::
       WriteMessageNoVirtualToArray(
         999, this->uninterpreted_option(i), target);
   }
-  
+
   // Extension range [1000, 536870912)
   target = _extensions_.SerializeWithCachedSizesToArray(
       1000, 536870912, target);
-  
+
   if (!unknown_fields().empty()) {
     target = ::google::protobuf::internal::WireFormatLite::SerializeUnknownFieldsToArray(
         unknown_fields(), target);
@@ -5480,31 +5720,41 @@
 
 int FieldOptions::ByteSize() const {
   int total_size = 0;
-  
+
   if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) {
     // optional .google.protobuf.FieldOptions.CType ctype = 1 [default = STRING];
     if (has_ctype()) {
       total_size += 1 +
         ::google::protobuf::internal::WireFormatLite::EnumSize(this->ctype());
     }
-    
+
     // optional bool packed = 2;
     if (has_packed()) {
       total_size += 1 + 1;
     }
-    
+
+    // optional bool lazy = 5 [default = false];
+    if (has_lazy()) {
+      total_size += 1 + 1;
+    }
+
     // optional bool deprecated = 3 [default = false];
     if (has_deprecated()) {
       total_size += 1 + 1;
     }
-    
+
     // optional string experimental_map_key = 9;
     if (has_experimental_map_key()) {
       total_size += 1 +
         ::google::protobuf::internal::WireFormatLite::StringSize(
           this->experimental_map_key());
     }
-    
+
+    // optional bool weak = 10 [default = false];
+    if (has_weak()) {
+      total_size += 1 + 1;
+    }
+
   }
   // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
   total_size += 2 * this->uninterpreted_option_size();
@@ -5513,9 +5763,9 @@
       ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
         this->uninterpreted_option(i));
   }
-  
+
   total_size += _extensions_.ByteSize();
-  
+
   if (!unknown_fields().empty()) {
     total_size +=
       ::google::protobuf::internal::WireFormatLite::ComputeUnknownFieldsSize(
@@ -5549,12 +5799,18 @@
     if (from.has_packed()) {
       set_packed(from.packed());
     }
+    if (from.has_lazy()) {
+      set_lazy(from.lazy());
+    }
     if (from.has_deprecated()) {
       set_deprecated(from.deprecated());
     }
     if (from.has_experimental_map_key()) {
       set_experimental_map_key(from.experimental_map_key());
     }
+    if (from.has_weak()) {
+      set_weak(from.weak());
+    }
   }
   _extensions_.MergeFrom(from._extensions_);
   mutable_unknown_fields()->MergeFrom(from.unknown_fields());
@@ -5573,11 +5829,11 @@
 }
 
 bool FieldOptions::IsInitialized() const {
-  
+
   for (int i = 0; i < uninterpreted_option_size(); i++) {
     if (!this->uninterpreted_option(i).IsInitialized()) return false;
   }
-  
+
   if (!_extensions_.IsInitialized()) return false;  return true;
 }
 
@@ -5585,8 +5841,10 @@
   if (other != this) {
     std::swap(ctype_, other->ctype_);
     std::swap(packed_, other->packed_);
+    std::swap(lazy_, other->lazy_);
     std::swap(deprecated_, other->deprecated_);
     std::swap(experimental_map_key_, other->experimental_map_key_);
+    std::swap(weak_, other->weak_);
     uninterpreted_option_.Swap(&other->uninterpreted_option_);
     std::swap(_has_bits_[0], other->_has_bits_[0]);
     _unknown_fields_.Swap(&other->_unknown_fields_);
@@ -5607,6 +5865,7 @@
 // ===================================================================
 
 #ifndef _MSC_VER
+const int EnumOptions::kAllowAliasFieldNumber;
 const int EnumOptions::kUninterpretedOptionFieldNumber;
 #endif  // !_MSC_VER
 
@@ -5626,6 +5885,7 @@
 
 void EnumOptions::SharedCtor() {
   _cached_size_ = 0;
+  allow_alias_ = true;
   ::memset(_has_bits_, 0, sizeof(_has_bits_));
 }
 
@@ -5661,6 +5921,9 @@
 
 void EnumOptions::Clear() {
   _extensions_.Clear();
+  if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) {
+    allow_alias_ = true;
+  }
   uninterpreted_option_.Clear();
   ::memset(_has_bits_, 0, sizeof(_has_bits_));
   mutable_unknown_fields()->Clear();
@@ -5672,6 +5935,21 @@
   ::google::protobuf::uint32 tag;
   while ((tag = input->ReadTag()) != 0) {
     switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+      // optional bool allow_alias = 2 [default = true];
+      case 2: {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) {
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>(
+                 input, &allow_alias_)));
+          set_has_allow_alias();
+        } else {
+          goto handle_uninterpreted;
+        }
+        if (input->ExpectTag(7994)) goto parse_uninterpreted_option;
+        break;
+      }
+
       // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
       case 999: {
         if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
@@ -5686,7 +5964,7 @@
         if (input->ExpectAtEnd()) return true;
         break;
       }
-      
+
       default: {
       handle_uninterpreted:
         if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
@@ -5698,7 +5976,8 @@
                                       mutable_unknown_fields()));
           continue;
         }
-        DO_(::google::protobuf::internal::WireFormatLite::SkipField(input, tag, mutable_unknown_fields()));
+        DO_(::google::protobuf::internal::WireFormatLite::SkipField(
+              input, tag, mutable_unknown_fields()));
         break;
       }
     }
@@ -5709,16 +5988,21 @@
 
 void EnumOptions::SerializeWithCachedSizes(
     ::google::protobuf::io::CodedOutputStream* output) const {
+  // optional bool allow_alias = 2 [default = true];
+  if (has_allow_alias()) {
+    ::google::protobuf::internal::WireFormatLite::WriteBool(2, this->allow_alias(), output);
+  }
+
   // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
   for (int i = 0; i < this->uninterpreted_option_size(); i++) {
     ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
       999, this->uninterpreted_option(i), output);
   }
-  
+
   // Extension range [1000, 536870912)
   _extensions_.SerializeWithCachedSizes(
       1000, 536870912, output);
-  
+
   if (!unknown_fields().empty()) {
     ::google::protobuf::internal::WireFormatLite::SerializeUnknownFields(
         unknown_fields(), output);
@@ -5727,17 +6011,22 @@
 
 ::google::protobuf::uint8* EnumOptions::SerializeWithCachedSizesToArray(
     ::google::protobuf::uint8* target) const {
+  // optional bool allow_alias = 2 [default = true];
+  if (has_allow_alias()) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(2, this->allow_alias(), target);
+  }
+
   // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
   for (int i = 0; i < this->uninterpreted_option_size(); i++) {
     target = ::google::protobuf::internal::WireFormatLite::
       WriteMessageNoVirtualToArray(
         999, this->uninterpreted_option(i), target);
   }
-  
+
   // Extension range [1000, 536870912)
   target = _extensions_.SerializeWithCachedSizesToArray(
       1000, 536870912, target);
-  
+
   if (!unknown_fields().empty()) {
     target = ::google::protobuf::internal::WireFormatLite::SerializeUnknownFieldsToArray(
         unknown_fields(), target);
@@ -5747,7 +6036,14 @@
 
 int EnumOptions::ByteSize() const {
   int total_size = 0;
-  
+
+  if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) {
+    // optional bool allow_alias = 2 [default = true];
+    if (has_allow_alias()) {
+      total_size += 1 + 1;
+    }
+
+  }
   // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
   total_size += 2 * this->uninterpreted_option_size();
   for (int i = 0; i < this->uninterpreted_option_size(); i++) {
@@ -5755,9 +6051,9 @@
       ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
         this->uninterpreted_option(i));
   }
-  
+
   total_size += _extensions_.ByteSize();
-  
+
   if (!unknown_fields().empty()) {
     total_size +=
       ::google::protobuf::internal::WireFormatLite::ComputeUnknownFieldsSize(
@@ -5784,6 +6080,11 @@
 void EnumOptions::MergeFrom(const EnumOptions& from) {
   GOOGLE_CHECK_NE(&from, this);
   uninterpreted_option_.MergeFrom(from.uninterpreted_option_);
+  if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) {
+    if (from.has_allow_alias()) {
+      set_allow_alias(from.allow_alias());
+    }
+  }
   _extensions_.MergeFrom(from._extensions_);
   mutable_unknown_fields()->MergeFrom(from.unknown_fields());
 }
@@ -5801,16 +6102,17 @@
 }
 
 bool EnumOptions::IsInitialized() const {
-  
+
   for (int i = 0; i < uninterpreted_option_size(); i++) {
     if (!this->uninterpreted_option(i).IsInitialized()) return false;
   }
-  
+
   if (!_extensions_.IsInitialized()) return false;  return true;
 }
 
 void EnumOptions::Swap(EnumOptions* other) {
   if (other != this) {
+    std::swap(allow_alias_, other->allow_alias_);
     uninterpreted_option_.Swap(&other->uninterpreted_option_);
     std::swap(_has_bits_[0], other->_has_bits_[0]);
     _unknown_fields_.Swap(&other->_unknown_fields_);
@@ -5910,7 +6212,7 @@
         if (input->ExpectAtEnd()) return true;
         break;
       }
-      
+
       default: {
       handle_uninterpreted:
         if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
@@ -5922,7 +6224,8 @@
                                       mutable_unknown_fields()));
           continue;
         }
-        DO_(::google::protobuf::internal::WireFormatLite::SkipField(input, tag, mutable_unknown_fields()));
+        DO_(::google::protobuf::internal::WireFormatLite::SkipField(
+              input, tag, mutable_unknown_fields()));
         break;
       }
     }
@@ -5938,11 +6241,11 @@
     ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
       999, this->uninterpreted_option(i), output);
   }
-  
+
   // Extension range [1000, 536870912)
   _extensions_.SerializeWithCachedSizes(
       1000, 536870912, output);
-  
+
   if (!unknown_fields().empty()) {
     ::google::protobuf::internal::WireFormatLite::SerializeUnknownFields(
         unknown_fields(), output);
@@ -5957,11 +6260,11 @@
       WriteMessageNoVirtualToArray(
         999, this->uninterpreted_option(i), target);
   }
-  
+
   // Extension range [1000, 536870912)
   target = _extensions_.SerializeWithCachedSizesToArray(
       1000, 536870912, target);
-  
+
   if (!unknown_fields().empty()) {
     target = ::google::protobuf::internal::WireFormatLite::SerializeUnknownFieldsToArray(
         unknown_fields(), target);
@@ -5971,7 +6274,7 @@
 
 int EnumValueOptions::ByteSize() const {
   int total_size = 0;
-  
+
   // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
   total_size += 2 * this->uninterpreted_option_size();
   for (int i = 0; i < this->uninterpreted_option_size(); i++) {
@@ -5979,9 +6282,9 @@
       ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
         this->uninterpreted_option(i));
   }
-  
+
   total_size += _extensions_.ByteSize();
-  
+
   if (!unknown_fields().empty()) {
     total_size +=
       ::google::protobuf::internal::WireFormatLite::ComputeUnknownFieldsSize(
@@ -6025,11 +6328,11 @@
 }
 
 bool EnumValueOptions::IsInitialized() const {
-  
+
   for (int i = 0; i < uninterpreted_option_size(); i++) {
     if (!this->uninterpreted_option(i).IsInitialized()) return false;
   }
-  
+
   if (!_extensions_.IsInitialized()) return false;  return true;
 }
 
@@ -6134,7 +6437,7 @@
         if (input->ExpectAtEnd()) return true;
         break;
       }
-      
+
       default: {
       handle_uninterpreted:
         if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
@@ -6146,7 +6449,8 @@
                                       mutable_unknown_fields()));
           continue;
         }
-        DO_(::google::protobuf::internal::WireFormatLite::SkipField(input, tag, mutable_unknown_fields()));
+        DO_(::google::protobuf::internal::WireFormatLite::SkipField(
+              input, tag, mutable_unknown_fields()));
         break;
       }
     }
@@ -6162,11 +6466,11 @@
     ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
       999, this->uninterpreted_option(i), output);
   }
-  
+
   // Extension range [1000, 536870912)
   _extensions_.SerializeWithCachedSizes(
       1000, 536870912, output);
-  
+
   if (!unknown_fields().empty()) {
     ::google::protobuf::internal::WireFormatLite::SerializeUnknownFields(
         unknown_fields(), output);
@@ -6181,11 +6485,11 @@
       WriteMessageNoVirtualToArray(
         999, this->uninterpreted_option(i), target);
   }
-  
+
   // Extension range [1000, 536870912)
   target = _extensions_.SerializeWithCachedSizesToArray(
       1000, 536870912, target);
-  
+
   if (!unknown_fields().empty()) {
     target = ::google::protobuf::internal::WireFormatLite::SerializeUnknownFieldsToArray(
         unknown_fields(), target);
@@ -6195,7 +6499,7 @@
 
 int ServiceOptions::ByteSize() const {
   int total_size = 0;
-  
+
   // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
   total_size += 2 * this->uninterpreted_option_size();
   for (int i = 0; i < this->uninterpreted_option_size(); i++) {
@@ -6203,9 +6507,9 @@
       ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
         this->uninterpreted_option(i));
   }
-  
+
   total_size += _extensions_.ByteSize();
-  
+
   if (!unknown_fields().empty()) {
     total_size +=
       ::google::protobuf::internal::WireFormatLite::ComputeUnknownFieldsSize(
@@ -6249,11 +6553,11 @@
 }
 
 bool ServiceOptions::IsInitialized() const {
-  
+
   for (int i = 0; i < uninterpreted_option_size(); i++) {
     if (!this->uninterpreted_option(i).IsInitialized()) return false;
   }
-  
+
   if (!_extensions_.IsInitialized()) return false;  return true;
 }
 
@@ -6358,7 +6662,7 @@
         if (input->ExpectAtEnd()) return true;
         break;
       }
-      
+
       default: {
       handle_uninterpreted:
         if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
@@ -6370,7 +6674,8 @@
                                       mutable_unknown_fields()));
           continue;
         }
-        DO_(::google::protobuf::internal::WireFormatLite::SkipField(input, tag, mutable_unknown_fields()));
+        DO_(::google::protobuf::internal::WireFormatLite::SkipField(
+              input, tag, mutable_unknown_fields()));
         break;
       }
     }
@@ -6386,11 +6691,11 @@
     ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
       999, this->uninterpreted_option(i), output);
   }
-  
+
   // Extension range [1000, 536870912)
   _extensions_.SerializeWithCachedSizes(
       1000, 536870912, output);
-  
+
   if (!unknown_fields().empty()) {
     ::google::protobuf::internal::WireFormatLite::SerializeUnknownFields(
         unknown_fields(), output);
@@ -6405,11 +6710,11 @@
       WriteMessageNoVirtualToArray(
         999, this->uninterpreted_option(i), target);
   }
-  
+
   // Extension range [1000, 536870912)
   target = _extensions_.SerializeWithCachedSizesToArray(
       1000, 536870912, target);
-  
+
   if (!unknown_fields().empty()) {
     target = ::google::protobuf::internal::WireFormatLite::SerializeUnknownFieldsToArray(
         unknown_fields(), target);
@@ -6419,7 +6724,7 @@
 
 int MethodOptions::ByteSize() const {
   int total_size = 0;
-  
+
   // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
   total_size += 2 * this->uninterpreted_option_size();
   for (int i = 0; i < this->uninterpreted_option_size(); i++) {
@@ -6427,9 +6732,9 @@
       ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
         this->uninterpreted_option(i));
   }
-  
+
   total_size += _extensions_.ByteSize();
-  
+
   if (!unknown_fields().empty()) {
     total_size +=
       ::google::protobuf::internal::WireFormatLite::ComputeUnknownFieldsSize(
@@ -6473,11 +6778,11 @@
 }
 
 bool MethodOptions::IsInitialized() const {
-  
+
   for (int i = 0; i < uninterpreted_option_size(); i++) {
     if (!this->uninterpreted_option(i).IsInitialized()) return false;
   }
-  
+
   if (!_extensions_.IsInitialized()) return false;  return true;
 }
 
@@ -6595,7 +6900,7 @@
         if (input->ExpectTag(16)) goto parse_is_extension;
         break;
       }
-      
+
       // required bool is_extension = 2;
       case 2: {
         if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
@@ -6611,14 +6916,15 @@
         if (input->ExpectAtEnd()) return true;
         break;
       }
-      
+
       default: {
       handle_uninterpreted:
         if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
             ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
           return true;
         }
-        DO_(::google::protobuf::internal::WireFormatLite::SkipField(input, tag, mutable_unknown_fields()));
+        DO_(::google::protobuf::internal::WireFormatLite::SkipField(
+              input, tag, mutable_unknown_fields()));
         break;
       }
     }
@@ -6637,12 +6943,12 @@
     ::google::protobuf::internal::WireFormatLite::WriteString(
       1, this->name_part(), output);
   }
-  
+
   // required bool is_extension = 2;
   if (has_is_extension()) {
     ::google::protobuf::internal::WireFormatLite::WriteBool(2, this->is_extension(), output);
   }
-  
+
   if (!unknown_fields().empty()) {
     ::google::protobuf::internal::WireFormatLite::SerializeUnknownFields(
         unknown_fields(), output);
@@ -6660,12 +6966,12 @@
       ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
         1, this->name_part(), target);
   }
-  
+
   // required bool is_extension = 2;
   if (has_is_extension()) {
     target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(2, this->is_extension(), target);
   }
-  
+
   if (!unknown_fields().empty()) {
     target = ::google::protobuf::internal::WireFormatLite::SerializeUnknownFieldsToArray(
         unknown_fields(), target);
@@ -6675,7 +6981,7 @@
 
 int UninterpretedOption_NamePart::ByteSize() const {
   int total_size = 0;
-  
+
   if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) {
     // required string name_part = 1;
     if (has_name_part()) {
@@ -6683,12 +6989,12 @@
         ::google::protobuf::internal::WireFormatLite::StringSize(
           this->name_part());
     }
-    
+
     // required bool is_extension = 2;
     if (has_is_extension()) {
       total_size += 1 + 1;
     }
-    
+
   }
   if (!unknown_fields().empty()) {
     total_size +=
@@ -6740,7 +7046,7 @@
 
 bool UninterpretedOption_NamePart::IsInitialized() const {
   if ((_has_bits_[0] & 0x00000003) != 0x00000003) return false;
-  
+
   return true;
 }
 
@@ -6885,7 +7191,7 @@
         if (input->ExpectTag(26)) goto parse_identifier_value;
         break;
       }
-      
+
       // optional string identifier_value = 3;
       case 3: {
         if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
@@ -6902,7 +7208,7 @@
         if (input->ExpectTag(32)) goto parse_positive_int_value;
         break;
       }
-      
+
       // optional uint64 positive_int_value = 4;
       case 4: {
         if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
@@ -6918,7 +7224,7 @@
         if (input->ExpectTag(40)) goto parse_negative_int_value;
         break;
       }
-      
+
       // optional int64 negative_int_value = 5;
       case 5: {
         if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
@@ -6934,7 +7240,7 @@
         if (input->ExpectTag(49)) goto parse_double_value;
         break;
       }
-      
+
       // optional double double_value = 6;
       case 6: {
         if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
@@ -6950,7 +7256,7 @@
         if (input->ExpectTag(58)) goto parse_string_value;
         break;
       }
-      
+
       // optional bytes string_value = 7;
       case 7: {
         if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
@@ -6964,7 +7270,7 @@
         if (input->ExpectTag(66)) goto parse_aggregate_value;
         break;
       }
-      
+
       // optional string aggregate_value = 8;
       case 8: {
         if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
@@ -6981,14 +7287,15 @@
         if (input->ExpectAtEnd()) return true;
         break;
       }
-      
+
       default: {
       handle_uninterpreted:
         if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
             ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
           return true;
         }
-        DO_(::google::protobuf::internal::WireFormatLite::SkipField(input, tag, mutable_unknown_fields()));
+        DO_(::google::protobuf::internal::WireFormatLite::SkipField(
+              input, tag, mutable_unknown_fields()));
         break;
       }
     }
@@ -7004,7 +7311,7 @@
     ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
       2, this->name(i), output);
   }
-  
+
   // optional string identifier_value = 3;
   if (has_identifier_value()) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8String(
@@ -7013,28 +7320,28 @@
     ::google::protobuf::internal::WireFormatLite::WriteString(
       3, this->identifier_value(), output);
   }
-  
+
   // optional uint64 positive_int_value = 4;
   if (has_positive_int_value()) {
     ::google::protobuf::internal::WireFormatLite::WriteUInt64(4, this->positive_int_value(), output);
   }
-  
+
   // optional int64 negative_int_value = 5;
   if (has_negative_int_value()) {
     ::google::protobuf::internal::WireFormatLite::WriteInt64(5, this->negative_int_value(), output);
   }
-  
+
   // optional double double_value = 6;
   if (has_double_value()) {
     ::google::protobuf::internal::WireFormatLite::WriteDouble(6, this->double_value(), output);
   }
-  
+
   // optional bytes string_value = 7;
   if (has_string_value()) {
     ::google::protobuf::internal::WireFormatLite::WriteBytes(
       7, this->string_value(), output);
   }
-  
+
   // optional string aggregate_value = 8;
   if (has_aggregate_value()) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8String(
@@ -7043,7 +7350,7 @@
     ::google::protobuf::internal::WireFormatLite::WriteString(
       8, this->aggregate_value(), output);
   }
-  
+
   if (!unknown_fields().empty()) {
     ::google::protobuf::internal::WireFormatLite::SerializeUnknownFields(
         unknown_fields(), output);
@@ -7058,7 +7365,7 @@
       WriteMessageNoVirtualToArray(
         2, this->name(i), target);
   }
-  
+
   // optional string identifier_value = 3;
   if (has_identifier_value()) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8String(
@@ -7068,29 +7375,29 @@
       ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
         3, this->identifier_value(), target);
   }
-  
+
   // optional uint64 positive_int_value = 4;
   if (has_positive_int_value()) {
     target = ::google::protobuf::internal::WireFormatLite::WriteUInt64ToArray(4, this->positive_int_value(), target);
   }
-  
+
   // optional int64 negative_int_value = 5;
   if (has_negative_int_value()) {
     target = ::google::protobuf::internal::WireFormatLite::WriteInt64ToArray(5, this->negative_int_value(), target);
   }
-  
+
   // optional double double_value = 6;
   if (has_double_value()) {
     target = ::google::protobuf::internal::WireFormatLite::WriteDoubleToArray(6, this->double_value(), target);
   }
-  
+
   // optional bytes string_value = 7;
   if (has_string_value()) {
     target =
       ::google::protobuf::internal::WireFormatLite::WriteBytesToArray(
         7, this->string_value(), target);
   }
-  
+
   // optional string aggregate_value = 8;
   if (has_aggregate_value()) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8String(
@@ -7100,7 +7407,7 @@
       ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
         8, this->aggregate_value(), target);
   }
-  
+
   if (!unknown_fields().empty()) {
     target = ::google::protobuf::internal::WireFormatLite::SerializeUnknownFieldsToArray(
         unknown_fields(), target);
@@ -7110,7 +7417,7 @@
 
 int UninterpretedOption::ByteSize() const {
   int total_size = 0;
-  
+
   if (_has_bits_[1 / 32] & (0xffu << (1 % 32))) {
     // optional string identifier_value = 3;
     if (has_identifier_value()) {
@@ -7118,40 +7425,40 @@
         ::google::protobuf::internal::WireFormatLite::StringSize(
           this->identifier_value());
     }
-    
+
     // optional uint64 positive_int_value = 4;
     if (has_positive_int_value()) {
       total_size += 1 +
         ::google::protobuf::internal::WireFormatLite::UInt64Size(
           this->positive_int_value());
     }
-    
+
     // optional int64 negative_int_value = 5;
     if (has_negative_int_value()) {
       total_size += 1 +
         ::google::protobuf::internal::WireFormatLite::Int64Size(
           this->negative_int_value());
     }
-    
+
     // optional double double_value = 6;
     if (has_double_value()) {
       total_size += 1 + 8;
     }
-    
+
     // optional bytes string_value = 7;
     if (has_string_value()) {
       total_size += 1 +
         ::google::protobuf::internal::WireFormatLite::BytesSize(
           this->string_value());
     }
-    
+
     // optional string aggregate_value = 8;
     if (has_aggregate_value()) {
       total_size += 1 +
         ::google::protobuf::internal::WireFormatLite::StringSize(
           this->aggregate_value());
     }
-    
+
   }
   // repeated .google.protobuf.UninterpretedOption.NamePart name = 2;
   total_size += 1 * this->name_size();
@@ -7160,7 +7467,7 @@
       ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
         this->name(i));
   }
-  
+
   if (!unknown_fields().empty()) {
     total_size +=
       ::google::protobuf::internal::WireFormatLite::ComputeUnknownFieldsSize(
@@ -7223,7 +7530,7 @@
 }
 
 bool UninterpretedOption::IsInitialized() const {
-  
+
   for (int i = 0; i < name_size(); i++) {
     if (!this->name(i).IsInitialized()) return false;
   }
@@ -7259,6 +7566,8 @@
 #ifndef _MSC_VER
 const int SourceCodeInfo_Location::kPathFieldNumber;
 const int SourceCodeInfo_Location::kSpanFieldNumber;
+const int SourceCodeInfo_Location::kLeadingCommentsFieldNumber;
+const int SourceCodeInfo_Location::kTrailingCommentsFieldNumber;
 #endif  // !_MSC_VER
 
 SourceCodeInfo_Location::SourceCodeInfo_Location()
@@ -7277,6 +7586,8 @@
 
 void SourceCodeInfo_Location::SharedCtor() {
   _cached_size_ = 0;
+  leading_comments_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
+  trailing_comments_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
   ::memset(_has_bits_, 0, sizeof(_has_bits_));
 }
 
@@ -7285,6 +7596,12 @@
 }
 
 void SourceCodeInfo_Location::SharedDtor() {
+  if (leading_comments_ != &::google::protobuf::internal::kEmptyString) {
+    delete leading_comments_;
+  }
+  if (trailing_comments_ != &::google::protobuf::internal::kEmptyString) {
+    delete trailing_comments_;
+  }
   if (this != default_instance_) {
   }
 }
@@ -7311,6 +7628,18 @@
 }
 
 void SourceCodeInfo_Location::Clear() {
+  if (_has_bits_[2 / 32] & (0xffu << (2 % 32))) {
+    if (has_leading_comments()) {
+      if (leading_comments_ != &::google::protobuf::internal::kEmptyString) {
+        leading_comments_->clear();
+      }
+    }
+    if (has_trailing_comments()) {
+      if (trailing_comments_ != &::google::protobuf::internal::kEmptyString) {
+        trailing_comments_->clear();
+      }
+    }
+  }
   path_.Clear();
   span_.Clear();
   ::memset(_has_bits_, 0, sizeof(_has_bits_));
@@ -7342,7 +7671,7 @@
         if (input->ExpectTag(18)) goto parse_span;
         break;
       }
-      
+
       // repeated int32 span = 2 [packed = true];
       case 2: {
         if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
@@ -7360,17 +7689,52 @@
         } else {
           goto handle_uninterpreted;
         }
+        if (input->ExpectTag(26)) goto parse_leading_comments;
+        break;
+      }
+
+      // optional string leading_comments = 3;
+      case 3: {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
+         parse_leading_comments:
+          DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+                input, this->mutable_leading_comments()));
+          ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+            this->leading_comments().data(), this->leading_comments().length(),
+            ::google::protobuf::internal::WireFormat::PARSE);
+        } else {
+          goto handle_uninterpreted;
+        }
+        if (input->ExpectTag(34)) goto parse_trailing_comments;
+        break;
+      }
+
+      // optional string trailing_comments = 4;
+      case 4: {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
+         parse_trailing_comments:
+          DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+                input, this->mutable_trailing_comments()));
+          ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+            this->trailing_comments().data(), this->trailing_comments().length(),
+            ::google::protobuf::internal::WireFormat::PARSE);
+        } else {
+          goto handle_uninterpreted;
+        }
         if (input->ExpectAtEnd()) return true;
         break;
       }
-      
+
       default: {
       handle_uninterpreted:
         if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
             ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
           return true;
         }
-        DO_(::google::protobuf::internal::WireFormatLite::SkipField(input, tag, mutable_unknown_fields()));
+        DO_(::google::protobuf::internal::WireFormatLite::SkipField(
+              input, tag, mutable_unknown_fields()));
         break;
       }
     }
@@ -7390,7 +7754,7 @@
     ::google::protobuf::internal::WireFormatLite::WriteInt32NoTag(
       this->path(i), output);
   }
-  
+
   // repeated int32 span = 2 [packed = true];
   if (this->span_size() > 0) {
     ::google::protobuf::internal::WireFormatLite::WriteTag(2, ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED, output);
@@ -7400,7 +7764,25 @@
     ::google::protobuf::internal::WireFormatLite::WriteInt32NoTag(
       this->span(i), output);
   }
-  
+
+  // optional string leading_comments = 3;
+  if (has_leading_comments()) {
+    ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+      this->leading_comments().data(), this->leading_comments().length(),
+      ::google::protobuf::internal::WireFormat::SERIALIZE);
+    ::google::protobuf::internal::WireFormatLite::WriteString(
+      3, this->leading_comments(), output);
+  }
+
+  // optional string trailing_comments = 4;
+  if (has_trailing_comments()) {
+    ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+      this->trailing_comments().data(), this->trailing_comments().length(),
+      ::google::protobuf::internal::WireFormat::SERIALIZE);
+    ::google::protobuf::internal::WireFormatLite::WriteString(
+      4, this->trailing_comments(), output);
+  }
+
   if (!unknown_fields().empty()) {
     ::google::protobuf::internal::WireFormatLite::SerializeUnknownFields(
         unknown_fields(), output);
@@ -7422,7 +7804,7 @@
     target = ::google::protobuf::internal::WireFormatLite::
       WriteInt32NoTagToArray(this->path(i), target);
   }
-  
+
   // repeated int32 span = 2 [packed = true];
   if (this->span_size() > 0) {
     target = ::google::protobuf::internal::WireFormatLite::WriteTagToArray(
@@ -7436,7 +7818,27 @@
     target = ::google::protobuf::internal::WireFormatLite::
       WriteInt32NoTagToArray(this->span(i), target);
   }
-  
+
+  // optional string leading_comments = 3;
+  if (has_leading_comments()) {
+    ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+      this->leading_comments().data(), this->leading_comments().length(),
+      ::google::protobuf::internal::WireFormat::SERIALIZE);
+    target =
+      ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+        3, this->leading_comments(), target);
+  }
+
+  // optional string trailing_comments = 4;
+  if (has_trailing_comments()) {
+    ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+      this->trailing_comments().data(), this->trailing_comments().length(),
+      ::google::protobuf::internal::WireFormat::SERIALIZE);
+    target =
+      ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+        4, this->trailing_comments(), target);
+  }
+
   if (!unknown_fields().empty()) {
     target = ::google::protobuf::internal::WireFormatLite::SerializeUnknownFieldsToArray(
         unknown_fields(), target);
@@ -7446,7 +7848,23 @@
 
 int SourceCodeInfo_Location::ByteSize() const {
   int total_size = 0;
-  
+
+  if (_has_bits_[2 / 32] & (0xffu << (2 % 32))) {
+    // optional string leading_comments = 3;
+    if (has_leading_comments()) {
+      total_size += 1 +
+        ::google::protobuf::internal::WireFormatLite::StringSize(
+          this->leading_comments());
+    }
+
+    // optional string trailing_comments = 4;
+    if (has_trailing_comments()) {
+      total_size += 1 +
+        ::google::protobuf::internal::WireFormatLite::StringSize(
+          this->trailing_comments());
+    }
+
+  }
   // repeated int32 path = 1 [packed = true];
   {
     int data_size = 0;
@@ -7458,10 +7876,12 @@
       total_size += 1 +
         ::google::protobuf::internal::WireFormatLite::Int32Size(data_size);
     }
+    GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
     _path_cached_byte_size_ = data_size;
+    GOOGLE_SAFE_CONCURRENT_WRITES_END();
     total_size += data_size;
   }
-  
+
   // repeated int32 span = 2 [packed = true];
   {
     int data_size = 0;
@@ -7473,10 +7893,12 @@
       total_size += 1 +
         ::google::protobuf::internal::WireFormatLite::Int32Size(data_size);
     }
+    GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
     _span_cached_byte_size_ = data_size;
+    GOOGLE_SAFE_CONCURRENT_WRITES_END();
     total_size += data_size;
   }
-  
+
   if (!unknown_fields().empty()) {
     total_size +=
       ::google::protobuf::internal::WireFormatLite::ComputeUnknownFieldsSize(
@@ -7504,6 +7926,14 @@
   GOOGLE_CHECK_NE(&from, this);
   path_.MergeFrom(from.path_);
   span_.MergeFrom(from.span_);
+  if (from._has_bits_[2 / 32] & (0xffu << (2 % 32))) {
+    if (from.has_leading_comments()) {
+      set_leading_comments(from.leading_comments());
+    }
+    if (from.has_trailing_comments()) {
+      set_trailing_comments(from.trailing_comments());
+    }
+  }
   mutable_unknown_fields()->MergeFrom(from.unknown_fields());
 }
 
@@ -7520,7 +7950,7 @@
 }
 
 bool SourceCodeInfo_Location::IsInitialized() const {
-  
+
   return true;
 }
 
@@ -7528,6 +7958,8 @@
   if (other != this) {
     path_.Swap(&other->path_);
     span_.Swap(&other->span_);
+    std::swap(leading_comments_, other->leading_comments_);
+    std::swap(trailing_comments_, other->trailing_comments_);
     std::swap(_has_bits_[0], other->_has_bits_[0]);
     _unknown_fields_.Swap(&other->_unknown_fields_);
     std::swap(_cached_size_, other->_cached_size_);
@@ -7624,14 +8056,15 @@
         if (input->ExpectAtEnd()) return true;
         break;
       }
-      
+
       default: {
       handle_uninterpreted:
         if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
             ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
           return true;
         }
-        DO_(::google::protobuf::internal::WireFormatLite::SkipField(input, tag, mutable_unknown_fields()));
+        DO_(::google::protobuf::internal::WireFormatLite::SkipField(
+              input, tag, mutable_unknown_fields()));
         break;
       }
     }
@@ -7647,7 +8080,7 @@
     ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
       1, this->location(i), output);
   }
-  
+
   if (!unknown_fields().empty()) {
     ::google::protobuf::internal::WireFormatLite::SerializeUnknownFields(
         unknown_fields(), output);
@@ -7662,7 +8095,7 @@
       WriteMessageNoVirtualToArray(
         1, this->location(i), target);
   }
-  
+
   if (!unknown_fields().empty()) {
     target = ::google::protobuf::internal::WireFormatLite::SerializeUnknownFieldsToArray(
         unknown_fields(), target);
@@ -7672,7 +8105,7 @@
 
 int SourceCodeInfo::ByteSize() const {
   int total_size = 0;
-  
+
   // repeated .google.protobuf.SourceCodeInfo.Location location = 1;
   total_size += 1 * this->location_size();
   for (int i = 0; i < this->location_size(); i++) {
@@ -7680,7 +8113,7 @@
       ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
         this->location(i));
   }
-  
+
   if (!unknown_fields().empty()) {
     total_size +=
       ::google::protobuf::internal::WireFormatLite::ComputeUnknownFieldsSize(
@@ -7723,7 +8156,7 @@
 }
 
 bool SourceCodeInfo::IsInitialized() const {
-  
+
   return true;
 }
 
diff --git a/third_party/protobuf/src/google/protobuf/descriptor.pb.h b/third_party/protobuf/src/google/protobuf/descriptor.pb.h
index 1f91d79..5c1175c 100644
--- a/third_party/protobuf/src/google/protobuf/descriptor.pb.h
+++ b/third_party/protobuf/src/google/protobuf/descriptor.pb.h
@@ -20,10 +20,11 @@
 #endif
 
 #include <google/protobuf/generated_message_util.h>
+#include <google/protobuf/message.h>
 #include <google/protobuf/repeated_field.h>
 #include <google/protobuf/extension_set.h>
+#include <google/protobuf/generated_enum_reflection.h>
 #include <google/protobuf/unknown_field_set.h>
-#include <google/protobuf/generated_message_reflection.h>
 // @@protoc_insertion_point(includes)
 
 namespace google {
@@ -156,29 +157,29 @@
  public:
   FileDescriptorSet();
   virtual ~FileDescriptorSet();
-  
+
   FileDescriptorSet(const FileDescriptorSet& from);
-  
+
   inline FileDescriptorSet& operator=(const FileDescriptorSet& from) {
     CopyFrom(from);
     return *this;
   }
-  
+
   inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
     return _unknown_fields_;
   }
-  
+
   inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
     return &_unknown_fields_;
   }
-  
+
   static const ::google::protobuf::Descriptor* descriptor();
   static const FileDescriptorSet& default_instance();
-  
+
   void Swap(FileDescriptorSet* other);
-  
+
   // implements Message ----------------------------------------------
-  
+
   FileDescriptorSet* New() const;
   void CopyFrom(const ::google::protobuf::Message& from);
   void MergeFrom(const ::google::protobuf::Message& from);
@@ -186,7 +187,7 @@
   void MergeFrom(const FileDescriptorSet& from);
   void Clear();
   bool IsInitialized() const;
-  
+
   int ByteSize() const;
   bool MergePartialFromCodedStream(
       ::google::protobuf::io::CodedInputStream* input);
@@ -199,13 +200,13 @@
   void SharedDtor();
   void SetCachedSize(int size) const;
   public:
-  
+
   ::google::protobuf::Metadata GetMetadata() const;
-  
+
   // nested types ----------------------------------------------------
-  
+
   // accessors -------------------------------------------------------
-  
+
   // repeated .google.protobuf.FileDescriptorProto file = 1;
   inline int file_size() const;
   inline void clear_file();
@@ -217,21 +218,21 @@
       file() const;
   inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >*
       mutable_file();
-  
+
   // @@protoc_insertion_point(class_scope:google.protobuf.FileDescriptorSet)
  private:
-  
+
   ::google::protobuf::UnknownFieldSet _unknown_fields_;
-  
+
   ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto > file_;
-  
+
   mutable int _cached_size_;
   ::google::protobuf::uint32 _has_bits_[(1 + 31) / 32];
-  
+
   friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto();
-  
+
   void InitAsDefaultInstance();
   static FileDescriptorSet* default_instance_;
 };
@@ -241,29 +242,29 @@
  public:
   FileDescriptorProto();
   virtual ~FileDescriptorProto();
-  
+
   FileDescriptorProto(const FileDescriptorProto& from);
-  
+
   inline FileDescriptorProto& operator=(const FileDescriptorProto& from) {
     CopyFrom(from);
     return *this;
   }
-  
+
   inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
     return _unknown_fields_;
   }
-  
+
   inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
     return &_unknown_fields_;
   }
-  
+
   static const ::google::protobuf::Descriptor* descriptor();
   static const FileDescriptorProto& default_instance();
-  
+
   void Swap(FileDescriptorProto* other);
-  
+
   // implements Message ----------------------------------------------
-  
+
   FileDescriptorProto* New() const;
   void CopyFrom(const ::google::protobuf::Message& from);
   void MergeFrom(const ::google::protobuf::Message& from);
@@ -271,7 +272,7 @@
   void MergeFrom(const FileDescriptorProto& from);
   void Clear();
   bool IsInitialized() const;
-  
+
   int ByteSize() const;
   bool MergePartialFromCodedStream(
       ::google::protobuf::io::CodedInputStream* input);
@@ -284,13 +285,13 @@
   void SharedDtor();
   void SetCachedSize(int size) const;
   public:
-  
+
   ::google::protobuf::Metadata GetMetadata() const;
-  
+
   // nested types ----------------------------------------------------
-  
+
   // accessors -------------------------------------------------------
-  
+
   // optional string name = 1;
   inline bool has_name() const;
   inline void clear_name();
@@ -301,7 +302,8 @@
   inline void set_name(const char* value, size_t size);
   inline ::std::string* mutable_name();
   inline ::std::string* release_name();
-  
+  inline void set_allocated_name(::std::string* name);
+
   // optional string package = 2;
   inline bool has_package() const;
   inline void clear_package();
@@ -312,7 +314,8 @@
   inline void set_package(const char* value, size_t size);
   inline ::std::string* mutable_package();
   inline ::std::string* release_package();
-  
+  inline void set_allocated_package(::std::string* package);
+
   // repeated string dependency = 3;
   inline int dependency_size() const;
   inline void clear_dependency();
@@ -328,7 +331,31 @@
   inline void add_dependency(const char* value, size_t size);
   inline const ::google::protobuf::RepeatedPtrField< ::std::string>& dependency() const;
   inline ::google::protobuf::RepeatedPtrField< ::std::string>* mutable_dependency();
-  
+
+  // repeated int32 public_dependency = 10;
+  inline int public_dependency_size() const;
+  inline void clear_public_dependency();
+  static const int kPublicDependencyFieldNumber = 10;
+  inline ::google::protobuf::int32 public_dependency(int index) const;
+  inline void set_public_dependency(int index, ::google::protobuf::int32 value);
+  inline void add_public_dependency(::google::protobuf::int32 value);
+  inline const ::google::protobuf::RepeatedField< ::google::protobuf::int32 >&
+      public_dependency() const;
+  inline ::google::protobuf::RepeatedField< ::google::protobuf::int32 >*
+      mutable_public_dependency();
+
+  // repeated int32 weak_dependency = 11;
+  inline int weak_dependency_size() const;
+  inline void clear_weak_dependency();
+  static const int kWeakDependencyFieldNumber = 11;
+  inline ::google::protobuf::int32 weak_dependency(int index) const;
+  inline void set_weak_dependency(int index, ::google::protobuf::int32 value);
+  inline void add_weak_dependency(::google::protobuf::int32 value);
+  inline const ::google::protobuf::RepeatedField< ::google::protobuf::int32 >&
+      weak_dependency() const;
+  inline ::google::protobuf::RepeatedField< ::google::protobuf::int32 >*
+      mutable_weak_dependency();
+
   // repeated .google.protobuf.DescriptorProto message_type = 4;
   inline int message_type_size() const;
   inline void clear_message_type();
@@ -340,7 +367,7 @@
       message_type() const;
   inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >*
       mutable_message_type();
-  
+
   // repeated .google.protobuf.EnumDescriptorProto enum_type = 5;
   inline int enum_type_size() const;
   inline void clear_enum_type();
@@ -352,7 +379,7 @@
       enum_type() const;
   inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >*
       mutable_enum_type();
-  
+
   // repeated .google.protobuf.ServiceDescriptorProto service = 6;
   inline int service_size() const;
   inline void clear_service();
@@ -364,7 +391,7 @@
       service() const;
   inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::ServiceDescriptorProto >*
       mutable_service();
-  
+
   // repeated .google.protobuf.FieldDescriptorProto extension = 7;
   inline int extension_size() const;
   inline void clear_extension();
@@ -376,7 +403,7 @@
       extension() const;
   inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >*
       mutable_extension();
-  
+
   // optional .google.protobuf.FileOptions options = 8;
   inline bool has_options() const;
   inline void clear_options();
@@ -384,7 +411,8 @@
   inline const ::google::protobuf::FileOptions& options() const;
   inline ::google::protobuf::FileOptions* mutable_options();
   inline ::google::protobuf::FileOptions* release_options();
-  
+  inline void set_allocated_options(::google::protobuf::FileOptions* options);
+
   // optional .google.protobuf.SourceCodeInfo source_code_info = 9;
   inline bool has_source_code_info() const;
   inline void clear_source_code_info();
@@ -392,7 +420,8 @@
   inline const ::google::protobuf::SourceCodeInfo& source_code_info() const;
   inline ::google::protobuf::SourceCodeInfo* mutable_source_code_info();
   inline ::google::protobuf::SourceCodeInfo* release_source_code_info();
-  
+  inline void set_allocated_source_code_info(::google::protobuf::SourceCodeInfo* source_code_info);
+
   // @@protoc_insertion_point(class_scope:google.protobuf.FileDescriptorProto)
  private:
   inline void set_has_name();
@@ -403,26 +432,28 @@
   inline void clear_has_options();
   inline void set_has_source_code_info();
   inline void clear_has_source_code_info();
-  
+
   ::google::protobuf::UnknownFieldSet _unknown_fields_;
-  
+
   ::std::string* name_;
   ::std::string* package_;
   ::google::protobuf::RepeatedPtrField< ::std::string> dependency_;
+  ::google::protobuf::RepeatedField< ::google::protobuf::int32 > public_dependency_;
+  ::google::protobuf::RepeatedField< ::google::protobuf::int32 > weak_dependency_;
   ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto > message_type_;
   ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto > enum_type_;
   ::google::protobuf::RepeatedPtrField< ::google::protobuf::ServiceDescriptorProto > service_;
   ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto > extension_;
   ::google::protobuf::FileOptions* options_;
   ::google::protobuf::SourceCodeInfo* source_code_info_;
-  
+
   mutable int _cached_size_;
-  ::google::protobuf::uint32 _has_bits_[(9 + 31) / 32];
-  
+  ::google::protobuf::uint32 _has_bits_[(11 + 31) / 32];
+
   friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto();
-  
+
   void InitAsDefaultInstance();
   static FileDescriptorProto* default_instance_;
 };
@@ -432,29 +463,29 @@
  public:
   DescriptorProto_ExtensionRange();
   virtual ~DescriptorProto_ExtensionRange();
-  
+
   DescriptorProto_ExtensionRange(const DescriptorProto_ExtensionRange& from);
-  
+
   inline DescriptorProto_ExtensionRange& operator=(const DescriptorProto_ExtensionRange& from) {
     CopyFrom(from);
     return *this;
   }
-  
+
   inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
     return _unknown_fields_;
   }
-  
+
   inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
     return &_unknown_fields_;
   }
-  
+
   static const ::google::protobuf::Descriptor* descriptor();
   static const DescriptorProto_ExtensionRange& default_instance();
-  
+
   void Swap(DescriptorProto_ExtensionRange* other);
-  
+
   // implements Message ----------------------------------------------
-  
+
   DescriptorProto_ExtensionRange* New() const;
   void CopyFrom(const ::google::protobuf::Message& from);
   void MergeFrom(const ::google::protobuf::Message& from);
@@ -462,7 +493,7 @@
   void MergeFrom(const DescriptorProto_ExtensionRange& from);
   void Clear();
   bool IsInitialized() const;
-  
+
   int ByteSize() const;
   bool MergePartialFromCodedStream(
       ::google::protobuf::io::CodedInputStream* input);
@@ -475,46 +506,46 @@
   void SharedDtor();
   void SetCachedSize(int size) const;
   public:
-  
+
   ::google::protobuf::Metadata GetMetadata() const;
-  
+
   // nested types ----------------------------------------------------
-  
+
   // accessors -------------------------------------------------------
-  
+
   // optional int32 start = 1;
   inline bool has_start() const;
   inline void clear_start();
   static const int kStartFieldNumber = 1;
   inline ::google::protobuf::int32 start() const;
   inline void set_start(::google::protobuf::int32 value);
-  
+
   // optional int32 end = 2;
   inline bool has_end() const;
   inline void clear_end();
   static const int kEndFieldNumber = 2;
   inline ::google::protobuf::int32 end() const;
   inline void set_end(::google::protobuf::int32 value);
-  
+
   // @@protoc_insertion_point(class_scope:google.protobuf.DescriptorProto.ExtensionRange)
  private:
   inline void set_has_start();
   inline void clear_has_start();
   inline void set_has_end();
   inline void clear_has_end();
-  
+
   ::google::protobuf::UnknownFieldSet _unknown_fields_;
-  
+
   ::google::protobuf::int32 start_;
   ::google::protobuf::int32 end_;
-  
+
   mutable int _cached_size_;
   ::google::protobuf::uint32 _has_bits_[(2 + 31) / 32];
-  
+
   friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto();
-  
+
   void InitAsDefaultInstance();
   static DescriptorProto_ExtensionRange* default_instance_;
 };
@@ -524,29 +555,29 @@
  public:
   DescriptorProto();
   virtual ~DescriptorProto();
-  
+
   DescriptorProto(const DescriptorProto& from);
-  
+
   inline DescriptorProto& operator=(const DescriptorProto& from) {
     CopyFrom(from);
     return *this;
   }
-  
+
   inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
     return _unknown_fields_;
   }
-  
+
   inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
     return &_unknown_fields_;
   }
-  
+
   static const ::google::protobuf::Descriptor* descriptor();
   static const DescriptorProto& default_instance();
-  
+
   void Swap(DescriptorProto* other);
-  
+
   // implements Message ----------------------------------------------
-  
+
   DescriptorProto* New() const;
   void CopyFrom(const ::google::protobuf::Message& from);
   void MergeFrom(const ::google::protobuf::Message& from);
@@ -554,7 +585,7 @@
   void MergeFrom(const DescriptorProto& from);
   void Clear();
   bool IsInitialized() const;
-  
+
   int ByteSize() const;
   bool MergePartialFromCodedStream(
       ::google::protobuf::io::CodedInputStream* input);
@@ -567,15 +598,15 @@
   void SharedDtor();
   void SetCachedSize(int size) const;
   public:
-  
+
   ::google::protobuf::Metadata GetMetadata() const;
-  
+
   // nested types ----------------------------------------------------
-  
+
   typedef DescriptorProto_ExtensionRange ExtensionRange;
-  
+
   // accessors -------------------------------------------------------
-  
+
   // optional string name = 1;
   inline bool has_name() const;
   inline void clear_name();
@@ -586,7 +617,8 @@
   inline void set_name(const char* value, size_t size);
   inline ::std::string* mutable_name();
   inline ::std::string* release_name();
-  
+  inline void set_allocated_name(::std::string* name);
+
   // repeated .google.protobuf.FieldDescriptorProto field = 2;
   inline int field_size() const;
   inline void clear_field();
@@ -598,7 +630,7 @@
       field() const;
   inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >*
       mutable_field();
-  
+
   // repeated .google.protobuf.FieldDescriptorProto extension = 6;
   inline int extension_size() const;
   inline void clear_extension();
@@ -610,7 +642,7 @@
       extension() const;
   inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >*
       mutable_extension();
-  
+
   // repeated .google.protobuf.DescriptorProto nested_type = 3;
   inline int nested_type_size() const;
   inline void clear_nested_type();
@@ -622,7 +654,7 @@
       nested_type() const;
   inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >*
       mutable_nested_type();
-  
+
   // repeated .google.protobuf.EnumDescriptorProto enum_type = 4;
   inline int enum_type_size() const;
   inline void clear_enum_type();
@@ -634,7 +666,7 @@
       enum_type() const;
   inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >*
       mutable_enum_type();
-  
+
   // repeated .google.protobuf.DescriptorProto.ExtensionRange extension_range = 5;
   inline int extension_range_size() const;
   inline void clear_extension_range();
@@ -646,7 +678,7 @@
       extension_range() const;
   inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto_ExtensionRange >*
       mutable_extension_range();
-  
+
   // optional .google.protobuf.MessageOptions options = 7;
   inline bool has_options() const;
   inline void clear_options();
@@ -654,16 +686,17 @@
   inline const ::google::protobuf::MessageOptions& options() const;
   inline ::google::protobuf::MessageOptions* mutable_options();
   inline ::google::protobuf::MessageOptions* release_options();
-  
+  inline void set_allocated_options(::google::protobuf::MessageOptions* options);
+
   // @@protoc_insertion_point(class_scope:google.protobuf.DescriptorProto)
  private:
   inline void set_has_name();
   inline void clear_has_name();
   inline void set_has_options();
   inline void clear_has_options();
-  
+
   ::google::protobuf::UnknownFieldSet _unknown_fields_;
-  
+
   ::std::string* name_;
   ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto > field_;
   ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto > extension_;
@@ -671,14 +704,14 @@
   ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto > enum_type_;
   ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto_ExtensionRange > extension_range_;
   ::google::protobuf::MessageOptions* options_;
-  
+
   mutable int _cached_size_;
   ::google::protobuf::uint32 _has_bits_[(7 + 31) / 32];
-  
+
   friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto();
-  
+
   void InitAsDefaultInstance();
   static DescriptorProto* default_instance_;
 };
@@ -688,29 +721,29 @@
  public:
   FieldDescriptorProto();
   virtual ~FieldDescriptorProto();
-  
+
   FieldDescriptorProto(const FieldDescriptorProto& from);
-  
+
   inline FieldDescriptorProto& operator=(const FieldDescriptorProto& from) {
     CopyFrom(from);
     return *this;
   }
-  
+
   inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
     return _unknown_fields_;
   }
-  
+
   inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
     return &_unknown_fields_;
   }
-  
+
   static const ::google::protobuf::Descriptor* descriptor();
   static const FieldDescriptorProto& default_instance();
-  
+
   void Swap(FieldDescriptorProto* other);
-  
+
   // implements Message ----------------------------------------------
-  
+
   FieldDescriptorProto* New() const;
   void CopyFrom(const ::google::protobuf::Message& from);
   void MergeFrom(const ::google::protobuf::Message& from);
@@ -718,7 +751,7 @@
   void MergeFrom(const FieldDescriptorProto& from);
   void Clear();
   bool IsInitialized() const;
-  
+
   int ByteSize() const;
   bool MergePartialFromCodedStream(
       ::google::protobuf::io::CodedInputStream* input);
@@ -731,11 +764,11 @@
   void SharedDtor();
   void SetCachedSize(int size) const;
   public:
-  
+
   ::google::protobuf::Metadata GetMetadata() const;
-  
+
   // nested types ----------------------------------------------------
-  
+
   typedef FieldDescriptorProto_Type Type;
   static const Type TYPE_DOUBLE = FieldDescriptorProto_Type_TYPE_DOUBLE;
   static const Type TYPE_FLOAT = FieldDescriptorProto_Type_TYPE_FLOAT;
@@ -775,7 +808,7 @@
       Type* value) {
     return FieldDescriptorProto_Type_Parse(name, value);
   }
-  
+
   typedef FieldDescriptorProto_Label Label;
   static const Label LABEL_OPTIONAL = FieldDescriptorProto_Label_LABEL_OPTIONAL;
   static const Label LABEL_REQUIRED = FieldDescriptorProto_Label_LABEL_REQUIRED;
@@ -800,9 +833,9 @@
       Label* value) {
     return FieldDescriptorProto_Label_Parse(name, value);
   }
-  
+
   // accessors -------------------------------------------------------
-  
+
   // optional string name = 1;
   inline bool has_name() const;
   inline void clear_name();
@@ -813,28 +846,29 @@
   inline void set_name(const char* value, size_t size);
   inline ::std::string* mutable_name();
   inline ::std::string* release_name();
-  
+  inline void set_allocated_name(::std::string* name);
+
   // optional int32 number = 3;
   inline bool has_number() const;
   inline void clear_number();
   static const int kNumberFieldNumber = 3;
   inline ::google::protobuf::int32 number() const;
   inline void set_number(::google::protobuf::int32 value);
-  
+
   // optional .google.protobuf.FieldDescriptorProto.Label label = 4;
   inline bool has_label() const;
   inline void clear_label();
   static const int kLabelFieldNumber = 4;
   inline ::google::protobuf::FieldDescriptorProto_Label label() const;
   inline void set_label(::google::protobuf::FieldDescriptorProto_Label value);
-  
+
   // optional .google.protobuf.FieldDescriptorProto.Type type = 5;
   inline bool has_type() const;
   inline void clear_type();
   static const int kTypeFieldNumber = 5;
   inline ::google::protobuf::FieldDescriptorProto_Type type() const;
   inline void set_type(::google::protobuf::FieldDescriptorProto_Type value);
-  
+
   // optional string type_name = 6;
   inline bool has_type_name() const;
   inline void clear_type_name();
@@ -845,7 +879,8 @@
   inline void set_type_name(const char* value, size_t size);
   inline ::std::string* mutable_type_name();
   inline ::std::string* release_type_name();
-  
+  inline void set_allocated_type_name(::std::string* type_name);
+
   // optional string extendee = 2;
   inline bool has_extendee() const;
   inline void clear_extendee();
@@ -856,7 +891,8 @@
   inline void set_extendee(const char* value, size_t size);
   inline ::std::string* mutable_extendee();
   inline ::std::string* release_extendee();
-  
+  inline void set_allocated_extendee(::std::string* extendee);
+
   // optional string default_value = 7;
   inline bool has_default_value() const;
   inline void clear_default_value();
@@ -867,7 +903,8 @@
   inline void set_default_value(const char* value, size_t size);
   inline ::std::string* mutable_default_value();
   inline ::std::string* release_default_value();
-  
+  inline void set_allocated_default_value(::std::string* default_value);
+
   // optional .google.protobuf.FieldOptions options = 8;
   inline bool has_options() const;
   inline void clear_options();
@@ -875,7 +912,8 @@
   inline const ::google::protobuf::FieldOptions& options() const;
   inline ::google::protobuf::FieldOptions* mutable_options();
   inline ::google::protobuf::FieldOptions* release_options();
-  
+  inline void set_allocated_options(::google::protobuf::FieldOptions* options);
+
   // @@protoc_insertion_point(class_scope:google.protobuf.FieldDescriptorProto)
  private:
   inline void set_has_name();
@@ -894,9 +932,9 @@
   inline void clear_has_default_value();
   inline void set_has_options();
   inline void clear_has_options();
-  
+
   ::google::protobuf::UnknownFieldSet _unknown_fields_;
-  
+
   ::std::string* name_;
   ::google::protobuf::int32 number_;
   int label_;
@@ -905,14 +943,14 @@
   ::std::string* default_value_;
   ::google::protobuf::FieldOptions* options_;
   int type_;
-  
+
   mutable int _cached_size_;
   ::google::protobuf::uint32 _has_bits_[(8 + 31) / 32];
-  
+
   friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto();
-  
+
   void InitAsDefaultInstance();
   static FieldDescriptorProto* default_instance_;
 };
@@ -922,29 +960,29 @@
  public:
   EnumDescriptorProto();
   virtual ~EnumDescriptorProto();
-  
+
   EnumDescriptorProto(const EnumDescriptorProto& from);
-  
+
   inline EnumDescriptorProto& operator=(const EnumDescriptorProto& from) {
     CopyFrom(from);
     return *this;
   }
-  
+
   inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
     return _unknown_fields_;
   }
-  
+
   inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
     return &_unknown_fields_;
   }
-  
+
   static const ::google::protobuf::Descriptor* descriptor();
   static const EnumDescriptorProto& default_instance();
-  
+
   void Swap(EnumDescriptorProto* other);
-  
+
   // implements Message ----------------------------------------------
-  
+
   EnumDescriptorProto* New() const;
   void CopyFrom(const ::google::protobuf::Message& from);
   void MergeFrom(const ::google::protobuf::Message& from);
@@ -952,7 +990,7 @@
   void MergeFrom(const EnumDescriptorProto& from);
   void Clear();
   bool IsInitialized() const;
-  
+
   int ByteSize() const;
   bool MergePartialFromCodedStream(
       ::google::protobuf::io::CodedInputStream* input);
@@ -965,13 +1003,13 @@
   void SharedDtor();
   void SetCachedSize(int size) const;
   public:
-  
+
   ::google::protobuf::Metadata GetMetadata() const;
-  
+
   // nested types ----------------------------------------------------
-  
+
   // accessors -------------------------------------------------------
-  
+
   // optional string name = 1;
   inline bool has_name() const;
   inline void clear_name();
@@ -982,7 +1020,8 @@
   inline void set_name(const char* value, size_t size);
   inline ::std::string* mutable_name();
   inline ::std::string* release_name();
-  
+  inline void set_allocated_name(::std::string* name);
+
   // repeated .google.protobuf.EnumValueDescriptorProto value = 2;
   inline int value_size() const;
   inline void clear_value();
@@ -994,7 +1033,7 @@
       value() const;
   inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumValueDescriptorProto >*
       mutable_value();
-  
+
   // optional .google.protobuf.EnumOptions options = 3;
   inline bool has_options() const;
   inline void clear_options();
@@ -1002,27 +1041,28 @@
   inline const ::google::protobuf::EnumOptions& options() const;
   inline ::google::protobuf::EnumOptions* mutable_options();
   inline ::google::protobuf::EnumOptions* release_options();
-  
+  inline void set_allocated_options(::google::protobuf::EnumOptions* options);
+
   // @@protoc_insertion_point(class_scope:google.protobuf.EnumDescriptorProto)
  private:
   inline void set_has_name();
   inline void clear_has_name();
   inline void set_has_options();
   inline void clear_has_options();
-  
+
   ::google::protobuf::UnknownFieldSet _unknown_fields_;
-  
+
   ::std::string* name_;
   ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumValueDescriptorProto > value_;
   ::google::protobuf::EnumOptions* options_;
-  
+
   mutable int _cached_size_;
   ::google::protobuf::uint32 _has_bits_[(3 + 31) / 32];
-  
+
   friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto();
-  
+
   void InitAsDefaultInstance();
   static EnumDescriptorProto* default_instance_;
 };
@@ -1032,29 +1072,29 @@
  public:
   EnumValueDescriptorProto();
   virtual ~EnumValueDescriptorProto();
-  
+
   EnumValueDescriptorProto(const EnumValueDescriptorProto& from);
-  
+
   inline EnumValueDescriptorProto& operator=(const EnumValueDescriptorProto& from) {
     CopyFrom(from);
     return *this;
   }
-  
+
   inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
     return _unknown_fields_;
   }
-  
+
   inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
     return &_unknown_fields_;
   }
-  
+
   static const ::google::protobuf::Descriptor* descriptor();
   static const EnumValueDescriptorProto& default_instance();
-  
+
   void Swap(EnumValueDescriptorProto* other);
-  
+
   // implements Message ----------------------------------------------
-  
+
   EnumValueDescriptorProto* New() const;
   void CopyFrom(const ::google::protobuf::Message& from);
   void MergeFrom(const ::google::protobuf::Message& from);
@@ -1062,7 +1102,7 @@
   void MergeFrom(const EnumValueDescriptorProto& from);
   void Clear();
   bool IsInitialized() const;
-  
+
   int ByteSize() const;
   bool MergePartialFromCodedStream(
       ::google::protobuf::io::CodedInputStream* input);
@@ -1075,13 +1115,13 @@
   void SharedDtor();
   void SetCachedSize(int size) const;
   public:
-  
+
   ::google::protobuf::Metadata GetMetadata() const;
-  
+
   // nested types ----------------------------------------------------
-  
+
   // accessors -------------------------------------------------------
-  
+
   // optional string name = 1;
   inline bool has_name() const;
   inline void clear_name();
@@ -1092,14 +1132,15 @@
   inline void set_name(const char* value, size_t size);
   inline ::std::string* mutable_name();
   inline ::std::string* release_name();
-  
+  inline void set_allocated_name(::std::string* name);
+
   // optional int32 number = 2;
   inline bool has_number() const;
   inline void clear_number();
   static const int kNumberFieldNumber = 2;
   inline ::google::protobuf::int32 number() const;
   inline void set_number(::google::protobuf::int32 value);
-  
+
   // optional .google.protobuf.EnumValueOptions options = 3;
   inline bool has_options() const;
   inline void clear_options();
@@ -1107,7 +1148,8 @@
   inline const ::google::protobuf::EnumValueOptions& options() const;
   inline ::google::protobuf::EnumValueOptions* mutable_options();
   inline ::google::protobuf::EnumValueOptions* release_options();
-  
+  inline void set_allocated_options(::google::protobuf::EnumValueOptions* options);
+
   // @@protoc_insertion_point(class_scope:google.protobuf.EnumValueDescriptorProto)
  private:
   inline void set_has_name();
@@ -1116,20 +1158,20 @@
   inline void clear_has_number();
   inline void set_has_options();
   inline void clear_has_options();
-  
+
   ::google::protobuf::UnknownFieldSet _unknown_fields_;
-  
+
   ::std::string* name_;
   ::google::protobuf::EnumValueOptions* options_;
   ::google::protobuf::int32 number_;
-  
+
   mutable int _cached_size_;
   ::google::protobuf::uint32 _has_bits_[(3 + 31) / 32];
-  
+
   friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto();
-  
+
   void InitAsDefaultInstance();
   static EnumValueDescriptorProto* default_instance_;
 };
@@ -1139,29 +1181,29 @@
  public:
   ServiceDescriptorProto();
   virtual ~ServiceDescriptorProto();
-  
+
   ServiceDescriptorProto(const ServiceDescriptorProto& from);
-  
+
   inline ServiceDescriptorProto& operator=(const ServiceDescriptorProto& from) {
     CopyFrom(from);
     return *this;
   }
-  
+
   inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
     return _unknown_fields_;
   }
-  
+
   inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
     return &_unknown_fields_;
   }
-  
+
   static const ::google::protobuf::Descriptor* descriptor();
   static const ServiceDescriptorProto& default_instance();
-  
+
   void Swap(ServiceDescriptorProto* other);
-  
+
   // implements Message ----------------------------------------------
-  
+
   ServiceDescriptorProto* New() const;
   void CopyFrom(const ::google::protobuf::Message& from);
   void MergeFrom(const ::google::protobuf::Message& from);
@@ -1169,7 +1211,7 @@
   void MergeFrom(const ServiceDescriptorProto& from);
   void Clear();
   bool IsInitialized() const;
-  
+
   int ByteSize() const;
   bool MergePartialFromCodedStream(
       ::google::protobuf::io::CodedInputStream* input);
@@ -1182,13 +1224,13 @@
   void SharedDtor();
   void SetCachedSize(int size) const;
   public:
-  
+
   ::google::protobuf::Metadata GetMetadata() const;
-  
+
   // nested types ----------------------------------------------------
-  
+
   // accessors -------------------------------------------------------
-  
+
   // optional string name = 1;
   inline bool has_name() const;
   inline void clear_name();
@@ -1199,7 +1241,8 @@
   inline void set_name(const char* value, size_t size);
   inline ::std::string* mutable_name();
   inline ::std::string* release_name();
-  
+  inline void set_allocated_name(::std::string* name);
+
   // repeated .google.protobuf.MethodDescriptorProto method = 2;
   inline int method_size() const;
   inline void clear_method();
@@ -1211,7 +1254,7 @@
       method() const;
   inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::MethodDescriptorProto >*
       mutable_method();
-  
+
   // optional .google.protobuf.ServiceOptions options = 3;
   inline bool has_options() const;
   inline void clear_options();
@@ -1219,27 +1262,28 @@
   inline const ::google::protobuf::ServiceOptions& options() const;
   inline ::google::protobuf::ServiceOptions* mutable_options();
   inline ::google::protobuf::ServiceOptions* release_options();
-  
+  inline void set_allocated_options(::google::protobuf::ServiceOptions* options);
+
   // @@protoc_insertion_point(class_scope:google.protobuf.ServiceDescriptorProto)
  private:
   inline void set_has_name();
   inline void clear_has_name();
   inline void set_has_options();
   inline void clear_has_options();
-  
+
   ::google::protobuf::UnknownFieldSet _unknown_fields_;
-  
+
   ::std::string* name_;
   ::google::protobuf::RepeatedPtrField< ::google::protobuf::MethodDescriptorProto > method_;
   ::google::protobuf::ServiceOptions* options_;
-  
+
   mutable int _cached_size_;
   ::google::protobuf::uint32 _has_bits_[(3 + 31) / 32];
-  
+
   friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto();
-  
+
   void InitAsDefaultInstance();
   static ServiceDescriptorProto* default_instance_;
 };
@@ -1249,29 +1293,29 @@
  public:
   MethodDescriptorProto();
   virtual ~MethodDescriptorProto();
-  
+
   MethodDescriptorProto(const MethodDescriptorProto& from);
-  
+
   inline MethodDescriptorProto& operator=(const MethodDescriptorProto& from) {
     CopyFrom(from);
     return *this;
   }
-  
+
   inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
     return _unknown_fields_;
   }
-  
+
   inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
     return &_unknown_fields_;
   }
-  
+
   static const ::google::protobuf::Descriptor* descriptor();
   static const MethodDescriptorProto& default_instance();
-  
+
   void Swap(MethodDescriptorProto* other);
-  
+
   // implements Message ----------------------------------------------
-  
+
   MethodDescriptorProto* New() const;
   void CopyFrom(const ::google::protobuf::Message& from);
   void MergeFrom(const ::google::protobuf::Message& from);
@@ -1279,7 +1323,7 @@
   void MergeFrom(const MethodDescriptorProto& from);
   void Clear();
   bool IsInitialized() const;
-  
+
   int ByteSize() const;
   bool MergePartialFromCodedStream(
       ::google::protobuf::io::CodedInputStream* input);
@@ -1292,13 +1336,13 @@
   void SharedDtor();
   void SetCachedSize(int size) const;
   public:
-  
+
   ::google::protobuf::Metadata GetMetadata() const;
-  
+
   // nested types ----------------------------------------------------
-  
+
   // accessors -------------------------------------------------------
-  
+
   // optional string name = 1;
   inline bool has_name() const;
   inline void clear_name();
@@ -1309,7 +1353,8 @@
   inline void set_name(const char* value, size_t size);
   inline ::std::string* mutable_name();
   inline ::std::string* release_name();
-  
+  inline void set_allocated_name(::std::string* name);
+
   // optional string input_type = 2;
   inline bool has_input_type() const;
   inline void clear_input_type();
@@ -1320,7 +1365,8 @@
   inline void set_input_type(const char* value, size_t size);
   inline ::std::string* mutable_input_type();
   inline ::std::string* release_input_type();
-  
+  inline void set_allocated_input_type(::std::string* input_type);
+
   // optional string output_type = 3;
   inline bool has_output_type() const;
   inline void clear_output_type();
@@ -1331,7 +1377,8 @@
   inline void set_output_type(const char* value, size_t size);
   inline ::std::string* mutable_output_type();
   inline ::std::string* release_output_type();
-  
+  inline void set_allocated_output_type(::std::string* output_type);
+
   // optional .google.protobuf.MethodOptions options = 4;
   inline bool has_options() const;
   inline void clear_options();
@@ -1339,7 +1386,8 @@
   inline const ::google::protobuf::MethodOptions& options() const;
   inline ::google::protobuf::MethodOptions* mutable_options();
   inline ::google::protobuf::MethodOptions* release_options();
-  
+  inline void set_allocated_options(::google::protobuf::MethodOptions* options);
+
   // @@protoc_insertion_point(class_scope:google.protobuf.MethodDescriptorProto)
  private:
   inline void set_has_name();
@@ -1350,21 +1398,21 @@
   inline void clear_has_output_type();
   inline void set_has_options();
   inline void clear_has_options();
-  
+
   ::google::protobuf::UnknownFieldSet _unknown_fields_;
-  
+
   ::std::string* name_;
   ::std::string* input_type_;
   ::std::string* output_type_;
   ::google::protobuf::MethodOptions* options_;
-  
+
   mutable int _cached_size_;
   ::google::protobuf::uint32 _has_bits_[(4 + 31) / 32];
-  
+
   friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto();
-  
+
   void InitAsDefaultInstance();
   static MethodDescriptorProto* default_instance_;
 };
@@ -1374,29 +1422,29 @@
  public:
   FileOptions();
   virtual ~FileOptions();
-  
+
   FileOptions(const FileOptions& from);
-  
+
   inline FileOptions& operator=(const FileOptions& from) {
     CopyFrom(from);
     return *this;
   }
-  
+
   inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
     return _unknown_fields_;
   }
-  
+
   inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
     return &_unknown_fields_;
   }
-  
+
   static const ::google::protobuf::Descriptor* descriptor();
   static const FileOptions& default_instance();
-  
+
   void Swap(FileOptions* other);
-  
+
   // implements Message ----------------------------------------------
-  
+
   FileOptions* New() const;
   void CopyFrom(const ::google::protobuf::Message& from);
   void MergeFrom(const ::google::protobuf::Message& from);
@@ -1404,7 +1452,7 @@
   void MergeFrom(const FileOptions& from);
   void Clear();
   bool IsInitialized() const;
-  
+
   int ByteSize() const;
   bool MergePartialFromCodedStream(
       ::google::protobuf::io::CodedInputStream* input);
@@ -1417,11 +1465,11 @@
   void SharedDtor();
   void SetCachedSize(int size) const;
   public:
-  
+
   ::google::protobuf::Metadata GetMetadata() const;
-  
+
   // nested types ----------------------------------------------------
-  
+
   typedef FileOptions_OptimizeMode OptimizeMode;
   static const OptimizeMode SPEED = FileOptions_OptimizeMode_SPEED;
   static const OptimizeMode CODE_SIZE = FileOptions_OptimizeMode_CODE_SIZE;
@@ -1446,9 +1494,9 @@
       OptimizeMode* value) {
     return FileOptions_OptimizeMode_Parse(name, value);
   }
-  
+
   // accessors -------------------------------------------------------
-  
+
   // optional string java_package = 1;
   inline bool has_java_package() const;
   inline void clear_java_package();
@@ -1459,7 +1507,8 @@
   inline void set_java_package(const char* value, size_t size);
   inline ::std::string* mutable_java_package();
   inline ::std::string* release_java_package();
-  
+  inline void set_allocated_java_package(::std::string* java_package);
+
   // optional string java_outer_classname = 8;
   inline bool has_java_outer_classname() const;
   inline void clear_java_outer_classname();
@@ -1470,56 +1519,69 @@
   inline void set_java_outer_classname(const char* value, size_t size);
   inline ::std::string* mutable_java_outer_classname();
   inline ::std::string* release_java_outer_classname();
-  
+  inline void set_allocated_java_outer_classname(::std::string* java_outer_classname);
+
   // optional bool java_multiple_files = 10 [default = false];
   inline bool has_java_multiple_files() const;
   inline void clear_java_multiple_files();
   static const int kJavaMultipleFilesFieldNumber = 10;
   inline bool java_multiple_files() const;
   inline void set_java_multiple_files(bool value);
-  
-  // optional bool retain_unknown_fields = 11 [default = false];
+
+  // optional bool retain_unknown_fields = 12 [default = false];
   inline bool has_retain_unknown_fields() const;
   inline void clear_retain_unknown_fields();
-  static const int kRetainUnknownFieldsFieldNumber = 11;
+  static const int kRetainUnknownFieldsFieldNumber = 12;
   inline bool retain_unknown_fields() const;
   inline void set_retain_unknown_fields(bool value);
-  
+
   // optional bool java_generate_equals_and_hash = 20 [default = false];
   inline bool has_java_generate_equals_and_hash() const;
   inline void clear_java_generate_equals_and_hash();
   static const int kJavaGenerateEqualsAndHashFieldNumber = 20;
   inline bool java_generate_equals_and_hash() const;
   inline void set_java_generate_equals_and_hash(bool value);
-  
+
   // optional .google.protobuf.FileOptions.OptimizeMode optimize_for = 9 [default = SPEED];
   inline bool has_optimize_for() const;
   inline void clear_optimize_for();
   static const int kOptimizeForFieldNumber = 9;
   inline ::google::protobuf::FileOptions_OptimizeMode optimize_for() const;
   inline void set_optimize_for(::google::protobuf::FileOptions_OptimizeMode value);
-  
+
+  // optional string go_package = 11;
+  inline bool has_go_package() const;
+  inline void clear_go_package();
+  static const int kGoPackageFieldNumber = 11;
+  inline const ::std::string& go_package() const;
+  inline void set_go_package(const ::std::string& value);
+  inline void set_go_package(const char* value);
+  inline void set_go_package(const char* value, size_t size);
+  inline ::std::string* mutable_go_package();
+  inline ::std::string* release_go_package();
+  inline void set_allocated_go_package(::std::string* go_package);
+
   // optional bool cc_generic_services = 16 [default = false];
   inline bool has_cc_generic_services() const;
   inline void clear_cc_generic_services();
   static const int kCcGenericServicesFieldNumber = 16;
   inline bool cc_generic_services() const;
   inline void set_cc_generic_services(bool value);
-  
+
   // optional bool java_generic_services = 17 [default = false];
   inline bool has_java_generic_services() const;
   inline void clear_java_generic_services();
   static const int kJavaGenericServicesFieldNumber = 17;
   inline bool java_generic_services() const;
   inline void set_java_generic_services(bool value);
-  
+
   // optional bool py_generic_services = 18 [default = false];
   inline bool has_py_generic_services() const;
   inline void clear_py_generic_services();
   static const int kPyGenericServicesFieldNumber = 18;
   inline bool py_generic_services() const;
   inline void set_py_generic_services(bool value);
-  
+
   // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
   inline int uninterpreted_option_size() const;
   inline void clear_uninterpreted_option();
@@ -1531,7 +1593,7 @@
       uninterpreted_option() const;
   inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
       mutable_uninterpreted_option();
-  
+
   GOOGLE_PROTOBUF_EXTENSION_ACCESSORS(FileOptions)
   // @@protoc_insertion_point(class_scope:google.protobuf.FileOptions)
  private:
@@ -1547,17 +1609,19 @@
   inline void clear_has_java_generate_equals_and_hash();
   inline void set_has_optimize_for();
   inline void clear_has_optimize_for();
+  inline void set_has_go_package();
+  inline void clear_has_go_package();
   inline void set_has_cc_generic_services();
   inline void clear_has_cc_generic_services();
   inline void set_has_java_generic_services();
   inline void clear_has_java_generic_services();
   inline void set_has_py_generic_services();
   inline void clear_has_py_generic_services();
-  
+
   ::google::protobuf::internal::ExtensionSet _extensions_;
-  
+
   ::google::protobuf::UnknownFieldSet _unknown_fields_;
-  
+
   ::std::string* java_package_;
   ::std::string* java_outer_classname_;
   bool java_multiple_files_;
@@ -1565,17 +1629,18 @@
   bool java_generate_equals_and_hash_;
   bool cc_generic_services_;
   int optimize_for_;
+  ::std::string* go_package_;
   ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption > uninterpreted_option_;
   bool java_generic_services_;
   bool py_generic_services_;
-  
+
   mutable int _cached_size_;
-  ::google::protobuf::uint32 _has_bits_[(10 + 31) / 32];
-  
+  ::google::protobuf::uint32 _has_bits_[(11 + 31) / 32];
+
   friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto();
-  
+
   void InitAsDefaultInstance();
   static FileOptions* default_instance_;
 };
@@ -1585,29 +1650,29 @@
  public:
   MessageOptions();
   virtual ~MessageOptions();
-  
+
   MessageOptions(const MessageOptions& from);
-  
+
   inline MessageOptions& operator=(const MessageOptions& from) {
     CopyFrom(from);
     return *this;
   }
-  
+
   inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
     return _unknown_fields_;
   }
-  
+
   inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
     return &_unknown_fields_;
   }
-  
+
   static const ::google::protobuf::Descriptor* descriptor();
   static const MessageOptions& default_instance();
-  
+
   void Swap(MessageOptions* other);
-  
+
   // implements Message ----------------------------------------------
-  
+
   MessageOptions* New() const;
   void CopyFrom(const ::google::protobuf::Message& from);
   void MergeFrom(const ::google::protobuf::Message& from);
@@ -1615,7 +1680,7 @@
   void MergeFrom(const MessageOptions& from);
   void Clear();
   bool IsInitialized() const;
-  
+
   int ByteSize() const;
   bool MergePartialFromCodedStream(
       ::google::protobuf::io::CodedInputStream* input);
@@ -1628,27 +1693,27 @@
   void SharedDtor();
   void SetCachedSize(int size) const;
   public:
-  
+
   ::google::protobuf::Metadata GetMetadata() const;
-  
+
   // nested types ----------------------------------------------------
-  
+
   // accessors -------------------------------------------------------
-  
+
   // optional bool message_set_wire_format = 1 [default = false];
   inline bool has_message_set_wire_format() const;
   inline void clear_message_set_wire_format();
   static const int kMessageSetWireFormatFieldNumber = 1;
   inline bool message_set_wire_format() const;
   inline void set_message_set_wire_format(bool value);
-  
+
   // optional bool no_standard_descriptor_accessor = 2 [default = false];
   inline bool has_no_standard_descriptor_accessor() const;
   inline void clear_no_standard_descriptor_accessor();
   static const int kNoStandardDescriptorAccessorFieldNumber = 2;
   inline bool no_standard_descriptor_accessor() const;
   inline void set_no_standard_descriptor_accessor(bool value);
-  
+
   // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
   inline int uninterpreted_option_size() const;
   inline void clear_uninterpreted_option();
@@ -1660,7 +1725,7 @@
       uninterpreted_option() const;
   inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
       mutable_uninterpreted_option();
-  
+
   GOOGLE_PROTOBUF_EXTENSION_ACCESSORS(MessageOptions)
   // @@protoc_insertion_point(class_scope:google.protobuf.MessageOptions)
  private:
@@ -1668,22 +1733,22 @@
   inline void clear_has_message_set_wire_format();
   inline void set_has_no_standard_descriptor_accessor();
   inline void clear_has_no_standard_descriptor_accessor();
-  
+
   ::google::protobuf::internal::ExtensionSet _extensions_;
-  
+
   ::google::protobuf::UnknownFieldSet _unknown_fields_;
-  
+
   ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption > uninterpreted_option_;
   bool message_set_wire_format_;
   bool no_standard_descriptor_accessor_;
-  
+
   mutable int _cached_size_;
   ::google::protobuf::uint32 _has_bits_[(3 + 31) / 32];
-  
+
   friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto();
-  
+
   void InitAsDefaultInstance();
   static MessageOptions* default_instance_;
 };
@@ -1693,29 +1758,29 @@
  public:
   FieldOptions();
   virtual ~FieldOptions();
-  
+
   FieldOptions(const FieldOptions& from);
-  
+
   inline FieldOptions& operator=(const FieldOptions& from) {
     CopyFrom(from);
     return *this;
   }
-  
+
   inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
     return _unknown_fields_;
   }
-  
+
   inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
     return &_unknown_fields_;
   }
-  
+
   static const ::google::protobuf::Descriptor* descriptor();
   static const FieldOptions& default_instance();
-  
+
   void Swap(FieldOptions* other);
-  
+
   // implements Message ----------------------------------------------
-  
+
   FieldOptions* New() const;
   void CopyFrom(const ::google::protobuf::Message& from);
   void MergeFrom(const ::google::protobuf::Message& from);
@@ -1723,7 +1788,7 @@
   void MergeFrom(const FieldOptions& from);
   void Clear();
   bool IsInitialized() const;
-  
+
   int ByteSize() const;
   bool MergePartialFromCodedStream(
       ::google::protobuf::io::CodedInputStream* input);
@@ -1736,11 +1801,11 @@
   void SharedDtor();
   void SetCachedSize(int size) const;
   public:
-  
+
   ::google::protobuf::Metadata GetMetadata() const;
-  
+
   // nested types ----------------------------------------------------
-  
+
   typedef FieldOptions_CType CType;
   static const CType STRING = FieldOptions_CType_STRING;
   static const CType CORD = FieldOptions_CType_CORD;
@@ -1765,30 +1830,37 @@
       CType* value) {
     return FieldOptions_CType_Parse(name, value);
   }
-  
+
   // accessors -------------------------------------------------------
-  
+
   // optional .google.protobuf.FieldOptions.CType ctype = 1 [default = STRING];
   inline bool has_ctype() const;
   inline void clear_ctype();
   static const int kCtypeFieldNumber = 1;
   inline ::google::protobuf::FieldOptions_CType ctype() const;
   inline void set_ctype(::google::protobuf::FieldOptions_CType value);
-  
+
   // optional bool packed = 2;
   inline bool has_packed() const;
   inline void clear_packed();
   static const int kPackedFieldNumber = 2;
   inline bool packed() const;
   inline void set_packed(bool value);
-  
+
+  // optional bool lazy = 5 [default = false];
+  inline bool has_lazy() const;
+  inline void clear_lazy();
+  static const int kLazyFieldNumber = 5;
+  inline bool lazy() const;
+  inline void set_lazy(bool value);
+
   // optional bool deprecated = 3 [default = false];
   inline bool has_deprecated() const;
   inline void clear_deprecated();
   static const int kDeprecatedFieldNumber = 3;
   inline bool deprecated() const;
   inline void set_deprecated(bool value);
-  
+
   // optional string experimental_map_key = 9;
   inline bool has_experimental_map_key() const;
   inline void clear_experimental_map_key();
@@ -1799,7 +1871,15 @@
   inline void set_experimental_map_key(const char* value, size_t size);
   inline ::std::string* mutable_experimental_map_key();
   inline ::std::string* release_experimental_map_key();
-  
+  inline void set_allocated_experimental_map_key(::std::string* experimental_map_key);
+
+  // optional bool weak = 10 [default = false];
+  inline bool has_weak() const;
+  inline void clear_weak();
+  static const int kWeakFieldNumber = 10;
+  inline bool weak() const;
+  inline void set_weak(bool value);
+
   // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
   inline int uninterpreted_option_size() const;
   inline void clear_uninterpreted_option();
@@ -1811,7 +1891,7 @@
       uninterpreted_option() const;
   inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
       mutable_uninterpreted_option();
-  
+
   GOOGLE_PROTOBUF_EXTENSION_ACCESSORS(FieldOptions)
   // @@protoc_insertion_point(class_scope:google.protobuf.FieldOptions)
  private:
@@ -1819,28 +1899,34 @@
   inline void clear_has_ctype();
   inline void set_has_packed();
   inline void clear_has_packed();
+  inline void set_has_lazy();
+  inline void clear_has_lazy();
   inline void set_has_deprecated();
   inline void clear_has_deprecated();
   inline void set_has_experimental_map_key();
   inline void clear_has_experimental_map_key();
-  
+  inline void set_has_weak();
+  inline void clear_has_weak();
+
   ::google::protobuf::internal::ExtensionSet _extensions_;
-  
+
   ::google::protobuf::UnknownFieldSet _unknown_fields_;
-  
+
   int ctype_;
   bool packed_;
+  bool lazy_;
   bool deprecated_;
+  bool weak_;
   ::std::string* experimental_map_key_;
   ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption > uninterpreted_option_;
-  
+
   mutable int _cached_size_;
-  ::google::protobuf::uint32 _has_bits_[(5 + 31) / 32];
-  
+  ::google::protobuf::uint32 _has_bits_[(7 + 31) / 32];
+
   friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto();
-  
+
   void InitAsDefaultInstance();
   static FieldOptions* default_instance_;
 };
@@ -1850,29 +1936,29 @@
  public:
   EnumOptions();
   virtual ~EnumOptions();
-  
+
   EnumOptions(const EnumOptions& from);
-  
+
   inline EnumOptions& operator=(const EnumOptions& from) {
     CopyFrom(from);
     return *this;
   }
-  
+
   inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
     return _unknown_fields_;
   }
-  
+
   inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
     return &_unknown_fields_;
   }
-  
+
   static const ::google::protobuf::Descriptor* descriptor();
   static const EnumOptions& default_instance();
-  
+
   void Swap(EnumOptions* other);
-  
+
   // implements Message ----------------------------------------------
-  
+
   EnumOptions* New() const;
   void CopyFrom(const ::google::protobuf::Message& from);
   void MergeFrom(const ::google::protobuf::Message& from);
@@ -1880,7 +1966,7 @@
   void MergeFrom(const EnumOptions& from);
   void Clear();
   bool IsInitialized() const;
-  
+
   int ByteSize() const;
   bool MergePartialFromCodedStream(
       ::google::protobuf::io::CodedInputStream* input);
@@ -1893,13 +1979,20 @@
   void SharedDtor();
   void SetCachedSize(int size) const;
   public:
-  
+
   ::google::protobuf::Metadata GetMetadata() const;
-  
+
   // nested types ----------------------------------------------------
-  
+
   // accessors -------------------------------------------------------
-  
+
+  // optional bool allow_alias = 2 [default = true];
+  inline bool has_allow_alias() const;
+  inline void clear_allow_alias();
+  static const int kAllowAliasFieldNumber = 2;
+  inline bool allow_alias() const;
+  inline void set_allow_alias(bool value);
+
   // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
   inline int uninterpreted_option_size() const;
   inline void clear_uninterpreted_option();
@@ -1911,24 +2004,27 @@
       uninterpreted_option() const;
   inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
       mutable_uninterpreted_option();
-  
+
   GOOGLE_PROTOBUF_EXTENSION_ACCESSORS(EnumOptions)
   // @@protoc_insertion_point(class_scope:google.protobuf.EnumOptions)
  private:
-  
+  inline void set_has_allow_alias();
+  inline void clear_has_allow_alias();
+
   ::google::protobuf::internal::ExtensionSet _extensions_;
-  
+
   ::google::protobuf::UnknownFieldSet _unknown_fields_;
-  
+
   ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption > uninterpreted_option_;
-  
+  bool allow_alias_;
+
   mutable int _cached_size_;
-  ::google::protobuf::uint32 _has_bits_[(1 + 31) / 32];
-  
+  ::google::protobuf::uint32 _has_bits_[(2 + 31) / 32];
+
   friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto();
-  
+
   void InitAsDefaultInstance();
   static EnumOptions* default_instance_;
 };
@@ -1938,29 +2034,29 @@
  public:
   EnumValueOptions();
   virtual ~EnumValueOptions();
-  
+
   EnumValueOptions(const EnumValueOptions& from);
-  
+
   inline EnumValueOptions& operator=(const EnumValueOptions& from) {
     CopyFrom(from);
     return *this;
   }
-  
+
   inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
     return _unknown_fields_;
   }
-  
+
   inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
     return &_unknown_fields_;
   }
-  
+
   static const ::google::protobuf::Descriptor* descriptor();
   static const EnumValueOptions& default_instance();
-  
+
   void Swap(EnumValueOptions* other);
-  
+
   // implements Message ----------------------------------------------
-  
+
   EnumValueOptions* New() const;
   void CopyFrom(const ::google::protobuf::Message& from);
   void MergeFrom(const ::google::protobuf::Message& from);
@@ -1968,7 +2064,7 @@
   void MergeFrom(const EnumValueOptions& from);
   void Clear();
   bool IsInitialized() const;
-  
+
   int ByteSize() const;
   bool MergePartialFromCodedStream(
       ::google::protobuf::io::CodedInputStream* input);
@@ -1981,13 +2077,13 @@
   void SharedDtor();
   void SetCachedSize(int size) const;
   public:
-  
+
   ::google::protobuf::Metadata GetMetadata() const;
-  
+
   // nested types ----------------------------------------------------
-  
+
   // accessors -------------------------------------------------------
-  
+
   // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
   inline int uninterpreted_option_size() const;
   inline void clear_uninterpreted_option();
@@ -1999,24 +2095,24 @@
       uninterpreted_option() const;
   inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
       mutable_uninterpreted_option();
-  
+
   GOOGLE_PROTOBUF_EXTENSION_ACCESSORS(EnumValueOptions)
   // @@protoc_insertion_point(class_scope:google.protobuf.EnumValueOptions)
  private:
-  
+
   ::google::protobuf::internal::ExtensionSet _extensions_;
-  
+
   ::google::protobuf::UnknownFieldSet _unknown_fields_;
-  
+
   ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption > uninterpreted_option_;
-  
+
   mutable int _cached_size_;
   ::google::protobuf::uint32 _has_bits_[(1 + 31) / 32];
-  
+
   friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto();
-  
+
   void InitAsDefaultInstance();
   static EnumValueOptions* default_instance_;
 };
@@ -2026,29 +2122,29 @@
  public:
   ServiceOptions();
   virtual ~ServiceOptions();
-  
+
   ServiceOptions(const ServiceOptions& from);
-  
+
   inline ServiceOptions& operator=(const ServiceOptions& from) {
     CopyFrom(from);
     return *this;
   }
-  
+
   inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
     return _unknown_fields_;
   }
-  
+
   inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
     return &_unknown_fields_;
   }
-  
+
   static const ::google::protobuf::Descriptor* descriptor();
   static const ServiceOptions& default_instance();
-  
+
   void Swap(ServiceOptions* other);
-  
+
   // implements Message ----------------------------------------------
-  
+
   ServiceOptions* New() const;
   void CopyFrom(const ::google::protobuf::Message& from);
   void MergeFrom(const ::google::protobuf::Message& from);
@@ -2056,7 +2152,7 @@
   void MergeFrom(const ServiceOptions& from);
   void Clear();
   bool IsInitialized() const;
-  
+
   int ByteSize() const;
   bool MergePartialFromCodedStream(
       ::google::protobuf::io::CodedInputStream* input);
@@ -2069,13 +2165,13 @@
   void SharedDtor();
   void SetCachedSize(int size) const;
   public:
-  
+
   ::google::protobuf::Metadata GetMetadata() const;
-  
+
   // nested types ----------------------------------------------------
-  
+
   // accessors -------------------------------------------------------
-  
+
   // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
   inline int uninterpreted_option_size() const;
   inline void clear_uninterpreted_option();
@@ -2087,24 +2183,24 @@
       uninterpreted_option() const;
   inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
       mutable_uninterpreted_option();
-  
+
   GOOGLE_PROTOBUF_EXTENSION_ACCESSORS(ServiceOptions)
   // @@protoc_insertion_point(class_scope:google.protobuf.ServiceOptions)
  private:
-  
+
   ::google::protobuf::internal::ExtensionSet _extensions_;
-  
+
   ::google::protobuf::UnknownFieldSet _unknown_fields_;
-  
+
   ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption > uninterpreted_option_;
-  
+
   mutable int _cached_size_;
   ::google::protobuf::uint32 _has_bits_[(1 + 31) / 32];
-  
+
   friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto();
-  
+
   void InitAsDefaultInstance();
   static ServiceOptions* default_instance_;
 };
@@ -2114,29 +2210,29 @@
  public:
   MethodOptions();
   virtual ~MethodOptions();
-  
+
   MethodOptions(const MethodOptions& from);
-  
+
   inline MethodOptions& operator=(const MethodOptions& from) {
     CopyFrom(from);
     return *this;
   }
-  
+
   inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
     return _unknown_fields_;
   }
-  
+
   inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
     return &_unknown_fields_;
   }
-  
+
   static const ::google::protobuf::Descriptor* descriptor();
   static const MethodOptions& default_instance();
-  
+
   void Swap(MethodOptions* other);
-  
+
   // implements Message ----------------------------------------------
-  
+
   MethodOptions* New() const;
   void CopyFrom(const ::google::protobuf::Message& from);
   void MergeFrom(const ::google::protobuf::Message& from);
@@ -2144,7 +2240,7 @@
   void MergeFrom(const MethodOptions& from);
   void Clear();
   bool IsInitialized() const;
-  
+
   int ByteSize() const;
   bool MergePartialFromCodedStream(
       ::google::protobuf::io::CodedInputStream* input);
@@ -2157,13 +2253,13 @@
   void SharedDtor();
   void SetCachedSize(int size) const;
   public:
-  
+
   ::google::protobuf::Metadata GetMetadata() const;
-  
+
   // nested types ----------------------------------------------------
-  
+
   // accessors -------------------------------------------------------
-  
+
   // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
   inline int uninterpreted_option_size() const;
   inline void clear_uninterpreted_option();
@@ -2175,24 +2271,24 @@
       uninterpreted_option() const;
   inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
       mutable_uninterpreted_option();
-  
+
   GOOGLE_PROTOBUF_EXTENSION_ACCESSORS(MethodOptions)
   // @@protoc_insertion_point(class_scope:google.protobuf.MethodOptions)
  private:
-  
+
   ::google::protobuf::internal::ExtensionSet _extensions_;
-  
+
   ::google::protobuf::UnknownFieldSet _unknown_fields_;
-  
+
   ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption > uninterpreted_option_;
-  
+
   mutable int _cached_size_;
   ::google::protobuf::uint32 _has_bits_[(1 + 31) / 32];
-  
+
   friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto();
-  
+
   void InitAsDefaultInstance();
   static MethodOptions* default_instance_;
 };
@@ -2202,29 +2298,29 @@
  public:
   UninterpretedOption_NamePart();
   virtual ~UninterpretedOption_NamePart();
-  
+
   UninterpretedOption_NamePart(const UninterpretedOption_NamePart& from);
-  
+
   inline UninterpretedOption_NamePart& operator=(const UninterpretedOption_NamePart& from) {
     CopyFrom(from);
     return *this;
   }
-  
+
   inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
     return _unknown_fields_;
   }
-  
+
   inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
     return &_unknown_fields_;
   }
-  
+
   static const ::google::protobuf::Descriptor* descriptor();
   static const UninterpretedOption_NamePart& default_instance();
-  
+
   void Swap(UninterpretedOption_NamePart* other);
-  
+
   // implements Message ----------------------------------------------
-  
+
   UninterpretedOption_NamePart* New() const;
   void CopyFrom(const ::google::protobuf::Message& from);
   void MergeFrom(const ::google::protobuf::Message& from);
@@ -2232,7 +2328,7 @@
   void MergeFrom(const UninterpretedOption_NamePart& from);
   void Clear();
   bool IsInitialized() const;
-  
+
   int ByteSize() const;
   bool MergePartialFromCodedStream(
       ::google::protobuf::io::CodedInputStream* input);
@@ -2245,13 +2341,13 @@
   void SharedDtor();
   void SetCachedSize(int size) const;
   public:
-  
+
   ::google::protobuf::Metadata GetMetadata() const;
-  
+
   // nested types ----------------------------------------------------
-  
+
   // accessors -------------------------------------------------------
-  
+
   // required string name_part = 1;
   inline bool has_name_part() const;
   inline void clear_name_part();
@@ -2262,33 +2358,34 @@
   inline void set_name_part(const char* value, size_t size);
   inline ::std::string* mutable_name_part();
   inline ::std::string* release_name_part();
-  
+  inline void set_allocated_name_part(::std::string* name_part);
+
   // required bool is_extension = 2;
   inline bool has_is_extension() const;
   inline void clear_is_extension();
   static const int kIsExtensionFieldNumber = 2;
   inline bool is_extension() const;
   inline void set_is_extension(bool value);
-  
+
   // @@protoc_insertion_point(class_scope:google.protobuf.UninterpretedOption.NamePart)
  private:
   inline void set_has_name_part();
   inline void clear_has_name_part();
   inline void set_has_is_extension();
   inline void clear_has_is_extension();
-  
+
   ::google::protobuf::UnknownFieldSet _unknown_fields_;
-  
+
   ::std::string* name_part_;
   bool is_extension_;
-  
+
   mutable int _cached_size_;
   ::google::protobuf::uint32 _has_bits_[(2 + 31) / 32];
-  
+
   friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto();
-  
+
   void InitAsDefaultInstance();
   static UninterpretedOption_NamePart* default_instance_;
 };
@@ -2298,29 +2395,29 @@
  public:
   UninterpretedOption();
   virtual ~UninterpretedOption();
-  
+
   UninterpretedOption(const UninterpretedOption& from);
-  
+
   inline UninterpretedOption& operator=(const UninterpretedOption& from) {
     CopyFrom(from);
     return *this;
   }
-  
+
   inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
     return _unknown_fields_;
   }
-  
+
   inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
     return &_unknown_fields_;
   }
-  
+
   static const ::google::protobuf::Descriptor* descriptor();
   static const UninterpretedOption& default_instance();
-  
+
   void Swap(UninterpretedOption* other);
-  
+
   // implements Message ----------------------------------------------
-  
+
   UninterpretedOption* New() const;
   void CopyFrom(const ::google::protobuf::Message& from);
   void MergeFrom(const ::google::protobuf::Message& from);
@@ -2328,7 +2425,7 @@
   void MergeFrom(const UninterpretedOption& from);
   void Clear();
   bool IsInitialized() const;
-  
+
   int ByteSize() const;
   bool MergePartialFromCodedStream(
       ::google::protobuf::io::CodedInputStream* input);
@@ -2341,15 +2438,15 @@
   void SharedDtor();
   void SetCachedSize(int size) const;
   public:
-  
+
   ::google::protobuf::Metadata GetMetadata() const;
-  
+
   // nested types ----------------------------------------------------
-  
+
   typedef UninterpretedOption_NamePart NamePart;
-  
+
   // accessors -------------------------------------------------------
-  
+
   // repeated .google.protobuf.UninterpretedOption.NamePart name = 2;
   inline int name_size() const;
   inline void clear_name();
@@ -2361,7 +2458,7 @@
       name() const;
   inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption_NamePart >*
       mutable_name();
-  
+
   // optional string identifier_value = 3;
   inline bool has_identifier_value() const;
   inline void clear_identifier_value();
@@ -2372,28 +2469,29 @@
   inline void set_identifier_value(const char* value, size_t size);
   inline ::std::string* mutable_identifier_value();
   inline ::std::string* release_identifier_value();
-  
+  inline void set_allocated_identifier_value(::std::string* identifier_value);
+
   // optional uint64 positive_int_value = 4;
   inline bool has_positive_int_value() const;
   inline void clear_positive_int_value();
   static const int kPositiveIntValueFieldNumber = 4;
   inline ::google::protobuf::uint64 positive_int_value() const;
   inline void set_positive_int_value(::google::protobuf::uint64 value);
-  
+
   // optional int64 negative_int_value = 5;
   inline bool has_negative_int_value() const;
   inline void clear_negative_int_value();
   static const int kNegativeIntValueFieldNumber = 5;
   inline ::google::protobuf::int64 negative_int_value() const;
   inline void set_negative_int_value(::google::protobuf::int64 value);
-  
+
   // optional double double_value = 6;
   inline bool has_double_value() const;
   inline void clear_double_value();
   static const int kDoubleValueFieldNumber = 6;
   inline double double_value() const;
   inline void set_double_value(double value);
-  
+
   // optional bytes string_value = 7;
   inline bool has_string_value() const;
   inline void clear_string_value();
@@ -2404,7 +2502,8 @@
   inline void set_string_value(const void* value, size_t size);
   inline ::std::string* mutable_string_value();
   inline ::std::string* release_string_value();
-  
+  inline void set_allocated_string_value(::std::string* string_value);
+
   // optional string aggregate_value = 8;
   inline bool has_aggregate_value() const;
   inline void clear_aggregate_value();
@@ -2415,7 +2514,8 @@
   inline void set_aggregate_value(const char* value, size_t size);
   inline ::std::string* mutable_aggregate_value();
   inline ::std::string* release_aggregate_value();
-  
+  inline void set_allocated_aggregate_value(::std::string* aggregate_value);
+
   // @@protoc_insertion_point(class_scope:google.protobuf.UninterpretedOption)
  private:
   inline void set_has_identifier_value();
@@ -2430,9 +2530,9 @@
   inline void clear_has_string_value();
   inline void set_has_aggregate_value();
   inline void clear_has_aggregate_value();
-  
+
   ::google::protobuf::UnknownFieldSet _unknown_fields_;
-  
+
   ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption_NamePart > name_;
   ::std::string* identifier_value_;
   ::google::protobuf::uint64 positive_int_value_;
@@ -2440,14 +2540,14 @@
   double double_value_;
   ::std::string* string_value_;
   ::std::string* aggregate_value_;
-  
+
   mutable int _cached_size_;
   ::google::protobuf::uint32 _has_bits_[(7 + 31) / 32];
-  
+
   friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto();
-  
+
   void InitAsDefaultInstance();
   static UninterpretedOption* default_instance_;
 };
@@ -2457,29 +2557,29 @@
  public:
   SourceCodeInfo_Location();
   virtual ~SourceCodeInfo_Location();
-  
+
   SourceCodeInfo_Location(const SourceCodeInfo_Location& from);
-  
+
   inline SourceCodeInfo_Location& operator=(const SourceCodeInfo_Location& from) {
     CopyFrom(from);
     return *this;
   }
-  
+
   inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
     return _unknown_fields_;
   }
-  
+
   inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
     return &_unknown_fields_;
   }
-  
+
   static const ::google::protobuf::Descriptor* descriptor();
   static const SourceCodeInfo_Location& default_instance();
-  
+
   void Swap(SourceCodeInfo_Location* other);
-  
+
   // implements Message ----------------------------------------------
-  
+
   SourceCodeInfo_Location* New() const;
   void CopyFrom(const ::google::protobuf::Message& from);
   void MergeFrom(const ::google::protobuf::Message& from);
@@ -2487,7 +2587,7 @@
   void MergeFrom(const SourceCodeInfo_Location& from);
   void Clear();
   bool IsInitialized() const;
-  
+
   int ByteSize() const;
   bool MergePartialFromCodedStream(
       ::google::protobuf::io::CodedInputStream* input);
@@ -2500,13 +2600,13 @@
   void SharedDtor();
   void SetCachedSize(int size) const;
   public:
-  
+
   ::google::protobuf::Metadata GetMetadata() const;
-  
+
   // nested types ----------------------------------------------------
-  
+
   // accessors -------------------------------------------------------
-  
+
   // repeated int32 path = 1 [packed = true];
   inline int path_size() const;
   inline void clear_path();
@@ -2518,7 +2618,7 @@
       path() const;
   inline ::google::protobuf::RepeatedField< ::google::protobuf::int32 >*
       mutable_path();
-  
+
   // repeated int32 span = 2 [packed = true];
   inline int span_size() const;
   inline void clear_span();
@@ -2530,24 +2630,54 @@
       span() const;
   inline ::google::protobuf::RepeatedField< ::google::protobuf::int32 >*
       mutable_span();
-  
+
+  // optional string leading_comments = 3;
+  inline bool has_leading_comments() const;
+  inline void clear_leading_comments();
+  static const int kLeadingCommentsFieldNumber = 3;
+  inline const ::std::string& leading_comments() const;
+  inline void set_leading_comments(const ::std::string& value);
+  inline void set_leading_comments(const char* value);
+  inline void set_leading_comments(const char* value, size_t size);
+  inline ::std::string* mutable_leading_comments();
+  inline ::std::string* release_leading_comments();
+  inline void set_allocated_leading_comments(::std::string* leading_comments);
+
+  // optional string trailing_comments = 4;
+  inline bool has_trailing_comments() const;
+  inline void clear_trailing_comments();
+  static const int kTrailingCommentsFieldNumber = 4;
+  inline const ::std::string& trailing_comments() const;
+  inline void set_trailing_comments(const ::std::string& value);
+  inline void set_trailing_comments(const char* value);
+  inline void set_trailing_comments(const char* value, size_t size);
+  inline ::std::string* mutable_trailing_comments();
+  inline ::std::string* release_trailing_comments();
+  inline void set_allocated_trailing_comments(::std::string* trailing_comments);
+
   // @@protoc_insertion_point(class_scope:google.protobuf.SourceCodeInfo.Location)
  private:
-  
+  inline void set_has_leading_comments();
+  inline void clear_has_leading_comments();
+  inline void set_has_trailing_comments();
+  inline void clear_has_trailing_comments();
+
   ::google::protobuf::UnknownFieldSet _unknown_fields_;
-  
+
   ::google::protobuf::RepeatedField< ::google::protobuf::int32 > path_;
   mutable int _path_cached_byte_size_;
   ::google::protobuf::RepeatedField< ::google::protobuf::int32 > span_;
   mutable int _span_cached_byte_size_;
-  
+  ::std::string* leading_comments_;
+  ::std::string* trailing_comments_;
+
   mutable int _cached_size_;
-  ::google::protobuf::uint32 _has_bits_[(2 + 31) / 32];
-  
+  ::google::protobuf::uint32 _has_bits_[(4 + 31) / 32];
+
   friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto();
-  
+
   void InitAsDefaultInstance();
   static SourceCodeInfo_Location* default_instance_;
 };
@@ -2557,29 +2687,29 @@
  public:
   SourceCodeInfo();
   virtual ~SourceCodeInfo();
-  
+
   SourceCodeInfo(const SourceCodeInfo& from);
-  
+
   inline SourceCodeInfo& operator=(const SourceCodeInfo& from) {
     CopyFrom(from);
     return *this;
   }
-  
+
   inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
     return _unknown_fields_;
   }
-  
+
   inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
     return &_unknown_fields_;
   }
-  
+
   static const ::google::protobuf::Descriptor* descriptor();
   static const SourceCodeInfo& default_instance();
-  
+
   void Swap(SourceCodeInfo* other);
-  
+
   // implements Message ----------------------------------------------
-  
+
   SourceCodeInfo* New() const;
   void CopyFrom(const ::google::protobuf::Message& from);
   void MergeFrom(const ::google::protobuf::Message& from);
@@ -2587,7 +2717,7 @@
   void MergeFrom(const SourceCodeInfo& from);
   void Clear();
   bool IsInitialized() const;
-  
+
   int ByteSize() const;
   bool MergePartialFromCodedStream(
       ::google::protobuf::io::CodedInputStream* input);
@@ -2600,15 +2730,15 @@
   void SharedDtor();
   void SetCachedSize(int size) const;
   public:
-  
+
   ::google::protobuf::Metadata GetMetadata() const;
-  
+
   // nested types ----------------------------------------------------
-  
+
   typedef SourceCodeInfo_Location Location;
-  
+
   // accessors -------------------------------------------------------
-  
+
   // repeated .google.protobuf.SourceCodeInfo.Location location = 1;
   inline int location_size() const;
   inline void clear_location();
@@ -2620,21 +2750,21 @@
       location() const;
   inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::SourceCodeInfo_Location >*
       mutable_location();
-  
+
   // @@protoc_insertion_point(class_scope:google.protobuf.SourceCodeInfo)
  private:
-  
+
   ::google::protobuf::UnknownFieldSet _unknown_fields_;
-  
+
   ::google::protobuf::RepeatedPtrField< ::google::protobuf::SourceCodeInfo_Location > location_;
-  
+
   mutable int _cached_size_;
   ::google::protobuf::uint32 _has_bits_[(1 + 31) / 32];
-  
+
   friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto();
-  
+
   void InitAsDefaultInstance();
   static SourceCodeInfo* default_instance_;
 };
@@ -2731,6 +2861,18 @@
     return temp;
   }
 }
+inline void FileDescriptorProto::set_allocated_name(::std::string* name) {
+  if (name_ != &::google::protobuf::internal::kEmptyString) {
+    delete name_;
+  }
+  if (name) {
+    set_has_name();
+    name_ = name;
+  } else {
+    clear_has_name();
+    name_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
+  }
+}
 
 // optional string package = 2;
 inline bool FileDescriptorProto::has_package() const {
@@ -2789,6 +2931,18 @@
     return temp;
   }
 }
+inline void FileDescriptorProto::set_allocated_package(::std::string* package) {
+  if (package_ != &::google::protobuf::internal::kEmptyString) {
+    delete package_;
+  }
+  if (package) {
+    set_has_package();
+    package_ = package;
+  } else {
+    clear_has_package();
+    package_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
+  }
+}
 
 // repeated string dependency = 3;
 inline int FileDescriptorProto::dependency_size() const {
@@ -2834,6 +2988,56 @@
   return &dependency_;
 }
 
+// repeated int32 public_dependency = 10;
+inline int FileDescriptorProto::public_dependency_size() const {
+  return public_dependency_.size();
+}
+inline void FileDescriptorProto::clear_public_dependency() {
+  public_dependency_.Clear();
+}
+inline ::google::protobuf::int32 FileDescriptorProto::public_dependency(int index) const {
+  return public_dependency_.Get(index);
+}
+inline void FileDescriptorProto::set_public_dependency(int index, ::google::protobuf::int32 value) {
+  public_dependency_.Set(index, value);
+}
+inline void FileDescriptorProto::add_public_dependency(::google::protobuf::int32 value) {
+  public_dependency_.Add(value);
+}
+inline const ::google::protobuf::RepeatedField< ::google::protobuf::int32 >&
+FileDescriptorProto::public_dependency() const {
+  return public_dependency_;
+}
+inline ::google::protobuf::RepeatedField< ::google::protobuf::int32 >*
+FileDescriptorProto::mutable_public_dependency() {
+  return &public_dependency_;
+}
+
+// repeated int32 weak_dependency = 11;
+inline int FileDescriptorProto::weak_dependency_size() const {
+  return weak_dependency_.size();
+}
+inline void FileDescriptorProto::clear_weak_dependency() {
+  weak_dependency_.Clear();
+}
+inline ::google::protobuf::int32 FileDescriptorProto::weak_dependency(int index) const {
+  return weak_dependency_.Get(index);
+}
+inline void FileDescriptorProto::set_weak_dependency(int index, ::google::protobuf::int32 value) {
+  weak_dependency_.Set(index, value);
+}
+inline void FileDescriptorProto::add_weak_dependency(::google::protobuf::int32 value) {
+  weak_dependency_.Add(value);
+}
+inline const ::google::protobuf::RepeatedField< ::google::protobuf::int32 >&
+FileDescriptorProto::weak_dependency() const {
+  return weak_dependency_;
+}
+inline ::google::protobuf::RepeatedField< ::google::protobuf::int32 >*
+FileDescriptorProto::mutable_weak_dependency() {
+  return &weak_dependency_;
+}
+
 // repeated .google.protobuf.DescriptorProto message_type = 4;
 inline int FileDescriptorProto::message_type_size() const {
   return message_type_.size();
@@ -2936,13 +3140,13 @@
 
 // optional .google.protobuf.FileOptions options = 8;
 inline bool FileDescriptorProto::has_options() const {
-  return (_has_bits_[0] & 0x00000080u) != 0;
+  return (_has_bits_[0] & 0x00000200u) != 0;
 }
 inline void FileDescriptorProto::set_has_options() {
-  _has_bits_[0] |= 0x00000080u;
+  _has_bits_[0] |= 0x00000200u;
 }
 inline void FileDescriptorProto::clear_has_options() {
-  _has_bits_[0] &= ~0x00000080u;
+  _has_bits_[0] &= ~0x00000200u;
 }
 inline void FileDescriptorProto::clear_options() {
   if (options_ != NULL) options_->::google::protobuf::FileOptions::Clear();
@@ -2962,16 +3166,25 @@
   options_ = NULL;
   return temp;
 }
+inline void FileDescriptorProto::set_allocated_options(::google::protobuf::FileOptions* options) {
+  delete options_;
+  options_ = options;
+  if (options) {
+    set_has_options();
+  } else {
+    clear_has_options();
+  }
+}
 
 // optional .google.protobuf.SourceCodeInfo source_code_info = 9;
 inline bool FileDescriptorProto::has_source_code_info() const {
-  return (_has_bits_[0] & 0x00000100u) != 0;
+  return (_has_bits_[0] & 0x00000400u) != 0;
 }
 inline void FileDescriptorProto::set_has_source_code_info() {
-  _has_bits_[0] |= 0x00000100u;
+  _has_bits_[0] |= 0x00000400u;
 }
 inline void FileDescriptorProto::clear_has_source_code_info() {
-  _has_bits_[0] &= ~0x00000100u;
+  _has_bits_[0] &= ~0x00000400u;
 }
 inline void FileDescriptorProto::clear_source_code_info() {
   if (source_code_info_ != NULL) source_code_info_->::google::protobuf::SourceCodeInfo::Clear();
@@ -2991,6 +3204,15 @@
   source_code_info_ = NULL;
   return temp;
 }
+inline void FileDescriptorProto::set_allocated_source_code_info(::google::protobuf::SourceCodeInfo* source_code_info) {
+  delete source_code_info_;
+  source_code_info_ = source_code_info;
+  if (source_code_info) {
+    set_has_source_code_info();
+  } else {
+    clear_has_source_code_info();
+  }
+}
 
 // -------------------------------------------------------------------
 
@@ -3101,6 +3323,18 @@
     return temp;
   }
 }
+inline void DescriptorProto::set_allocated_name(::std::string* name) {
+  if (name_ != &::google::protobuf::internal::kEmptyString) {
+    delete name_;
+  }
+  if (name) {
+    set_has_name();
+    name_ = name;
+  } else {
+    clear_has_name();
+    name_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
+  }
+}
 
 // repeated .google.protobuf.FieldDescriptorProto field = 2;
 inline int DescriptorProto::field_size() const {
@@ -3255,6 +3489,15 @@
   options_ = NULL;
   return temp;
 }
+inline void DescriptorProto::set_allocated_options(::google::protobuf::MessageOptions* options) {
+  delete options_;
+  options_ = options;
+  if (options) {
+    set_has_options();
+  } else {
+    clear_has_options();
+  }
+}
 
 // -------------------------------------------------------------------
 
@@ -3317,6 +3560,18 @@
     return temp;
   }
 }
+inline void FieldDescriptorProto::set_allocated_name(::std::string* name) {
+  if (name_ != &::google::protobuf::internal::kEmptyString) {
+    delete name_;
+  }
+  if (name) {
+    set_has_name();
+    name_ = name;
+  } else {
+    clear_has_name();
+    name_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
+  }
+}
 
 // optional int32 number = 3;
 inline bool FieldDescriptorProto::has_number() const {
@@ -3358,7 +3613,7 @@
   return static_cast< ::google::protobuf::FieldDescriptorProto_Label >(label_);
 }
 inline void FieldDescriptorProto::set_label(::google::protobuf::FieldDescriptorProto_Label value) {
-  GOOGLE_DCHECK(::google::protobuf::FieldDescriptorProto_Label_IsValid(value));
+  assert(::google::protobuf::FieldDescriptorProto_Label_IsValid(value));
   set_has_label();
   label_ = value;
 }
@@ -3381,7 +3636,7 @@
   return static_cast< ::google::protobuf::FieldDescriptorProto_Type >(type_);
 }
 inline void FieldDescriptorProto::set_type(::google::protobuf::FieldDescriptorProto_Type value) {
-  GOOGLE_DCHECK(::google::protobuf::FieldDescriptorProto_Type_IsValid(value));
+  assert(::google::protobuf::FieldDescriptorProto_Type_IsValid(value));
   set_has_type();
   type_ = value;
 }
@@ -3443,6 +3698,18 @@
     return temp;
   }
 }
+inline void FieldDescriptorProto::set_allocated_type_name(::std::string* type_name) {
+  if (type_name_ != &::google::protobuf::internal::kEmptyString) {
+    delete type_name_;
+  }
+  if (type_name) {
+    set_has_type_name();
+    type_name_ = type_name;
+  } else {
+    clear_has_type_name();
+    type_name_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
+  }
+}
 
 // optional string extendee = 2;
 inline bool FieldDescriptorProto::has_extendee() const {
@@ -3501,6 +3768,18 @@
     return temp;
   }
 }
+inline void FieldDescriptorProto::set_allocated_extendee(::std::string* extendee) {
+  if (extendee_ != &::google::protobuf::internal::kEmptyString) {
+    delete extendee_;
+  }
+  if (extendee) {
+    set_has_extendee();
+    extendee_ = extendee;
+  } else {
+    clear_has_extendee();
+    extendee_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
+  }
+}
 
 // optional string default_value = 7;
 inline bool FieldDescriptorProto::has_default_value() const {
@@ -3559,6 +3838,18 @@
     return temp;
   }
 }
+inline void FieldDescriptorProto::set_allocated_default_value(::std::string* default_value) {
+  if (default_value_ != &::google::protobuf::internal::kEmptyString) {
+    delete default_value_;
+  }
+  if (default_value) {
+    set_has_default_value();
+    default_value_ = default_value;
+  } else {
+    clear_has_default_value();
+    default_value_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
+  }
+}
 
 // optional .google.protobuf.FieldOptions options = 8;
 inline bool FieldDescriptorProto::has_options() const {
@@ -3588,6 +3879,15 @@
   options_ = NULL;
   return temp;
 }
+inline void FieldDescriptorProto::set_allocated_options(::google::protobuf::FieldOptions* options) {
+  delete options_;
+  options_ = options;
+  if (options) {
+    set_has_options();
+  } else {
+    clear_has_options();
+  }
+}
 
 // -------------------------------------------------------------------
 
@@ -3650,6 +3950,18 @@
     return temp;
   }
 }
+inline void EnumDescriptorProto::set_allocated_name(::std::string* name) {
+  if (name_ != &::google::protobuf::internal::kEmptyString) {
+    delete name_;
+  }
+  if (name) {
+    set_has_name();
+    name_ = name;
+  } else {
+    clear_has_name();
+    name_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
+  }
+}
 
 // repeated .google.protobuf.EnumValueDescriptorProto value = 2;
 inline int EnumDescriptorProto::value_size() const {
@@ -3704,6 +4016,15 @@
   options_ = NULL;
   return temp;
 }
+inline void EnumDescriptorProto::set_allocated_options(::google::protobuf::EnumOptions* options) {
+  delete options_;
+  options_ = options;
+  if (options) {
+    set_has_options();
+  } else {
+    clear_has_options();
+  }
+}
 
 // -------------------------------------------------------------------
 
@@ -3766,6 +4087,18 @@
     return temp;
   }
 }
+inline void EnumValueDescriptorProto::set_allocated_name(::std::string* name) {
+  if (name_ != &::google::protobuf::internal::kEmptyString) {
+    delete name_;
+  }
+  if (name) {
+    set_has_name();
+    name_ = name;
+  } else {
+    clear_has_name();
+    name_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
+  }
+}
 
 // optional int32 number = 2;
 inline bool EnumValueDescriptorProto::has_number() const {
@@ -3817,6 +4150,15 @@
   options_ = NULL;
   return temp;
 }
+inline void EnumValueDescriptorProto::set_allocated_options(::google::protobuf::EnumValueOptions* options) {
+  delete options_;
+  options_ = options;
+  if (options) {
+    set_has_options();
+  } else {
+    clear_has_options();
+  }
+}
 
 // -------------------------------------------------------------------
 
@@ -3879,6 +4221,18 @@
     return temp;
   }
 }
+inline void ServiceDescriptorProto::set_allocated_name(::std::string* name) {
+  if (name_ != &::google::protobuf::internal::kEmptyString) {
+    delete name_;
+  }
+  if (name) {
+    set_has_name();
+    name_ = name;
+  } else {
+    clear_has_name();
+    name_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
+  }
+}
 
 // repeated .google.protobuf.MethodDescriptorProto method = 2;
 inline int ServiceDescriptorProto::method_size() const {
@@ -3933,6 +4287,15 @@
   options_ = NULL;
   return temp;
 }
+inline void ServiceDescriptorProto::set_allocated_options(::google::protobuf::ServiceOptions* options) {
+  delete options_;
+  options_ = options;
+  if (options) {
+    set_has_options();
+  } else {
+    clear_has_options();
+  }
+}
 
 // -------------------------------------------------------------------
 
@@ -3995,6 +4358,18 @@
     return temp;
   }
 }
+inline void MethodDescriptorProto::set_allocated_name(::std::string* name) {
+  if (name_ != &::google::protobuf::internal::kEmptyString) {
+    delete name_;
+  }
+  if (name) {
+    set_has_name();
+    name_ = name;
+  } else {
+    clear_has_name();
+    name_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
+  }
+}
 
 // optional string input_type = 2;
 inline bool MethodDescriptorProto::has_input_type() const {
@@ -4053,6 +4428,18 @@
     return temp;
   }
 }
+inline void MethodDescriptorProto::set_allocated_input_type(::std::string* input_type) {
+  if (input_type_ != &::google::protobuf::internal::kEmptyString) {
+    delete input_type_;
+  }
+  if (input_type) {
+    set_has_input_type();
+    input_type_ = input_type;
+  } else {
+    clear_has_input_type();
+    input_type_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
+  }
+}
 
 // optional string output_type = 3;
 inline bool MethodDescriptorProto::has_output_type() const {
@@ -4111,6 +4498,18 @@
     return temp;
   }
 }
+inline void MethodDescriptorProto::set_allocated_output_type(::std::string* output_type) {
+  if (output_type_ != &::google::protobuf::internal::kEmptyString) {
+    delete output_type_;
+  }
+  if (output_type) {
+    set_has_output_type();
+    output_type_ = output_type;
+  } else {
+    clear_has_output_type();
+    output_type_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
+  }
+}
 
 // optional .google.protobuf.MethodOptions options = 4;
 inline bool MethodDescriptorProto::has_options() const {
@@ -4140,6 +4539,15 @@
   options_ = NULL;
   return temp;
 }
+inline void MethodDescriptorProto::set_allocated_options(::google::protobuf::MethodOptions* options) {
+  delete options_;
+  options_ = options;
+  if (options) {
+    set_has_options();
+  } else {
+    clear_has_options();
+  }
+}
 
 // -------------------------------------------------------------------
 
@@ -4202,6 +4610,18 @@
     return temp;
   }
 }
+inline void FileOptions::set_allocated_java_package(::std::string* java_package) {
+  if (java_package_ != &::google::protobuf::internal::kEmptyString) {
+    delete java_package_;
+  }
+  if (java_package) {
+    set_has_java_package();
+    java_package_ = java_package;
+  } else {
+    clear_has_java_package();
+    java_package_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
+  }
+}
 
 // optional string java_outer_classname = 8;
 inline bool FileOptions::has_java_outer_classname() const {
@@ -4260,6 +4680,18 @@
     return temp;
   }
 }
+inline void FileOptions::set_allocated_java_outer_classname(::std::string* java_outer_classname) {
+  if (java_outer_classname_ != &::google::protobuf::internal::kEmptyString) {
+    delete java_outer_classname_;
+  }
+  if (java_outer_classname) {
+    set_has_java_outer_classname();
+    java_outer_classname_ = java_outer_classname;
+  } else {
+    clear_has_java_outer_classname();
+    java_outer_classname_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
+  }
+}
 
 // optional bool java_multiple_files = 10 [default = false];
 inline bool FileOptions::has_java_multiple_files() const {
@@ -4283,7 +4715,7 @@
   java_multiple_files_ = value;
 }
 
-// optional bool retain_unknown_fields = 11 [default = false];
+// optional bool retain_unknown_fields = 12 [default = false];
 inline bool FileOptions::has_retain_unknown_fields() const {
   return (_has_bits_[0] & 0x00000008u) != 0;
 }
@@ -4345,21 +4777,91 @@
   return static_cast< ::google::protobuf::FileOptions_OptimizeMode >(optimize_for_);
 }
 inline void FileOptions::set_optimize_for(::google::protobuf::FileOptions_OptimizeMode value) {
-  GOOGLE_DCHECK(::google::protobuf::FileOptions_OptimizeMode_IsValid(value));
+  assert(::google::protobuf::FileOptions_OptimizeMode_IsValid(value));
   set_has_optimize_for();
   optimize_for_ = value;
 }
 
-// optional bool cc_generic_services = 16 [default = false];
-inline bool FileOptions::has_cc_generic_services() const {
+// optional string go_package = 11;
+inline bool FileOptions::has_go_package() const {
   return (_has_bits_[0] & 0x00000040u) != 0;
 }
-inline void FileOptions::set_has_cc_generic_services() {
+inline void FileOptions::set_has_go_package() {
   _has_bits_[0] |= 0x00000040u;
 }
-inline void FileOptions::clear_has_cc_generic_services() {
+inline void FileOptions::clear_has_go_package() {
   _has_bits_[0] &= ~0x00000040u;
 }
+inline void FileOptions::clear_go_package() {
+  if (go_package_ != &::google::protobuf::internal::kEmptyString) {
+    go_package_->clear();
+  }
+  clear_has_go_package();
+}
+inline const ::std::string& FileOptions::go_package() const {
+  return *go_package_;
+}
+inline void FileOptions::set_go_package(const ::std::string& value) {
+  set_has_go_package();
+  if (go_package_ == &::google::protobuf::internal::kEmptyString) {
+    go_package_ = new ::std::string;
+  }
+  go_package_->assign(value);
+}
+inline void FileOptions::set_go_package(const char* value) {
+  set_has_go_package();
+  if (go_package_ == &::google::protobuf::internal::kEmptyString) {
+    go_package_ = new ::std::string;
+  }
+  go_package_->assign(value);
+}
+inline void FileOptions::set_go_package(const char* value, size_t size) {
+  set_has_go_package();
+  if (go_package_ == &::google::protobuf::internal::kEmptyString) {
+    go_package_ = new ::std::string;
+  }
+  go_package_->assign(reinterpret_cast<const char*>(value), size);
+}
+inline ::std::string* FileOptions::mutable_go_package() {
+  set_has_go_package();
+  if (go_package_ == &::google::protobuf::internal::kEmptyString) {
+    go_package_ = new ::std::string;
+  }
+  return go_package_;
+}
+inline ::std::string* FileOptions::release_go_package() {
+  clear_has_go_package();
+  if (go_package_ == &::google::protobuf::internal::kEmptyString) {
+    return NULL;
+  } else {
+    ::std::string* temp = go_package_;
+    go_package_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
+    return temp;
+  }
+}
+inline void FileOptions::set_allocated_go_package(::std::string* go_package) {
+  if (go_package_ != &::google::protobuf::internal::kEmptyString) {
+    delete go_package_;
+  }
+  if (go_package) {
+    set_has_go_package();
+    go_package_ = go_package;
+  } else {
+    clear_has_go_package();
+    go_package_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
+  }
+}
+
+// optional bool cc_generic_services = 16 [default = false];
+inline bool FileOptions::has_cc_generic_services() const {
+  return (_has_bits_[0] & 0x00000080u) != 0;
+}
+inline void FileOptions::set_has_cc_generic_services() {
+  _has_bits_[0] |= 0x00000080u;
+}
+inline void FileOptions::clear_has_cc_generic_services() {
+  _has_bits_[0] &= ~0x00000080u;
+}
 inline void FileOptions::clear_cc_generic_services() {
   cc_generic_services_ = false;
   clear_has_cc_generic_services();
@@ -4374,13 +4876,13 @@
 
 // optional bool java_generic_services = 17 [default = false];
 inline bool FileOptions::has_java_generic_services() const {
-  return (_has_bits_[0] & 0x00000080u) != 0;
+  return (_has_bits_[0] & 0x00000100u) != 0;
 }
 inline void FileOptions::set_has_java_generic_services() {
-  _has_bits_[0] |= 0x00000080u;
+  _has_bits_[0] |= 0x00000100u;
 }
 inline void FileOptions::clear_has_java_generic_services() {
-  _has_bits_[0] &= ~0x00000080u;
+  _has_bits_[0] &= ~0x00000100u;
 }
 inline void FileOptions::clear_java_generic_services() {
   java_generic_services_ = false;
@@ -4396,13 +4898,13 @@
 
 // optional bool py_generic_services = 18 [default = false];
 inline bool FileOptions::has_py_generic_services() const {
-  return (_has_bits_[0] & 0x00000100u) != 0;
+  return (_has_bits_[0] & 0x00000200u) != 0;
 }
 inline void FileOptions::set_has_py_generic_services() {
-  _has_bits_[0] |= 0x00000100u;
+  _has_bits_[0] |= 0x00000200u;
 }
 inline void FileOptions::clear_has_py_generic_services() {
-  _has_bits_[0] &= ~0x00000100u;
+  _has_bits_[0] &= ~0x00000200u;
 }
 inline void FileOptions::clear_py_generic_services() {
   py_generic_services_ = false;
@@ -4536,7 +5038,7 @@
   return static_cast< ::google::protobuf::FieldOptions_CType >(ctype_);
 }
 inline void FieldOptions::set_ctype(::google::protobuf::FieldOptions_CType value) {
-  GOOGLE_DCHECK(::google::protobuf::FieldOptions_CType_IsValid(value));
+  assert(::google::protobuf::FieldOptions_CType_IsValid(value));
   set_has_ctype();
   ctype_ = value;
 }
@@ -4563,16 +5065,38 @@
   packed_ = value;
 }
 
-// optional bool deprecated = 3 [default = false];
-inline bool FieldOptions::has_deprecated() const {
+// optional bool lazy = 5 [default = false];
+inline bool FieldOptions::has_lazy() const {
   return (_has_bits_[0] & 0x00000004u) != 0;
 }
-inline void FieldOptions::set_has_deprecated() {
+inline void FieldOptions::set_has_lazy() {
   _has_bits_[0] |= 0x00000004u;
 }
-inline void FieldOptions::clear_has_deprecated() {
+inline void FieldOptions::clear_has_lazy() {
   _has_bits_[0] &= ~0x00000004u;
 }
+inline void FieldOptions::clear_lazy() {
+  lazy_ = false;
+  clear_has_lazy();
+}
+inline bool FieldOptions::lazy() const {
+  return lazy_;
+}
+inline void FieldOptions::set_lazy(bool value) {
+  set_has_lazy();
+  lazy_ = value;
+}
+
+// optional bool deprecated = 3 [default = false];
+inline bool FieldOptions::has_deprecated() const {
+  return (_has_bits_[0] & 0x00000008u) != 0;
+}
+inline void FieldOptions::set_has_deprecated() {
+  _has_bits_[0] |= 0x00000008u;
+}
+inline void FieldOptions::clear_has_deprecated() {
+  _has_bits_[0] &= ~0x00000008u;
+}
 inline void FieldOptions::clear_deprecated() {
   deprecated_ = false;
   clear_has_deprecated();
@@ -4587,13 +5111,13 @@
 
 // optional string experimental_map_key = 9;
 inline bool FieldOptions::has_experimental_map_key() const {
-  return (_has_bits_[0] & 0x00000008u) != 0;
+  return (_has_bits_[0] & 0x00000010u) != 0;
 }
 inline void FieldOptions::set_has_experimental_map_key() {
-  _has_bits_[0] |= 0x00000008u;
+  _has_bits_[0] |= 0x00000010u;
 }
 inline void FieldOptions::clear_has_experimental_map_key() {
-  _has_bits_[0] &= ~0x00000008u;
+  _has_bits_[0] &= ~0x00000010u;
 }
 inline void FieldOptions::clear_experimental_map_key() {
   if (experimental_map_key_ != &::google::protobuf::internal::kEmptyString) {
@@ -4642,6 +5166,40 @@
     return temp;
   }
 }
+inline void FieldOptions::set_allocated_experimental_map_key(::std::string* experimental_map_key) {
+  if (experimental_map_key_ != &::google::protobuf::internal::kEmptyString) {
+    delete experimental_map_key_;
+  }
+  if (experimental_map_key) {
+    set_has_experimental_map_key();
+    experimental_map_key_ = experimental_map_key;
+  } else {
+    clear_has_experimental_map_key();
+    experimental_map_key_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
+  }
+}
+
+// optional bool weak = 10 [default = false];
+inline bool FieldOptions::has_weak() const {
+  return (_has_bits_[0] & 0x00000020u) != 0;
+}
+inline void FieldOptions::set_has_weak() {
+  _has_bits_[0] |= 0x00000020u;
+}
+inline void FieldOptions::clear_has_weak() {
+  _has_bits_[0] &= ~0x00000020u;
+}
+inline void FieldOptions::clear_weak() {
+  weak_ = false;
+  clear_has_weak();
+}
+inline bool FieldOptions::weak() const {
+  return weak_;
+}
+inline void FieldOptions::set_weak(bool value) {
+  set_has_weak();
+  weak_ = value;
+}
 
 // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
 inline int FieldOptions::uninterpreted_option_size() const {
@@ -4672,6 +5230,28 @@
 
 // EnumOptions
 
+// optional bool allow_alias = 2 [default = true];
+inline bool EnumOptions::has_allow_alias() const {
+  return (_has_bits_[0] & 0x00000001u) != 0;
+}
+inline void EnumOptions::set_has_allow_alias() {
+  _has_bits_[0] |= 0x00000001u;
+}
+inline void EnumOptions::clear_has_allow_alias() {
+  _has_bits_[0] &= ~0x00000001u;
+}
+inline void EnumOptions::clear_allow_alias() {
+  allow_alias_ = true;
+  clear_has_allow_alias();
+}
+inline bool EnumOptions::allow_alias() const {
+  return allow_alias_;
+}
+inline void EnumOptions::set_allow_alias(bool value) {
+  set_has_allow_alias();
+  allow_alias_ = value;
+}
+
 // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
 inline int EnumOptions::uninterpreted_option_size() const {
   return uninterpreted_option_.size();
@@ -4845,6 +5425,18 @@
     return temp;
   }
 }
+inline void UninterpretedOption_NamePart::set_allocated_name_part(::std::string* name_part) {
+  if (name_part_ != &::google::protobuf::internal::kEmptyString) {
+    delete name_part_;
+  }
+  if (name_part) {
+    set_has_name_part();
+    name_part_ = name_part;
+  } else {
+    clear_has_name_part();
+    name_part_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
+  }
+}
 
 // required bool is_extension = 2;
 inline bool UninterpretedOption_NamePart::has_is_extension() const {
@@ -4954,6 +5546,18 @@
     return temp;
   }
 }
+inline void UninterpretedOption::set_allocated_identifier_value(::std::string* identifier_value) {
+  if (identifier_value_ != &::google::protobuf::internal::kEmptyString) {
+    delete identifier_value_;
+  }
+  if (identifier_value) {
+    set_has_identifier_value();
+    identifier_value_ = identifier_value;
+  } else {
+    clear_has_identifier_value();
+    identifier_value_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
+  }
+}
 
 // optional uint64 positive_int_value = 4;
 inline bool UninterpretedOption::has_positive_int_value() const {
@@ -5078,6 +5682,18 @@
     return temp;
   }
 }
+inline void UninterpretedOption::set_allocated_string_value(::std::string* string_value) {
+  if (string_value_ != &::google::protobuf::internal::kEmptyString) {
+    delete string_value_;
+  }
+  if (string_value) {
+    set_has_string_value();
+    string_value_ = string_value;
+  } else {
+    clear_has_string_value();
+    string_value_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
+  }
+}
 
 // optional string aggregate_value = 8;
 inline bool UninterpretedOption::has_aggregate_value() const {
@@ -5136,6 +5752,18 @@
     return temp;
   }
 }
+inline void UninterpretedOption::set_allocated_aggregate_value(::std::string* aggregate_value) {
+  if (aggregate_value_ != &::google::protobuf::internal::kEmptyString) {
+    delete aggregate_value_;
+  }
+  if (aggregate_value) {
+    set_has_aggregate_value();
+    aggregate_value_ = aggregate_value;
+  } else {
+    clear_has_aggregate_value();
+    aggregate_value_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
+  }
+}
 
 // -------------------------------------------------------------------
 
@@ -5191,6 +5819,146 @@
   return &span_;
 }
 
+// optional string leading_comments = 3;
+inline bool SourceCodeInfo_Location::has_leading_comments() const {
+  return (_has_bits_[0] & 0x00000004u) != 0;
+}
+inline void SourceCodeInfo_Location::set_has_leading_comments() {
+  _has_bits_[0] |= 0x00000004u;
+}
+inline void SourceCodeInfo_Location::clear_has_leading_comments() {
+  _has_bits_[0] &= ~0x00000004u;
+}
+inline void SourceCodeInfo_Location::clear_leading_comments() {
+  if (leading_comments_ != &::google::protobuf::internal::kEmptyString) {
+    leading_comments_->clear();
+  }
+  clear_has_leading_comments();
+}
+inline const ::std::string& SourceCodeInfo_Location::leading_comments() const {
+  return *leading_comments_;
+}
+inline void SourceCodeInfo_Location::set_leading_comments(const ::std::string& value) {
+  set_has_leading_comments();
+  if (leading_comments_ == &::google::protobuf::internal::kEmptyString) {
+    leading_comments_ = new ::std::string;
+  }
+  leading_comments_->assign(value);
+}
+inline void SourceCodeInfo_Location::set_leading_comments(const char* value) {
+  set_has_leading_comments();
+  if (leading_comments_ == &::google::protobuf::internal::kEmptyString) {
+    leading_comments_ = new ::std::string;
+  }
+  leading_comments_->assign(value);
+}
+inline void SourceCodeInfo_Location::set_leading_comments(const char* value, size_t size) {
+  set_has_leading_comments();
+  if (leading_comments_ == &::google::protobuf::internal::kEmptyString) {
+    leading_comments_ = new ::std::string;
+  }
+  leading_comments_->assign(reinterpret_cast<const char*>(value), size);
+}
+inline ::std::string* SourceCodeInfo_Location::mutable_leading_comments() {
+  set_has_leading_comments();
+  if (leading_comments_ == &::google::protobuf::internal::kEmptyString) {
+    leading_comments_ = new ::std::string;
+  }
+  return leading_comments_;
+}
+inline ::std::string* SourceCodeInfo_Location::release_leading_comments() {
+  clear_has_leading_comments();
+  if (leading_comments_ == &::google::protobuf::internal::kEmptyString) {
+    return NULL;
+  } else {
+    ::std::string* temp = leading_comments_;
+    leading_comments_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
+    return temp;
+  }
+}
+inline void SourceCodeInfo_Location::set_allocated_leading_comments(::std::string* leading_comments) {
+  if (leading_comments_ != &::google::protobuf::internal::kEmptyString) {
+    delete leading_comments_;
+  }
+  if (leading_comments) {
+    set_has_leading_comments();
+    leading_comments_ = leading_comments;
+  } else {
+    clear_has_leading_comments();
+    leading_comments_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
+  }
+}
+
+// optional string trailing_comments = 4;
+inline bool SourceCodeInfo_Location::has_trailing_comments() const {
+  return (_has_bits_[0] & 0x00000008u) != 0;
+}
+inline void SourceCodeInfo_Location::set_has_trailing_comments() {
+  _has_bits_[0] |= 0x00000008u;
+}
+inline void SourceCodeInfo_Location::clear_has_trailing_comments() {
+  _has_bits_[0] &= ~0x00000008u;
+}
+inline void SourceCodeInfo_Location::clear_trailing_comments() {
+  if (trailing_comments_ != &::google::protobuf::internal::kEmptyString) {
+    trailing_comments_->clear();
+  }
+  clear_has_trailing_comments();
+}
+inline const ::std::string& SourceCodeInfo_Location::trailing_comments() const {
+  return *trailing_comments_;
+}
+inline void SourceCodeInfo_Location::set_trailing_comments(const ::std::string& value) {
+  set_has_trailing_comments();
+  if (trailing_comments_ == &::google::protobuf::internal::kEmptyString) {
+    trailing_comments_ = new ::std::string;
+  }
+  trailing_comments_->assign(value);
+}
+inline void SourceCodeInfo_Location::set_trailing_comments(const char* value) {
+  set_has_trailing_comments();
+  if (trailing_comments_ == &::google::protobuf::internal::kEmptyString) {
+    trailing_comments_ = new ::std::string;
+  }
+  trailing_comments_->assign(value);
+}
+inline void SourceCodeInfo_Location::set_trailing_comments(const char* value, size_t size) {
+  set_has_trailing_comments();
+  if (trailing_comments_ == &::google::protobuf::internal::kEmptyString) {
+    trailing_comments_ = new ::std::string;
+  }
+  trailing_comments_->assign(reinterpret_cast<const char*>(value), size);
+}
+inline ::std::string* SourceCodeInfo_Location::mutable_trailing_comments() {
+  set_has_trailing_comments();
+  if (trailing_comments_ == &::google::protobuf::internal::kEmptyString) {
+    trailing_comments_ = new ::std::string;
+  }
+  return trailing_comments_;
+}
+inline ::std::string* SourceCodeInfo_Location::release_trailing_comments() {
+  clear_has_trailing_comments();
+  if (trailing_comments_ == &::google::protobuf::internal::kEmptyString) {
+    return NULL;
+  } else {
+    ::std::string* temp = trailing_comments_;
+    trailing_comments_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
+    return temp;
+  }
+}
+inline void SourceCodeInfo_Location::set_allocated_trailing_comments(::std::string* trailing_comments) {
+  if (trailing_comments_ != &::google::protobuf::internal::kEmptyString) {
+    delete trailing_comments_;
+  }
+  if (trailing_comments) {
+    set_has_trailing_comments();
+    trailing_comments_ = trailing_comments;
+  } else {
+    clear_has_trailing_comments();
+    trailing_comments_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
+  }
+}
+
 // -------------------------------------------------------------------
 
 // SourceCodeInfo
diff --git a/third_party/protobuf/src/google/protobuf/descriptor.proto b/third_party/protobuf/src/google/protobuf/descriptor.proto
index bd3cb96..ef9eb65 100644
--- a/third_party/protobuf/src/google/protobuf/descriptor.proto
+++ b/third_party/protobuf/src/google/protobuf/descriptor.proto
@@ -59,6 +59,11 @@
 
   // Names of files imported by this file.
   repeated string dependency = 3;
+  // Indexes of the public imported files in the dependency list above.
+  repeated int32 public_dependency = 10;
+  // Indexes of the weak imported files in the dependency list.
+  // For Google-internal migration only. Do not use.
+  repeated int32 weak_dependency = 11;
 
   // All top-level definitions in this file.
   repeated DescriptorProto message_type = 4;
@@ -101,13 +106,13 @@
     // Order is weird for historical reasons.
     TYPE_DOUBLE         = 1;
     TYPE_FLOAT          = 2;
-    TYPE_INT64          = 3;   // Not ZigZag encoded.  Negative numbers
-                               // take 10 bytes.  Use TYPE_SINT64 if negative
-                               // values are likely.
+    // Not ZigZag encoded.  Negative numbers take 10 bytes.  Use TYPE_SINT64 if
+    // negative values are likely.
+    TYPE_INT64          = 3;
     TYPE_UINT64         = 4;
-    TYPE_INT32          = 5;   // Not ZigZag encoded.  Negative numbers
-                               // take 10 bytes.  Use TYPE_SINT32 if negative
-                               // values are likely.
+    // Not ZigZag encoded.  Negative numbers take 10 bytes.  Use TYPE_SINT32 if
+    // negative values are likely.
+    TYPE_INT32          = 5;
     TYPE_FIXED64        = 6;
     TYPE_FIXED32        = 7;
     TYPE_BOOL           = 8;
@@ -199,6 +204,7 @@
   optional MethodOptions options = 4;
 }
 
+
 // ===================================================================
 // Options
 
@@ -260,7 +266,7 @@
   // reserializing a message will retain them. This is the default behaviour
   // unless LITE_RUNTIME is specified. Therefore, this option only makes sense
   // when LITE_RUNTIME is in use.
-  optional bool retain_unknown_fields = 11 [default=false];
+  optional bool retain_unknown_fields = 12 [default=false];
 
   // If set true, then the Java code generator will generate equals() and
   // hashCode() methods for all messages defined in the .proto file. This is
@@ -277,6 +283,9 @@
   }
   optional OptimizeMode optimize_for = 9 [default=SPEED];
 
+  // Sets the Go package where structs generated from this .proto will be
+  // placed.  There is no default.
+  optional string go_package = 11;
 
 
 
@@ -355,6 +364,37 @@
   optional bool packed = 2;
 
 
+
+  // Should this field be parsed lazily?  Lazy applies only to message-type
+  // fields.  It means that when the outer message is initially parsed, the
+  // inner message's contents will not be parsed but instead stored in encoded
+  // form.  The inner message will actually be parsed when it is first accessed.
+  //
+  // This is only a hint.  Implementations are free to choose whether to use
+  // eager or lazy parsing regardless of the value of this option.  However,
+  // setting this option true suggests that the protocol author believes that
+  // using lazy parsing on this field is worth the additional bookkeeping
+  // overhead typically needed to implement it.
+  //
+  // This option does not affect the public interface of any generated code;
+  // all method signatures remain the same.  Furthermore, thread-safety of the
+  // interface is not affected by this option; const methods remain safe to
+  // call from multiple threads concurrently, while non-const methods continue
+  // to require exclusive access.
+  //
+  //
+  // Note that implementations may choose not to check required fields within
+  // a lazy sub-message.  That is, calling IsInitialized() on the outher message
+  // may return true even if the inner message has missing required fields.
+  // This is necessary because otherwise the inner message would have to be
+  // parsed in order to perform the check, defeating the purpose of lazy
+  // parsing.  An implementation which chooses not to check required fields
+  // must be consistent about it.  That is, for any particular sub-message, the
+  // implementation must either *always* check its required fields, or *never*
+  // check its required fields, regardless of whether or not the message has
+  // been parsed.
+  optional bool lazy = 5 [default=false];
+
   // Is this field deprecated?
   // Depending on the target platform, this can emit Deprecated annotations
   // for accessors, or it will be completely ignored; in the very least, this
@@ -375,6 +415,9 @@
   // TODO: Fully-implement this, then remove the "experimental_" prefix.
   optional string experimental_map_key = 9;
 
+  // For Google-internal migration only. Do not use.
+  optional bool weak = 10 [default=false];
+
   // The parser stores options it doesn't recognize here. See above.
   repeated UninterpretedOption uninterpreted_option = 999;
 
@@ -384,6 +427,10 @@
 
 message EnumOptions {
 
+  // Set this option to false to disallow mapping different tag names to a same
+  // value.
+  optional bool allow_alias = 2 [default=true];
+
   // The parser stores options it doesn't recognize here. See above.
   repeated UninterpretedOption uninterpreted_option = 999;
 
@@ -427,6 +474,7 @@
   extensions 1000 to max;
 }
 
+
 // A message representing a option the parser does not recognize. This only
 // appears in options protos created by the compiler::Parser class.
 // DescriptorPool resolves these when building Descriptor objects. Therefore,
@@ -538,7 +586,41 @@
     // 1 to each before displaying to a user.
     repeated int32 span = 2 [packed=true];
 
-    // TODO(kenton):  Record comments appearing before and after the
-    // declaration.
+    // If this SourceCodeInfo represents a complete declaration, these are any
+    // comments appearing before and after the declaration which appear to be
+    // attached to the declaration.
+    //
+    // A series of line comments appearing on consecutive lines, with no other
+    // tokens appearing on those lines, will be treated as a single comment.
+    //
+    // Only the comment content is provided; comment markers (e.g. //) are
+    // stripped out.  For block comments, leading whitespace and an asterisk
+    // will be stripped from the beginning of each line other than the first.
+    // Newlines are included in the output.
+    //
+    // Examples:
+    //
+    //   optional int32 foo = 1;  // Comment attached to foo.
+    //   // Comment attached to bar.
+    //   optional int32 bar = 2;
+    //
+    //   optional string baz = 3;
+    //   // Comment attached to baz.
+    //   // Another line attached to baz.
+    //
+    //   // Comment attached to qux.
+    //   //
+    //   // Another line attached to qux.
+    //   optional double qux = 4;
+    //
+    //   optional string corge = 5;
+    //   /* Block comment attached
+    //    * to corge.  Leading asterisks
+    //    * will be removed. */
+    //   /* Block comment attached to
+    //    * grault. */
+    //   optional int32 grault = 6;
+    optional string leading_comments = 3;
+    optional string trailing_comments = 4;
   }
 }
diff --git a/third_party/protobuf/src/google/protobuf/descriptor_database.cc b/third_party/protobuf/src/google/protobuf/descriptor_database.cc
index 23e48a6..35e459d 100644
--- a/third_party/protobuf/src/google/protobuf/descriptor_database.cc
+++ b/third_party/protobuf/src/google/protobuf/descriptor_database.cc
@@ -39,7 +39,7 @@
 #include <google/protobuf/descriptor.pb.h>
 #include <google/protobuf/wire_format_lite_inl.h>
 #include <google/protobuf/stubs/strutil.h>
-#include <google/protobuf/stubs/stl_util-inl.h>
+#include <google/protobuf/stubs/stl_util.h>
 #include <google/protobuf/stubs/map-util.h>
 
 namespace google {
diff --git a/third_party/protobuf/src/google/protobuf/descriptor_database.h b/third_party/protobuf/src/google/protobuf/descriptor_database.h
index f32b1db..2ccb145 100644
--- a/third_party/protobuf/src/google/protobuf/descriptor_database.h
+++ b/third_party/protobuf/src/google/protobuf/descriptor_database.h
@@ -41,6 +41,7 @@
 #include <string>
 #include <utility>
 #include <vector>
+#include <google/protobuf/stubs/common.h>
 #include <google/protobuf/descriptor.h>
 
 namespace google {
diff --git a/third_party/protobuf/src/google/protobuf/descriptor_unittest.cc b/third_party/protobuf/src/google/protobuf/descriptor_unittest.cc
index 55aebfd..3503f13 100644
--- a/third_party/protobuf/src/google/protobuf/descriptor_unittest.cc
+++ b/third_party/protobuf/src/google/protobuf/descriptor_unittest.cc
@@ -36,13 +36,15 @@
 
 #include <vector>
 
+#include <google/protobuf/compiler/importer.h>
+#include <google/protobuf/unittest.pb.h>
+#include <google/protobuf/unittest_custom_options.pb.h>
+#include <google/protobuf/io/zero_copy_stream_impl.h>
+#include <google/protobuf/descriptor.pb.h>
 #include <google/protobuf/descriptor.h>
 #include <google/protobuf/descriptor_database.h>
 #include <google/protobuf/dynamic_message.h>
-#include <google/protobuf/descriptor.pb.h>
 #include <google/protobuf/text_format.h>
-#include <google/protobuf/unittest.pb.h>
-#include <google/protobuf/unittest_custom_options.pb.h>
 #include <google/protobuf/stubs/strutil.h>
 #include <google/protobuf/stubs/substitute.h>
 
@@ -1518,9 +1520,8 @@
 
 class MiscTest : public testing::Test {
  protected:
-  // Function which makes a field of the given type just to find out what its
-  // cpp_type is.
-  FieldDescriptor::CppType GetCppTypeForFieldType(FieldDescriptor::Type type) {
+  // Function which makes a field descriptor of the given type.
+  const FieldDescriptor* GetFieldDescriptorOfType(FieldDescriptor::Type type) {
     FileDescriptorProto file_proto;
     file_proto.set_name("foo.proto");
     AddEmptyEnum(&file_proto, "DummyEnum");
@@ -1538,19 +1539,62 @@
     }
 
     // Build the descriptors and get the pointers.
-    DescriptorPool pool;
-    const FileDescriptor* file = pool.BuildFile(file_proto);
+    pool_.reset(new DescriptorPool());
+    const FileDescriptor* file = pool_->BuildFile(file_proto);
 
     if (file != NULL &&
         file->message_type_count() == 1 &&
         file->message_type(0)->field_count() == 1) {
-      return file->message_type(0)->field(0)->cpp_type();
+      return file->message_type(0)->field(0);
     } else {
-      return static_cast<FieldDescriptor::CppType>(0);
+      return NULL;
     }
   }
+
+  const char* GetTypeNameForFieldType(FieldDescriptor::Type type) {
+    const FieldDescriptor* field = GetFieldDescriptorOfType(type);
+    return field != NULL ? field->type_name() : "";
+  }
+
+  FieldDescriptor::CppType GetCppTypeForFieldType(FieldDescriptor::Type type) {
+    const FieldDescriptor* field = GetFieldDescriptorOfType(type);
+    return field != NULL ? field->cpp_type() :
+        static_cast<FieldDescriptor::CppType>(0);
+  }
+
+  const char* GetCppTypeNameForFieldType(FieldDescriptor::Type type) {
+    const FieldDescriptor* field = GetFieldDescriptorOfType(type);
+    return field != NULL ? field->cpp_type_name() : "";
+  }
+
+  scoped_ptr<DescriptorPool> pool_;
 };
 
+TEST_F(MiscTest, TypeNames) {
+  // Test that correct type names are returned.
+
+  typedef FieldDescriptor FD;  // avoid ugly line wrapping
+
+  EXPECT_STREQ("double"  , GetTypeNameForFieldType(FD::TYPE_DOUBLE  ));
+  EXPECT_STREQ("float"   , GetTypeNameForFieldType(FD::TYPE_FLOAT   ));
+  EXPECT_STREQ("int64"   , GetTypeNameForFieldType(FD::TYPE_INT64   ));
+  EXPECT_STREQ("uint64"  , GetTypeNameForFieldType(FD::TYPE_UINT64  ));
+  EXPECT_STREQ("int32"   , GetTypeNameForFieldType(FD::TYPE_INT32   ));
+  EXPECT_STREQ("fixed64" , GetTypeNameForFieldType(FD::TYPE_FIXED64 ));
+  EXPECT_STREQ("fixed32" , GetTypeNameForFieldType(FD::TYPE_FIXED32 ));
+  EXPECT_STREQ("bool"    , GetTypeNameForFieldType(FD::TYPE_BOOL    ));
+  EXPECT_STREQ("string"  , GetTypeNameForFieldType(FD::TYPE_STRING  ));
+  EXPECT_STREQ("group"   , GetTypeNameForFieldType(FD::TYPE_GROUP   ));
+  EXPECT_STREQ("message" , GetTypeNameForFieldType(FD::TYPE_MESSAGE ));
+  EXPECT_STREQ("bytes"   , GetTypeNameForFieldType(FD::TYPE_BYTES   ));
+  EXPECT_STREQ("uint32"  , GetTypeNameForFieldType(FD::TYPE_UINT32  ));
+  EXPECT_STREQ("enum"    , GetTypeNameForFieldType(FD::TYPE_ENUM    ));
+  EXPECT_STREQ("sfixed32", GetTypeNameForFieldType(FD::TYPE_SFIXED32));
+  EXPECT_STREQ("sfixed64", GetTypeNameForFieldType(FD::TYPE_SFIXED64));
+  EXPECT_STREQ("sint32"  , GetTypeNameForFieldType(FD::TYPE_SINT32  ));
+  EXPECT_STREQ("sint64"  , GetTypeNameForFieldType(FD::TYPE_SINT64  ));
+}
+
 TEST_F(MiscTest, CppTypes) {
   // Test that CPP types are assigned correctly.
 
@@ -1576,6 +1620,31 @@
   EXPECT_EQ(FD::CPPTYPE_INT64  , GetCppTypeForFieldType(FD::TYPE_SINT64  ));
 }
 
+TEST_F(MiscTest, CppTypeNames) {
+  // Test that correct CPP type names are returned.
+
+  typedef FieldDescriptor FD;  // avoid ugly line wrapping
+
+  EXPECT_STREQ("double" , GetCppTypeNameForFieldType(FD::TYPE_DOUBLE  ));
+  EXPECT_STREQ("float"  , GetCppTypeNameForFieldType(FD::TYPE_FLOAT   ));
+  EXPECT_STREQ("int64"  , GetCppTypeNameForFieldType(FD::TYPE_INT64   ));
+  EXPECT_STREQ("uint64" , GetCppTypeNameForFieldType(FD::TYPE_UINT64  ));
+  EXPECT_STREQ("int32"  , GetCppTypeNameForFieldType(FD::TYPE_INT32   ));
+  EXPECT_STREQ("uint64" , GetCppTypeNameForFieldType(FD::TYPE_FIXED64 ));
+  EXPECT_STREQ("uint32" , GetCppTypeNameForFieldType(FD::TYPE_FIXED32 ));
+  EXPECT_STREQ("bool"   , GetCppTypeNameForFieldType(FD::TYPE_BOOL    ));
+  EXPECT_STREQ("string" , GetCppTypeNameForFieldType(FD::TYPE_STRING  ));
+  EXPECT_STREQ("message", GetCppTypeNameForFieldType(FD::TYPE_GROUP   ));
+  EXPECT_STREQ("message", GetCppTypeNameForFieldType(FD::TYPE_MESSAGE ));
+  EXPECT_STREQ("string" , GetCppTypeNameForFieldType(FD::TYPE_BYTES   ));
+  EXPECT_STREQ("uint32" , GetCppTypeNameForFieldType(FD::TYPE_UINT32  ));
+  EXPECT_STREQ("enum"   , GetCppTypeNameForFieldType(FD::TYPE_ENUM    ));
+  EXPECT_STREQ("int32"  , GetCppTypeNameForFieldType(FD::TYPE_SFIXED32));
+  EXPECT_STREQ("int64"  , GetCppTypeNameForFieldType(FD::TYPE_SFIXED64));
+  EXPECT_STREQ("int32"  , GetCppTypeNameForFieldType(FD::TYPE_SINT32  ));
+  EXPECT_STREQ("int64"  , GetCppTypeNameForFieldType(FD::TYPE_SINT64  ));
+}
+
 TEST_F(MiscTest, DefaultValues) {
   // Test that setting default values works.
   FileDescriptorProto file_proto;
@@ -1739,13 +1808,31 @@
 }
 
 // ===================================================================
+enum DescriptorPoolMode {
+  NO_DATABASE,
+  FALLBACK_DATABASE
+};
 
-class AllowUnknownDependenciesTest : public testing::Test {
+class AllowUnknownDependenciesTest
+    : public testing::TestWithParam<DescriptorPoolMode> {
  protected:
+  DescriptorPoolMode mode() {
+    return GetParam();
+   }
+
   virtual void SetUp() {
     FileDescriptorProto foo_proto, bar_proto;
 
-    pool_.AllowUnknownDependencies();
+    switch (mode()) {
+      case NO_DATABASE:
+        pool_.reset(new DescriptorPool);
+        break;
+      case FALLBACK_DATABASE:
+        pool_.reset(new DescriptorPool(&db_));
+        break;
+    }
+
+    pool_->AllowUnknownDependencies();
 
     ASSERT_TRUE(TextFormat::ParseFromString(
       "name: 'foo.proto'"
@@ -1776,13 +1863,13 @@
       &bar_proto));
 
     // Collect pointers to stuff.
-    bar_file_ = pool_.BuildFile(bar_proto);
+    bar_file_ = BuildFile(bar_proto);
     ASSERT_TRUE(bar_file_ != NULL);
 
     ASSERT_EQ(1, bar_file_->message_type_count());
     bar_type_ = bar_file_->message_type(0);
 
-    foo_file_ = pool_.BuildFile(foo_proto);
+    foo_file_ = BuildFile(foo_proto);
     ASSERT_TRUE(foo_file_ != NULL);
 
     ASSERT_EQ(1, foo_file_->message_type_count());
@@ -1794,6 +1881,20 @@
     qux_field_ = foo_type_->field(2);
   }
 
+  const FileDescriptor* BuildFile(const FileDescriptorProto& proto) {
+    switch (mode()) {
+      case NO_DATABASE:
+        return pool_->BuildFile(proto);
+        break;
+      case FALLBACK_DATABASE: {
+        EXPECT_TRUE(db_.Add(proto));
+        return pool_->FindFileByName(proto.name());
+      }
+    }
+    GOOGLE_LOG(FATAL) << "Can't get here.";
+    return NULL;
+  }
+
   const FileDescriptor* bar_file_;
   const Descriptor* bar_type_;
   const FileDescriptor* foo_file_;
@@ -1802,10 +1903,11 @@
   const FieldDescriptor* baz_field_;
   const FieldDescriptor* qux_field_;
 
-  DescriptorPool pool_;
+  SimpleDescriptorDatabase db_;        // used if in FALLBACK_DATABASE mode.
+  scoped_ptr<DescriptorPool> pool_;
 };
 
-TEST_F(AllowUnknownDependenciesTest, PlaceholderFile) {
+TEST_P(AllowUnknownDependenciesTest, PlaceholderFile) {
   ASSERT_EQ(2, foo_file_->dependency_count());
   EXPECT_EQ(bar_file_, foo_file_->dependency(0));
 
@@ -1814,11 +1916,11 @@
   EXPECT_EQ(0, baz_file->message_type_count());
 
   // Placeholder files should not be findable.
-  EXPECT_EQ(bar_file_, pool_.FindFileByName(bar_file_->name()));
-  EXPECT_TRUE(pool_.FindFileByName(baz_file->name()) == NULL);
+  EXPECT_EQ(bar_file_, pool_->FindFileByName(bar_file_->name()));
+  EXPECT_TRUE(pool_->FindFileByName(baz_file->name()) == NULL);
 }
 
-TEST_F(AllowUnknownDependenciesTest, PlaceholderTypes) {
+TEST_P(AllowUnknownDependenciesTest, PlaceholderTypes) {
   ASSERT_EQ(FieldDescriptor::TYPE_MESSAGE, bar_field_->type());
   EXPECT_EQ(bar_type_, bar_field_->message_type());
 
@@ -1836,12 +1938,12 @@
   EXPECT_EQ("corge.Qux.placeholder.proto", qux_type->file()->name());
 
   // Placeholder types should not be findable.
-  EXPECT_EQ(bar_type_, pool_.FindMessageTypeByName(bar_type_->full_name()));
-  EXPECT_TRUE(pool_.FindMessageTypeByName(baz_type->full_name()) == NULL);
-  EXPECT_TRUE(pool_.FindEnumTypeByName(qux_type->full_name()) == NULL);
+  EXPECT_EQ(bar_type_, pool_->FindMessageTypeByName(bar_type_->full_name()));
+  EXPECT_TRUE(pool_->FindMessageTypeByName(baz_type->full_name()) == NULL);
+  EXPECT_TRUE(pool_->FindEnumTypeByName(qux_type->full_name()) == NULL);
 }
 
-TEST_F(AllowUnknownDependenciesTest, CopyTo) {
+TEST_P(AllowUnknownDependenciesTest, CopyTo) {
   // FieldDescriptor::CopyTo() should write non-fully-qualified type names
   // for placeholder types which were not originally fully-qualified.
   FieldDescriptorProto proto;
@@ -1864,7 +1966,7 @@
   EXPECT_EQ(FieldDescriptorProto::TYPE_ENUM, proto.type());
 }
 
-TEST_F(AllowUnknownDependenciesTest, CustomOptions) {
+TEST_P(AllowUnknownDependenciesTest, CustomOptions) {
   // Qux should still have the uninterpreted option attached.
   ASSERT_EQ(1, qux_field_->options().uninterpreted_option_size());
   const UninterpretedOption& option =
@@ -1873,7 +1975,7 @@
   EXPECT_EQ("grault", option.name(0).name_part());
 }
 
-TEST_F(AllowUnknownDependenciesTest, UnknownExtendee) {
+TEST_P(AllowUnknownDependenciesTest, UnknownExtendee) {
   // Test that we can extend an unknown type.  This is slightly tricky because
   // it means that the placeholder type must have an extension range.
 
@@ -1884,7 +1986,7 @@
     "extension { extendee: 'UnknownType' name:'some_extension' number:123"
     "            label:LABEL_OPTIONAL type:TYPE_INT32 }",
     &extension_proto));
-  const FileDescriptor* file = pool_.BuildFile(extension_proto);
+  const FileDescriptor* file = BuildFile(extension_proto);
 
   ASSERT_TRUE(file != NULL);
 
@@ -1896,7 +1998,7 @@
   EXPECT_EQ(FieldDescriptor::kMaxNumber + 1, extendee->extension_range(0)->end);
 }
 
-TEST_F(AllowUnknownDependenciesTest, CustomOption) {
+TEST_P(AllowUnknownDependenciesTest, CustomOption) {
   // Test that we can use a custom option without having parsed
   // descriptor.proto.
 
@@ -1937,7 +2039,7 @@
     "}",
     &option_proto));
 
-  const FileDescriptor* file = pool_.BuildFile(option_proto);
+  const FileDescriptor* file = BuildFile(option_proto);
   ASSERT_TRUE(file != NULL);
 
   // Verify that no extension options were set, but they were left as
@@ -1949,6 +2051,81 @@
   EXPECT_EQ(2, file->options().uninterpreted_option_size());
 }
 
+TEST_P(AllowUnknownDependenciesTest,
+       UndeclaredDependencyTriggersBuildOfDependency) {
+  // Crazy case: suppose foo.proto refers to a symbol without declaring the
+  // dependency that finds it. In the event that the pool is backed by a
+  // DescriptorDatabase, the pool will attempt to find the symbol in the
+  // database. If successful, it will build the undeclared dependency to verify
+  // that the file does indeed contain the symbol. If that file fails to build,
+  // then its descriptors must be rolled back. However, we still want foo.proto
+  // to build successfully, since we are allowing unknown dependencies.
+
+  FileDescriptorProto undeclared_dep_proto;
+  // We make this file fail to build by giving it two fields with tag 1.
+  ASSERT_TRUE(TextFormat::ParseFromString(
+    "name: \"invalid_file_as_undeclared_dep.proto\" "
+    "package: \"undeclared\" "
+    "message_type: {  "
+    "  name: \"Quux\"  "
+    "  field { "
+    "    name:'qux' number:1 label:LABEL_OPTIONAL type: TYPE_INT32 "
+    "  }"
+    "  field { "
+    "    name:'quux' number:1 label:LABEL_OPTIONAL type: TYPE_INT64 "
+    "  }"
+    "}",
+    &undeclared_dep_proto));
+  // We can't use the BuildFile() helper because we don't actually want to build
+  // it into the descriptor pool in the fallback database case: it just needs to
+  // be sitting in the database so that it gets built during the building of
+  // test.proto below.
+  switch (mode()) {
+    case NO_DATABASE: {
+      ASSERT_TRUE(pool_->BuildFile(undeclared_dep_proto) == NULL);
+      break;
+    }
+    case FALLBACK_DATABASE: {
+      ASSERT_TRUE(db_.Add(undeclared_dep_proto));
+    }
+  }
+
+  FileDescriptorProto test_proto;
+  ASSERT_TRUE(TextFormat::ParseFromString(
+    "name: \"test.proto\" "
+    "message_type: { "
+    "  name: \"Corge\" "
+    "  field { "
+    "    name:'quux' number:1 label: LABEL_OPTIONAL "
+    "    type_name:'undeclared.Quux' type: TYPE_MESSAGE "
+    "  }"
+    "}",
+    &test_proto));
+
+  const FileDescriptor* file = BuildFile(test_proto);
+  ASSERT_TRUE(file != NULL);
+  GOOGLE_LOG(INFO) << file->DebugString();
+
+  EXPECT_EQ(0, file->dependency_count());
+  ASSERT_EQ(1, file->message_type_count());
+  const Descriptor* corge_desc = file->message_type(0);
+  ASSERT_EQ("Corge", corge_desc->name());
+  ASSERT_EQ(1, corge_desc->field_count());
+
+  const FieldDescriptor* quux_field = corge_desc->field(0);
+  ASSERT_EQ(FieldDescriptor::TYPE_MESSAGE, quux_field->type());
+  ASSERT_EQ("Quux", quux_field->message_type()->name());
+  ASSERT_EQ("undeclared.Quux", quux_field->message_type()->full_name());
+  EXPECT_EQ("undeclared.Quux.placeholder.proto",
+            quux_field->message_type()->file()->name());
+  // The place holder type should not be findable.
+  ASSERT_TRUE(pool_->FindMessageTypeByName("undeclared.Quux") == NULL);
+}
+
+INSTANTIATE_TEST_CASE_P(DatabaseSource,
+                        AllowUnknownDependenciesTest,
+                        testing::Values(NO_DATABASE, FALLBACK_DATABASE));
+
 // ===================================================================
 
 TEST(CustomOptions, OptionLocations) {
@@ -2451,6 +2628,15 @@
     "bar.proto: bar.proto: OTHER: Import \"foo.proto\" has not been loaded.\n");
 }
 
+TEST_F(ValidationErrorTest, InvalidPublicDependencyIndex) {
+  BuildFile("name: \"foo.proto\"");
+  BuildFileWithErrors(
+    "name: \"bar.proto\" "
+    "dependency: \"foo.proto\" "
+    "public_dependency: 1",
+    "bar.proto: bar.proto: OTHER: Invalid public dependency index.\n");
+}
+
 TEST_F(ValidationErrorTest, ForeignUnimportedPackageNoCrash) {
   // Used to crash:  If we depend on a non-existent file and then refer to a
   // package defined in a file that we didn't import, and that package is
@@ -2829,6 +3015,164 @@
       "necessary import.\n");
 }
 
+TEST_F(ValidationErrorTest, FieldTypeDefinedInIndirectDependency) {
+  // Test for hidden dependencies.
+  //
+  // // bar.proto
+  // message Bar{}
+  //
+  // // forward.proto
+  // import "bar.proto"
+  //
+  // // foo.proto
+  // import "forward.proto"
+  // message Foo {
+  //   optional Bar foo = 1;  // Error, needs to import bar.proto explicitly.
+  // }
+  //
+  BuildFile(
+    "name: \"bar.proto\" "
+    "message_type { name: \"Bar\" }");
+
+  BuildFile(
+    "name: \"forward.proto\""
+    "dependency: \"bar.proto\"");
+
+  BuildFileWithErrors(
+    "name: \"foo.proto\" "
+    "dependency: \"forward.proto\" "
+    "message_type {"
+    "  name: \"Foo\""
+    "  field { name:\"foo\" number:1 label:LABEL_OPTIONAL type_name:\"Bar\" }"
+    "}",
+    "foo.proto: Foo.foo: TYPE: \"Bar\" seems to be defined in \"bar.proto\", "
+      "which is not imported by \"foo.proto\".  To use it here, please add the "
+      "necessary import.\n");
+}
+
+TEST_F(ValidationErrorTest, FieldTypeDefinedInPublicDependency) {
+  // Test for public dependencies.
+  //
+  // // bar.proto
+  // message Bar{}
+  //
+  // // forward.proto
+  // import public "bar.proto"
+  //
+  // // foo.proto
+  // import "forward.proto"
+  // message Foo {
+  //   optional Bar foo = 1;  // Correct. "bar.proto" is public imported into
+  //                          // forward.proto, so when "foo.proto" imports
+  //                          // "forward.proto", it imports "bar.proto" too.
+  // }
+  //
+  BuildFile(
+    "name: \"bar.proto\" "
+    "message_type { name: \"Bar\" }");
+
+  BuildFile(
+    "name: \"forward.proto\""
+    "dependency: \"bar.proto\" "
+    "public_dependency: 0");
+
+  BuildFile(
+    "name: \"foo.proto\" "
+    "dependency: \"forward.proto\" "
+    "message_type {"
+    "  name: \"Foo\""
+    "  field { name:\"foo\" number:1 label:LABEL_OPTIONAL type_name:\"Bar\" }"
+    "}");
+}
+
+TEST_F(ValidationErrorTest, FieldTypeDefinedInTransitivePublicDependency) {
+  // Test for public dependencies.
+  //
+  // // bar.proto
+  // message Bar{}
+  //
+  // // forward.proto
+  // import public "bar.proto"
+  //
+  // // forward2.proto
+  // import public "forward.proto"
+  //
+  // // foo.proto
+  // import "forward2.proto"
+  // message Foo {
+  //   optional Bar foo = 1;  // Correct, public imports are transitive.
+  // }
+  //
+  BuildFile(
+    "name: \"bar.proto\" "
+    "message_type { name: \"Bar\" }");
+
+  BuildFile(
+    "name: \"forward.proto\""
+    "dependency: \"bar.proto\" "
+    "public_dependency: 0");
+
+  BuildFile(
+    "name: \"forward2.proto\""
+    "dependency: \"forward.proto\" "
+    "public_dependency: 0");
+
+  BuildFile(
+    "name: \"foo.proto\" "
+    "dependency: \"forward2.proto\" "
+    "message_type {"
+    "  name: \"Foo\""
+    "  field { name:\"foo\" number:1 label:LABEL_OPTIONAL type_name:\"Bar\" }"
+    "}");
+}
+
+TEST_F(ValidationErrorTest,
+       FieldTypeDefinedInPrivateDependencyOfPublicDependency) {
+  // Test for public dependencies.
+  //
+  // // bar.proto
+  // message Bar{}
+  //
+  // // forward.proto
+  // import "bar.proto"
+  //
+  // // forward2.proto
+  // import public "forward.proto"
+  //
+  // // foo.proto
+  // import "forward2.proto"
+  // message Foo {
+  //   optional Bar foo = 1;  // Error, the "bar.proto" is not public imported
+  //                          // into "forward.proto", so will not be imported
+  //                          // into either "forward2.proto" or "foo.proto".
+  // }
+  //
+  BuildFile(
+    "name: \"bar.proto\" "
+    "message_type { name: \"Bar\" }");
+
+  BuildFile(
+    "name: \"forward.proto\""
+    "dependency: \"bar.proto\"");
+
+  BuildFile(
+    "name: \"forward2.proto\""
+    "dependency: \"forward.proto\" "
+    "public_dependency: 0");
+
+  BuildFileWithErrors(
+    "name: \"foo.proto\" "
+    "dependency: \"forward2.proto\" "
+    "message_type {"
+    "  name: \"Foo\""
+    "  field { name:\"foo\" number:1 label:LABEL_OPTIONAL type_name:\"Bar\" }"
+    "}",
+    "foo.proto: Foo.foo: TYPE: \"Bar\" seems to be defined in \"bar.proto\", "
+      "which is not imported by \"foo.proto\".  To use it here, please add the "
+      "necessary import.\n");
+}
+
+
 TEST_F(ValidationErrorTest, SearchMostLocalFirst) {
   // The following should produce an error that Bar.Baz is not defined:
   //   message Bar { message Baz {} }
@@ -3031,7 +3375,8 @@
     "  method { name: \"A\" input_type: \"Bar\" output_type: \"Foo\" }"
     "}",
 
-    "foo.proto: TestService.A: INPUT_TYPE: \"Bar\" is not defined.\n");
+    "foo.proto: TestService.A: INPUT_TYPE: \"Bar\" is not defined.\n"
+    );
 }
 
 TEST_F(ValidationErrorTest, InputTypeNotAMessage) {
@@ -3044,7 +3389,8 @@
     "  method { name: \"A\" input_type: \"Bar\" output_type: \"Foo\" }"
     "}",
 
-    "foo.proto: TestService.A: INPUT_TYPE: \"Bar\" is not a message type.\n");
+    "foo.proto: TestService.A: INPUT_TYPE: \"Bar\" is not a message type.\n"
+    );
 }
 
 TEST_F(ValidationErrorTest, OutputTypeNotDefined) {
@@ -3056,7 +3402,8 @@
     "  method { name: \"A\" input_type: \"Foo\" output_type: \"Bar\" }"
     "}",
 
-    "foo.proto: TestService.A: OUTPUT_TYPE: \"Bar\" is not defined.\n");
+    "foo.proto: TestService.A: OUTPUT_TYPE: \"Bar\" is not defined.\n"
+    );
 }
 
 TEST_F(ValidationErrorTest, OutputTypeNotAMessage) {
@@ -3069,9 +3416,11 @@
     "  method { name: \"A\" input_type: \"Foo\" output_type: \"Bar\" }"
     "}",
 
-    "foo.proto: TestService.A: OUTPUT_TYPE: \"Bar\" is not a message type.\n");
+    "foo.proto: TestService.A: OUTPUT_TYPE: \"Bar\" is not a message type.\n"
+    );
 }
 
+
 TEST_F(ValidationErrorTest, IllegalPackedField) {
   BuildFileWithErrors(
     "name: \"foo.proto\" "
@@ -3592,7 +3941,8 @@
     "  }"
     "}",
 
-    "foo.proto: TestService.Baz: INPUT_TYPE: \"NoSuchType\" is not defined.\n");
+    "foo.proto: TestService.Baz: INPUT_TYPE: \"NoSuchType\" is not defined.\n"
+    );
 
   // Make sure that if we build the same file again with the error fixed,
   // it works.  If the above rollback was incomplete, then some symbols will
@@ -3641,6 +3991,19 @@
   EXPECT_EQ("  Foo: \"Foo\" is already defined.", errors[1]);
 }
 
+TEST_F(ValidationErrorTest, DisallowEnumAlias) {
+  BuildFileWithErrors(
+    "name: \"foo.proto\" "
+    "enum_type {"
+    "  name: \"Bar\""
+    "  value { name:\"ENUM_A\" number:0 }"
+    "  value { name:\"ENUM_B\" number:0 }"
+    "  options { allow_alias: false }"
+    "}",
+    "foo.proto: Bar: NUMBER: "
+    "\"ENUM_B\" uses the same enum value as \"ENUM_A\"\n");
+}
+
 // ===================================================================
 // DescriptorDatabase
 
@@ -3659,16 +4022,23 @@
 
   virtual void SetUp() {
     AddToDatabase(&database_,
-      "name: \"foo.proto\" "
-      "message_type { name:\"Foo\" extension_range { start: 1 end: 100 } } "
-      "enum_type { name:\"TestEnum\" value { name:\"DUMMY\" number:0 } } "
-      "service { name:\"TestService\" } ");
+      "name: 'foo.proto' "
+      "message_type { name:'Foo' extension_range { start: 1 end: 100 } } "
+      "enum_type { name:'TestEnum' value { name:'DUMMY' number:0 } } "
+      "service { name:'TestService' } ");
     AddToDatabase(&database_,
-      "name: \"bar.proto\" "
-      "dependency: \"foo.proto\" "
-      "message_type { name:\"Bar\" } "
-      "extension { name:\"foo_ext\" extendee: \".Foo\" number:5 "
+      "name: 'bar.proto' "
+      "dependency: 'foo.proto' "
+      "message_type { name:'Bar' } "
+      "extension { name:'foo_ext' extendee: '.Foo' number:5 "
       "            label:LABEL_OPTIONAL type:TYPE_INT32 } ");
+    // Baz has an undeclared dependency on Foo.
+    AddToDatabase(&database_,
+      "name: 'baz.proto' "
+      "message_type { "
+      "  name:'Baz' "
+      "  field { name:'foo' number:1 label:LABEL_OPTIONAL type_name:'Foo' } "
+      "}");
   }
 
   // We can't inject a file containing errors into a DescriptorPool, so we
@@ -3907,6 +4277,33 @@
     error_collector.text_);
 }
 
+TEST_F(DatabaseBackedPoolTest, UndeclaredDependencyOnUnbuiltType) {
+  // Check that we find and report undeclared dependencies on types that exist
+  // in the descriptor database but that have not not been built yet.
+  MockErrorCollector error_collector;
+  DescriptorPool pool(&database_, &error_collector);
+  EXPECT_TRUE(pool.FindMessageTypeByName("Baz") == NULL);
+  EXPECT_EQ(
+    "baz.proto: Baz.foo: TYPE: \"Foo\" seems to be defined in \"foo.proto\", "
+    "which is not imported by \"baz.proto\".  To use it here, please add "
+    "the necessary import.\n",
+    error_collector.text_);
+}
+
+TEST_F(DatabaseBackedPoolTest, RollbackAfterError) {
+  // Make sure that all traces of bad types are removed from the pool. This used
+  // to be b/4529436, due to the fact that a symbol resolution failure could
+  // potentially cause another file to be recursively built, which would trigger
+  // a checkpoint _past_ possibly invalid symbols.
+  // Baz is defined in the database, but the file is invalid because it is
+  // missing a necessary import.
+  DescriptorPool pool(&database_);
+  EXPECT_TRUE(pool.FindMessageTypeByName("Baz") == NULL);
+  // Make sure that searching again for the file or the type fails.
+  EXPECT_TRUE(pool.FindFileByName("baz.proto") == NULL);
+  EXPECT_TRUE(pool.FindMessageTypeByName("Baz") == NULL);
+}
+
 TEST_F(DatabaseBackedPoolTest, UnittestProto) {
   // Try to load all of unittest.proto from a DescriptorDatabase.  This should
   // thoroughly test all paths through DescriptorBuilder to insure that there
@@ -3963,6 +4360,16 @@
   EXPECT_TRUE(file->FindEnumValueByName("NO_SUCH_VALUE") == NULL);
   EXPECT_TRUE(file->FindServiceByName("NO_SUCH_VALUE") == NULL);
   EXPECT_TRUE(file->FindExtensionByName("no_such_extension") == NULL);
+
+  EXPECT_TRUE(pool.FindFileContainingSymbol("Foo.no.such.field") == NULL);
+  EXPECT_TRUE(pool.FindFileContainingSymbol("Foo.no_such_field") == NULL);
+  EXPECT_TRUE(pool.FindMessageTypeByName("Foo.NoSuchMessageType") == NULL);
+  EXPECT_TRUE(pool.FindFieldByName("Foo.no_such_field") == NULL);
+  EXPECT_TRUE(pool.FindExtensionByName("Foo.no_such_extension") == NULL);
+  EXPECT_TRUE(pool.FindEnumTypeByName("Foo.NoSuchEnumType") == NULL);
+  EXPECT_TRUE(pool.FindEnumValueByName("Foo.NO_SUCH_VALUE") == NULL);
+  EXPECT_TRUE(pool.FindMethodByName("TestService.NoSuchMethod") == NULL);
+
   EXPECT_EQ(0, call_counter.call_count_);
 }
 
@@ -4028,6 +4435,219 @@
 
 // ===================================================================
 
+class AbortingErrorCollector : public DescriptorPool::ErrorCollector {
+ public:
+  AbortingErrorCollector() {}
+
+  virtual void AddError(
+      const string &filename,
+      const string &element_name,
+      const Message *message,
+      ErrorLocation location,
+      const string &error_message) {
+    GOOGLE_LOG(FATAL) << "AddError() called unexpectedly: " << filename << ": "
+               << error_message;
+  }
+ private:
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(AbortingErrorCollector);
+};
+
+// A source tree containing only one file.
+class SingletonSourceTree : public compiler::SourceTree {
+ public:
+  SingletonSourceTree(const string& filename, const string& contents)
+      : filename_(filename), contents_(contents) {}
+
+  virtual io::ZeroCopyInputStream* Open(const string& filename) {
+    return filename == filename_ ?
+        new io::ArrayInputStream(contents_.data(), contents_.size()) : NULL;
+  }
+
+ private:
+  const string filename_;
+  const string contents_;
+
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(SingletonSourceTree);
+};
+
+const char *const kSourceLocationTestInput =
+  "syntax = \"proto2\";\n"
+  "message A {\n"
+  "  optional int32 a = 1;\n"
+  "  message B {\n"
+  "    required double b = 1;\n"
+  "  }\n"
+  "}\n"
+  "enum Indecision {\n"
+  "  YES   = 1;\n"
+  "  NO    = 2;\n"
+  "  MAYBE = 3;\n"
+  "}\n"
+  "service S {\n"
+  "  rpc Method(A) returns (A.B);\n"
+  // Put an empty line here to make the source location range match.
+  "\n"
+  "}\n";
+
+class SourceLocationTest : public testing::Test {
+ public:
+  SourceLocationTest()
+      : source_tree_("/test/test.proto", kSourceLocationTestInput),
+        db_(&source_tree_),
+        pool_(&db_, &collector_) {}
+
+  static string PrintSourceLocation(const SourceLocation &loc) {
+    return strings::Substitute("$0:$1-$2:$3",
+                               1 + loc.start_line,
+                               1 + loc.start_column,
+                               1 + loc.end_line,
+                               1 + loc.end_column);
+  }
+
+ private:
+  AbortingErrorCollector collector_;
+  SingletonSourceTree source_tree_;
+  compiler::SourceTreeDescriptorDatabase db_;
+
+ protected:
+  DescriptorPool pool_;
+};
+
+// TODO(adonovan): implement support for option fields and for
+// subparts of declarations.
+
+TEST_F(SourceLocationTest, GetSourceLocation) {
+  SourceLocation loc;
+
+  const FileDescriptor *file_desc =
+      GOOGLE_CHECK_NOTNULL(pool_.FindFileByName("/test/test.proto"));
+
+  const Descriptor *a_desc = file_desc->FindMessageTypeByName("A");
+  EXPECT_TRUE(a_desc->GetSourceLocation(&loc));
+  EXPECT_EQ("2:1-7:2", PrintSourceLocation(loc));
+
+  const Descriptor *a_b_desc = a_desc->FindNestedTypeByName("B");
+  EXPECT_TRUE(a_b_desc->GetSourceLocation(&loc));
+  EXPECT_EQ("4:3-6:4", PrintSourceLocation(loc));
+
+  const EnumDescriptor *e_desc = file_desc->FindEnumTypeByName("Indecision");
+  EXPECT_TRUE(e_desc->GetSourceLocation(&loc));
+  EXPECT_EQ("8:1-12:2", PrintSourceLocation(loc));
+
+  const EnumValueDescriptor *yes_desc = e_desc->FindValueByName("YES");
+  EXPECT_TRUE(yes_desc->GetSourceLocation(&loc));
+  EXPECT_EQ("9:3-9:13", PrintSourceLocation(loc));
+
+  const ServiceDescriptor *s_desc = file_desc->FindServiceByName("S");
+  EXPECT_TRUE(s_desc->GetSourceLocation(&loc));
+  EXPECT_EQ("13:1-16:2", PrintSourceLocation(loc));
+
+  const MethodDescriptor *m_desc = s_desc->FindMethodByName("Method");
+  EXPECT_TRUE(m_desc->GetSourceLocation(&loc));
+  EXPECT_EQ("14:3-14:31", PrintSourceLocation(loc));
+
+}
+
+// Missing SourceCodeInfo doesn't cause crash:
+TEST_F(SourceLocationTest, GetSourceLocation_MissingSourceCodeInfo) {
+  SourceLocation loc;
+
+  const FileDescriptor *file_desc =
+      GOOGLE_CHECK_NOTNULL(pool_.FindFileByName("/test/test.proto"));
+
+  FileDescriptorProto proto;
+  file_desc->CopyTo(&proto);  // Note, this discards the SourceCodeInfo.
+  EXPECT_FALSE(proto.has_source_code_info());
+
+  DescriptorPool bad1_pool(&pool_);
+  const FileDescriptor* bad1_file_desc =
+      GOOGLE_CHECK_NOTNULL(bad1_pool.BuildFile(proto));
+  const Descriptor *bad1_a_desc = bad1_file_desc->FindMessageTypeByName("A");
+  EXPECT_FALSE(bad1_a_desc->GetSourceLocation(&loc));
+}
+
+// Corrupt SourceCodeInfo doesn't cause crash:
+TEST_F(SourceLocationTest, GetSourceLocation_BogusSourceCodeInfo) {
+  SourceLocation loc;
+
+  const FileDescriptor *file_desc =
+      GOOGLE_CHECK_NOTNULL(pool_.FindFileByName("/test/test.proto"));
+
+  FileDescriptorProto proto;
+  file_desc->CopyTo(&proto);  // Note, this discards the SourceCodeInfo.
+  EXPECT_FALSE(proto.has_source_code_info());
+  SourceCodeInfo_Location *loc_msg =
+      proto.mutable_source_code_info()->add_location();
+  loc_msg->add_path(1);
+  loc_msg->add_path(2);
+  loc_msg->add_path(3);
+  loc_msg->add_span(4);
+  loc_msg->add_span(5);
+  loc_msg->add_span(6);
+
+  DescriptorPool bad2_pool(&pool_);
+  const FileDescriptor* bad2_file_desc =
+      GOOGLE_CHECK_NOTNULL(bad2_pool.BuildFile(proto));
+  const Descriptor *bad2_a_desc = bad2_file_desc->FindMessageTypeByName("A");
+  EXPECT_FALSE(bad2_a_desc->GetSourceLocation(&loc));
+}
+
+// ===================================================================
+
+const char* const kCopySourceCodeInfoToTestInput =
+  "syntax = \"proto2\";\n"
+  "message Foo {}\n";
+
+// Required since source code information is not preserved by
+// FileDescriptorTest.
+class CopySourceCodeInfoToTest : public testing::Test {
+ public:
+  CopySourceCodeInfoToTest()
+      : source_tree_("/test/test.proto", kCopySourceCodeInfoToTestInput),
+        db_(&source_tree_),
+        pool_(&db_, &collector_) {}
+
+ private:
+  AbortingErrorCollector collector_;
+  SingletonSourceTree source_tree_;
+  compiler::SourceTreeDescriptorDatabase db_;
+
+ protected:
+  DescriptorPool pool_;
+};
+
+TEST_F(CopySourceCodeInfoToTest, CopyTo_DoesNotCopySourceCodeInfo) {
+  const FileDescriptor* file_desc =
+      GOOGLE_CHECK_NOTNULL(pool_.FindFileByName("/test/test.proto"));
+  FileDescriptorProto file_desc_proto;
+  ASSERT_FALSE(file_desc_proto.has_source_code_info());
+
+  file_desc->CopyTo(&file_desc_proto);
+  EXPECT_FALSE(file_desc_proto.has_source_code_info());
+}
+
+TEST_F(CopySourceCodeInfoToTest, CopySourceCodeInfoTo) {
+  const FileDescriptor* file_desc =
+      GOOGLE_CHECK_NOTNULL(pool_.FindFileByName("/test/test.proto"));
+  FileDescriptorProto file_desc_proto;
+  ASSERT_FALSE(file_desc_proto.has_source_code_info());
+
+  file_desc->CopySourceCodeInfoTo(&file_desc_proto);
+  const SourceCodeInfo& info = file_desc_proto.source_code_info();
+  ASSERT_EQ(3, info.location_size());
+  // Get the Foo message location
+  const SourceCodeInfo_Location& foo_location = info.location(1);
+  ASSERT_EQ(2, foo_location.path_size());
+  EXPECT_EQ(FileDescriptorProto::kMessageTypeFieldNumber, foo_location.path(0));
+  EXPECT_EQ(0, foo_location.path(1));      // Foo is the first message defined
+  ASSERT_EQ(3, foo_location.span_size());  // Foo spans one line
+  EXPECT_EQ(1, foo_location.span(0));      // Foo is declared on line 1
+  EXPECT_EQ(0, foo_location.span(1));      // Foo starts at column 0
+  EXPECT_EQ(14, foo_location.span(2));     // Foo ends on column 14
+}
+
+// ===================================================================
+
 
 }  // namespace descriptor_unittest
 }  // namespace protobuf
diff --git a/third_party/protobuf/src/google/protobuf/dynamic_message.cc b/third_party/protobuf/src/google/protobuf/dynamic_message.cc
index c711a2d..e4bebb2 100644
--- a/third_party/protobuf/src/google/protobuf/dynamic_message.cc
+++ b/third_party/protobuf/src/google/protobuf/dynamic_message.cc
@@ -123,7 +123,9 @@
       case FD::CPPTYPE_FLOAT  : return sizeof(float   );
       case FD::CPPTYPE_BOOL   : return sizeof(bool    );
       case FD::CPPTYPE_ENUM   : return sizeof(int     );
-      case FD::CPPTYPE_MESSAGE: return sizeof(Message*);
+
+      case FD::CPPTYPE_MESSAGE:
+        return sizeof(Message*);
 
       case FD::CPPTYPE_STRING:
         switch (field->options().ctype()) {
@@ -178,7 +180,17 @@
     //   important (the prototype must be deleted *before* the offsets).
     scoped_array<int> offsets;
     scoped_ptr<const GeneratedMessageReflection> reflection;
-    scoped_ptr<const DynamicMessage> prototype;
+    // Don't use a scoped_ptr to hold the prototype: the destructor for
+    // DynamicMessage needs to know whether it is the prototype, and does so by
+    // looking back at this field. This would assume details about the
+    // implementation of scoped_ptr.
+    const DynamicMessage* prototype;
+
+    TypeInfo() : prototype(NULL) {}
+
+    ~TypeInfo() {
+      delete prototype;
+    }
   };
 
   DynamicMessage(const TypeInfo* type_info);
@@ -196,6 +208,14 @@
 
   Metadata GetMetadata() const;
 
+  // We actually allocate more memory than sizeof(*this) when this
+  // class's memory is allocated via the global operator new. Thus, we need to
+  // manually call the global operator delete. Calling the destructor is taken
+  // care of for us.
+  static void operator delete(void* ptr) {
+    ::operator delete(ptr);
+  }
+
  private:
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(DynamicMessage);
 
@@ -368,11 +388,12 @@
           break;
         }
       }
-    } else if ((field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) &&
-               !is_prototype()) {
-      Message* message = *reinterpret_cast<Message**>(field_ptr);
-      if (message != NULL) {
-        delete message;
+    } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
+      if (!is_prototype()) {
+        Message* message = *reinterpret_cast<Message**>(field_ptr);
+        if (message != NULL) {
+          delete message;
+        }
       }
     }
   }
@@ -403,7 +424,7 @@
 }
 
 Message* DynamicMessage::New() const {
-  void* new_base = reinterpret_cast<uint8*>(operator new(type_info_->size));
+  void* new_base = operator new(type_info_->size);
   memset(new_base, 0, type_info_->size);
   return new(new_base) DynamicMessage(type_info_);
 }
@@ -465,7 +486,7 @@
   const DynamicMessage::TypeInfo** target = &prototypes_->map_[type];
   if (*target != NULL) {
     // Already exists.
-    return (*target)->prototype.get();
+    return (*target)->prototype;
   }
 
   DynamicMessage::TypeInfo* type_info = new DynamicMessage::TypeInfo;
@@ -533,13 +554,13 @@
   void* base = operator new(size);
   memset(base, 0, size);
   DynamicMessage* prototype = new(base) DynamicMessage(type_info);
-  type_info->prototype.reset(prototype);
+  type_info->prototype = prototype;
 
   // Construct the reflection object.
   type_info->reflection.reset(
     new GeneratedMessageReflection(
       type_info->type,
-      type_info->prototype.get(),
+      type_info->prototype,
       type_info->offsets.get(),
       type_info->has_bits_offset,
       type_info->unknown_fields_offset,
diff --git a/third_party/protobuf/src/google/protobuf/dynamic_message.h b/third_party/protobuf/src/google/protobuf/dynamic_message.h
index 81dd2c6..b3d1e5d 100644
--- a/third_party/protobuf/src/google/protobuf/dynamic_message.h
+++ b/third_party/protobuf/src/google/protobuf/dynamic_message.h
@@ -68,7 +68,7 @@
 class LIBPROTOBUF_EXPORT DynamicMessageFactory : public MessageFactory {
  public:
   // Construct a DynamicMessageFactory that will search for extensions in
-  // the DescriptorPool in which the exendee is defined.
+  // the DescriptorPool in which the extendee is defined.
   DynamicMessageFactory();
 
   // Construct a DynamicMessageFactory that will search for extensions in
@@ -102,7 +102,7 @@
   // object.  The returned object remains property of the factory and will
   // be destroyed when the factory is destroyed.  Also, any objects created
   // by calling the prototype's New() method share some data with the
-  // prototype, so these must be destoyed before the DynamicMessageFactory
+  // prototype, so these must be destroyed before the DynamicMessageFactory
   // is destroyed.
   //
   // The given descriptor must outlive the returned message, and hence must
diff --git a/third_party/protobuf/src/google/protobuf/dynamic_message_unittest.cc b/third_party/protobuf/src/google/protobuf/dynamic_message_unittest.cc
index 41b89ab..e461597 100644
--- a/third_party/protobuf/src/google/protobuf/dynamic_message_unittest.cc
+++ b/third_party/protobuf/src/google/protobuf/dynamic_message_unittest.cc
@@ -73,11 +73,15 @@
     // unittest_import.proto.
     FileDescriptorProto unittest_file;
     FileDescriptorProto unittest_import_file;
+    FileDescriptorProto unittest_import_public_file;
 
     unittest::TestAllTypes::descriptor()->file()->CopyTo(&unittest_file);
     unittest_import::ImportMessage::descriptor()->file()->CopyTo(
       &unittest_import_file);
+    unittest_import::PublicImportMessage::descriptor()->file()->CopyTo(
+      &unittest_import_public_file);
 
+    ASSERT_TRUE(pool_.BuildFile(unittest_import_public_file) != NULL);
     ASSERT_TRUE(pool_.BuildFile(unittest_import_file) != NULL);
     ASSERT_TRUE(pool_.BuildFile(unittest_file) != NULL);
 
diff --git a/third_party/protobuf/src/google/protobuf/extension_set.cc b/third_party/protobuf/src/google/protobuf/extension_set.cc
index dbb0915..418e068 100644
--- a/third_party/protobuf/src/google/protobuf/extension_set.cc
+++ b/third_party/protobuf/src/google/protobuf/extension_set.cc
@@ -71,7 +71,7 @@
 
 void InitRegistry() {
   registry_ = new ExtensionRegistry;
-  internal::OnShutdown(&DeleteRegistry);
+  OnShutdown(&DeleteRegistry);
 }
 
 // This function is only called at startup, so there is no need for thread-
@@ -180,6 +180,17 @@
   return !iter->second.is_cleared;
 }
 
+int ExtensionSet::NumExtensions() const {
+  int result = 0;
+  for (map<int, Extension>::const_iterator iter = extensions_.begin();
+       iter != extensions_.end(); ++iter) {
+    if (!iter->second.is_cleared) {
+      ++result;
+    }
+  }
+  return result;
+}
+
 int ExtensionSet::ExtensionSize(int number) const {
   map<int, Extension>::const_iterator iter = extensions_.find(number);
   if (iter == extensions_.end()) return false;
@@ -293,6 +304,14 @@
 
 #undef PRIMITIVE_ACCESSORS
 
+void* ExtensionSet::MutableRawRepeatedField(int number) {
+  // We assume that all the RepeatedField<>* pointers have the same
+  // size and alignment within the anonymous union in Extension.
+  map<int, Extension>::const_iterator iter = extensions_.find(number);
+  GOOGLE_CHECK(iter != extensions_.end()) << "no extension numbered " << number;
+  return iter->second.repeated_int32_value;
+}
+
 // -------------------------------------------------------------------
 // Enums
 
@@ -422,7 +441,11 @@
     return default_value;
   } else {
     GOOGLE_DCHECK_TYPE(iter->second, OPTIONAL, MESSAGE);
-    return *iter->second.message_value;
+    if (iter->second.is_lazy) {
+      return iter->second.lazymessage_value->GetMessage(default_value);
+    } else {
+      return *iter->second.message_value;
+    }
   }
 }
 
@@ -439,12 +462,19 @@
     extension->type = type;
     GOOGLE_DCHECK_EQ(cpp_type(extension->type), WireFormatLite::CPPTYPE_MESSAGE);
     extension->is_repeated = false;
+    extension->is_lazy = false;
     extension->message_value = prototype.New();
+    extension->is_cleared = false;
+    return extension->message_value;
   } else {
     GOOGLE_DCHECK_TYPE(*extension, OPTIONAL, MESSAGE);
+    extension->is_cleared = false;
+    if (extension->is_lazy) {
+      return extension->lazymessage_value->MutableMessage(prototype);
+    } else {
+      return extension->message_value;
+    }
   }
-  extension->is_cleared = false;
-  return extension->message_value;
 }
 
 // Defined in extension_set_heavy.cc.
@@ -452,6 +482,56 @@
 //                                           const Descriptor* message_type,
 //                                           MessageFactory* factory)
 
+void ExtensionSet::SetAllocatedMessage(int number, FieldType type,
+                                       const FieldDescriptor* descriptor,
+                                       MessageLite* message) {
+  if (message == NULL) {
+    ClearExtension(number);
+    return;
+  }
+  Extension* extension;
+  if (MaybeNewExtension(number, descriptor, &extension)) {
+    extension->type = type;
+    GOOGLE_DCHECK_EQ(cpp_type(extension->type), WireFormatLite::CPPTYPE_MESSAGE);
+    extension->is_repeated = false;
+    extension->is_lazy = false;
+    extension->message_value = message;
+  } else {
+    GOOGLE_DCHECK_TYPE(*extension, OPTIONAL, MESSAGE);
+    if (extension->is_lazy) {
+      extension->lazymessage_value->SetAllocatedMessage(message);
+    } else {
+      delete extension->message_value;
+      extension->message_value = message;
+    }
+  }
+  extension->is_cleared = false;
+}
+
+MessageLite* ExtensionSet::ReleaseMessage(int number,
+                                          const MessageLite& prototype) {
+  map<int, Extension>::iterator iter = extensions_.find(number);
+  if (iter == extensions_.end()) {
+    // Not present.  Return NULL.
+    return NULL;
+  } else {
+    GOOGLE_DCHECK_TYPE(iter->second, OPTIONAL, MESSAGE);
+    MessageLite* ret = NULL;
+    if (iter->second.is_lazy) {
+      ret = iter->second.lazymessage_value->ReleaseMessage(prototype);
+      delete iter->second.lazymessage_value;
+    } else {
+      ret = iter->second.message_value;
+    }
+    extensions_.erase(number);
+    return ret;
+  }
+}
+
+// Defined in extension_set_heavy.cc.
+// MessageLite* ExtensionSet::ReleaseMessage(const FieldDescriptor* descriptor,
+//                                           MessageFactory* factory);
+
 const MessageLite& ExtensionSet::GetRepeatedMessage(
     int number, int index) const {
   map<int, Extension>::const_iterator iter = extensions_.find(number);
@@ -484,7 +564,7 @@
   // RepeatedPtrField<MessageLite> does not know how to Add() since it cannot
   // allocate an abstract object, so we have to be tricky.
   MessageLite* result = extension->repeated_message_value
-      ->AddFromCleared<internal::GenericTypeHandler<MessageLite> >();
+      ->AddFromCleared<GenericTypeHandler<MessageLite> >();
   if (result == NULL) {
     result = prototype.New();
     extension->repeated_message_value->AddAllocated(result);
@@ -540,6 +620,16 @@
   }
 }
 
+MessageLite* ExtensionSet::ReleaseLast(int number) {
+  map<int, Extension>::iterator iter = extensions_.find(number);
+  GOOGLE_CHECK(iter != extensions_.end()) << "Index out-of-bounds (field is empty).";
+
+  Extension* extension = &iter->second;
+  GOOGLE_DCHECK(extension->is_repeated);
+  GOOGLE_DCHECK(cpp_type(extension->type) == WireFormatLite::CPPTYPE_MESSAGE);
+  return extension->repeated_message_value->ReleaseLast();
+}
+
 void ExtensionSet::SwapElements(int number, int index1, int index2) {
   map<int, Extension>::iterator iter = extensions_.find(number);
   GOOGLE_CHECK(iter != extensions_.end()) << "Index out-of-bounds (field is empty).";
@@ -602,9 +692,11 @@
       if (is_new) {
         // Extension did not already exist in set.
         extension->type = other_extension.type;
+        extension->is_packed = other_extension.is_packed;
         extension->is_repeated = true;
       } else {
         GOOGLE_DCHECK_EQ(extension->type, other_extension.type);
+        GOOGLE_DCHECK_EQ(extension->is_packed, other_extension.is_packed);
         GOOGLE_DCHECK(extension->is_repeated);
       }
 
@@ -675,12 +767,55 @@
                       *other_extension.string_value,
                       other_extension.descriptor);
             break;
-          case WireFormatLite::CPPTYPE_MESSAGE:
-            MutableMessage(iter->first, other_extension.type,
-                           *other_extension.message_value,
-                           other_extension.descriptor)
-              ->CheckTypeAndMergeFrom(*other_extension.message_value);
+          case WireFormatLite::CPPTYPE_MESSAGE: {
+            Extension* extension;
+            bool is_new = MaybeNewExtension(iter->first,
+                                            other_extension.descriptor,
+                                            &extension);
+            if (is_new) {
+              extension->type = other_extension.type;
+              extension->is_packed = other_extension.is_packed;
+              extension->is_repeated = false;
+              if (other_extension.is_lazy) {
+                extension->is_lazy = true;
+                extension->lazymessage_value =
+                    other_extension.lazymessage_value->New();
+                extension->lazymessage_value->MergeFrom(
+                    *other_extension.lazymessage_value);
+              } else {
+                extension->is_lazy = false;
+                extension->message_value =
+                    other_extension.message_value->New();
+                extension->message_value->CheckTypeAndMergeFrom(
+                    *other_extension.message_value);
+              }
+            } else {
+              GOOGLE_DCHECK_EQ(extension->type, other_extension.type);
+              GOOGLE_DCHECK_EQ(extension->is_packed,other_extension.is_packed);
+              GOOGLE_DCHECK(!extension->is_repeated);
+              if (other_extension.is_lazy) {
+                if (extension->is_lazy) {
+                  extension->lazymessage_value->MergeFrom(
+                      *other_extension.lazymessage_value);
+                } else {
+                  extension->message_value->CheckTypeAndMergeFrom(
+                      other_extension.lazymessage_value->GetMessage(
+                          *extension->message_value));
+                }
+              } else {
+                if (extension->is_lazy) {
+                  extension->lazymessage_value->MutableMessage(
+                      *other_extension.message_value)->CheckTypeAndMergeFrom(
+                          *other_extension.message_value);
+                } else {
+                  extension->message_value->CheckTypeAndMergeFrom(
+                      *other_extension.message_value);
+                }
+              }
+            }
+            extension->is_cleared = false;
             break;
+          }
         }
       }
     }
@@ -706,7 +841,11 @@
         }
       } else {
         if (!extension.is_cleared) {
-          if (!extension.message_value->IsInitialized()) return false;
+          if (extension.is_lazy) {
+            if (!extension.lazymessage_value->IsInitialized()) return false;
+          } else {
+            if (!extension.message_value->IsInitialized()) return false;
+          }
         }
       }
     }
@@ -715,27 +854,42 @@
   return true;
 }
 
-bool ExtensionSet::ParseField(uint32 tag, io::CodedInputStream* input,
-                              ExtensionFinder* extension_finder,
-                              FieldSkipper* field_skipper) {
-  int number = WireFormatLite::GetTagFieldNumber(tag);
+bool ExtensionSet::FindExtensionInfoFromTag(
+    uint32 tag, ExtensionFinder* extension_finder,
+    int* field_number, ExtensionInfo* extension) {
+  *field_number = WireFormatLite::GetTagFieldNumber(tag);
   WireFormatLite::WireType wire_type = WireFormatLite::GetTagWireType(tag);
 
-  ExtensionInfo extension;
   bool is_unknown;
-  if (!extension_finder->Find(number, &extension)) {
+  if (!extension_finder->Find(*field_number, extension)) {
     is_unknown = true;
-  } else if (extension.is_packed) {
+  } else if (extension->is_packed) {
     is_unknown = (wire_type != WireFormatLite::WIRETYPE_LENGTH_DELIMITED);
   } else {
     WireFormatLite::WireType expected_wire_type =
-        WireFormatLite::WireTypeForFieldType(real_type(extension.type));
+        WireFormatLite::WireTypeForFieldType(real_type(extension->type));
     is_unknown = (wire_type != expected_wire_type);
   }
+  return !is_unknown;
+}
 
-  if (is_unknown) {
-    field_skipper->SkipField(input, tag);
-  } else if (extension.is_packed) {
+bool ExtensionSet::ParseField(uint32 tag, io::CodedInputStream* input,
+                              ExtensionFinder* extension_finder,
+                              FieldSkipper* field_skipper) {
+  int number;
+  ExtensionInfo extension;
+  if (!FindExtensionInfoFromTag(tag, extension_finder, &number, &extension)) {
+    return field_skipper->SkipField(input, tag);
+  } else {
+    return ParseFieldWithExtensionInfo(number, extension, input, field_skipper);
+  }
+}
+
+bool ExtensionSet::ParseFieldWithExtensionInfo(
+    int number, const ExtensionInfo& extension,
+    io::CodedInputStream* input,
+    FieldSkipper* field_skipper) {
+  if (extension.is_packed) {
     uint32 size;
     if (!input->ReadVarint32(&size)) return false;
     io::CodedInputStream::Limit limit = input->PushLimit(size);
@@ -852,8 +1006,8 @@
 
       case WireFormatLite::TYPE_BYTES:  {
         string* value = extension.is_repeated ?
-          AddString(number, WireFormatLite::TYPE_STRING, extension.descriptor) :
-          MutableString(number, WireFormatLite::TYPE_STRING,
+          AddString(number, WireFormatLite::TYPE_BYTES, extension.descriptor) :
+          MutableString(number, WireFormatLite::TYPE_BYTES,
                         extension.descriptor);
         if (!WireFormatLite::ReadBytes(input, value)) return false;
         break;
@@ -897,121 +1051,11 @@
 //                                    const Message* containing_type,
 //                                    UnknownFieldSet* unknown_fields)
 
-bool ExtensionSet::ParseMessageSet(io::CodedInputStream* input,
-                                   ExtensionFinder* extension_finder,
-                                   FieldSkipper* field_skipper) {
-  while (true) {
-    uint32 tag = input->ReadTag();
-    switch (tag) {
-      case 0:
-        return true;
-      case WireFormatLite::kMessageSetItemStartTag:
-        if (!ParseMessageSetItem(input, extension_finder, field_skipper)) {
-          return false;
-        }
-        break;
-      default:
-        if (!ParseField(tag, input, extension_finder, field_skipper)) {
-          return false;
-        }
-        break;
-    }
-  }
-}
-
-bool ExtensionSet::ParseMessageSet(io::CodedInputStream* input,
-                                   const MessageLite* containing_type,
-                                   UnknownFieldSet* unknown_fields) {
-  FieldSkipper skipper(unknown_fields);
-  GeneratedExtensionFinder finder(containing_type);
-  return ParseMessageSet(input, &finder, &skipper);
-}
-
 // Defined in extension_set_heavy.cc.
 // bool ExtensionSet::ParseMessageSetHeavy(io::CodedInputStream* input,
 //                                         const Message* containing_type,
 //                                         UnknownFieldSet* unknown_fields);
 
-bool ExtensionSet::ParseMessageSetItem(io::CodedInputStream* input,
-                                       ExtensionFinder* extension_finder,
-                                       FieldSkipper* field_skipper) {
-  // TODO(kenton):  It would be nice to share code between this and
-  // WireFormatLite::ParseAndMergeMessageSetItem(), but I think the
-  // differences would be hard to factor out.
-
-  // This method parses a group which should contain two fields:
-  //   required int32 type_id = 2;
-  //   required data message = 3;
-
-  // Once we see a type_id, we'll construct a fake tag for this extension
-  // which is the tag it would have had under the proto2 extensions wire
-  // format.
-  uint32 fake_tag = 0;
-
-  // If we see message data before the type_id, we'll append it to this so
-  // we can parse it later.  This will probably never happen in practice,
-  // as no MessageSet encoder I know of writes the message before the type ID.
-  // But, it's technically valid so we should allow it.
-  // TODO(kenton):  Use a Cord instead?  Do I care?
-  string message_data;
-
-  while (true) {
-    uint32 tag = input->ReadTag();
-    if (tag == 0) return false;
-
-    switch (tag) {
-      case WireFormatLite::kMessageSetTypeIdTag: {
-        uint32 type_id;
-        if (!input->ReadVarint32(&type_id)) return false;
-        fake_tag = WireFormatLite::MakeTag(type_id,
-            WireFormatLite::WIRETYPE_LENGTH_DELIMITED);
-
-        if (!message_data.empty()) {
-          // We saw some message data before the type_id.  Have to parse it
-          // now.
-          io::CodedInputStream sub_input(
-              reinterpret_cast<const uint8*>(message_data.data()),
-              message_data.size());
-          if (!ParseField(fake_tag, &sub_input,
-                          extension_finder, field_skipper)) {
-            return false;
-          }
-          message_data.clear();
-        }
-
-        break;
-      }
-
-      case WireFormatLite::kMessageSetMessageTag: {
-        if (fake_tag == 0) {
-          // We haven't seen a type_id yet.  Append this data to message_data.
-          string temp;
-          uint32 length;
-          if (!input->ReadVarint32(&length)) return false;
-          if (!input->ReadString(&temp, length)) return false;
-          message_data.append(temp);
-        } else {
-          // Already saw type_id, so we can parse this directly.
-          if (!ParseField(fake_tag, input,
-                          extension_finder, field_skipper)) {
-            return false;
-          }
-        }
-
-        break;
-      }
-
-      case WireFormatLite::kMessageSetItemEndTag: {
-        return true;
-      }
-
-      default: {
-        if (!field_skipper->SkipField(input, tag)) return false;
-      }
-    }
-  }
-}
-
 void ExtensionSet::SerializeWithCachedSizes(
     int start_field_number, int end_field_number,
     io::CodedOutputStream* output) const {
@@ -1023,14 +1067,6 @@
   }
 }
 
-void ExtensionSet::SerializeMessageSetWithCachedSizes(
-    io::CodedOutputStream* output) const {
-  map<int, Extension>::const_iterator iter;
-  for (iter = extensions_.begin(); iter != extensions_.end(); ++iter) {
-    iter->second.SerializeMessageSetItemWithCachedSizes(iter->first, output);
-  }
-}
-
 int ExtensionSet::ByteSize() const {
   int total_size = 0;
 
@@ -1042,17 +1078,6 @@
   return total_size;
 }
 
-int ExtensionSet::MessageSetByteSize() const {
-  int total_size = 0;
-
-  for (map<int, Extension>::const_iterator iter = extensions_.begin();
-       iter != extensions_.end(); ++iter) {
-    total_size += iter->second.MessageSetItemByteSize(iter->first);
-  }
-
-  return total_size;
-}
-
 // Defined in extension_set_heavy.cc.
 // int ExtensionSet::SpaceUsedExcludingSelf() const
 
@@ -1096,7 +1121,11 @@
           string_value->clear();
           break;
         case WireFormatLite::CPPTYPE_MESSAGE:
-          message_value->Clear();
+          if (is_lazy) {
+            lazymessage_value->Clear();
+          } else {
+            message_value->Clear();
+          }
           break;
         default:
           // No need to do anything.  Get*() will return the default value
@@ -1208,40 +1237,18 @@
       HANDLE_TYPE(   BYTES,    Bytes,  *string_value);
       HANDLE_TYPE(    ENUM,     Enum,     enum_value);
       HANDLE_TYPE(   GROUP,    Group, *message_value);
-      HANDLE_TYPE( MESSAGE,  Message, *message_value);
 #undef HANDLE_TYPE
+      case WireFormatLite::TYPE_MESSAGE:
+        if (is_lazy) {
+          lazymessage_value->WriteMessage(number, output);
+        } else {
+          WireFormatLite::WriteMessage(number, *message_value, output);
+        }
+        break;
     }
   }
 }
 
-void ExtensionSet::Extension::SerializeMessageSetItemWithCachedSizes(
-    int number,
-    io::CodedOutputStream* output) const {
-  if (type != WireFormatLite::TYPE_MESSAGE || is_repeated) {
-    // Not a valid MessageSet extension, but serialize it the normal way.
-    SerializeFieldWithCachedSizes(number, output);
-    return;
-  }
-
-  if (is_cleared) return;
-
-  // Start group.
-  output->WriteTag(WireFormatLite::kMessageSetItemStartTag);
-
-  // Write type ID.
-  WireFormatLite::WriteUInt32(WireFormatLite::kMessageSetTypeIdNumber,
-                              number,
-                              output);
-  // Write message.
-  WireFormatLite::WriteMessageMaybeToArray(
-      WireFormatLite::kMessageSetMessageNumber,
-      *message_value,
-      output);
-
-  // End group.
-  output->WriteTag(WireFormatLite::kMessageSetItemEndTag);
-}
-
 int ExtensionSet::Extension::ByteSize(int number) const {
   int result = 0;
 
@@ -1355,8 +1362,16 @@
       HANDLE_TYPE(   BYTES,    Bytes,  *string_value);
       HANDLE_TYPE(    ENUM,     Enum,     enum_value);
       HANDLE_TYPE(   GROUP,    Group, *message_value);
-      HANDLE_TYPE( MESSAGE,  Message, *message_value);
 #undef HANDLE_TYPE
+      case WireFormatLite::TYPE_MESSAGE: {
+        if (is_lazy) {
+          int size = lazymessage_value->ByteSize();
+          result += io::CodedOutputStream::VarintSize32(size) + size;
+        } else {
+          result += WireFormatLite::MessageSize(*message_value);
+        }
+        break;
+      }
 
       // Stuff with fixed size.
 #define HANDLE_TYPE(UPPERCASE, CAMELCASE)                                 \
@@ -1377,29 +1392,6 @@
   return result;
 }
 
-int ExtensionSet::Extension::MessageSetItemByteSize(int number) const {
-  if (type != WireFormatLite::TYPE_MESSAGE || is_repeated) {
-    // Not a valid MessageSet extension, but compute the byte size for it the
-    // normal way.
-    return ByteSize(number);
-  }
-
-  if (is_cleared) return 0;
-
-  int our_size = WireFormatLite::kMessageSetItemTagsSize;
-
-  // type_id
-  our_size += io::CodedOutputStream::VarintSize32(number);
-
-  // message
-  int message_size = message_value->ByteSize();
-
-  our_size += io::CodedOutputStream::VarintSize32(message_size);
-  our_size += message_size;
-
-  return our_size;
-}
-
 int ExtensionSet::Extension::GetSize() const {
   GOOGLE_DCHECK(is_repeated);
   switch (cpp_type(type)) {
@@ -1450,7 +1442,11 @@
         delete string_value;
         break;
       case WireFormatLite::CPPTYPE_MESSAGE:
-        delete message_value;
+        if (is_lazy) {
+          delete lazymessage_value;
+        } else {
+          delete message_value;
+        }
         break;
       default:
         break;
diff --git a/third_party/protobuf/src/google/protobuf/extension_set.h b/third_party/protobuf/src/google/protobuf/extension_set.h
index a1b6f35..f3935fb 100644
--- a/third_party/protobuf/src/google/protobuf/extension_set.h
+++ b/third_party/protobuf/src/google/protobuf/extension_set.h
@@ -89,8 +89,8 @@
 // Information about a registered extension.
 struct ExtensionInfo {
   inline ExtensionInfo() {}
-  inline ExtensionInfo(FieldType type, bool is_repeated, bool is_packed)
-      : type(type), is_repeated(is_repeated), is_packed(is_packed),
+  inline ExtensionInfo(FieldType type_param, bool isrepeated, bool ispacked)
+      : type(type_param), is_repeated(isrepeated), is_packed(ispacked),
         descriptor(NULL) {}
 
   FieldType type;
@@ -214,6 +214,7 @@
 
   bool Has(int number) const;
   int ExtensionSize(int number) const;   // Size of a repeated extension.
+  int NumExtensions() const;  // The number of extensions
   FieldType ExtensionType(int number) const;
   void ClearExtension(int number);
 
@@ -251,10 +252,21 @@
                               const MessageLite& prototype, desc);
   MessageLite* MutableMessage(const FieldDescriptor* decsriptor,
                               MessageFactory* factory);
+  // Adds the given message to the ExtensionSet, taking ownership of the
+  // message object. Existing message with the same number will be deleted.
+  // If "message" is NULL, this is equivalent to "ClearExtension(number)".
+  void SetAllocatedMessage(int number, FieldType type,
+                           const FieldDescriptor* descriptor,
+                           MessageLite* message);
+  MessageLite* ReleaseMessage(int number, const MessageLite& prototype);
+  MessageLite* ReleaseMessage(const FieldDescriptor* descriptor,
+                              MessageFactory* factory);
 #undef desc
 
   // repeated fields -------------------------------------------------
 
+  void* MutableRawRepeatedField(int number);
+
   int32  GetRepeatedInt32 (int number, int index) const;
   int64  GetRepeatedInt64 (int number, int index) const;
   uint32 GetRepeatedUInt32(int number, int index) const;
@@ -296,6 +308,7 @@
 #undef desc
 
   void RemoveLast(int number);
+  MessageLite* ReleaseLast(int number);
   void SwapElements(int number, int index1, int index2);
 
   // -----------------------------------------------------------------
@@ -312,18 +325,18 @@
   void Swap(ExtensionSet* other);
   bool IsInitialized() const;
 
-  // Parses a single extension from the input.  The input should start out
-  // positioned immediately after the tag.  |containing_type| is the default
-  // instance for the containing message; it is used only to look up the
-  // extension by number.  See RegisterExtension(), above.  Unlike the other
-  // methods of ExtensionSet, this only works for generated message types --
-  // it looks up extensions registered using RegisterExtension().
+  // Parses a single extension from the input. The input should start out
+  // positioned immediately after the tag.
   bool ParseField(uint32 tag, io::CodedInputStream* input,
                   ExtensionFinder* extension_finder,
                   FieldSkipper* field_skipper);
 
   // Specific versions for lite or full messages (constructs the appropriate
-  // FieldSkipper automatically).
+  // FieldSkipper automatically).  |containing_type| is the default
+  // instance for the containing message; it is used only to look up the
+  // extension by number.  See RegisterExtension(), above.  Unlike the other
+  // methods of ExtensionSet, this only works for generated message types --
+  // it looks up extensions registered using RegisterExtension().
   bool ParseField(uint32 tag, io::CodedInputStream* input,
                   const MessageLite* containing_type,
                   UnknownFieldSet* unknown_fields);
@@ -384,18 +397,49 @@
 
  private:
 
+  // Interface of a lazily parsed singular message extension.
+  class LIBPROTOBUF_EXPORT LazyMessageExtension {
+   public:
+    LazyMessageExtension() {}
+    virtual ~LazyMessageExtension() {}
+
+    virtual LazyMessageExtension* New() const = 0;
+    virtual const MessageLite& GetMessage(
+        const MessageLite& prototype) const = 0;
+    virtual MessageLite* MutableMessage(const MessageLite& prototype) = 0;
+    virtual void SetAllocatedMessage(MessageLite *message) = 0;
+    virtual MessageLite* ReleaseMessage(const MessageLite& prototype) = 0;
+
+    virtual bool IsInitialized() const = 0;
+    virtual int ByteSize() const = 0;
+    virtual int SpaceUsed() const = 0;
+
+    virtual void MergeFrom(const LazyMessageExtension& other) = 0;
+    virtual void Clear() = 0;
+
+    virtual bool ReadMessage(const MessageLite& prototype,
+                             io::CodedInputStream* input) = 0;
+    virtual void WriteMessage(int number,
+                              io::CodedOutputStream* output) const = 0;
+    virtual uint8* WriteMessageToArray(int number, uint8* target) const = 0;
+   private:
+    GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(LazyMessageExtension);
+  };
   struct Extension {
+    // The order of these fields packs Extension into 24 bytes when using 8
+    // byte alignment. Consider this when adding or removing fields here.
     union {
-      int32        int32_value;
-      int64        int64_value;
-      uint32       uint32_value;
-      uint64       uint64_value;
-      float        float_value;
-      double       double_value;
-      bool         bool_value;
-      int          enum_value;
-      string*      string_value;
-      MessageLite* message_value;
+      int32                 int32_value;
+      int64                 int64_value;
+      uint32                uint32_value;
+      uint64                uint64_value;
+      float                 float_value;
+      double                double_value;
+      bool                  bool_value;
+      int                   enum_value;
+      string*               string_value;
+      MessageLite*          message_value;
+      LazyMessageExtension* lazymessage_value;
 
       RepeatedField   <int32      >* repeated_int32_value;
       RepeatedField   <int64      >* repeated_int64_value;
@@ -418,21 +462,28 @@
     // removing it from the map, we just set is_cleared = true.  This has no
     // meaning for repeated types; for those, the size of the RepeatedField
     // simply becomes zero when cleared.
-    bool is_cleared;
+    bool is_cleared : 4;
+
+    // For singular message types, indicates whether lazy parsing is enabled
+    // for this extension. This field is only valid when type == TYPE_MESSAGE
+    // and !is_repeated because we only support lazy parsing for singular
+    // message types currently. If is_lazy = true, the extension is stored in
+    // lazymessage_value. Otherwise, the extension will be message_value.
+    bool is_lazy : 4;
 
     // For repeated types, this indicates if the [packed=true] option is set.
     bool is_packed;
 
-    // The descriptor for this extension, if one exists and is known.  May be
-    // NULL.  Must not be NULL if the descriptor for the extension does not
-    // live in the same pool as the descriptor for the containing type.
-    const FieldDescriptor* descriptor;
-
     // For packed fields, the size of the packed data is recorded here when
     // ByteSize() is called then used during serialization.
     // TODO(kenton):  Use atomic<int> when C++ supports it.
     mutable int cached_size;
 
+    // The descriptor for this extension, if one exists and is known.  May be
+    // NULL.  Must not be NULL if the descriptor for the extension does not
+    // live in the same pool as the descriptor for the containing type.
+    const FieldDescriptor* descriptor;
+
     // Some helper methods for operations on a single Extension.
     void SerializeFieldWithCachedSizes(
         int number,
@@ -455,6 +506,25 @@
   };
 
 
+  // Returns true and fills field_number and extension if extension is found.
+  bool FindExtensionInfoFromTag(uint32 tag, ExtensionFinder* extension_finder,
+                                int* field_number, ExtensionInfo* extension);
+
+  // Parses a single extension from the input. The input should start out
+  // positioned immediately after the wire tag. This method is called in
+  // ParseField() after field number is extracted from the wire tag and
+  // ExtensionInfo is found by the field number.
+  bool ParseFieldWithExtensionInfo(int field_number,
+                                   const ExtensionInfo& extension,
+                                   io::CodedInputStream* input,
+                                   FieldSkipper* field_skipper);
+
+  // Like ParseField(), but this method may parse singular message extensions
+  // lazily depending on the value of FLAGS_eagerly_parse_message_sets.
+  bool ParseFieldMaybeLazily(uint32 tag, io::CodedInputStream* input,
+                             ExtensionFinder* extension_finder,
+                             FieldSkipper* field_skipper);
+
   // Gets the extension with the given number, creating it if it does not
   // already exist.  Returns true if the extension did not already exist.
   bool MaybeNewExtension(int number, const FieldDescriptor* descriptor,
@@ -722,6 +792,15 @@
     return static_cast<Type*>(
       set->MutableMessage(number, field_type, Type::default_instance(), NULL));
   }
+  static inline void SetAllocated(int number, FieldType field_type,
+                                  MutableType message, ExtensionSet* set) {
+    set->SetAllocatedMessage(number, field_type, NULL, message);
+  }
+  static inline MutableType Release(int number, FieldType field_type,
+                                    ExtensionSet* set) {
+    return static_cast<Type*>(set->ReleaseMessage(
+        number, Type::default_instance()));
+  }
 };
 
 template <typename Type>
@@ -789,113 +868,137 @@
 // causes problems if the class has a nested message or enum type with that
 // name and "_TypeTraits" is technically reserved for the C++ library since
 // it starts with an underscore followed by a capital letter.
+//
+// For similar reason, we use "_field_type" and "_is_packed" as parameter names
+// below, so that "field_type" and "is_packed" can be used as field names.
 #define GOOGLE_PROTOBUF_EXTENSION_ACCESSORS(CLASSNAME)                        \
   /* Has, Size, Clear */                                                      \
   template <typename _proto_TypeTraits,                                       \
-            ::google::protobuf::internal::FieldType field_type,                         \
-            bool is_packed>                                                   \
+            ::google::protobuf::internal::FieldType _field_type,                        \
+            bool _is_packed>                                                  \
   inline bool HasExtension(                                                   \
       const ::google::protobuf::internal::ExtensionIdentifier<                          \
-        CLASSNAME, _proto_TypeTraits, field_type, is_packed>& id) const {     \
+        CLASSNAME, _proto_TypeTraits, _field_type, _is_packed>& id) const {   \
     return _extensions_.Has(id.number());                                     \
   }                                                                           \
                                                                               \
   template <typename _proto_TypeTraits,                                       \
-            ::google::protobuf::internal::FieldType field_type,                         \
-            bool is_packed>                                                   \
+            ::google::protobuf::internal::FieldType _field_type,                        \
+            bool _is_packed>                                                  \
   inline void ClearExtension(                                                 \
       const ::google::protobuf::internal::ExtensionIdentifier<                          \
-        CLASSNAME, _proto_TypeTraits, field_type, is_packed>& id) {           \
+        CLASSNAME, _proto_TypeTraits, _field_type, _is_packed>& id) {         \
     _extensions_.ClearExtension(id.number());                                 \
   }                                                                           \
                                                                               \
   template <typename _proto_TypeTraits,                                       \
-            ::google::protobuf::internal::FieldType field_type,                         \
-            bool is_packed>                                                   \
+            ::google::protobuf::internal::FieldType _field_type,                        \
+            bool _is_packed>                                                  \
   inline int ExtensionSize(                                                   \
       const ::google::protobuf::internal::ExtensionIdentifier<                          \
-        CLASSNAME, _proto_TypeTraits, field_type, is_packed>& id) const {     \
+        CLASSNAME, _proto_TypeTraits, _field_type, _is_packed>& id) const {   \
     return _extensions_.ExtensionSize(id.number());                           \
   }                                                                           \
                                                                               \
   /* Singular accessors */                                                    \
   template <typename _proto_TypeTraits,                                       \
-            ::google::protobuf::internal::FieldType field_type,                         \
-            bool is_packed>                                                   \
+            ::google::protobuf::internal::FieldType _field_type,                        \
+            bool _is_packed>                                                  \
   inline typename _proto_TypeTraits::ConstType GetExtension(                  \
       const ::google::protobuf::internal::ExtensionIdentifier<                          \
-        CLASSNAME, _proto_TypeTraits, field_type, is_packed>& id) const {     \
+        CLASSNAME, _proto_TypeTraits, _field_type, _is_packed>& id) const {   \
     return _proto_TypeTraits::Get(id.number(), _extensions_,                  \
                                   id.default_value());                        \
   }                                                                           \
                                                                               \
   template <typename _proto_TypeTraits,                                       \
-            ::google::protobuf::internal::FieldType field_type,                         \
-            bool is_packed>                                                   \
+            ::google::protobuf::internal::FieldType _field_type,                        \
+            bool _is_packed>                                                  \
   inline typename _proto_TypeTraits::MutableType MutableExtension(            \
       const ::google::protobuf::internal::ExtensionIdentifier<                          \
-        CLASSNAME, _proto_TypeTraits, field_type, is_packed>& id) {           \
-    return _proto_TypeTraits::Mutable(id.number(), field_type, &_extensions_);\
+        CLASSNAME, _proto_TypeTraits, _field_type, _is_packed>& id) {         \
+    return _proto_TypeTraits::Mutable(id.number(), _field_type,               \
+                                      &_extensions_);                         \
   }                                                                           \
                                                                               \
   template <typename _proto_TypeTraits,                                       \
-            ::google::protobuf::internal::FieldType field_type,                         \
-            bool is_packed>                                                   \
+            ::google::protobuf::internal::FieldType _field_type,                        \
+            bool _is_packed>                                                  \
   inline void SetExtension(                                                   \
       const ::google::protobuf::internal::ExtensionIdentifier<                          \
-        CLASSNAME, _proto_TypeTraits, field_type, is_packed>& id,             \
+        CLASSNAME, _proto_TypeTraits, _field_type, _is_packed>& id,           \
       typename _proto_TypeTraits::ConstType value) {                          \
-    _proto_TypeTraits::Set(id.number(), field_type, value, &_extensions_);    \
+    _proto_TypeTraits::Set(id.number(), _field_type, value, &_extensions_);   \
+  }                                                                           \
+                                                                              \
+  template <typename _proto_TypeTraits,                                       \
+            ::google::protobuf::internal::FieldType _field_type,                        \
+            bool _is_packed>                                                  \
+  inline void SetAllocatedExtension(                                          \
+      const ::google::protobuf::internal::ExtensionIdentifier<                          \
+        CLASSNAME, _proto_TypeTraits, _field_type, _is_packed>& id,           \
+      typename _proto_TypeTraits::MutableType value) {                        \
+    _proto_TypeTraits::SetAllocated(id.number(), _field_type,                 \
+                                    value, &_extensions_);                    \
+  }                                                                           \
+  template <typename _proto_TypeTraits,                                       \
+            ::google::protobuf::internal::FieldType _field_type,                        \
+            bool _is_packed>                                                  \
+  inline typename _proto_TypeTraits::MutableType ReleaseExtension(            \
+      const ::google::protobuf::internal::ExtensionIdentifier<                          \
+        CLASSNAME, _proto_TypeTraits, _field_type, _is_packed>& id) {         \
+    return _proto_TypeTraits::Release(id.number(), _field_type,               \
+                                      &_extensions_);                         \
   }                                                                           \
                                                                               \
   /* Repeated accessors */                                                    \
   template <typename _proto_TypeTraits,                                       \
-            ::google::protobuf::internal::FieldType field_type,                         \
-            bool is_packed>                                                   \
+            ::google::protobuf::internal::FieldType _field_type,                        \
+            bool _is_packed>                                                  \
   inline typename _proto_TypeTraits::ConstType GetExtension(                  \
       const ::google::protobuf::internal::ExtensionIdentifier<                          \
-        CLASSNAME, _proto_TypeTraits, field_type, is_packed>& id,             \
+        CLASSNAME, _proto_TypeTraits, _field_type, _is_packed>& id,           \
       int index) const {                                                      \
     return _proto_TypeTraits::Get(id.number(), _extensions_, index);          \
   }                                                                           \
                                                                               \
   template <typename _proto_TypeTraits,                                       \
-            ::google::protobuf::internal::FieldType field_type,                         \
-            bool is_packed>                                                   \
+            ::google::protobuf::internal::FieldType _field_type,                        \
+            bool _is_packed>                                                  \
   inline typename _proto_TypeTraits::MutableType MutableExtension(            \
       const ::google::protobuf::internal::ExtensionIdentifier<                          \
-        CLASSNAME, _proto_TypeTraits, field_type, is_packed>& id,             \
+        CLASSNAME, _proto_TypeTraits, _field_type, _is_packed>& id,           \
       int index) {                                                            \
     return _proto_TypeTraits::Mutable(id.number(), index, &_extensions_);     \
   }                                                                           \
                                                                               \
   template <typename _proto_TypeTraits,                                       \
-            ::google::protobuf::internal::FieldType field_type,                         \
-            bool is_packed>                                                   \
+            ::google::protobuf::internal::FieldType _field_type,                        \
+            bool _is_packed>                                                  \
   inline void SetExtension(                                                   \
       const ::google::protobuf::internal::ExtensionIdentifier<                          \
-        CLASSNAME, _proto_TypeTraits, field_type, is_packed>& id,             \
+        CLASSNAME, _proto_TypeTraits, _field_type, _is_packed>& id,           \
       int index, typename _proto_TypeTraits::ConstType value) {               \
     _proto_TypeTraits::Set(id.number(), index, value, &_extensions_);         \
   }                                                                           \
                                                                               \
   template <typename _proto_TypeTraits,                                       \
-            ::google::protobuf::internal::FieldType field_type,                         \
-            bool is_packed>                                                   \
+            ::google::protobuf::internal::FieldType _field_type,                        \
+            bool _is_packed>                                                  \
   inline typename _proto_TypeTraits::MutableType AddExtension(                \
       const ::google::protobuf::internal::ExtensionIdentifier<                          \
-        CLASSNAME, _proto_TypeTraits, field_type, is_packed>& id) {           \
-    return _proto_TypeTraits::Add(id.number(), field_type, &_extensions_);    \
+        CLASSNAME, _proto_TypeTraits, _field_type, _is_packed>& id) {         \
+    return _proto_TypeTraits::Add(id.number(), _field_type, &_extensions_);   \
   }                                                                           \
                                                                               \
   template <typename _proto_TypeTraits,                                       \
-            ::google::protobuf::internal::FieldType field_type,                         \
-            bool is_packed>                                                   \
+            ::google::protobuf::internal::FieldType _field_type,                        \
+            bool _is_packed>                                                  \
   inline void AddExtension(                                                   \
       const ::google::protobuf::internal::ExtensionIdentifier<                          \
-        CLASSNAME, _proto_TypeTraits, field_type, is_packed>& id,             \
+        CLASSNAME, _proto_TypeTraits, _field_type, _is_packed>& id,           \
       typename _proto_TypeTraits::ConstType value) {                          \
-    _proto_TypeTraits::Add(id.number(), field_type, is_packed,                \
+    _proto_TypeTraits::Add(id.number(), _field_type, _is_packed,              \
                            value, &_extensions_);                             \
   }
 
diff --git a/third_party/protobuf/src/google/protobuf/extension_set_heavy.cc b/third_party/protobuf/src/google/protobuf/extension_set_heavy.cc
index e00fd4d..01b9490 100644
--- a/third_party/protobuf/src/google/protobuf/extension_set_heavy.cc
+++ b/third_party/protobuf/src/google/protobuf/extension_set_heavy.cc
@@ -35,17 +35,20 @@
 // Contains methods defined in extension_set.h which cannot be part of the
 // lite library because they use descriptors or reflection.
 
-#include <google/protobuf/extension_set.h>
+#include <google/protobuf/io/zero_copy_stream_impl_lite.h>
 #include <google/protobuf/descriptor.h>
+#include <google/protobuf/extension_set.h>
 #include <google/protobuf/message.h>
 #include <google/protobuf/repeated_field.h>
 #include <google/protobuf/wire_format.h>
 #include <google/protobuf/wire_format_lite_inl.h>
 
 namespace google {
+
 namespace protobuf {
 namespace internal {
 
+
 // Implementation of ExtensionFinder which finds extensions in a given
 // DescriptorPool, using the given MessageFactory to construct sub-objects.
 // This class is implemented in extension_set_heavy.cc.
@@ -103,6 +106,11 @@
       static_cast<FieldDescriptor::Type>(type));
 }
 
+inline WireFormatLite::FieldType field_type(FieldType type) {
+  GOOGLE_DCHECK(type > 0 && type <= WireFormatLite::MAX_FIELD_TYPE);
+  return static_cast<WireFormatLite::FieldType>(type);
+}
+
 #define GOOGLE_DCHECK_TYPE(EXTENSION, LABEL, CPPTYPE)                            \
   GOOGLE_DCHECK_EQ((EXTENSION).is_repeated ? FieldDescriptor::LABEL_REPEATED     \
                                   : FieldDescriptor::LABEL_OPTIONAL,      \
@@ -118,7 +126,12 @@
     return *factory->GetPrototype(message_type);
   } else {
     GOOGLE_DCHECK_TYPE(iter->second, OPTIONAL, MESSAGE);
-    return *iter->second.message_value;
+    if (iter->second.is_lazy) {
+      return iter->second.lazymessage_value->GetMessage(
+          *factory->GetPrototype(message_type));
+    } else {
+      return *iter->second.message_value;
+    }
   }
 }
 
@@ -132,13 +145,41 @@
     extension->is_packed = false;
     const MessageLite* prototype =
         factory->GetPrototype(descriptor->message_type());
-    GOOGLE_CHECK(prototype != NULL);
+    extension->is_lazy = false;
     extension->message_value = prototype->New();
+    extension->is_cleared = false;
+    return extension->message_value;
   } else {
     GOOGLE_DCHECK_TYPE(*extension, OPTIONAL, MESSAGE);
+    extension->is_cleared = false;
+    if (extension->is_lazy) {
+      return extension->lazymessage_value->MutableMessage(
+          *factory->GetPrototype(descriptor->message_type()));
+    } else {
+      return extension->message_value;
+    }
   }
-  extension->is_cleared = false;
-  return extension->message_value;
+}
+
+MessageLite* ExtensionSet::ReleaseMessage(const FieldDescriptor* descriptor,
+                                          MessageFactory* factory) {
+  map<int, Extension>::iterator iter = extensions_.find(descriptor->number());
+  if (iter == extensions_.end()) {
+    // Not present.  Return NULL.
+    return NULL;
+  } else {
+    GOOGLE_DCHECK_TYPE(iter->second, OPTIONAL, MESSAGE);
+    MessageLite* ret = NULL;
+    if (iter->second.is_lazy) {
+      ret = iter->second.lazymessage_value->ReleaseMessage(
+        *factory->GetPrototype(descriptor->message_type()));
+      delete iter->second.lazymessage_value;
+    } else {
+      ret = iter->second.message_value;
+    }
+    extensions_.erase(descriptor->number());
+    return ret;
+  }
 }
 
 MessageLite* ExtensionSet::AddMessage(const FieldDescriptor* descriptor,
@@ -157,7 +198,7 @@
   // RepeatedPtrField<Message> does not know how to Add() since it cannot
   // allocate an abstract object, so we have to be tricky.
   MessageLite* result = extension->repeated_message_value
-      ->AddFromCleared<internal::GenericTypeHandler<MessageLite> >();
+      ->AddFromCleared<GenericTypeHandler<MessageLite> >();
   if (result == NULL) {
     const MessageLite* prototype;
     if (extension->repeated_message_value->size() == 0) {
@@ -286,7 +327,11 @@
                       StringSpaceUsedExcludingSelf(*string_value);
         break;
       case FieldDescriptor::CPPTYPE_MESSAGE:
-        total_size += down_cast<Message*>(message_value)->SpaceUsed();
+        if (is_lazy) {
+          total_size += lazymessage_value->SpaceUsed();
+        } else {
+          total_size += down_cast<Message*>(message_value)->SpaceUsed();
+        }
         break;
       default:
         // No extra storage costs for primitive types.
@@ -419,8 +464,15 @@
       HANDLE_TYPE(   BYTES,    Bytes,  *string_value);
       HANDLE_TYPE(    ENUM,     Enum,     enum_value);
       HANDLE_TYPE(   GROUP,    Group, *message_value);
-      HANDLE_TYPE( MESSAGE,  Message, *message_value);
 #undef HANDLE_TYPE
+      case FieldDescriptor::TYPE_MESSAGE:
+        if (is_lazy) {
+          target = lazymessage_value->WriteMessageToArray(number, target);
+        } else {
+          target = WireFormatLite::WriteMessageToArray(
+              number, *message_value, target);
+        }
+        break;
     }
   }
   return target;
@@ -444,14 +496,217 @@
   target = WireFormatLite::WriteUInt32ToArray(
       WireFormatLite::kMessageSetTypeIdNumber, number, target);
   // Write message.
-  target = WireFormatLite::WriteMessageToArray(
-      WireFormatLite::kMessageSetMessageNumber, *message_value, target);
+  if (is_lazy) {
+    target = lazymessage_value->WriteMessageToArray(
+        WireFormatLite::kMessageSetMessageNumber, target);
+  } else {
+    target = WireFormatLite::WriteMessageToArray(
+        WireFormatLite::kMessageSetMessageNumber, *message_value, target);
+  }
   // End group.
   target = io::CodedOutputStream::WriteTagToArray(
       WireFormatLite::kMessageSetItemEndTag, target);
   return target;
 }
 
+
+bool ExtensionSet::ParseFieldMaybeLazily(
+    uint32 tag, io::CodedInputStream* input,
+    ExtensionFinder* extension_finder,
+    FieldSkipper* field_skipper) {
+  return ParseField(tag, input, extension_finder, field_skipper);
+}
+
+bool ExtensionSet::ParseMessageSet(io::CodedInputStream* input,
+                                   ExtensionFinder* extension_finder,
+                                   FieldSkipper* field_skipper) {
+  while (true) {
+    uint32 tag = input->ReadTag();
+    switch (tag) {
+      case 0:
+        return true;
+      case WireFormatLite::kMessageSetItemStartTag:
+        if (!ParseMessageSetItem(input, extension_finder, field_skipper)) {
+          return false;
+        }
+        break;
+      default:
+        if (!ParseField(tag, input, extension_finder, field_skipper)) {
+          return false;
+        }
+        break;
+    }
+  }
+}
+
+bool ExtensionSet::ParseMessageSet(io::CodedInputStream* input,
+                                   const MessageLite* containing_type,
+                                   UnknownFieldSet* unknown_fields) {
+  FieldSkipper skipper(unknown_fields);
+  GeneratedExtensionFinder finder(containing_type);
+  return ParseMessageSet(input, &finder, &skipper);
+}
+
+bool ExtensionSet::ParseMessageSetItem(io::CodedInputStream* input,
+                                       ExtensionFinder* extension_finder,
+                                       FieldSkipper* field_skipper) {
+  // TODO(kenton):  It would be nice to share code between this and
+  // WireFormatLite::ParseAndMergeMessageSetItem(), but I think the
+  // differences would be hard to factor out.
+
+  // This method parses a group which should contain two fields:
+  //   required int32 type_id = 2;
+  //   required data message = 3;
+
+  // Once we see a type_id, we'll construct a fake tag for this extension
+  // which is the tag it would have had under the proto2 extensions wire
+  // format.
+  uint32 fake_tag = 0;
+
+  // If we see message data before the type_id, we'll append it to this so
+  // we can parse it later.
+  string message_data;
+
+  while (true) {
+    uint32 tag = input->ReadTag();
+    if (tag == 0) return false;
+
+    switch (tag) {
+      case WireFormatLite::kMessageSetTypeIdTag: {
+        uint32 type_id;
+        if (!input->ReadVarint32(&type_id)) return false;
+        fake_tag = WireFormatLite::MakeTag(type_id,
+            WireFormatLite::WIRETYPE_LENGTH_DELIMITED);
+
+        if (!message_data.empty()) {
+          // We saw some message data before the type_id.  Have to parse it
+          // now.
+          io::CodedInputStream sub_input(
+              reinterpret_cast<const uint8*>(message_data.data()),
+              message_data.size());
+          if (!ParseFieldMaybeLazily(fake_tag, &sub_input,
+                                     extension_finder, field_skipper)) {
+            return false;
+          }
+          message_data.clear();
+        }
+
+        break;
+      }
+
+      case WireFormatLite::kMessageSetMessageTag: {
+        if (fake_tag == 0) {
+          // We haven't seen a type_id yet.  Append this data to message_data.
+          string temp;
+          uint32 length;
+          if (!input->ReadVarint32(&length)) return false;
+          if (!input->ReadString(&temp, length)) return false;
+          io::StringOutputStream output_stream(&message_data);
+          io::CodedOutputStream coded_output(&output_stream);
+          coded_output.WriteVarint32(length);
+          coded_output.WriteString(temp);
+        } else {
+          // Already saw type_id, so we can parse this directly.
+          if (!ParseFieldMaybeLazily(fake_tag, input,
+                                     extension_finder, field_skipper)) {
+            return false;
+          }
+        }
+
+        break;
+      }
+
+      case WireFormatLite::kMessageSetItemEndTag: {
+        return true;
+      }
+
+      default: {
+        if (!field_skipper->SkipField(input, tag)) return false;
+      }
+    }
+  }
+}
+
+void ExtensionSet::Extension::SerializeMessageSetItemWithCachedSizes(
+    int number,
+    io::CodedOutputStream* output) const {
+  if (type != WireFormatLite::TYPE_MESSAGE || is_repeated) {
+    // Not a valid MessageSet extension, but serialize it the normal way.
+    SerializeFieldWithCachedSizes(number, output);
+    return;
+  }
+
+  if (is_cleared) return;
+
+  // Start group.
+  output->WriteTag(WireFormatLite::kMessageSetItemStartTag);
+
+  // Write type ID.
+  WireFormatLite::WriteUInt32(WireFormatLite::kMessageSetTypeIdNumber,
+                              number,
+                              output);
+  // Write message.
+  if (is_lazy) {
+    lazymessage_value->WriteMessage(
+        WireFormatLite::kMessageSetMessageNumber, output);
+  } else {
+    WireFormatLite::WriteMessageMaybeToArray(
+        WireFormatLite::kMessageSetMessageNumber,
+        *message_value,
+        output);
+  }
+
+  // End group.
+  output->WriteTag(WireFormatLite::kMessageSetItemEndTag);
+}
+
+int ExtensionSet::Extension::MessageSetItemByteSize(int number) const {
+  if (type != WireFormatLite::TYPE_MESSAGE || is_repeated) {
+    // Not a valid MessageSet extension, but compute the byte size for it the
+    // normal way.
+    return ByteSize(number);
+  }
+
+  if (is_cleared) return 0;
+
+  int our_size = WireFormatLite::kMessageSetItemTagsSize;
+
+  // type_id
+  our_size += io::CodedOutputStream::VarintSize32(number);
+
+  // message
+  int message_size = 0;
+  if (is_lazy) {
+    message_size = lazymessage_value->ByteSize();
+  } else {
+    message_size = message_value->ByteSize();
+  }
+
+  our_size += io::CodedOutputStream::VarintSize32(message_size);
+  our_size += message_size;
+
+  return our_size;
+}
+
+void ExtensionSet::SerializeMessageSetWithCachedSizes(
+    io::CodedOutputStream* output) const {
+  map<int, Extension>::const_iterator iter;
+  for (iter = extensions_.begin(); iter != extensions_.end(); ++iter) {
+    iter->second.SerializeMessageSetItemWithCachedSizes(iter->first, output);
+  }
+}
+
+int ExtensionSet::MessageSetByteSize() const {
+  int total_size = 0;
+
+  for (map<int, Extension>::const_iterator iter = extensions_.begin();
+       iter != extensions_.end(); ++iter) {
+    total_size += iter->second.MessageSetItemByteSize(iter->first);
+  }
+
+  return total_size;
+}
+
 }  // namespace internal
 }  // namespace protobuf
 }  // namespace google
diff --git a/third_party/protobuf/src/google/protobuf/extension_set_unittest.cc b/third_party/protobuf/src/google/protobuf/extension_set_unittest.cc
index 000f846..1e7c5a5 100644
--- a/third_party/protobuf/src/google/protobuf/extension_set_unittest.cc
+++ b/third_party/protobuf/src/google/protobuf/extension_set_unittest.cc
@@ -34,6 +34,7 @@
 
 #include <google/protobuf/extension_set.h>
 #include <google/protobuf/unittest.pb.h>
+#include <google/protobuf/unittest_mset.pb.h>
 #include <google/protobuf/test_util.h>
 #include <google/protobuf/descriptor.pb.h>
 #include <google/protobuf/descriptor.h>
@@ -46,9 +47,10 @@
 #include <google/protobuf/stubs/strutil.h>
 #include <google/protobuf/testing/googletest.h>
 #include <gtest/gtest.h>
-#include <google/protobuf/stubs/stl_util-inl.h>
+#include <google/protobuf/stubs/stl_util.h>
 
 namespace google {
+
 namespace protobuf {
 namespace internal {
 namespace {
@@ -140,23 +142,98 @@
   TestUtil::ExpectAllExtensionsSet(message);
 }
 
+TEST(ExtensionSetTest, SetAllocatedExtensin) {
+  unittest::TestAllExtensions message;
+  EXPECT_FALSE(message.HasExtension(
+      unittest::optional_foreign_message_extension));
+  // Add a extension using SetAllocatedExtension
+  unittest::ForeignMessage* foreign_message = new unittest::ForeignMessage();
+  message.SetAllocatedExtension(unittest::optional_foreign_message_extension,
+                                foreign_message);
+  EXPECT_TRUE(message.HasExtension(
+      unittest::optional_foreign_message_extension));
+  EXPECT_EQ(foreign_message,
+            message.MutableExtension(
+                unittest::optional_foreign_message_extension));
+  EXPECT_EQ(foreign_message,
+            &message.GetExtension(
+                unittest::optional_foreign_message_extension));
+
+  // SetAllocatedExtension should delete the previously existing extension.
+  // (We reply on unittest to check memory leaks for this case)
+  message.SetAllocatedExtension(unittest::optional_foreign_message_extension,
+                                 new unittest::ForeignMessage());
+
+  // SetAllocatedExtension with a NULL parameter is equivalent to ClearExtenion.
+  message.SetAllocatedExtension(unittest::optional_foreign_message_extension,
+                                 NULL);
+  EXPECT_FALSE(message.HasExtension(
+      unittest::optional_foreign_message_extension));
+}
+
+TEST(ExtensionSetTest, ReleaseExtension) {
+  unittest::TestMessageSet message;
+  EXPECT_FALSE(message.HasExtension(
+      unittest::TestMessageSetExtension1::message_set_extension));
+  // Add a extension using SetAllocatedExtension
+  unittest::TestMessageSetExtension1* extension =
+      new unittest::TestMessageSetExtension1();
+  message.SetAllocatedExtension(
+      unittest::TestMessageSetExtension1::message_set_extension,
+      extension);
+  EXPECT_TRUE(message.HasExtension(
+      unittest::TestMessageSetExtension1::message_set_extension));
+  // Release the extension using ReleaseExtension
+  unittest::TestMessageSetExtension1* released_extension =
+      message.ReleaseExtension(
+        unittest::TestMessageSetExtension1::message_set_extension);
+  EXPECT_EQ(extension, released_extension);
+  EXPECT_FALSE(message.HasExtension(
+      unittest::TestMessageSetExtension1::message_set_extension));
+  // ReleaseExtension will return the underlying object even after
+  // ClearExtension is called.
+  message.SetAllocatedExtension(
+      unittest::TestMessageSetExtension1::message_set_extension,
+      extension);
+  message.ClearExtension(
+      unittest::TestMessageSetExtension1::message_set_extension);
+  released_extension = message.ReleaseExtension(
+        unittest::TestMessageSetExtension1::message_set_extension);
+  EXPECT_TRUE(released_extension != NULL);
+  delete released_extension;
+}
+
+
 TEST(ExtensionSetTest, CopyFrom) {
   unittest::TestAllExtensions message1, message2;
-  string data;
 
   TestUtil::SetAllExtensions(&message1);
   message2.CopyFrom(message1);
   TestUtil::ExpectAllExtensionsSet(message2);
+  message2.CopyFrom(message1);  // exercise copy when fields already exist
+  TestUtil::ExpectAllExtensionsSet(message2);
+}
+
+TEST(ExtensioSetTest, CopyFromPacked) {
+  unittest::TestPackedExtensions message1, message2;
+
+  TestUtil::SetPackedExtensions(&message1);
+  message2.CopyFrom(message1);
+  TestUtil::ExpectPackedExtensionsSet(message2);
+  message2.CopyFrom(message1);  // exercise copy when fields already exist
+  TestUtil::ExpectPackedExtensionsSet(message2);
 }
 
 TEST(ExtensionSetTest, CopyFromUpcasted) {
   unittest::TestAllExtensions message1, message2;
-  string data;
   const Message& upcasted_message = message1;
 
   TestUtil::SetAllExtensions(&message1);
   message2.CopyFrom(upcasted_message);
   TestUtil::ExpectAllExtensionsSet(message2);
+  // exercise copy when fields already exist
+  message2.CopyFrom(upcasted_message);
+  TestUtil::ExpectAllExtensionsSet(message2);
 }
 
 TEST(ExtensionSetTest, SwapWithEmpty) {
@@ -418,7 +495,8 @@
     for (int i = 0; i < 16; ++i) {                                             \
       message.AddExtension(unittest::repeated_##type##_extension, value);      \
     }                                                                          \
-    int expected_size = sizeof(cpptype) * 16 + empty_repeated_field_size;      \
+    int expected_size = sizeof(cpptype) * (16 -                                \
+        kMinRepeatedFieldAllocationSize) + empty_repeated_field_size;          \
     EXPECT_EQ(expected_size, message.SpaceUsed()) << #type;                    \
   } while (0)
 
@@ -450,7 +528,8 @@
     for (int i = 0; i < 16; ++i) {
       message.AddExtension(unittest::repeated_string_extension, value);
     }
-    min_expected_size += (sizeof(value) + value.size()) * 16;
+    min_expected_size += (sizeof(value) + value.size()) *
+        (16 - kMinRepeatedFieldAllocationSize);
     EXPECT_LE(min_expected_size, message.SpaceUsed());
   }
   // Repeated messages
@@ -465,7 +544,8 @@
       message.AddExtension(unittest::repeated_foreign_message_extension)->
           CopyFrom(prototype);
     }
-    min_expected_size += 16 * prototype.SpaceUsed();
+    min_expected_size +=
+        (16 - kMinRepeatedFieldAllocationSize) * prototype.SpaceUsed();
     EXPECT_LE(min_expected_size, message.SpaceUsed());
   }
 }
diff --git a/third_party/protobuf/src/google/protobuf/generated_enum_reflection.h b/third_party/protobuf/src/google/protobuf/generated_enum_reflection.h
new file mode 100644
index 0000000..a09a540
--- /dev/null
+++ b/third_party/protobuf/src/google/protobuf/generated_enum_reflection.h
@@ -0,0 +1,85 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 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.
+
+// Author: jasonh@google.com (Jason Hsueh)
+//
+// This header is logically internal, but is made public because it is used
+// from protocol-compiler-generated code, which may reside in other components.
+// It provides reflection support for generated enums, and is included in
+// generated .pb.h files and should have minimal dependencies. The methods are
+// implemented in generated_message_reflection.cc.
+
+#ifndef GOOGLE_PROTOBUF_GENERATED_ENUM_REFLECTION_H__
+#define GOOGLE_PROTOBUF_GENERATED_ENUM_REFLECTION_H__
+
+#include <string>
+
+namespace google {
+namespace protobuf {
+  class EnumDescriptor;
+}  // namespace protobuf
+
+namespace protobuf {
+
+// Returns the EnumDescriptor for enum type E, which must be a
+// proto-declared enum type.  Code generated by the protocol compiler
+// will include specializations of this template for each enum type declared.
+template <typename E>
+const EnumDescriptor* GetEnumDescriptor();
+
+namespace internal {
+
+// Helper for EnumType_Parse functions: try to parse the string 'name' as an
+// enum name of the given type, returning true and filling in value on success,
+// or returning false and leaving value unchanged on failure.
+LIBPROTOBUF_EXPORT bool ParseNamedEnum(const EnumDescriptor* descriptor,
+                    const string& name,
+                    int* value);
+
+template<typename EnumType>
+bool ParseNamedEnum(const EnumDescriptor* descriptor,
+                    const string& name,
+                    EnumType* value) {
+  int tmp;
+  if (!ParseNamedEnum(descriptor, name, &tmp)) return false;
+  *value = static_cast<EnumType>(tmp);
+  return true;
+}
+
+// Just a wrapper around printing the name of a value. The main point of this
+// function is not to be inlined, so that you can do this without including
+// descriptor.h.
+LIBPROTOBUF_EXPORT const string& NameOfEnum(const EnumDescriptor* descriptor, int value);
+
+}  // namespace internal
+}  // namespace protobuf
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_GENERATED_ENUM_REFLECTION_H__
diff --git a/third_party/protobuf/src/google/protobuf/generated_message_reflection.cc b/third_party/protobuf/src/google/protobuf/generated_message_reflection.cc
index 226e951..09b0699 100644
--- a/third_party/protobuf/src/google/protobuf/generated_message_reflection.cc
+++ b/third_party/protobuf/src/google/protobuf/generated_message_reflection.cc
@@ -33,9 +33,9 @@
 //  Sanjay Ghemawat, Jeff Dean, and others.
 
 #include <algorithm>
+#include <google/protobuf/descriptor.pb.h>
 #include <google/protobuf/generated_message_reflection.h>
 #include <google/protobuf/descriptor.h>
-#include <google/protobuf/descriptor.pb.h>
 #include <google/protobuf/repeated_field.h>
 #include <google/protobuf/extension_set.h>
 #include <google/protobuf/generated_message_util.h>
@@ -309,7 +309,7 @@
        "descriptor.";
   GOOGLE_CHECK_EQ(message2->GetReflection(), this)
     << "Second argument to Swap() (of type \""
-    << message1->GetDescriptor()->full_name()
+    << message2->GetDescriptor()->full_name()
     << "\") is not compatible with this reflection object (which is for type \""
     << descriptor_->full_name()
     << "\").  Note that the exact same class is required; not just the same "
@@ -368,8 +368,11 @@
           SWAP_VALUES(DOUBLE, double);
           SWAP_VALUES(BOOL  , bool  );
           SWAP_VALUES(ENUM  , int   );
-          SWAP_VALUES(MESSAGE, Message*);
 #undef SWAP_VALUES
+        case FieldDescriptor::CPPTYPE_MESSAGE:
+          std::swap(*MutableRaw<Message*>(message1, field),
+                    *MutableRaw<Message*>(message2, field));
+          break;
 
         case FieldDescriptor::CPPTYPE_STRING:
           switch (field->options().ctype()) {
@@ -576,6 +579,20 @@
   }
 }
 
+Message* GeneratedMessageReflection::ReleaseLast(
+    Message* message,
+    const FieldDescriptor* field) const {
+  USAGE_CHECK_ALL(ReleaseLast, REPEATED, MESSAGE);
+
+  if (field->is_extension()) {
+    return static_cast<Message*>(
+        MutableExtensionSet(message)->ReleaseLast(field->number()));
+  } else {
+    return MutableRaw<RepeatedPtrFieldBase>(message, field)
+        ->ReleaseLast<GenericTypeHandler<Message> >();
+  }
+}
+
 void GeneratedMessageReflection::SwapElements(
     Message* message,
     const FieldDescriptor* field,
@@ -877,7 +894,9 @@
   }
   const EnumValueDescriptor* result =
     field->enum_type()->FindValueByNumber(value);
-  GOOGLE_CHECK(result != NULL);
+  GOOGLE_CHECK(result != NULL) << "Value " << value << " is not valid for field "
+                        << field->full_name() << " of type "
+                        << field->enum_type()->full_name() << ".";
   return result;
 }
 
@@ -907,7 +926,9 @@
   }
   const EnumValueDescriptor* result =
     field->enum_type()->FindValueByNumber(value);
-  GOOGLE_CHECK(result != NULL);
+  GOOGLE_CHECK(result != NULL) << "Value " << value << " is not valid for field "
+                        << field->full_name() << " of type "
+                        << field->enum_type()->full_name() << ".";
   return result;
 }
 
@@ -948,13 +969,15 @@
     MessageFactory* factory) const {
   USAGE_CHECK_ALL(GetMessage, SINGULAR, MESSAGE);
 
+  if (factory == NULL) factory = message_factory_;
+
   if (field->is_extension()) {
     return static_cast<const Message&>(
         GetExtensionSet(message).GetMessage(
-          field->number(), field->message_type(),
-          factory == NULL ? message_factory_ : factory));
+          field->number(), field->message_type(), factory));
   } else {
-    const Message* result = GetRaw<const Message*>(message, field);
+    const Message* result;
+    result = GetRaw<const Message*>(message, field);
     if (result == NULL) {
       result = DefaultRaw<const Message*>(field);
     }
@@ -967,17 +990,40 @@
     MessageFactory* factory) const {
   USAGE_CHECK_ALL(MutableMessage, SINGULAR, MESSAGE);
 
+  if (factory == NULL) factory = message_factory_;
+
   if (field->is_extension()) {
     return static_cast<Message*>(
-        MutableExtensionSet(message)->MutableMessage(field,
-          factory == NULL ? message_factory_ : factory));
+        MutableExtensionSet(message)->MutableMessage(field, factory));
   } else {
-    Message** result = MutableField<Message*>(message, field);
-    if (*result == NULL) {
+    Message* result;
+    Message** result_holder = MutableField<Message*>(message, field);
+    if (*result_holder == NULL) {
       const Message* default_message = DefaultRaw<const Message*>(field);
-      *result = default_message->New();
+      *result_holder = default_message->New();
     }
-    return *result;
+    result = *result_holder;
+    return result;
+  }
+}
+
+Message* GeneratedMessageReflection::ReleaseMessage(
+    Message* message,
+    const FieldDescriptor* field,
+    MessageFactory* factory) const {
+  USAGE_CHECK_ALL(ReleaseMessage, SINGULAR, MESSAGE);
+
+  if (factory == NULL) factory = message_factory_;
+
+  if (field->is_extension()) {
+    return static_cast<Message*>(
+        MutableExtensionSet(message)->ReleaseMessage(field, factory));
+  } else {
+    ClearBit(message, field);
+    Message** result = MutableRaw<Message*>(message, field);
+    Message* ret = *result;
+    *result = NULL;
+    return ret;
   }
 }
 
@@ -1022,7 +1068,7 @@
     // We can't use AddField<Message>() because RepeatedPtrFieldBase doesn't
     // know how to allocate one.
     RepeatedPtrFieldBase* repeated =
-      MutableRaw<RepeatedPtrFieldBase>(message, field);
+        MutableRaw<RepeatedPtrFieldBase>(message, field);
     Message* result = repeated->AddFromCleared<GenericTypeHandler<Message> >();
     if (result == NULL) {
       // We must allocate a new object.
@@ -1039,7 +1085,26 @@
   }
 }
 
-// -------------------------------------------------------------------
+void* GeneratedMessageReflection::MutableRawRepeatedField(
+    Message* message, const FieldDescriptor* field,
+    FieldDescriptor::CppType cpptype,
+    int ctype, const Descriptor* desc) const {
+  USAGE_CHECK_REPEATED("MutableRawRepeatedField");
+  if (field->cpp_type() != cpptype)
+    ReportReflectionUsageTypeError(descriptor_,
+        field, "MutableRawRepeatedField", cpptype);
+  if (ctype >= 0)
+    GOOGLE_CHECK_EQ(field->options().ctype(), ctype) << "subtype mismatch";
+  if (desc != NULL)
+    GOOGLE_CHECK_EQ(field->message_type(), desc) << "wrong submessage type";
+  if (field->is_extension())
+    return MutableExtensionSet(message)->MutableRawRepeatedField(
+        field->number());
+  else
+    return reinterpret_cast<uint8*>(message) + offsets_[field->index()];
+}
+
+// -----------------------------------------------------------------------------
 
 const FieldDescriptor* GeneratedMessageReflection::FindKnownExtensionByName(
     const string& name) const {
diff --git a/third_party/protobuf/src/google/protobuf/generated_message_reflection.h b/third_party/protobuf/src/google/protobuf/generated_message_reflection.h
index b545fa1..e6670ae 100644
--- a/third_party/protobuf/src/google/protobuf/generated_message_reflection.h
+++ b/third_party/protobuf/src/google/protobuf/generated_message_reflection.h
@@ -40,17 +40,23 @@
 
 #include <string>
 #include <vector>
+#include <google/protobuf/stubs/common.h>
+// TODO(jasonh): Remove this once the compiler change to directly include this
+// is released to components.
+#include <google/protobuf/generated_enum_reflection.h>
 #include <google/protobuf/message.h>
 #include <google/protobuf/unknown_field_set.h>
 
 
 namespace google {
+namespace upb {
+namespace proto2_bridge_opensource {
+class FieldAccessor;
+}  // namespace protobuf_bridge_google3
+}  // namespace upb
+
 namespace protobuf {
   class DescriptorPool;
-  // Generated code needs these to have been forward-declared.  Easier to do it
-  // here than to print them inside every .pb.h file.
-  class FileDescriptor;
-  class EnumDescriptor;
 }
 
 namespace protobuf {
@@ -141,6 +147,7 @@
   int FieldSize(const Message& message, const FieldDescriptor* field) const;
   void ClearField(Message* message, const FieldDescriptor* field) const;
   void RemoveLast(Message* message, const FieldDescriptor* field) const;
+  Message* ReleaseLast(Message* message, const FieldDescriptor* field) const;
   void Swap(Message* message1, Message* message2) const;
   void SwapElements(Message* message, const FieldDescriptor* field,
             int index1, int index2) const;
@@ -193,6 +200,8 @@
                  const EnumValueDescriptor* value) const;
   Message* MutableMessage(Message* message, const FieldDescriptor* field,
                           MessageFactory* factory = NULL) const;
+  Message* ReleaseMessage(Message* message, const FieldDescriptor* field,
+                          MessageFactory* factory = NULL) const;
 
   int32  GetRepeatedInt32 (const Message& message,
                            const FieldDescriptor* field, int index) const;
@@ -270,9 +279,18 @@
   const FieldDescriptor* FindKnownExtensionByName(const string& name) const;
   const FieldDescriptor* FindKnownExtensionByNumber(int number) const;
 
+ protected:
+  virtual void* MutableRawRepeatedField(
+      Message* message, const FieldDescriptor* field, FieldDescriptor::CppType,
+      int ctype, const Descriptor* desc) const;
+
  private:
   friend class GeneratedMessage;
 
+  // To parse directly into a proto2 generated class, FieldAccessor needs
+  // access to member offsets and hasbits.
+  friend class LIBPROTOBUF_EXPORT upb::proto2_bridge_opensource::FieldAccessor;
+
   const Descriptor* descriptor_;
   const Message* default_instance_;
   const int* offsets_;
@@ -293,7 +311,6 @@
                           const FieldDescriptor* field) const;
   template <typename Type>
   inline const Type& DefaultRaw(const FieldDescriptor* field) const;
-  inline const Message* GetMessagePrototype(const FieldDescriptor* field) const;
 
   inline const uint32* GetHasBits(const Message& message) const;
   inline uint32* MutableHasBits(Message* message) const;
@@ -395,28 +412,6 @@
 #endif
 }
 
-// Helper for EnumType_Parse functions: try to parse the string 'name' as an
-// enum name of the given type, returning true and filling in value on success,
-// or returning false and leaving value unchanged on failure.
-LIBPROTOBUF_EXPORT bool ParseNamedEnum(const EnumDescriptor* descriptor,
-                    const string& name,
-                    int* value);
-
-template<typename EnumType>
-bool ParseNamedEnum(const EnumDescriptor* descriptor,
-                    const string& name,
-                    EnumType* value) {
-  int tmp;
-  if (!ParseNamedEnum(descriptor, name, &tmp)) return false;
-  *value = static_cast<EnumType>(tmp);
-  return true;
-}
-
-// Just a wrapper around printing the name of a value. The main point of this
-// function is not to be inlined, so that you can do this without including
-// descriptor.h.
-LIBPROTOBUF_EXPORT const string& NameOfEnum(const EnumDescriptor* descriptor, int value);
-
 }  // namespace internal
 }  // namespace protobuf
 
diff --git a/third_party/protobuf/src/google/protobuf/generated_message_reflection_unittest.cc b/third_party/protobuf/src/google/protobuf/generated_message_reflection_unittest.cc
index a03bcdb..f60e430 100644
--- a/third_party/protobuf/src/google/protobuf/generated_message_reflection_unittest.cc
+++ b/third_party/protobuf/src/google/protobuf/generated_message_reflection_unittest.cc
@@ -225,11 +225,59 @@
     unittest::TestAllExtensions::descriptor());
 
   TestUtil::SetAllExtensions(&message);
+
   reflection_tester.RemoveLastRepeatedsViaReflection(&message);
 
   TestUtil::ExpectLastRepeatedExtensionsRemoved(message);
 }
 
+TEST(GeneratedMessageReflectionTest, ReleaseLast) {
+  unittest::TestAllTypes message;
+  const Descriptor* descriptor = message.GetDescriptor();
+  TestUtil::ReflectionTester reflection_tester(descriptor);
+
+  TestUtil::SetAllFields(&message);
+
+  reflection_tester.ReleaseLastRepeatedsViaReflection(&message, false);
+
+  TestUtil::ExpectLastRepeatedsReleased(message);
+
+  // Now test that we actually release the right message.
+  message.Clear();
+  TestUtil::SetAllFields(&message);
+  ASSERT_EQ(2, message.repeated_foreign_message_size());
+  const protobuf_unittest::ForeignMessage* expected =
+      message.mutable_repeated_foreign_message(1);
+  scoped_ptr<Message> released(message.GetReflection()->ReleaseLast(
+      &message, descriptor->FindFieldByName("repeated_foreign_message")));
+  EXPECT_EQ(expected, released.get());
+}
+
+TEST(GeneratedMessageReflectionTest, ReleaseLastExtensions) {
+  unittest::TestAllExtensions message;
+  const Descriptor* descriptor = message.GetDescriptor();
+  TestUtil::ReflectionTester reflection_tester(descriptor);
+
+  TestUtil::SetAllExtensions(&message);
+
+  reflection_tester.ReleaseLastRepeatedsViaReflection(&message, true);
+
+  TestUtil::ExpectLastRepeatedExtensionsReleased(message);
+
+  // Now test that we actually release the right message.
+  message.Clear();
+  TestUtil::SetAllExtensions(&message);
+  ASSERT_EQ(2, message.ExtensionSize(
+      unittest::repeated_foreign_message_extension));
+  const protobuf_unittest::ForeignMessage* expected = message.MutableExtension(
+      unittest::repeated_foreign_message_extension, 1);
+  scoped_ptr<Message> released(message.GetReflection()->ReleaseLast(
+      &message, descriptor->file()->FindExtensionByName(
+          "repeated_foreign_message_extension")));
+  EXPECT_EQ(expected, released.get());
+
+}
+
 TEST(GeneratedMessageReflectionTest, SwapRepeatedElements) {
   unittest::TestAllTypes message;
   TestUtil::ReflectionTester reflection_tester(
@@ -327,6 +375,58 @@
               FindKnownExtensionByName(extension1->full_name()) == NULL);
 }
 
+TEST(GeneratedMessageReflectionTest, ReleaseMessageTest) {
+  unittest::TestAllTypes message;
+  TestUtil::ReflectionTester reflection_tester(
+    unittest::TestAllTypes::descriptor());
+
+  // When nothing is set, we expect all released messages to be NULL.
+  reflection_tester.ExpectMessagesReleasedViaReflection(
+      &message, TestUtil::ReflectionTester::IS_NULL);
+
+  // After fields are set we should get non-NULL releases.
+  reflection_tester.SetAllFieldsViaReflection(&message);
+  reflection_tester.ExpectMessagesReleasedViaReflection(
+      &message, TestUtil::ReflectionTester::NOT_NULL);
+
+  // After Clear() we may or may not get a message from ReleaseMessage().
+  // This is implementation specific.
+  reflection_tester.SetAllFieldsViaReflection(&message);
+  message.Clear();
+  reflection_tester.ExpectMessagesReleasedViaReflection(
+      &message, TestUtil::ReflectionTester::CAN_BE_NULL);
+
+  // Test a different code path for setting after releasing.
+  TestUtil::SetAllFields(&message);
+  TestUtil::ExpectAllFieldsSet(message);
+}
+
+TEST(GeneratedMessageReflectionTest, ReleaseExtensionMessageTest) {
+  unittest::TestAllExtensions message;
+  TestUtil::ReflectionTester reflection_tester(
+    unittest::TestAllExtensions::descriptor());
+
+  // When nothing is set, we expect all released messages to be NULL.
+  reflection_tester.ExpectMessagesReleasedViaReflection(
+      &message, TestUtil::ReflectionTester::IS_NULL);
+
+  // After fields are set we should get non-NULL releases.
+  reflection_tester.SetAllFieldsViaReflection(&message);
+  reflection_tester.ExpectMessagesReleasedViaReflection(
+      &message, TestUtil::ReflectionTester::NOT_NULL);
+
+  // After Clear() we may or may not get a message from ReleaseMessage().
+  // This is implementation specific.
+  reflection_tester.SetAllFieldsViaReflection(&message);
+  message.Clear();
+  reflection_tester.ExpectMessagesReleasedViaReflection(
+      &message, TestUtil::ReflectionTester::CAN_BE_NULL);
+
+  // Test a different code path for setting after releasing.
+  TestUtil::SetAllExtensions(&message);
+  TestUtil::ExpectAllExtensionsSet(message);
+}
+
 #ifdef GTEST_HAS_DEATH_TEST
 
 TEST(GeneratedMessageReflectionTest, UsageErrors) {
diff --git a/third_party/protobuf/src/google/protobuf/generated_message_util.cc b/third_party/protobuf/src/google/protobuf/generated_message_util.cc
index 76e547b..ac32150 100644
--- a/third_party/protobuf/src/google/protobuf/generated_message_util.cc
+++ b/third_party/protobuf/src/google/protobuf/generated_message_util.cc
@@ -49,7 +49,6 @@
 
 const ::std::string kEmptyString;
 
-
 }  // namespace internal
 }  // namespace protobuf
 }  // namespace google
diff --git a/third_party/protobuf/src/google/protobuf/generated_message_util.h b/third_party/protobuf/src/google/protobuf/generated_message_util.h
index 77ae106..b2fb8f0 100644
--- a/third_party/protobuf/src/google/protobuf/generated_message_util.h
+++ b/third_party/protobuf/src/google/protobuf/generated_message_util.h
@@ -41,16 +41,8 @@
 #include <string>
 
 #include <google/protobuf/stubs/common.h>
-
-
 namespace google {
 namespace protobuf {
-  namespace io {
-    class CodedInputStream;      // coded_stream.h
-  }
-}
-
-namespace protobuf {
 namespace internal {
 
 // Annotation for the compiler to emit a deprecation message if a field marked
@@ -60,11 +52,7 @@
 // For internal use in the pb.cc files, deprecation warnings are suppressed
 // there.
 #undef DEPRECATED_PROTOBUF_FIELD
-#if !defined(INTERNAL_SUPPRESS_PROTOBUF_FIELD_DEPRECATION)
-#  define PROTOBUF_DEPRECATED GOOGLE_ATTRIBUTE_DEPRECATED
-#else
-#  define PROTOBUF_DEPRECATED
-#endif
+#define PROTOBUF_DEPRECATED
 
 
 // Constants for special floating point values.
@@ -74,6 +62,13 @@
 // Constant used for empty default strings.
 LIBPROTOBUF_EXPORT extern const ::std::string kEmptyString;
 
+// Defined in generated_message_reflection.cc -- not actually part of the lite
+// library.
+//
+// TODO(jasonh): The various callers get this declaration from a variety of
+// places: probably in most cases repeated_field.h. Clean these up so they all
+// get the declaration from this file.
+LIBPROTOBUF_EXPORT int StringSpaceUsedExcludingSelf(const string& str);
 
 }  // namespace internal
 }  // namespace protobuf
diff --git a/third_party/protobuf/src/google/protobuf/io/coded_stream.cc b/third_party/protobuf/src/google/protobuf/io/coded_stream.cc
index 402a3ad..36add8c 100644
--- a/third_party/protobuf/src/google/protobuf/io/coded_stream.cc
+++ b/third_party/protobuf/src/google/protobuf/io/coded_stream.cc
@@ -43,7 +43,7 @@
 #include <limits.h>
 #include <google/protobuf/io/zero_copy_stream.h>
 #include <google/protobuf/stubs/common.h>
-#include <google/protobuf/stubs/stl_util-inl.h>
+#include <google/protobuf/stubs/stl_util.h>
 
 
 namespace google {
@@ -69,6 +69,19 @@
 
 // CodedInputStream ==================================================
 
+CodedInputStream::~CodedInputStream() {
+  if (input_ != NULL) {
+    BackUpInputToCurrentPosition();
+  }
+
+  if (total_bytes_warning_threshold_ == -2) {
+    GOOGLE_LOG(WARNING) << "The total number of bytes read was " << total_bytes_read_;
+  }
+}
+
+// Static.
+int CodedInputStream::default_recursion_limit_ = 100;
+
 
 void CodedInputStream::BackUpInputToCurrentPosition() {
   int backup_bytes = BufferSize() + buffer_size_after_limit_ + overflow_bytes_;
@@ -98,8 +111,7 @@
 
 CodedInputStream::Limit CodedInputStream::PushLimit(int byte_limit) {
   // Current position relative to the beginning of the stream.
-  int current_position = total_bytes_read_ -
-      (BufferSize() + buffer_size_after_limit_);
+  int current_position = CurrentPosition();
 
   Limit old_limit = current_limit_;
 
@@ -133,10 +145,9 @@
   legitimate_message_end_ = false;
 }
 
-int CodedInputStream::BytesUntilLimit() {
+int CodedInputStream::BytesUntilLimit() const {
   if (current_limit_ == INT_MAX) return -1;
-  int current_position = total_bytes_read_ -
-      (BufferSize() + buffer_size_after_limit_);
+  int current_position = CurrentPosition();
 
   return current_limit_ - current_position;
 }
@@ -145,10 +156,14 @@
     int total_bytes_limit, int warning_threshold) {
   // Make sure the limit isn't already past, since this could confuse other
   // code.
-  int current_position = total_bytes_read_ -
-      (BufferSize() + buffer_size_after_limit_);
+  int current_position = CurrentPosition();
   total_bytes_limit_ = max(current_position, total_bytes_limit);
-  total_bytes_warning_threshold_ = warning_threshold;
+  if (warning_threshold >= 0) {
+    total_bytes_warning_threshold_ = warning_threshold;
+  } else {
+    // warning_threshold is negative
+    total_bytes_warning_threshold_ = -1;
+  }
   RecomputeBufferLimits();
 }
 
@@ -368,16 +383,17 @@
 
   // For the slow path, just do a 64-bit read. Try to optimize for one-byte tags
   // again, since we have now refreshed the buffer.
-  uint64 result;
+  uint64 result = 0;
   if (!ReadVarint64(&result)) return 0;
   return static_cast<uint32>(result);
 }
 
 uint32 CodedInputStream::ReadTagFallback() {
-  if (BufferSize() >= kMaxVarintBytes ||
+  const int buf_size = BufferSize();
+  if (buf_size >= kMaxVarintBytes ||
       // Optimization:  If the varint ends at exactly the end of the buffer,
       // we can detect that and still use the fast path.
-      (buffer_end_ > buffer_ && !(buffer_end_[-1] & 0x80))) {
+      (buf_size > 0 && !(buffer_end_[-1] & 0x80))) {
     uint32 tag;
     const uint8* end = ReadVarint32FromArray(buffer_, &tag);
     if (end == NULL) {
@@ -388,7 +404,9 @@
   } else {
     // We are commonly at a limit when attempting to read tags. Try to quickly
     // detect this case without making another function call.
-    if (buffer_ == buffer_end_ && buffer_size_after_limit_ > 0 &&
+    if ((buf_size == 0) &&
+        ((buffer_size_after_limit_ > 0) ||
+         (total_bytes_read_ == current_limit_)) &&
         // Make sure that the limit we hit is not total_bytes_limit_, since
         // in that case we still need to call Refresh() so that it prints an
         // error.
@@ -492,8 +510,8 @@
                       "CodedInputStream::SetTotalBytesLimit() in "
                       "google/protobuf/io/coded_stream.h.";
 
-    // Don't warn again for this stream.
-    total_bytes_warning_threshold_ = -1;
+    // Don't warn again for this stream, and print total size at the end.
+    total_bytes_warning_threshold_ = -2;
   }
 
   const void* void_buffer;
diff --git a/third_party/protobuf/src/google/protobuf/io/coded_stream.h b/third_party/protobuf/src/google/protobuf/io/coded_stream.h
index 97ac507..66cbee0 100644
--- a/third_party/protobuf/src/google/protobuf/io/coded_stream.h
+++ b/third_party/protobuf/src/google/protobuf/io/coded_stream.h
@@ -170,6 +170,9 @@
   // successfully and the stream's byte limit.
   ~CodedInputStream();
 
+  // Return true if this CodedInputStream reads from a flat array instead of
+  // a ZeroCopyInputStream.
+  inline bool IsFlat() const;
 
   // Skips a number of bytes.  Returns false if an underlying read error
   // occurs.
@@ -311,7 +314,10 @@
 
   // Returns the number of bytes left until the nearest limit on the
   // stack is hit, or -1 if no limits are in place.
-  int BytesUntilLimit();
+  int BytesUntilLimit() const;
+
+  // Returns current position relative to the beginning of the input stream.
+  int CurrentPosition() const;
 
   // Total Bytes Limit -----------------------------------------------
   // To prevent malicious users from sending excessively large messages
@@ -327,8 +333,9 @@
   // cause integer overflows is 512MB.  The default limit is 64MB.  Apps
   // should set shorter limits if possible.  If warning_threshold is not -1,
   // a warning will be printed to stderr after warning_threshold bytes are
-  // read.  An error will always be printed to stderr if the limit is
-  // reached.
+  // read.  For backwards compatibility all negative values get squached to -1,
+  // as other negative values might have special internal meanings.
+  // An error will always be printed to stderr if the limit is reached.
   //
   // This is unrelated to PushLimit()/PopLimit().
   //
@@ -355,9 +362,10 @@
   // messages and groups.  CodedInputStream keeps track of this because it
   // is the only object that is passed down the stack during parsing.
 
-  // Sets the maximum recursion depth.  The default is 64.
+  // Sets the maximum recursion depth.  The default is 100.
   void SetRecursionLimit(int limit);
 
+
   // Increments the current recursion depth.  Returns true if the depth is
   // under the limit, false if it has gone over.
   bool IncrementRecursionDepth();
@@ -433,7 +441,8 @@
   //
   // Note that this feature is ignored when parsing "lite" messages as they do
   // not have descriptors.
-  void SetExtensionRegistry(DescriptorPool* pool, MessageFactory* factory);
+  void SetExtensionRegistry(const DescriptorPool* pool,
+                            MessageFactory* factory);
 
   // Get the DescriptorPool set via SetExtensionRegistry(), or NULL if no pool
   // has been provided.
@@ -482,6 +491,11 @@
   // Maximum number of bytes to read, period.  This is unrelated to
   // current_limit_.  Set using SetTotalBytesLimit().
   int total_bytes_limit_;
+
+  // If positive/0: Limit for bytes read after which a warning due to size
+  // should be logged.
+  // If -1: Printing of warning disabled. Can be set by client.
+  // If -2: Internal: Limit has been reached, print full size when destructing.
   int total_bytes_warning_threshold_;
 
   // Current recursion depth, controlled by IncrementRecursionDepth() and
@@ -539,7 +553,8 @@
   static const int kDefaultTotalBytesLimit = 64 << 20;  // 64MB
 
   static const int kDefaultTotalBytesWarningThreshold = 32 << 20;  // 32MB
-  static const int kDefaultRecursionLimit = 64;
+
+  static int default_recursion_limit_;  // 100 by default.
 };
 
 // Class which encodes and writes binary data which is composed of varint-
@@ -891,7 +906,9 @@
   // If we are at a limit we know no more bytes can be read.  Otherwise, it's
   // hard to say without calling Refresh(), and we'd rather not do that.
 
-  if (buffer_ == buffer_end_ && buffer_size_after_limit_ != 0) {
+  if (buffer_ == buffer_end_ &&
+      ((buffer_size_after_limit_ != 0) ||
+       (total_bytes_read_ == current_limit_))) {
     last_tag_ = 0;                   // Pretend we called ReadTag()...
     legitimate_message_end_ = true;  // ... and it hit EOF.
     return true;
@@ -900,6 +917,10 @@
   }
 }
 
+inline int CodedInputStream::CurrentPosition() const {
+  return total_bytes_read_ - (BufferSize() + buffer_size_after_limit_);
+}
+
 inline uint8* CodedOutputStream::GetDirectBufferForNBytesAndAdvance(int size) {
   if (buffer_size_ < size) {
     return NULL;
@@ -1039,7 +1060,7 @@
   if (recursion_depth_ > 0) --recursion_depth_;
 }
 
-inline void CodedInputStream::SetExtensionRegistry(DescriptorPool* pool,
+inline void CodedInputStream::SetExtensionRegistry(const DescriptorPool* pool,
                                                    MessageFactory* factory) {
   extension_pool_ = pool;
   extension_factory_ = factory;
@@ -1071,7 +1092,7 @@
     total_bytes_limit_(kDefaultTotalBytesLimit),
     total_bytes_warning_threshold_(kDefaultTotalBytesWarningThreshold),
     recursion_depth_(0),
-    recursion_limit_(kDefaultRecursionLimit),
+    recursion_limit_(default_recursion_limit_),
     extension_pool_(NULL),
     extension_factory_(NULL) {
   // Eagerly Refresh() so buffer space is immediately available.
@@ -1092,17 +1113,15 @@
     total_bytes_limit_(kDefaultTotalBytesLimit),
     total_bytes_warning_threshold_(kDefaultTotalBytesWarningThreshold),
     recursion_depth_(0),
-    recursion_limit_(kDefaultRecursionLimit),
+    recursion_limit_(default_recursion_limit_),
     extension_pool_(NULL),
     extension_factory_(NULL) {
   // Note that setting current_limit_ == size is important to prevent some
   // code paths from trying to access input_ and segfaulting.
 }
 
-inline CodedInputStream::~CodedInputStream() {
-  if (input_ != NULL) {
-    BackUpInputToCurrentPosition();
-  }
+inline bool CodedInputStream::IsFlat() const {
+  return input_ == NULL;
 }
 
 }  // namespace io
diff --git a/third_party/protobuf/src/google/protobuf/io/coded_stream_inl.h b/third_party/protobuf/src/google/protobuf/io/coded_stream_inl.h
index 8156602..144f44f 100644
--- a/third_party/protobuf/src/google/protobuf/io/coded_stream_inl.h
+++ b/third_party/protobuf/src/google/protobuf/io/coded_stream_inl.h
@@ -38,7 +38,7 @@
 
 #include <google/protobuf/io/coded_stream.h>
 #include <string>
-#include <google/protobuf/stubs/stl_util-inl.h>
+#include <google/protobuf/stubs/stl_util.h>
 
 namespace google {
 namespace protobuf {
diff --git a/third_party/protobuf/src/google/protobuf/io/coded_stream_unittest.cc b/third_party/protobuf/src/google/protobuf/io/coded_stream_unittest.cc
index ff268ab..2daab19 100644
--- a/third_party/protobuf/src/google/protobuf/io/coded_stream_unittest.cc
+++ b/third_party/protobuf/src/google/protobuf/io/coded_stream_unittest.cc
@@ -44,7 +44,6 @@
 #include <google/protobuf/testing/googletest.h>
 #include <gtest/gtest.h>
 #include <google/protobuf/io/zero_copy_stream_impl.h>
-#include <google/protobuf/stubs/strutil.h>
 
 
 // This declares an unsigned long long integer literal in a portable way.
@@ -125,6 +124,13 @@
 
 class CodedStreamTest : public testing::Test {
  protected:
+  // Helper method used by tests for bytes warning. See implementation comment
+  // for further information.
+  static void SetupTotalBytesLimitWarningTest(
+      int total_bytes_limit, int warning_threshold,
+      vector<string>* out_errors, vector<string>* out_warnings);
+
+  // Buffer used during most of the tests. This assumes tests run sequentially.
   static const int kBufferSize = 1024 * 64;
   static uint8 buffer_[kBufferSize];
 };
@@ -1022,6 +1028,59 @@
   EXPECT_FALSE(coded_input.ConsumedEntireMessage());
 }
 
+// This method is used by the tests below.
+// It constructs a CodedInputStream with the given limits and tries to read 2KiB
+// of data from it. Then it returns the logged errors and warnings in the given
+// vectors.
+void CodedStreamTest::SetupTotalBytesLimitWarningTest(
+    int total_bytes_limit, int warning_threshold,
+    vector<string>* out_errors, vector<string>* out_warnings) {
+  ArrayInputStream raw_input(buffer_, sizeof(buffer_), 128);
+
+  ScopedMemoryLog scoped_log;
+  {
+    CodedInputStream input(&raw_input);
+    input.SetTotalBytesLimit(total_bytes_limit, warning_threshold);
+    string str;
+    EXPECT_TRUE(input.ReadString(&str, 2048));
+  }
+
+  *out_errors = scoped_log.GetMessages(ERROR);
+  *out_warnings = scoped_log.GetMessages(WARNING);
+}
+
+TEST_F(CodedStreamTest, TotalBytesLimitWarning) {
+  vector<string> errors;
+  vector<string> warnings;
+  SetupTotalBytesLimitWarningTest(10240, 1024, &errors, &warnings);
+
+  EXPECT_EQ(0, errors.size());
+
+  ASSERT_EQ(2, warnings.size());
+  EXPECT_PRED_FORMAT2(testing::IsSubstring,
+    "Reading dangerously large protocol message.  If the message turns out to "
+    "be larger than 10240 bytes, parsing will be halted for security reasons.",
+    warnings[0]);
+  EXPECT_PRED_FORMAT2(testing::IsSubstring,
+    "The total number of bytes read was 2048",
+    warnings[1]);
+}
+
+TEST_F(CodedStreamTest, TotalBytesLimitWarningDisabled) {
+  vector<string> errors;
+  vector<string> warnings;
+
+  // Test with -1
+  SetupTotalBytesLimitWarningTest(10240, -1, &errors, &warnings);
+  EXPECT_EQ(0, errors.size());
+  EXPECT_EQ(0, warnings.size());
+
+  // Test again with -2, expecting the same result
+  SetupTotalBytesLimitWarningTest(10240, -2, &errors, &warnings);
+  EXPECT_EQ(0, errors.size());
+  EXPECT_EQ(0, warnings.size());
+}
+
 
 TEST_F(CodedStreamTest, RecursionLimit) {
   ArrayInputStream input(buffer_, sizeof(buffer_));
@@ -1060,6 +1119,7 @@
   EXPECT_FALSE(coded_input.IncrementRecursionDepth());     // 7
 }
 
+
 class ReallyBigInputStream : public ZeroCopyInputStream {
  public:
   ReallyBigInputStream() : backup_amount_(0), buffer_count_(0) {}
diff --git a/third_party/protobuf/src/google/protobuf/io/gzip_stream.cc b/third_party/protobuf/src/google/protobuf/io/gzip_stream.cc
index 0f1ff87..fe1f331 100644
--- a/third_party/protobuf/src/google/protobuf/io/gzip_stream.cc
+++ b/third_party/protobuf/src/google/protobuf/io/gzip_stream.cc
@@ -199,16 +199,6 @@
   Init(sub_stream, options);
 }
 
-GzipOutputStream::GzipOutputStream(
-    ZeroCopyOutputStream* sub_stream, Format format, int buffer_size) {
-  Options options;
-  options.format = format;
-  if (buffer_size != -1) {
-    options.buffer_size = buffer_size;
-  }
-  Init(sub_stream, options);
-}
-
 void GzipOutputStream::Init(ZeroCopyOutputStream* sub_stream,
                             const Options& options) {
   sub_stream_ = sub_stream;
@@ -309,10 +299,11 @@
 }
 
 bool GzipOutputStream::Flush() {
-  do {
-    zerror_ = Deflate(Z_FULL_FLUSH);
-  } while (zerror_ == Z_OK);
-  return zerror_ == Z_OK;
+  zerror_ = Deflate(Z_FULL_FLUSH);
+  // Return true if the flush succeeded or if it was a no-op.
+  return  (zerror_ == Z_OK) ||
+      (zerror_ == Z_BUF_ERROR && zcontext_.avail_in == 0 &&
+       zcontext_.avail_out != 0);
 }
 
 bool GzipOutputStream::Close() {
diff --git a/third_party/protobuf/src/google/protobuf/io/gzip_stream.h b/third_party/protobuf/src/google/protobuf/io/gzip_stream.h
index 65dbc5b..7ee24bc 100644
--- a/third_party/protobuf/src/google/protobuf/io/gzip_stream.h
+++ b/third_party/protobuf/src/google/protobuf/io/gzip_stream.h
@@ -45,6 +45,7 @@
 
 #include <zlib.h>
 
+#include <google/protobuf/stubs/common.h>
 #include <google/protobuf/io/zero_copy_stream.h>
 
 namespace google {
@@ -144,12 +145,6 @@
       ZeroCopyOutputStream* sub_stream,
       const Options& options);
 
-  // DEPRECATED:  Use one of the above constructors instead.
-  GzipOutputStream(
-      ZeroCopyOutputStream* sub_stream,
-      Format format,
-      int buffer_size = -1) GOOGLE_ATTRIBUTE_DEPRECATED;
-
   virtual ~GzipOutputStream();
 
   // Return last error message or NULL if no error.
@@ -165,6 +160,13 @@
   // necessary.
   // Compression may be less efficient stopping and starting around flushes.
   // Returns true if no error.
+  //
+  // Please ensure that block size is > 6. Here is an excerpt from the zlib
+  // doc that explains why:
+  //
+  // In the case of a Z_FULL_FLUSH or Z_SYNC_FLUSH, make sure that avail_out
+  // is greater than six to avoid repeated flush markers due to
+  // avail_out == 0 on return.
   bool Flush();
 
   // Writes out all data and closes the gzip stream.
diff --git a/third_party/protobuf/src/google/protobuf/io/printer.cc b/third_party/protobuf/src/google/protobuf/io/printer.cc
index 9ab90de..d2bf3f5 100644
--- a/third_party/protobuf/src/google/protobuf/io/printer.cc
+++ b/third_party/protobuf/src/google/protobuf/io/printer.cc
@@ -35,7 +35,6 @@
 #include <google/protobuf/io/printer.h>
 #include <google/protobuf/io/zero_copy_stream.h>
 #include <google/protobuf/stubs/common.h>
-#include <google/protobuf/stubs/strutil.h>
 
 namespace google {
 namespace protobuf {
@@ -51,8 +50,8 @@
 }
 
 Printer::~Printer() {
-  // Only BackUp() if we're sure we've successfully called Next() at least once.
-  if (buffer_size_ > 0) {
+  // Only BackUp() if we have called Next() at least once and never failed.
+  if (buffer_size_ > 0 && !failed_) {
     output_->BackUp(buffer_size_);
   }
 }
@@ -169,7 +168,7 @@
   if (failed_) return;
   if (size == 0) return;
 
-  if (at_start_of_line_) {
+  if (at_start_of_line_ && (size > 0) && (data[0] != '\n')) {
     // Insert an indent.
     at_start_of_line_ = false;
     WriteRaw(indent_.data(), indent_.size());
diff --git a/third_party/protobuf/src/google/protobuf/io/printer_unittest.cc b/third_party/protobuf/src/google/protobuf/io/printer_unittest.cc
index 580a53d..399395c 100644
--- a/third_party/protobuf/src/google/protobuf/io/printer_unittest.cc
+++ b/third_party/protobuf/src/google/protobuf/io/printer_unittest.cc
@@ -233,7 +233,31 @@
 }
 #endif  // GTEST_HAS_DEATH_TEST
 
-TEST(Printer, WriteFailure) {
+TEST(Printer, WriteFailurePartial) {
+  char buffer[17];
+
+  ArrayOutputStream output(buffer, sizeof(buffer));
+  Printer printer(&output, '$');
+
+  // Print 16 bytes to almost fill the buffer (should not fail).
+  printer.Print("0123456789abcdef");
+  EXPECT_FALSE(printer.failed());
+
+  // Try to print 2 chars. Only one fits.
+  printer.Print("<>");
+  EXPECT_TRUE(printer.failed());
+
+  // Anything else should fail too.
+  printer.Print(" ");
+  EXPECT_TRUE(printer.failed());
+  printer.Print("blah");
+  EXPECT_TRUE(printer.failed());
+
+  // Buffer should contain the first 17 bytes written.
+  EXPECT_EQ("0123456789abcdef<", string(buffer, sizeof(buffer)));
+}
+
+TEST(Printer, WriteFailureExact) {
   char buffer[16];
 
   ArrayOutputStream output(buffer, sizeof(buffer));
diff --git a/third_party/protobuf/src/google/protobuf/io/tokenizer.cc b/third_party/protobuf/src/google/protobuf/io/tokenizer.cc
index 513831d..a022b71 100644
--- a/third_party/protobuf/src/google/protobuf/io/tokenizer.cc
+++ b/third_party/protobuf/src/google/protobuf/io/tokenizer.cc
@@ -89,8 +89,11 @@
 // exactly pretty.
 
 #include <google/protobuf/io/tokenizer.h>
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/stringprintf.h>
 #include <google/protobuf/io/zero_copy_stream.h>
 #include <google/protobuf/stubs/strutil.h>
+#include <google/protobuf/stubs/stl_util.h>
 
 namespace google {
 namespace protobuf {
@@ -118,6 +121,8 @@
 
 CHARACTER_CLASS(Whitespace, c == ' ' || c == '\n' || c == '\t' ||
                             c == '\r' || c == '\v' || c == '\f');
+CHARACTER_CLASS(WhitespaceNoNewline, c == ' ' || c == '\t' ||
+                                     c == '\r' || c == '\v' || c == '\f');
 
 CHARACTER_CLASS(Unprintable, c < ' ' && c > '\0');
 
@@ -187,7 +192,8 @@
     read_error_(false),
     line_(0),
     column_(0),
-    token_start_(-1),
+    record_target_(NULL),
+    record_start_(-1),
     allow_f_after_float_(false),
     comment_style_(CPP_COMMENT_STYLE) {
 
@@ -238,9 +244,9 @@
   }
 
   // If we're in a token, append the rest of the buffer to it.
-  if (token_start_ >= 0 && token_start_ < buffer_size_) {
-    current_.text.append(buffer_ + token_start_, buffer_size_ - token_start_);
-    token_start_ = 0;
+  if (record_target_ != NULL && record_start_ < buffer_size_) {
+    record_target_->append(buffer_ + record_start_, buffer_size_ - record_start_);
+    record_start_ = 0;
   }
 
   const void* data = NULL;
@@ -261,23 +267,33 @@
   current_char_ = buffer_[0];
 }
 
-inline void Tokenizer::StartToken() {
-  token_start_ = buffer_pos_;
-  current_.type = TYPE_START;    // Just for the sake of initializing it.
-  current_.text.clear();
-  current_.line = line_;
-  current_.column = column_;
+inline void Tokenizer::RecordTo(string* target) {
+  record_target_ = target;
+  record_start_ = buffer_pos_;
 }
 
-inline void Tokenizer::EndToken() {
+inline void Tokenizer::StopRecording() {
   // Note:  The if() is necessary because some STL implementations crash when
   //   you call string::append(NULL, 0), presumably because they are trying to
   //   be helpful by detecting the NULL pointer, even though there's nothing
   //   wrong with reading zero bytes from NULL.
-  if (buffer_pos_ != token_start_) {
-    current_.text.append(buffer_ + token_start_, buffer_pos_ - token_start_);
+  if (buffer_pos_ != record_start_) {
+    record_target_->append(buffer_ + record_start_, buffer_pos_ - record_start_);
   }
-  token_start_ = -1;
+  record_target_ = NULL;
+  record_start_ = -1;
+}
+
+inline void Tokenizer::StartToken() {
+  current_.type = TYPE_START;    // Just for the sake of initializing it.
+  current_.text.clear();
+  current_.line = line_;
+  current_.column = column_;
+  RecordTo(&current_.text);
+}
+
+inline void Tokenizer::EndToken() {
+  StopRecording();
   current_.end_column = column_;
 }
 
@@ -353,6 +369,27 @@
             AddError("Expected hex digits for escape sequence.");
           }
           // Possibly followed by another hex digit, but again we don't care.
+        } else if (TryConsume('u')) {
+          if (!TryConsumeOne<HexDigit>() ||
+              !TryConsumeOne<HexDigit>() ||
+              !TryConsumeOne<HexDigit>() ||
+              !TryConsumeOne<HexDigit>()) {
+            AddError("Expected four hex digits for \\u escape sequence.");
+          }
+        } else if (TryConsume('U')) {
+          // We expect 8 hex digits; but only the range up to 0x10ffff is
+          // legal.
+          if (!TryConsume('0') ||
+              !TryConsume('0') ||
+              !(TryConsume('0') || TryConsume('1')) ||
+              !TryConsumeOne<HexDigit>() ||
+              !TryConsumeOne<HexDigit>() ||
+              !TryConsumeOne<HexDigit>() ||
+              !TryConsumeOne<HexDigit>() ||
+              !TryConsumeOne<HexDigit>()) {
+            AddError("Expected eight hex digits up to 10ffff for \\U escape "
+                     "sequence");
+          }
         } else {
           AddError("Invalid escape sequence in string literal.");
         }
@@ -426,26 +463,51 @@
   return is_float ? TYPE_FLOAT : TYPE_INTEGER;
 }
 
-void Tokenizer::ConsumeLineComment() {
+void Tokenizer::ConsumeLineComment(string* content) {
+  if (content != NULL) RecordTo(content);
+
   while (current_char_ != '\0' && current_char_ != '\n') {
     NextChar();
   }
   TryConsume('\n');
+
+  if (content != NULL) StopRecording();
 }
 
-void Tokenizer::ConsumeBlockComment() {
+void Tokenizer::ConsumeBlockComment(string* content) {
   int start_line = line_;
   int start_column = column_ - 2;
 
+  if (content != NULL) RecordTo(content);
+
   while (true) {
     while (current_char_ != '\0' &&
            current_char_ != '*' &&
-           current_char_ != '/') {
+           current_char_ != '/' &&
+           current_char_ != '\n') {
       NextChar();
     }
 
-    if (TryConsume('*') && TryConsume('/')) {
+    if (TryConsume('\n')) {
+      if (content != NULL) StopRecording();
+
+      // Consume leading whitespace and asterisk;
+      ConsumeZeroOrMore<WhitespaceNoNewline>();
+      if (TryConsume('*')) {
+        if (TryConsume('/')) {
+          // End of comment.
+          break;
+        }
+      }
+
+      if (content != NULL) RecordTo(content);
+    } else if (TryConsume('*') && TryConsume('/')) {
       // End of comment.
+      if (content != NULL) {
+        StopRecording();
+        // Strip trailing "*/".
+        content->erase(content->size() - 2);
+      }
       break;
     } else if (TryConsume('/') && current_char_ == '*') {
       // Note:  We didn't consume the '*' because if there is a '/' after it
@@ -456,42 +518,59 @@
       AddError("End-of-file inside block comment.");
       error_collector_->AddError(
         start_line, start_column, "  Comment started here.");
+      if (content != NULL) StopRecording();
       break;
     }
   }
 }
 
+Tokenizer::NextCommentStatus Tokenizer::TryConsumeCommentStart() {
+  if (comment_style_ == CPP_COMMENT_STYLE && TryConsume('/')) {
+    if (TryConsume('/')) {
+      return LINE_COMMENT;
+    } else if (TryConsume('*')) {
+      return BLOCK_COMMENT;
+    } else {
+      // Oops, it was just a slash.  Return it.
+      current_.type = TYPE_SYMBOL;
+      current_.text = "/";
+      current_.line = line_;
+      current_.column = column_ - 1;
+      current_.end_column = column_;
+      return SLASH_NOT_COMMENT;
+    }
+  } else if (comment_style_ == SH_COMMENT_STYLE && TryConsume('#')) {
+    return LINE_COMMENT;
+  } else {
+    return NO_COMMENT;
+  }
+}
+
 // -------------------------------------------------------------------
 
 bool Tokenizer::Next() {
   previous_ = current_;
 
-  // Did we skip any characters after the last token?
-  bool skipped_stuff = false;
-
   while (!read_error_) {
-    if (TryConsumeOne<Whitespace>()) {
-      ConsumeZeroOrMore<Whitespace>();
+    ConsumeZeroOrMore<Whitespace>();
 
-    } else if (comment_style_ == CPP_COMMENT_STYLE && TryConsume('/')) {
-      // Starting a comment?
-      if (TryConsume('/')) {
-        ConsumeLineComment();
-      } else if (TryConsume('*')) {
-        ConsumeBlockComment();
-      } else {
-        // Oops, it was just a slash.  Return it.
-        current_.type = TYPE_SYMBOL;
-        current_.text = "/";
-        current_.line = line_;
-        current_.column = column_ - 1;
+    switch (TryConsumeCommentStart()) {
+      case LINE_COMMENT:
+        ConsumeLineComment(NULL);
+        continue;
+      case BLOCK_COMMENT:
+        ConsumeBlockComment(NULL);
+        continue;
+      case SLASH_NOT_COMMENT:
         return true;
-      }
+      case NO_COMMENT:
+        break;
+    }
 
-    } else if (comment_style_ == SH_COMMENT_STYLE && TryConsume('#')) {
-      ConsumeLineComment();
+    // Check for EOF before continuing.
+    if (read_error_) break;
 
-    } else if (LookingAt<Unprintable>() || current_char_ == '\0') {
+    if (LookingAt<Unprintable>() || current_char_ == '\0') {
       AddError("Invalid control characters encountered in text.");
       NextChar();
       // Skip more unprintable characters, too.  But, remember that '\0' is
@@ -519,7 +598,9 @@
 
         if (TryConsumeOne<Digit>()) {
           // It's a floating-point number.
-          if (previous_.type == TYPE_IDENTIFIER && !skipped_stuff) {
+          if (previous_.type == TYPE_IDENTIFIER &&
+              current_.line == previous_.line &&
+              current_.column == previous_.end_column) {
             // We don't accept syntax like "blah.123".
             error_collector_->AddError(line_, column_ - 2,
               "Need space between identifier and decimal point.");
@@ -544,8 +625,6 @@
       EndToken();
       return true;
     }
-
-    skipped_stuff = true;
   }
 
   // EOF
@@ -557,6 +636,195 @@
   return false;
 }
 
+namespace {
+
+// Helper class for collecting comments and putting them in the right places.
+//
+// This basically just buffers the most recent comment until it can be decided
+// exactly where that comment should be placed.  When Flush() is called, the
+// current comment goes into either prev_trailing_comments or detached_comments.
+// When the CommentCollector is destroyed, the last buffered comment goes into
+// next_leading_comments.
+class CommentCollector {
+ public:
+  CommentCollector(string* prev_trailing_comments,
+                   vector<string>* detached_comments,
+                   string* next_leading_comments)
+      : prev_trailing_comments_(prev_trailing_comments),
+        detached_comments_(detached_comments),
+        next_leading_comments_(next_leading_comments),
+        has_comment_(false),
+        is_line_comment_(false),
+        can_attach_to_prev_(true) {
+    if (prev_trailing_comments != NULL) prev_trailing_comments->clear();
+    if (detached_comments != NULL) detached_comments->clear();
+    if (next_leading_comments != NULL) next_leading_comments->clear();
+  }
+
+  ~CommentCollector() {
+    // Whatever is in the buffer is a leading comment.
+    if (next_leading_comments_ != NULL && has_comment_) {
+      comment_buffer_.swap(*next_leading_comments_);
+    }
+  }
+
+  // About to read a line comment.  Get the comment buffer pointer in order to
+  // read into it.
+  string* GetBufferForLineComment() {
+    // We want to combine with previous line comments, but not block comments.
+    if (has_comment_ && !is_line_comment_) {
+      Flush();
+    }
+    has_comment_ = true;
+    is_line_comment_ = true;
+    return &comment_buffer_;
+  }
+
+  // About to read a block comment.  Get the comment buffer pointer in order to
+  // read into it.
+  string* GetBufferForBlockComment() {
+    if (has_comment_) {
+      Flush();
+    }
+    has_comment_ = true;
+    is_line_comment_ = false;
+    return &comment_buffer_;
+  }
+
+  void ClearBuffer() {
+    comment_buffer_.clear();
+    has_comment_ = false;
+  }
+
+  // Called once we know that the comment buffer is complete and is *not*
+  // connected to the next token.
+  void Flush() {
+    if (has_comment_) {
+      if (can_attach_to_prev_) {
+        if (prev_trailing_comments_ != NULL) {
+          prev_trailing_comments_->append(comment_buffer_);
+        }
+        can_attach_to_prev_ = false;
+      } else {
+        if (detached_comments_ != NULL) {
+          detached_comments_->push_back(comment_buffer_);
+        }
+      }
+      ClearBuffer();
+    }
+  }
+
+  void DetachFromPrev() {
+    can_attach_to_prev_ = false;
+  }
+
+ private:
+  string* prev_trailing_comments_;
+  vector<string>* detached_comments_;
+  string* next_leading_comments_;
+
+  string comment_buffer_;
+
+  // True if any comments were read into comment_buffer_.  This can be true even
+  // if comment_buffer_ is empty, namely if the comment was "/**/".
+  bool has_comment_;
+
+  // Is the comment in the comment buffer a line comment?
+  bool is_line_comment_;
+
+  // Is it still possible that we could be reading a comment attached to the
+  // previous token?
+  bool can_attach_to_prev_;
+};
+
+} // namespace
+
+bool Tokenizer::NextWithComments(string* prev_trailing_comments,
+                                 vector<string>* detached_comments,
+                                 string* next_leading_comments) {
+  CommentCollector collector(prev_trailing_comments, detached_comments,
+                             next_leading_comments);
+
+  if (current_.type == TYPE_START) {
+    collector.DetachFromPrev();
+  } else {
+    // A comment appearing on the same line must be attached to the previous
+    // declaration.
+    ConsumeZeroOrMore<WhitespaceNoNewline>();
+    switch (TryConsumeCommentStart()) {
+      case LINE_COMMENT:
+        ConsumeLineComment(collector.GetBufferForLineComment());
+
+        // Don't allow comments on subsequent lines to be attached to a trailing
+        // comment.
+        collector.Flush();
+        break;
+      case BLOCK_COMMENT:
+        ConsumeBlockComment(collector.GetBufferForBlockComment());
+
+        ConsumeZeroOrMore<WhitespaceNoNewline>();
+        if (!TryConsume('\n')) {
+          // Oops, the next token is on the same line.  If we recorded a comment
+          // we really have no idea which token it should be attached to.
+          collector.ClearBuffer();
+          return Next();
+        }
+
+        // Don't allow comments on subsequent lines to be attached to a trailing
+        // comment.
+        collector.Flush();
+        break;
+      case SLASH_NOT_COMMENT:
+        return true;
+      case NO_COMMENT:
+        if (!TryConsume('\n')) {
+          // The next token is on the same line.  There are no comments.
+          return Next();
+        }
+        break;
+    }
+  }
+
+  // OK, we are now on the line *after* the previous token.
+  while (true) {
+    ConsumeZeroOrMore<WhitespaceNoNewline>();
+
+    switch (TryConsumeCommentStart()) {
+      case LINE_COMMENT:
+        ConsumeLineComment(collector.GetBufferForLineComment());
+        break;
+      case BLOCK_COMMENT:
+        ConsumeBlockComment(collector.GetBufferForBlockComment());
+
+        // Consume the rest of the line so that we don't interpret it as a
+        // blank line the next time around the loop.
+        ConsumeZeroOrMore<WhitespaceNoNewline>();
+        TryConsume('\n');
+        break;
+      case SLASH_NOT_COMMENT:
+        return true;
+      case NO_COMMENT:
+        if (TryConsume('\n')) {
+          // Completely blank line.
+          collector.Flush();
+          collector.DetachFromPrev();
+        } else {
+          bool result = Next();
+          if (!result ||
+              current_.text == "}" ||
+              current_.text == "]" ||
+              current_.text == ")") {
+            // It looks like we're at the end of a scope.  In this case it
+            // makes no sense to attach a comment to the following token.
+            collector.Flush();
+          }
+          return result;
+        }
+        break;
+    }
+  }
+}
+
 // -------------------------------------------------------------------
 // Token-parsing helpers.  Remember that these don't need to report
 // errors since any errors should already have been reported while
@@ -626,17 +894,138 @@
   return result;
 }
 
+// Helper to append a Unicode code point to a string as UTF8, without bringing
+// in any external dependencies.
+static void AppendUTF8(uint32 code_point, string* output) {
+  uint32 tmp = 0;
+  int len = 0;
+  if (code_point <= 0x7f) {
+    tmp = code_point;
+    len = 1;
+  } else if (code_point <= 0x07ff) {
+    tmp = 0x0000c080 |
+        ((code_point & 0x07c0) << 2) |
+        (code_point & 0x003f);
+    len = 2;
+  } else if (code_point <= 0xffff) {
+    tmp = 0x00e08080 |
+        ((code_point & 0xf000) << 4) |
+        ((code_point & 0x0fc0) << 2) |
+        (code_point & 0x003f);
+    len = 3;
+  } else if (code_point <= 0x1fffff) {
+    tmp = 0xf0808080 |
+        ((code_point & 0x1c0000) << 6) |
+        ((code_point & 0x03f000) << 4) |
+        ((code_point & 0x000fc0) << 2) |
+        (code_point & 0x003f);
+    len = 4;
+  } else {
+    // UTF-16 is only defined for code points up to 0x10FFFF, and UTF-8 is
+    // normally only defined up to there as well.
+    StringAppendF(output, "\\U%08x", code_point);
+    return;
+  }
+  tmp = ghtonl(tmp);
+  output->append(reinterpret_cast<const char*>(&tmp) + sizeof(tmp) - len, len);
+}
+
+// Try to read <len> hex digits from ptr, and stuff the numeric result into
+// *result. Returns true if that many digits were successfully consumed.
+static bool ReadHexDigits(const char* ptr, int len, uint32* result) {
+  *result = 0;
+  if (len == 0) return false;
+  for (const char* end = ptr + len; ptr < end; ++ptr) {
+    if (*ptr == '\0') return false;
+    *result = (*result << 4) + DigitValue(*ptr);
+  }
+  return true;
+}
+
+// Handling UTF-16 surrogate pairs. UTF-16 encodes code points in the range
+// 0x10000...0x10ffff as a pair of numbers, a head surrogate followed by a trail
+// surrogate. These numbers are in a reserved range of Unicode code points, so
+// if we encounter such a pair we know how to parse it and convert it into a
+// single code point.
+static const uint32 kMinHeadSurrogate = 0xd800;
+static const uint32 kMaxHeadSurrogate = 0xdc00;
+static const uint32 kMinTrailSurrogate = 0xdc00;
+static const uint32 kMaxTrailSurrogate = 0xe000;
+
+static inline bool IsHeadSurrogate(uint32 code_point) {
+  return (code_point >= kMinHeadSurrogate) && (code_point < kMaxHeadSurrogate);
+}
+
+static inline bool IsTrailSurrogate(uint32 code_point) {
+  return (code_point >= kMinTrailSurrogate) &&
+      (code_point < kMaxTrailSurrogate);
+}
+
+// Combine a head and trail surrogate into a single Unicode code point.
+static uint32 AssembleUTF16(uint32 head_surrogate, uint32 trail_surrogate) {
+  GOOGLE_DCHECK(IsHeadSurrogate(head_surrogate));
+  GOOGLE_DCHECK(IsTrailSurrogate(trail_surrogate));
+  return 0x10000 + (((head_surrogate - kMinHeadSurrogate) << 10) |
+      (trail_surrogate - kMinTrailSurrogate));
+}
+
+// Convert the escape sequence parameter to a number of expected hex digits.
+static inline int UnicodeLength(char key) {
+  if (key == 'u') return 4;
+  if (key == 'U') return 8;
+  return 0;
+}
+
+// Given a pointer to the 'u' or 'U' starting a Unicode escape sequence, attempt
+// to parse that sequence. On success, returns a pointer to the first char
+// beyond that sequence, and fills in *code_point. On failure, returns ptr
+// itself.
+static const char* FetchUnicodePoint(const char* ptr, uint32* code_point) {
+  const char* p = ptr;
+  // Fetch the code point.
+  const int len = UnicodeLength(*p++);
+  if (!ReadHexDigits(p, len, code_point))
+    return ptr;
+  p += len;
+
+  // Check if the code point we read is a "head surrogate." If so, then we
+  // expect it to be immediately followed by another code point which is a valid
+  // "trail surrogate," and together they form a UTF-16 pair which decodes into
+  // a single Unicode point. Trail surrogates may only use \u, not \U.
+  if (IsHeadSurrogate(*code_point) && *p == '\\' && *(p + 1) == 'u') {
+    uint32 trail_surrogate;
+    if (ReadHexDigits(p + 2, 4, &trail_surrogate) &&
+        IsTrailSurrogate(trail_surrogate)) {
+      *code_point = AssembleUTF16(*code_point, trail_surrogate);
+      p += 6;
+    }
+    // If this failed, then we just emit the head surrogate as a code point.
+    // It's bogus, but so is the string.
+  }
+
+  return p;
+}
+
+// The text string must begin and end with single or double quote
+// characters.
 void Tokenizer::ParseStringAppend(const string& text, string* output) {
-  // Reminder:  text[0] is always the quote character.  (If text is
-  //   empty, it's invalid, so we'll just return.)
-  if (text.empty()) {
+  // Reminder: text[0] is always a quote character.  (If text is
+  // empty, it's invalid, so we'll just return).
+  const size_t text_size = text.size();
+  if (text_size == 0) {
     GOOGLE_LOG(DFATAL)
       << " Tokenizer::ParseStringAppend() passed text that could not"
          " have been tokenized as a string: " << CEscape(text);
     return;
   }
 
-  output->reserve(output->size() + text.size());
+  // Reserve room for new string. The branch is necessary because if
+  // there is already space available the reserve() call might
+  // downsize the output.
+  const size_t new_len = text_size + output->size();
+  if (new_len > output->capacity()) {
+    output->reserve(new_len);
+  }
 
   // Loop through the string copying characters to "output" and
   // interpreting escape sequences.  Note that any invalid escape
@@ -674,19 +1063,27 @@
         }
         output->push_back(static_cast<char>(code));
 
+      } else if (*ptr == 'u' || *ptr == 'U') {
+        uint32 unicode;
+        const char* end = FetchUnicodePoint(ptr, &unicode);
+        if (end == ptr) {
+          // Failure: Just dump out what we saw, don't try to parse it.
+          output->push_back(*ptr);
+        } else {
+          AppendUTF8(unicode, output);
+          ptr = end - 1;  // Because we're about to ++ptr.
+        }
       } else {
         // Some other escape code.
         output->push_back(TranslateEscape(*ptr));
       }
 
-    } else if (*ptr == text[0]) {
-      // Ignore quote matching the starting quote.
+    } else if (*ptr == text[0] && ptr[1] == '\0') {
+      // Ignore final quote matching the starting quote.
     } else {
       output->push_back(*ptr);
     }
   }
-
-  return;
 }
 
 }  // namespace io
diff --git a/third_party/protobuf/src/google/protobuf/io/tokenizer.h b/third_party/protobuf/src/google/protobuf/io/tokenizer.h
index 8f759ab..d85b82f 100644
--- a/third_party/protobuf/src/google/protobuf/io/tokenizer.h
+++ b/third_party/protobuf/src/google/protobuf/io/tokenizer.h
@@ -38,6 +38,7 @@
 #define GOOGLE_PROTOBUF_IO_TOKENIZER_H__
 
 #include <string>
+#include <vector>
 #include <google/protobuf/stubs/common.h>
 
 namespace google {
@@ -137,6 +138,53 @@
   // reached.
   bool Next();
 
+  // Like Next(), but also collects comments which appear between the previous
+  // and next tokens.
+  //
+  // Comments which appear to be attached to the previous token are stored
+  // in *prev_tailing_comments.  Comments which appear to be attached to the
+  // next token are stored in *next_leading_comments.  Comments appearing in
+  // between which do not appear to be attached to either will be added to
+  // detached_comments.  Any of these parameters can be NULL to simply discard
+  // the comments.
+  //
+  // A series of line comments appearing on consecutive lines, with no other
+  // tokens appearing on those lines, will be treated as a single comment.
+  //
+  // Only the comment content is returned; comment markers (e.g. //) are
+  // stripped out.  For block comments, leading whitespace and an asterisk will
+  // be stripped from the beginning of each line other than the first.  Newlines
+  // are included in the output.
+  //
+  // Examples:
+  //
+  //   optional int32 foo = 1;  // Comment attached to foo.
+  //   // Comment attached to bar.
+  //   optional int32 bar = 2;
+  //
+  //   optional string baz = 3;
+  //   // Comment attached to baz.
+  //   // Another line attached to baz.
+  //
+  //   // Comment attached to qux.
+  //   //
+  //   // Another line attached to qux.
+  //   optional double qux = 4;
+  //
+  //   // Detached comment.  This is not attached to qux or corge
+  //   // because there are blank lines separating it from both.
+  //
+  //   optional string corge = 5;
+  //   /* Block comment attached
+  //    * to corge.  Leading asterisks
+  //    * will be removed. */
+  //   /* Block comment attached to
+  //    * grault. */
+  //   optional int32 grault = 6;
+  bool NextWithComments(string* prev_trailing_comments,
+                        vector<string>* detached_comments,
+                        string* next_leading_comments);
+
   // Parse helpers ---------------------------------------------------
 
   // Parses a TYPE_FLOAT token.  This never fails, so long as the text actually
@@ -200,11 +248,12 @@
   int line_;
   int column_;
 
-  // Position in buffer_ where StartToken() was called.  If the token
-  // started in the previous buffer, this is zero, and current_.text already
-  // contains the part of the token from the previous buffer.  If not
-  // currently parsing a token, this is -1.
-  int token_start_;
+  // String to which text should be appended as we advance through it.
+  // Call RecordTo(&str) to start recording and StopRecording() to stop.
+  // E.g. StartToken() calls RecordTo(&current_.text).  record_start_ is the
+  // position within the current buffer where recording started.
+  string* record_target_;
+  int record_start_;
 
   // Options.
   bool allow_f_after_float_;
@@ -223,6 +272,9 @@
   // Read a new buffer from the input.
   void Refresh();
 
+  inline void RecordTo(string* target);
+  inline void StopRecording();
+
   // Called when the current character is the first character of a new
   // token (not including whitespace or comments).
   inline void StartToken();
@@ -255,9 +307,28 @@
   TokenType ConsumeNumber(bool started_with_zero, bool started_with_dot);
 
   // Consume the rest of a line.
-  void ConsumeLineComment();
+  void ConsumeLineComment(string* content);
   // Consume until "*/".
-  void ConsumeBlockComment();
+  void ConsumeBlockComment(string* content);
+
+  enum NextCommentStatus {
+    // Started a line comment.
+    LINE_COMMENT,
+
+    // Started a block comment.
+    BLOCK_COMMENT,
+
+    // Consumed a slash, then realized it wasn't a comment.  current_ has
+    // been filled in with a slash token.  The caller should return it.
+    SLASH_NOT_COMMENT,
+
+    // We do not appear to be starting a comment here.
+    NO_COMMENT
+  };
+
+  // If we're at the start of a new comment, consume it and return what kind
+  // of comment it is.
+  NextCommentStatus TryConsumeCommentStart();
 
   // -----------------------------------------------------------------
   // These helper methods make the parsing code more readable.  The
diff --git a/third_party/protobuf/src/google/protobuf/io/tokenizer_unittest.cc b/third_party/protobuf/src/google/protobuf/io/tokenizer_unittest.cc
index 106d080..8de4393 100644
--- a/third_party/protobuf/src/google/protobuf/io/tokenizer_unittest.cc
+++ b/third_party/protobuf/src/google/protobuf/io/tokenizer_unittest.cc
@@ -32,9 +32,10 @@
 //  Based on original Protocol Buffers design by
 //  Sanjay Ghemawat, Jeff Dean, and others.
 
-#include <vector>
-#include <math.h>
 #include <limits.h>
+#include <math.h>
+
+#include <vector>
 
 #include <google/protobuf/io/tokenizer.h>
 #include <google/protobuf/io/zero_copy_stream_impl.h>
@@ -514,6 +515,217 @@
 
 // -------------------------------------------------------------------
 
+// In each case, the input is expected to have two tokens named "prev" and
+// "next" with comments in between.
+struct DocCommentCase {
+  string input;
+
+  const char* prev_trailing_comments;
+  const char* detached_comments[10];
+  const char* next_leading_comments;
+};
+
+inline ostream& operator<<(ostream& out,
+                           const DocCommentCase& test_case) {
+  return out << CEscape(test_case.input);
+}
+
+DocCommentCase kDocCommentCases[] = {
+  {
+    "prev next",
+
+    "",
+    {},
+    ""
+      },
+
+        {
+      "prev /* ignored */ next",
+
+      "",
+      {},
+      ""
+        },
+
+          {
+        "prev // trailing comment\n"
+            "next",
+
+            " trailing comment\n",
+            {},
+            ""
+          },
+
+            {
+          "prev\n"
+              "// leading comment\n"
+              "// line 2\n"
+              "next",
+
+              "",
+              {},
+              " leading comment\n"
+              " line 2\n"
+            },
+
+              {
+            "prev\n"
+                "// trailing comment\n"
+                "// line 2\n"
+                "\n"
+                "next",
+
+                " trailing comment\n"
+                " line 2\n",
+                {},
+                ""
+              },
+
+                {
+              "prev // trailing comment\n"
+                  "// leading comment\n"
+                  "// line 2\n"
+                  "next",
+
+                  " trailing comment\n",
+                  {},
+                  " leading comment\n"
+                  " line 2\n"
+                },
+
+                  {
+                "prev /* trailing block comment */\n"
+                    "/* leading block comment\n"
+                    " * line 2\n"
+                    " * line 3 */"
+                    "next",
+
+                    " trailing block comment ",
+                    {},
+                    " leading block comment\n"
+                    " line 2\n"
+                    " line 3 "
+                  },
+
+                    {
+                  "prev\n"
+                      "/* trailing block comment\n"
+                      " * line 2\n"
+                      " * line 3\n"
+                      " */\n"
+                      "/* leading block comment\n"
+                      " * line 2\n"
+                      " * line 3 */"
+                      "next",
+
+                      " trailing block comment\n"
+                      " line 2\n"
+                      " line 3\n",
+                      {},
+                      " leading block comment\n"
+                      " line 2\n"
+                      " line 3 "
+                    },
+
+                      {
+                    "prev\n"
+                        "// trailing comment\n"
+                        "\n"
+                        "// detached comment\n"
+                        "// line 2\n"
+                        "\n"
+                        "// second detached comment\n"
+                        "/* third detached comment\n"
+                        " * line 2 */\n"
+                        "// leading comment\n"
+                        "next",
+
+                        " trailing comment\n",
+                        {
+                      " detached comment\n"
+                          " line 2\n",
+                          " second detached comment\n",
+                          " third detached comment\n"
+                          " line 2 "
+                        },
+                          " leading comment\n"
+                        },
+
+                          {
+                        "prev /**/\n"
+                            "\n"
+                            "// detached comment\n"
+                            "\n"
+                            "// leading comment\n"
+                            "next",
+
+                            "",
+                            {
+                          " detached comment\n"
+                            },
+                              " leading comment\n"
+                            },
+
+                              {
+                            "prev /**/\n"
+                                "// leading comment\n"
+                                "next",
+
+                                "",
+                                {},
+                                " leading comment\n"
+                              },
+                              };
+
+TEST_2D(TokenizerTest, DocComments, kDocCommentCases, kBlockSizes) {
+  // Set up the tokenizer.
+  TestInputStream input(kDocCommentCases_case.input.data(),
+                        kDocCommentCases_case.input.size(),
+                        kBlockSizes_case);
+  TestErrorCollector error_collector;
+  Tokenizer tokenizer(&input, &error_collector);
+
+  // Set up a second tokenizer where we'll pass all NULLs to NextWithComments().
+  TestInputStream input2(kDocCommentCases_case.input.data(),
+                        kDocCommentCases_case.input.size(),
+                        kBlockSizes_case);
+  Tokenizer tokenizer2(&input2, &error_collector);
+
+  tokenizer.Next();
+  tokenizer2.Next();
+
+  EXPECT_EQ("prev", tokenizer.current().text);
+  EXPECT_EQ("prev", tokenizer2.current().text);
+
+  string prev_trailing_comments;
+  vector<string> detached_comments;
+  string next_leading_comments;
+  tokenizer.NextWithComments(&prev_trailing_comments, &detached_comments,
+                             &next_leading_comments);
+  tokenizer2.NextWithComments(NULL, NULL, NULL);
+  EXPECT_EQ("next", tokenizer.current().text);
+  EXPECT_EQ("next", tokenizer2.current().text);
+
+  EXPECT_EQ(kDocCommentCases_case.prev_trailing_comments,
+            prev_trailing_comments);
+
+  for (int i = 0; i < detached_comments.size(); i++) {
+    ASSERT_LT(i, GOOGLE_ARRAYSIZE(kDocCommentCases));
+    ASSERT_TRUE(kDocCommentCases_case.detached_comments[i] != NULL);
+    EXPECT_EQ(kDocCommentCases_case.detached_comments[i],
+              detached_comments[i]);
+  }
+
+  // Verify that we matched all the detached comments.
+  EXPECT_EQ(NULL,
+      kDocCommentCases_case.detached_comments[detached_comments.size()]);
+
+  EXPECT_EQ(kDocCommentCases_case.next_leading_comments,
+            next_leading_comments);
+}
+
+// -------------------------------------------------------------------
+
 // Test parse helpers.  It's not really worth setting up a full data-driven
 // test here.
 TEST_F(TokenizerTest, ParseInteger) {
@@ -614,6 +826,22 @@
   Tokenizer::ParseString("'\\", &output);
   EXPECT_EQ("\\", output);
 
+  // Experiment with Unicode escapes. Here are one-, two- and three-byte Unicode
+  // characters.
+  Tokenizer::ParseString("'\\u0024\\u00a2\\u20ac\\U00024b62XX'", &output);
+  EXPECT_EQ("$¢€𤭢XX", output);
+  // Same thing encoded using UTF16.
+  Tokenizer::ParseString("'\\u0024\\u00a2\\u20ac\\ud852\\udf62XX'", &output);
+  EXPECT_EQ("$¢€𤭢XX", output);
+  // Here's some broken UTF16; there's a head surrogate with no tail surrogate.
+  // We just output this as if it were UTF8; it's not a defined code point, but
+  // it has a defined encoding.
+  Tokenizer::ParseString("'\\ud852XX'", &output);
+  EXPECT_EQ("\xed\xa1\x92XX", output);
+  // Malformed escape: Demons may fly out of the nose.
+  Tokenizer::ParseString("\\u0", &output);
+  EXPECT_EQ("u0", output);
+
   // Test invalid strings that will never be tokenized as strings.
 #ifdef GTEST_HAS_DEATH_TEST  // death tests do not work on Windows yet
   EXPECT_DEBUG_DEATH(Tokenizer::ParseString("", &output),
@@ -658,6 +886,12 @@
     "0:4: String literals cannot cross line boundaries.\n" },
   { "'bar\nfoo", true,
     "0:4: String literals cannot cross line boundaries.\n" },
+  { "'\\u01' foo", true,
+    "0:5: Expected four hex digits for \\u escape sequence.\n" },
+  { "'\\u01' foo", true,
+    "0:5: Expected four hex digits for \\u escape sequence.\n" },
+  { "'\\uXYZ' foo", true,
+    "0:3: Expected four hex digits for \\u escape sequence.\n" },
 
   // Integer errors.
   { "123foo", true,
@@ -734,7 +968,7 @@
   }
 
   // Check that the errors match what was expected.
-  EXPECT_EQ(error_collector.text_, kErrorCases_case.errors);
+  EXPECT_EQ(kErrorCases_case.errors, error_collector.text_);
 
   // If the error was recoverable, make sure we saw "foo" after it.
   if (kErrorCases_case.recoverable) {
@@ -760,6 +994,7 @@
   EXPECT_EQ(strlen("foo"), input.ByteCount());
 }
 
+
 }  // namespace
 }  // namespace io
 }  // namespace protobuf
diff --git a/third_party/protobuf/src/google/protobuf/io/zero_copy_stream_impl.cc b/third_party/protobuf/src/google/protobuf/io/zero_copy_stream_impl.cc
index 1384c74..9fcbb62 100644
--- a/third_party/protobuf/src/google/protobuf/io/zero_copy_stream_impl.cc
+++ b/third_party/protobuf/src/google/protobuf/io/zero_copy_stream_impl.cc
@@ -46,7 +46,8 @@
 
 #include <google/protobuf/io/zero_copy_stream_impl.h>
 #include <google/protobuf/stubs/common.h>
-#include <google/protobuf/stubs/stl_util-inl.h>
+#include <google/protobuf/stubs/stl_util.h>
+
 
 namespace google {
 namespace protobuf {
diff --git a/third_party/protobuf/src/google/protobuf/io/zero_copy_stream_impl_lite.cc b/third_party/protobuf/src/google/protobuf/io/zero_copy_stream_impl_lite.cc
index e801251..f552e1f 100644
--- a/third_party/protobuf/src/google/protobuf/io/zero_copy_stream_impl_lite.cc
+++ b/third_party/protobuf/src/google/protobuf/io/zero_copy_stream_impl_lite.cc
@@ -32,9 +32,9 @@
 //  Based on original Protocol Buffers design by
 //  Sanjay Ghemawat, Jeff Dean, and others.
 
-#include <google/protobuf/io/zero_copy_stream_impl.h>
+#include <google/protobuf/io/zero_copy_stream_impl_lite.h>
 #include <google/protobuf/stubs/common.h>
-#include <google/protobuf/stubs/stl_util-inl.h>
+#include <google/protobuf/stubs/stl_util.h>
 
 namespace google {
 namespace protobuf {
diff --git a/third_party/protobuf/src/google/protobuf/io/zero_copy_stream_unittest.cc b/third_party/protobuf/src/google/protobuf/io/zero_copy_stream_unittest.cc
index 5196d90..6f155df 100644
--- a/third_party/protobuf/src/google/protobuf/io/zero_copy_stream_unittest.cc
+++ b/third_party/protobuf/src/google/protobuf/io/zero_copy_stream_unittest.cc
@@ -370,6 +370,100 @@
   delete [] buffer;
 }
 
+TEST_F(IoTest, GzipIoWithFlush) {
+  const int kBufferSize = 2*1024;
+  uint8* buffer = new uint8[kBufferSize];
+  // We start with i = 4 as we want a block size > 6. With block size <= 6
+  // Flush() fills up the entire 2K buffer with flush markers and the test
+  // fails. See documentation for Flush() for more detail.
+  for (int i = 4; i < kBlockSizeCount; i++) {
+    for (int j = 0; j < kBlockSizeCount; j++) {
+      for (int z = 0; z < kBlockSizeCount; z++) {
+        int gzip_buffer_size = kBlockSizes[z];
+        int size;
+        {
+          ArrayOutputStream output(buffer, kBufferSize, kBlockSizes[i]);
+          GzipOutputStream::Options options;
+          options.format = GzipOutputStream::GZIP;
+          if (gzip_buffer_size != -1) {
+            options.buffer_size = gzip_buffer_size;
+          }
+          GzipOutputStream gzout(&output, options);
+          WriteStuff(&gzout);
+          EXPECT_TRUE(gzout.Flush());
+          gzout.Close();
+          size = output.ByteCount();
+        }
+        {
+          ArrayInputStream input(buffer, size, kBlockSizes[j]);
+          GzipInputStream gzin(
+              &input, GzipInputStream::GZIP, gzip_buffer_size);
+          ReadStuff(&gzin);
+        }
+      }
+    }
+  }
+  delete [] buffer;
+}
+
+TEST_F(IoTest, GzipIoContiguousFlushes) {
+  const int kBufferSize = 2*1024;
+  uint8* buffer = new uint8[kBufferSize];
+
+  int block_size = kBlockSizes[4];
+  int gzip_buffer_size = block_size;
+  int size;
+
+  ArrayOutputStream output(buffer, kBufferSize, block_size);
+  GzipOutputStream::Options options;
+  options.format = GzipOutputStream::GZIP;
+  if (gzip_buffer_size != -1) {
+    options.buffer_size = gzip_buffer_size;
+  }
+  GzipOutputStream gzout(&output, options);
+  WriteStuff(&gzout);
+  EXPECT_TRUE(gzout.Flush());
+  EXPECT_TRUE(gzout.Flush());
+  gzout.Close();
+  size = output.ByteCount();
+
+  ArrayInputStream input(buffer, size, block_size);
+  GzipInputStream gzin(
+      &input, GzipInputStream::GZIP, gzip_buffer_size);
+  ReadStuff(&gzin);
+
+  delete [] buffer;
+}
+
+TEST_F(IoTest, GzipIoReadAfterFlush) {
+  const int kBufferSize = 2*1024;
+  uint8* buffer = new uint8[kBufferSize];
+
+  int block_size = kBlockSizes[4];
+  int gzip_buffer_size = block_size;
+  int size;
+  ArrayOutputStream output(buffer, kBufferSize, block_size);
+  GzipOutputStream::Options options;
+  options.format = GzipOutputStream::GZIP;
+  if (gzip_buffer_size != -1) {
+    options.buffer_size = gzip_buffer_size;
+  }
+
+  GzipOutputStream gzout(&output, options);
+  WriteStuff(&gzout);
+  EXPECT_TRUE(gzout.Flush());
+  size = output.ByteCount();
+
+  ArrayInputStream input(buffer, size, block_size);
+  GzipInputStream gzin(
+      &input, GzipInputStream::GZIP, gzip_buffer_size);
+  ReadStuff(&gzin);
+
+  gzout.Close();
+
+  delete [] buffer;
+}
+
 TEST_F(IoTest, ZlibIo) {
   const int kBufferSize = 2*1024;
   uint8* buffer = new uint8[kBufferSize];
diff --git a/third_party/protobuf/src/google/protobuf/lite_unittest.cc b/third_party/protobuf/src/google/protobuf/lite_unittest.cc
index ffeec3c..7a0a57b 100644
--- a/third_party/protobuf/src/google/protobuf/lite_unittest.cc
+++ b/third_party/protobuf/src/google/protobuf/lite_unittest.cc
@@ -33,11 +33,32 @@
 #include <string>
 #include <iostream>
 
-#include <google/protobuf/test_util_lite.h>
 #include <google/protobuf/stubs/common.h>
+#include <google/protobuf/test_util_lite.h>
+#include <google/protobuf/unittest_lite.pb.h>
 
 using namespace std;
 
+namespace {
+// Helper methods to test parsing merge behavior.
+void ExpectMessageMerged(const google::protobuf::unittest::TestAllTypesLite& message) {
+  GOOGLE_CHECK(message.optional_int32() == 3);
+  GOOGLE_CHECK(message.optional_int64() == 2);
+  GOOGLE_CHECK(message.optional_string() == "hello");
+}
+
+void AssignParsingMergeMessages(
+    google::protobuf::unittest::TestAllTypesLite* msg1,
+    google::protobuf::unittest::TestAllTypesLite* msg2,
+    google::protobuf::unittest::TestAllTypesLite* msg3) {
+  msg1->set_optional_int32(1);
+  msg2->set_optional_int64(2);
+  msg3->set_optional_int32(3);
+  msg3->set_optional_string("hello");
+}
+
+}  // namespace
+
 int main(int argc, char* argv[]) {
   string data, packed_data;
 
@@ -107,6 +128,58 @@
     google::protobuf::TestUtilLite::ExpectPackedExtensionsClear(message);
   }
 
+  {
+    // Test that if an optional or required message/group field appears multiple
+    // times in the input, they need to be merged.
+    google::protobuf::unittest::TestParsingMergeLite::RepeatedFieldsGenerator generator;
+    google::protobuf::unittest::TestAllTypesLite* msg1;
+    google::protobuf::unittest::TestAllTypesLite* msg2;
+    google::protobuf::unittest::TestAllTypesLite* msg3;
+
+#define ASSIGN_REPEATED_FIELD(FIELD)                \
+  msg1 = generator.add_##FIELD();                   \
+  msg2 = generator.add_##FIELD();                   \
+  msg3 = generator.add_##FIELD();                   \
+  AssignParsingMergeMessages(msg1, msg2, msg3)
+
+    ASSIGN_REPEATED_FIELD(field1);
+    ASSIGN_REPEATED_FIELD(field2);
+    ASSIGN_REPEATED_FIELD(field3);
+    ASSIGN_REPEATED_FIELD(ext1);
+    ASSIGN_REPEATED_FIELD(ext2);
+
+#undef ASSIGN_REPEATED_FIELD
+#define ASSIGN_REPEATED_GROUP(FIELD)                \
+  msg1 = generator.add_##FIELD()->mutable_field1(); \
+  msg2 = generator.add_##FIELD()->mutable_field1(); \
+  msg3 = generator.add_##FIELD()->mutable_field1(); \
+  AssignParsingMergeMessages(msg1, msg2, msg3)
+
+    ASSIGN_REPEATED_GROUP(group1);
+    ASSIGN_REPEATED_GROUP(group2);
+
+#undef ASSIGN_REPEATED_GROUP
+
+    string buffer;
+    generator.SerializeToString(&buffer);
+    google::protobuf::unittest::TestParsingMergeLite parsing_merge;
+    parsing_merge.ParseFromString(buffer);
+
+    // Required and optional fields should be merged.
+    ExpectMessageMerged(parsing_merge.required_all_types());
+    ExpectMessageMerged(parsing_merge.optional_all_types());
+    ExpectMessageMerged(
+        parsing_merge.optionalgroup().optional_group_all_types());
+    ExpectMessageMerged(parsing_merge.GetExtension(
+        google::protobuf::unittest::TestParsingMergeLite::optional_ext));
+
+    // Repeated fields should not be merged.
+    GOOGLE_CHECK(parsing_merge.repeated_all_types_size() == 3);
+    GOOGLE_CHECK(parsing_merge.repeatedgroup_size() == 3);
+    GOOGLE_CHECK(parsing_merge.ExtensionSize(
+        google::protobuf::unittest::TestParsingMergeLite::repeated_ext) == 3);
+  }
+
   cout << "PASS" << endl;
   return 0;
 }
diff --git a/third_party/protobuf/src/google/protobuf/message.cc b/third_party/protobuf/src/google/protobuf/message.cc
index 0409a94..ab7efa9 100644
--- a/third_party/protobuf/src/google/protobuf/message.cc
+++ b/third_party/protobuf/src/google/protobuf/message.cc
@@ -44,11 +44,12 @@
 #include <google/protobuf/io/zero_copy_stream_impl.h>
 #include <google/protobuf/descriptor.pb.h>
 #include <google/protobuf/descriptor.h>
+#include <google/protobuf/generated_message_util.h>
 #include <google/protobuf/reflection_ops.h>
 #include <google/protobuf/wire_format.h>
 #include <google/protobuf/stubs/strutil.h>
 #include <google/protobuf/stubs/map-util.h>
-#include <google/protobuf/stubs/stl_util-inl.h>
+#include <google/protobuf/stubs/stl_util.h>
 
 namespace google {
 namespace protobuf {
@@ -182,9 +183,46 @@
 }
 
 
+// =============================================================================
+// Reflection and associated Template Specializations
+
 Reflection::~Reflection() {}
 
-// ===================================================================
+#define HANDLE_TYPE(TYPE, CPPTYPE, CTYPE)                             \
+template<>                                                            \
+const RepeatedField<TYPE>& Reflection::GetRepeatedField<TYPE>(        \
+    const Message& message, const FieldDescriptor* field) const {     \
+  return *static_cast<RepeatedField<TYPE>* >(                         \
+      MutableRawRepeatedField(const_cast<Message*>(&message),         \
+                          field, CPPTYPE, CTYPE, NULL));              \
+}                                                                     \
+                                                                      \
+template<>                                                            \
+RepeatedField<TYPE>* Reflection::MutableRepeatedField<TYPE>(          \
+    Message* message, const FieldDescriptor* field) const {           \
+  return static_cast<RepeatedField<TYPE>* >(                          \
+      MutableRawRepeatedField(message, field, CPPTYPE, CTYPE, NULL)); \
+}
+
+HANDLE_TYPE(int32,  FieldDescriptor::CPPTYPE_INT32,  -1);
+HANDLE_TYPE(int64,  FieldDescriptor::CPPTYPE_INT64,  -1);
+HANDLE_TYPE(uint32, FieldDescriptor::CPPTYPE_UINT32, -1);
+HANDLE_TYPE(uint64, FieldDescriptor::CPPTYPE_UINT64, -1);
+HANDLE_TYPE(float,  FieldDescriptor::CPPTYPE_FLOAT,  -1);
+HANDLE_TYPE(double, FieldDescriptor::CPPTYPE_DOUBLE, -1);
+HANDLE_TYPE(bool,   FieldDescriptor::CPPTYPE_BOOL,   -1);
+
+
+#undef HANDLE_TYPE
+
+void* Reflection::MutableRawRepeatedString(
+    Message* message, const FieldDescriptor* field, bool is_string) const {
+  return MutableRawRepeatedField(message, field,
+      FieldDescriptor::CPPTYPE_STRING, FieldOptions::STRING, NULL);
+}
+
+
+// =============================================================================
 // MessageFactory
 
 MessageFactory::~MessageFactory() {}
@@ -258,6 +296,7 @@
   }
 }
 
+
 const Message* GeneratedMessageFactory::GetPrototype(const Descriptor* type) {
   {
     ReaderMutexLock lock(&mutex_);
diff --git a/third_party/protobuf/src/google/protobuf/message.h b/third_party/protobuf/src/google/protobuf/message.h
index 4bbc641..77faa9a 100644
--- a/third_party/protobuf/src/google/protobuf/message.h
+++ b/third_party/protobuf/src/google/protobuf/message.h
@@ -79,18 +79,19 @@
 //     // Same as the last block, but do it dynamically via the Message
 //     // reflection interface.
 //     Message* foo = new Foo;
-//     Descriptor* descriptor = foo->GetDescriptor();
+//     const Descriptor* descriptor = foo->GetDescriptor();
 //
 //     // Get the descriptors for the fields we're interested in and verify
 //     // their types.
-//     FieldDescriptor* text_field = descriptor->FindFieldByName("text");
+//     const FieldDescriptor* text_field = descriptor->FindFieldByName("text");
 //     assert(text_field != NULL);
 //     assert(text_field->type() == FieldDescriptor::TYPE_STRING);
-//     assert(text_field->label() == FieldDescriptor::TYPE_OPTIONAL);
-//     FieldDescriptor* numbers_field = descriptor->FindFieldByName("numbers");
+//     assert(text_field->label() == FieldDescriptor::LABEL_OPTIONAL);
+//     const FieldDescriptor* numbers_field = descriptor->
+//                                            FindFieldByName("numbers");
 //     assert(numbers_field != NULL);
 //     assert(numbers_field->type() == FieldDescriptor::TYPE_INT32);
-//     assert(numbers_field->label() == FieldDescriptor::TYPE_REPEATED);
+//     assert(numbers_field->label() == FieldDescriptor::LABEL_REPEATED);
 //
 //     // Parse the message.
 //     foo->ParseFromString(data);
@@ -122,6 +123,7 @@
 #include <google/protobuf/message_lite.h>
 
 #include <google/protobuf/stubs/common.h>
+#include <google/protobuf/descriptor.h>
 
 
 namespace google {
@@ -133,17 +135,20 @@
 class MessageFactory;
 
 // Defined in other files.
-class Descriptor;            // descriptor.h
-class FieldDescriptor;       // descriptor.h
-class EnumDescriptor;        // descriptor.h
-class EnumValueDescriptor;   // descriptor.h
+class UnknownFieldSet;         // unknown_field_set.h
 namespace io {
   class ZeroCopyInputStream;   // zero_copy_stream.h
   class ZeroCopyOutputStream;  // zero_copy_stream.h
   class CodedInputStream;      // coded_stream.h
   class CodedOutputStream;     // coded_stream.h
 }
-class UnknownFieldSet;       // unknown_field_set.h
+
+
+template<typename T>
+class RepeatedField;     // repeated_field.h
+
+template<typename T>
+class RepeatedPtrField;  // repeated_field.h
 
 // A container to hold message metadata.
 struct Metadata {
@@ -151,12 +156,6 @@
   const Reflection* reflection;
 };
 
-// Returns the EnumDescriptor for enum type E, which must be a
-// proto-declared enum type.  Code generated by the protocol compiler
-// will include specializations of this template for each enum type declared.
-template <typename E>
-const EnumDescriptor* GetEnumDescriptor();
-
 // Abstract interface for protocol messages.
 //
 // See also MessageLite, which contains most every-day operations.  Message
@@ -360,7 +359,6 @@
 //   write fields from a Reflection without paying attention to the type.
 class LIBPROTOBUF_EXPORT Reflection {
  public:
-  // TODO(kenton):  Remove parameter.
   inline Reflection() {}
   virtual ~Reflection();
 
@@ -390,7 +388,7 @@
   virtual void ClearField(Message* message,
                           const FieldDescriptor* field) const = 0;
 
-  // Remove the last element of a repeated field.
+  // Removes the last element of a repeated field.
   // We don't provide a way to remove any element other than the last
   // because it invites inefficient use, such as O(n^2) filtering loops
   // that should have been O(n).  If you want to remove an element other
@@ -399,6 +397,10 @@
   // call RemoveLast().
   virtual void RemoveLast(Message* message,
                           const FieldDescriptor* field) const = 0;
+  // Removes the last element of a repeated message field, and returns the
+  // pointer to the caller.  Caller takes ownership of the returned pointer.
+  virtual Message* ReleaseLast(Message* message,
+                               const FieldDescriptor* field) const = 0;
 
   // Swap the complete contents of two messages.
   virtual void Swap(Message* message1, Message* message2) const = 0;
@@ -500,6 +502,16 @@
   virtual Message* MutableMessage(Message* message,
                                   const FieldDescriptor* field,
                                   MessageFactory* factory = NULL) const = 0;
+  // Releases the message specified by 'field' and returns the pointer,
+  // ReleaseMessage() will return the message the message object if it exists.
+  // Otherwise, it may or may not return NULL.  In any case, if the return value
+  // is non-NULL, the caller takes ownership of the pointer.
+  // If the field existed (HasField() is true), then the returned pointer will
+  // be the same as the pointer returned by MutableMessage().
+  // This function has the same effect as ClearField().
+  virtual Message* ReleaseMessage(Message* message,
+                                  const FieldDescriptor* field,
+                                  MessageFactory* factory = NULL) const = 0;
 
 
   // Repeated field getters ------------------------------------------
@@ -607,7 +619,39 @@
                               MessageFactory* factory = NULL) const = 0;
 
 
-  // Extensions ------------------------------------------------------
+  // Repeated field accessors  -------------------------------------------------
+  // The methods above, e.g. GetRepeatedInt32(msg, fd, index), provide singular
+  // access to the data in a RepeatedField.  The methods below provide aggregate
+  // access by exposing the RepeatedField object itself with the Message.
+  // Applying these templates to inappropriate types will lead to an undefined
+  // reference at link time (e.g. GetRepeatedField<***double>), or possibly a
+  // template matching error at compile time (e.g. GetRepeatedPtrField<File>).
+  //
+  // Usage example: my_doubs = refl->GetRepeatedField<double>(msg, fd);
+
+  // for T = Cord and all protobuf scalar types except enums.
+  template<typename T>
+  const RepeatedField<T>& GetRepeatedField(
+      const Message&, const FieldDescriptor*) const;
+
+  // for T = Cord and all protobuf scalar types except enums.
+  template<typename T>
+  RepeatedField<T>* MutableRepeatedField(
+      Message*, const FieldDescriptor*) const;
+
+  // for T = string, google::protobuf::internal::StringPieceField
+  //         google::protobuf::Message & descendants.
+  template<typename T>
+  const RepeatedPtrField<T>& GetRepeatedPtrField(
+      const Message&, const FieldDescriptor*) const;
+
+  // for T = string, google::protobuf::internal::StringPieceField
+  //         google::protobuf::Message & descendants.
+  template<typename T>
+  RepeatedPtrField<T>* MutableRepeatedPtrField(
+      Message*, const FieldDescriptor*) const;
+
+  // Extensions ----------------------------------------------------------------
 
   // Try to find an extension of this message type by fully-qualified field
   // name.  Returns NULL if no extension is known for this name or number.
@@ -619,7 +663,26 @@
   virtual const FieldDescriptor* FindKnownExtensionByNumber(
       int number) const = 0;
 
+  // ---------------------------------------------------------------------------
+
+ protected:
+  // Obtain a pointer to a Repeated Field Structure and do some type checking:
+  //   on field->cpp_type(),
+  //   on field->field_option().ctype() (if ctype >= 0)
+  //   of field->message_type() (if message_type != NULL).
+  // We use 1 routine rather than 4 (const vs mutable) x (scalar vs pointer).
+  virtual void* MutableRawRepeatedField(
+      Message* message, const FieldDescriptor* field, FieldDescriptor::CppType,
+      int ctype, const Descriptor* message_type) const = 0;
+
  private:
+  // Special version for specialized implementations of string.  We can't call
+  // MutableRawRepeatedField directly here because we don't have access to
+  // FieldOptions::* which are defined in descriptor.pb.h.  Including that
+  // file here is not possible because it would cause a circular include cycle.
+  void* MutableRawRepeatedString(
+      Message* message, const FieldDescriptor* field, bool is_string) const;
+
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Reflection);
 };
 
@@ -682,10 +745,71 @@
   static void InternalRegisterGeneratedMessage(const Descriptor* descriptor,
                                                const Message* prototype);
 
+
  private:
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageFactory);
 };
 
+// =============================================================================
+// Implementation details for {Get,Mutable}RawRepeatedPtrField.  We provide
+// specializations for <string>, <StringPieceField> and <Message> and handle
+// everything else with the default template which will match any type having
+// a method with signature "static const google::protobuf::Descriptor* descriptor()".
+// Such a type presumably is a descendant of google::protobuf::Message.
+
+template<>
+inline const RepeatedPtrField<string>& Reflection::GetRepeatedPtrField<string>(
+    const Message& message, const FieldDescriptor* field) const {
+  return *static_cast<RepeatedPtrField<string>* >(
+      MutableRawRepeatedString(const_cast<Message*>(&message), field, true));
+}
+
+template<>
+inline RepeatedPtrField<string>* Reflection::MutableRepeatedPtrField<string>(
+    Message* message, const FieldDescriptor* field) const {
+  return static_cast<RepeatedPtrField<string>* >(
+      MutableRawRepeatedString(message, field, true));
+}
+
+
+// -----
+
+template<>
+inline const RepeatedPtrField<Message>& Reflection::GetRepeatedPtrField(
+    const Message& message, const FieldDescriptor* field) const {
+  return *static_cast<RepeatedPtrField<Message>* >(
+      MutableRawRepeatedField(const_cast<Message*>(&message), field,
+          FieldDescriptor::CPPTYPE_MESSAGE, -1,
+          NULL));
+}
+
+template<>
+inline RepeatedPtrField<Message>* Reflection::MutableRepeatedPtrField(
+    Message* message, const FieldDescriptor* field) const {
+  return static_cast<RepeatedPtrField<Message>* >(
+      MutableRawRepeatedField(message, field,
+          FieldDescriptor::CPPTYPE_MESSAGE, -1,
+          NULL));
+}
+
+template<typename PB>
+inline const RepeatedPtrField<PB>& Reflection::GetRepeatedPtrField(
+    const Message& message, const FieldDescriptor* field) const {
+  return *static_cast<RepeatedPtrField<PB>* >(
+      MutableRawRepeatedField(const_cast<Message*>(&message), field,
+          FieldDescriptor::CPPTYPE_MESSAGE, -1,
+          PB::default_instance().GetDescriptor()));
+}
+
+template<typename PB>
+inline RepeatedPtrField<PB>* Reflection::MutableRepeatedPtrField(
+    Message* message, const FieldDescriptor* field) const {
+  return static_cast<RepeatedPtrField<PB>* >(
+      MutableRawRepeatedField(message, field,
+          FieldDescriptor::CPPTYPE_MESSAGE, -1,
+          PB::default_instance().GetDescriptor()));
+}
+
 }  // namespace protobuf
 
 }  // namespace google
diff --git a/third_party/protobuf/src/google/protobuf/message_lite.cc b/third_party/protobuf/src/google/protobuf/message_lite.cc
index 7c8f37d..49dbe6e 100644
--- a/third_party/protobuf/src/google/protobuf/message_lite.cc
+++ b/third_party/protobuf/src/google/protobuf/message_lite.cc
@@ -37,8 +37,8 @@
 #include <string>
 #include <google/protobuf/stubs/common.h>
 #include <google/protobuf/io/coded_stream.h>
-#include <google/protobuf/io/zero_copy_stream_impl.h>
-#include <google/protobuf/stubs/stl_util-inl.h>
+#include <google/protobuf/io/zero_copy_stream_impl_lite.h>
+#include <google/protobuf/stubs/stl_util.h>
 
 namespace google {
 namespace protobuf {
diff --git a/third_party/protobuf/src/google/protobuf/message_lite.h b/third_party/protobuf/src/google/protobuf/message_lite.h
index ebf4ba3..1ec3068 100644
--- a/third_party/protobuf/src/google/protobuf/message_lite.h
+++ b/third_party/protobuf/src/google/protobuf/message_lite.h
@@ -40,11 +40,17 @@
 #define GOOGLE_PROTOBUF_MESSAGE_LITE_H__
 
 #include <google/protobuf/stubs/common.h>
-#include <google/protobuf/io/coded_stream.h>
 
 namespace google {
 namespace protobuf {
 
+namespace io {
+  class CodedInputStream;
+  class CodedOutputStream;
+  class ZeroCopyInputStream;
+  class ZeroCopyOutputStream;
+}
+
 // Interface to light weight protocol messages.
 //
 // This interface is implemented by all protocol message objects.  Non-lite
@@ -158,6 +164,7 @@
   // followed by IsInitialized().
   virtual bool MergePartialFromCodedStream(io::CodedInputStream* input) = 0;
 
+
   // Serialization ---------------------------------------------------
   // Methods for serializing in protocol buffer format.  Most of these
   // are just simple wrappers around ByteSize() and SerializeWithCachedSizes().
diff --git a/third_party/protobuf/src/google/protobuf/message_unittest.cc b/third_party/protobuf/src/google/protobuf/message_unittest.cc
index 33b9e77..8aaeabb 100644
--- a/third_party/protobuf/src/google/protobuf/message_unittest.cc
+++ b/third_party/protobuf/src/google/protobuf/message_unittest.cc
@@ -257,6 +257,78 @@
   EXPECT_FALSE(message.ParseFromArray("\014", 1));
 }
 
+namespace {
+
+void ExpectMessageMerged(const unittest::TestAllTypes& message) {
+  EXPECT_EQ(3, message.optional_int32());
+  EXPECT_EQ(2, message.optional_int64());
+  EXPECT_EQ("hello", message.optional_string());
+}
+
+void AssignParsingMergeMessages(
+    unittest::TestAllTypes* msg1,
+    unittest::TestAllTypes* msg2,
+    unittest::TestAllTypes* msg3) {
+  msg1->set_optional_int32(1);
+  msg2->set_optional_int64(2);
+  msg3->set_optional_int32(3);
+  msg3->set_optional_string("hello");
+}
+
+}  // namespace
+
+// Test that if an optional or required message/group field appears multiple
+// times in the input, they need to be merged.
+TEST(MessageTest, ParsingMerge) {
+  unittest::TestParsingMerge::RepeatedFieldsGenerator generator;
+  unittest::TestAllTypes* msg1;
+  unittest::TestAllTypes* msg2;
+  unittest::TestAllTypes* msg3;
+
+#define ASSIGN_REPEATED_FIELD(FIELD)                \
+  msg1 = generator.add_##FIELD();                   \
+  msg2 = generator.add_##FIELD();                   \
+  msg3 = generator.add_##FIELD();                   \
+  AssignParsingMergeMessages(msg1, msg2, msg3)
+
+  ASSIGN_REPEATED_FIELD(field1);
+  ASSIGN_REPEATED_FIELD(field2);
+  ASSIGN_REPEATED_FIELD(field3);
+  ASSIGN_REPEATED_FIELD(ext1);
+  ASSIGN_REPEATED_FIELD(ext2);
+
+#undef ASSIGN_REPEATED_FIELD
+#define ASSIGN_REPEATED_GROUP(FIELD)                \
+  msg1 = generator.add_##FIELD()->mutable_field1(); \
+  msg2 = generator.add_##FIELD()->mutable_field1(); \
+  msg3 = generator.add_##FIELD()->mutable_field1(); \
+  AssignParsingMergeMessages(msg1, msg2, msg3)
+
+  ASSIGN_REPEATED_GROUP(group1);
+  ASSIGN_REPEATED_GROUP(group2);
+
+#undef ASSIGN_REPEATED_GROUP
+
+  string buffer;
+  generator.SerializeToString(&buffer);
+  unittest::TestParsingMerge parsing_merge;
+  parsing_merge.ParseFromString(buffer);
+
+  // Required and optional fields should be merged.
+  ExpectMessageMerged(parsing_merge.required_all_types());
+  ExpectMessageMerged(parsing_merge.optional_all_types());
+  ExpectMessageMerged(
+      parsing_merge.optionalgroup().optional_group_all_types());
+  ExpectMessageMerged(
+      parsing_merge.GetExtension(unittest::TestParsingMerge::optional_ext));
+
+  // Repeated fields should not be merged.
+  EXPECT_EQ(3, parsing_merge.repeated_all_types_size());
+  EXPECT_EQ(3, parsing_merge.repeatedgroup_size());
+  EXPECT_EQ(3, parsing_merge.ExtensionSize(
+      unittest::TestParsingMerge::repeated_ext));
+}
+
 TEST(MessageFactoryTest, GeneratedFactoryLookup) {
   EXPECT_EQ(
     MessageFactory::generated_factory()->GetPrototype(
@@ -277,5 +349,6 @@
     MessageFactory::generated_factory()->GetPrototype(descriptor) == NULL);
 }
 
+
 }  // namespace protobuf
 }  // namespace google
diff --git a/third_party/protobuf/src/google/protobuf/reflection_ops.cc b/third_party/protobuf/src/google/protobuf/reflection_ops.cc
index 897c0d7..f00997c 100644
--- a/third_party/protobuf/src/google/protobuf/reflection_ops.cc
+++ b/third_party/protobuf/src/google/protobuf/reflection_ops.cc
@@ -32,8 +32,12 @@
 //  Based on original Protocol Buffers design by
 //  Sanjay Ghemawat, Jeff Dean, and others.
 
+#include <string>
+#include <vector>
+
 #include <google/protobuf/reflection_ops.h>
 #include <google/protobuf/descriptor.h>
+#include <google/protobuf/descriptor.pb.h>
 #include <google/protobuf/unknown_field_set.h>
 #include <google/protobuf/stubs/strutil.h>
 
@@ -151,11 +155,12 @@
   for (int i = 0; i < fields.size(); i++) {
     const FieldDescriptor* field = fields[i];
     if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
+
       if (field->is_repeated()) {
         int size = reflection->FieldSize(message, field);
 
-        for (int i = 0; i < size; i++) {
-          if (!reflection->GetRepeatedMessage(message, field, i)
+        for (int j = 0; j < size; j++) {
+          if (!reflection->GetRepeatedMessage(message, field, j)
                           .IsInitialized()) {
             return false;
           }
@@ -183,8 +188,8 @@
     if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
       if (field->is_repeated()) {
         int size = reflection->FieldSize(*message, field);
-        for (int i = 0; i < size; i++) {
-          reflection->MutableRepeatedMessage(message, field, i)
+        for (int j = 0; j < size; j++) {
+          reflection->MutableRepeatedMessage(message, field, j)
                     ->DiscardUnknownFields();
         }
       } else {
@@ -240,11 +245,11 @@
       if (field->is_repeated()) {
         int size = reflection->FieldSize(message, field);
 
-        for (int i = 0; i < size; i++) {
+        for (int j = 0; j < size; j++) {
           const Message& sub_message =
-            reflection->GetRepeatedMessage(message, field, i);
+            reflection->GetRepeatedMessage(message, field, j);
           FindInitializationErrors(sub_message,
-                                   SubMessagePrefix(prefix, field, i),
+                                   SubMessagePrefix(prefix, field, j),
                                    errors);
         }
       } else {
diff --git a/third_party/protobuf/src/google/protobuf/reflection_ops.h b/third_party/protobuf/src/google/protobuf/reflection_ops.h
index 355a0a5..60165c2 100644
--- a/third_party/protobuf/src/google/protobuf/reflection_ops.h
+++ b/third_party/protobuf/src/google/protobuf/reflection_ops.h
@@ -38,6 +38,7 @@
 #ifndef GOOGLE_PROTOBUF_REFLECTION_OPS_H__
 #define GOOGLE_PROTOBUF_REFLECTION_OPS_H__
 
+#include <google/protobuf/stubs/common.h>
 #include <google/protobuf/message.h>
 
 namespace google {
diff --git a/third_party/protobuf/src/google/protobuf/repeated_field.cc b/third_party/protobuf/src/google/protobuf/repeated_field.cc
index 0937774..2c1f74c 100644
--- a/third_party/protobuf/src/google/protobuf/repeated_field.cc
+++ b/third_party/protobuf/src/google/protobuf/repeated_field.cc
@@ -46,42 +46,31 @@
   if (total_size_ >= new_size) return;
 
   void** old_elements = elements_;
-  total_size_ = max(total_size_ * 2, new_size);
+  total_size_ = max(kMinRepeatedFieldAllocationSize,
+                    max(total_size_ * 2, new_size));
   elements_ = new void*[total_size_];
-  memcpy(elements_, old_elements, allocated_size_ * sizeof(elements_[0]));
-  if (old_elements != initial_space_) {
+  if (old_elements != NULL) {
+    memcpy(elements_, old_elements, allocated_size_ * sizeof(elements_[0]));
     delete [] old_elements;
   }
 }
 
 void RepeatedPtrFieldBase::Swap(RepeatedPtrFieldBase* other) {
+  if (this == other) return;
   void** swap_elements       = elements_;
   int    swap_current_size   = current_size_;
   int    swap_allocated_size = allocated_size_;
   int    swap_total_size     = total_size_;
-  // We may not be using initial_space_ but it's not worth checking.  Just
-  // copy it anyway.
-  void* swap_initial_space[kInitialSize];
-  memcpy(swap_initial_space, initial_space_, sizeof(initial_space_));
 
   elements_       = other->elements_;
   current_size_   = other->current_size_;
   allocated_size_ = other->allocated_size_;
   total_size_     = other->total_size_;
-  memcpy(initial_space_, other->initial_space_, sizeof(initial_space_));
 
   other->elements_       = swap_elements;
   other->current_size_   = swap_current_size;
   other->allocated_size_ = swap_allocated_size;
   other->total_size_     = swap_total_size;
-  memcpy(other->initial_space_, swap_initial_space, sizeof(swap_initial_space));
-
-  if (elements_ == other->initial_space_) {
-    elements_ = initial_space_;
-  }
-  if (other->elements_ == initial_space_) {
-    other->elements_ = other->initial_space_;
-  }
 }
 
 string* StringTypeHandlerBase::New() {
diff --git a/third_party/protobuf/src/google/protobuf/repeated_field.h b/third_party/protobuf/src/google/protobuf/repeated_field.h
index aed4ce9..b9db2b6 100644
--- a/third_party/protobuf/src/google/protobuf/repeated_field.h
+++ b/third_party/protobuf/src/google/protobuf/repeated_field.h
@@ -46,24 +46,35 @@
 #ifndef GOOGLE_PROTOBUF_REPEATED_FIELD_H__
 #define GOOGLE_PROTOBUF_REPEATED_FIELD_H__
 
+#include <algorithm>
 #include <string>
 #include <iterator>
 #include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/type_traits.h>
+#include <google/protobuf/generated_message_util.h>
 #include <google/protobuf/message_lite.h>
 
 namespace google {
 
+namespace upb {
+namespace proto2_bridge_opensource {
+class FieldAccessor;
+}  // namespace protobuf_bridge_opensource
+}  // namespace upb
+
 namespace protobuf {
 
 class Message;
 
 namespace internal {
 
-// We need this (from generated_message_reflection.cc).
-LIBPROTOBUF_EXPORT int StringSpaceUsedExcludingSelf(const string& str);
+static const int kMinRepeatedFieldAllocationSize = 4;
 
+// A utility function for logging that doesn't need any template types.
+void LogIndexOutOfBounds(int index, int size);
 }  // namespace internal
 
+
 // RepeatedField is used to represent repeated fields of a primitive type (in
 // other words, everything except strings and nested Messages).  Most users will
 // not ever use a RepeatedField directly; they will use the get-by-index,
@@ -73,6 +84,8 @@
  public:
   RepeatedField();
   RepeatedField(const RepeatedField& other);
+  template <typename Iter>
+  RepeatedField(Iter begin, const Iter& end);
   ~RepeatedField();
 
   RepeatedField& operator=(const RepeatedField& other);
@@ -85,12 +98,14 @@
   void Add(const Element& value);
   Element* Add();
   // Remove the last element in the array.
-  // We don't provide a way to remove any element other than the last
-  // because it invites inefficient use, such as O(n^2) filtering loops
-  // that should have been O(n).  If you want to remove an element other
-  // than the last, the best way to do it is to re-arrange the elements
-  // so that the one you want removed is at the end, then call RemoveLast().
   void RemoveLast();
+
+  // Extract elements with indices in "[start .. start+num-1]".
+  // Copy them into "elements[0 .. num-1]" if "elements" is not NULL.
+  // Caution: implementation also moves elements with indices [start+num ..].
+  // Calling this routine inside a loop can cause quadratic behavior.
+  void ExtractSubrange(int start, int num, Element* elements);
+
   void Clear();
   void MergeFrom(const RepeatedField& other);
   void CopyFrom(const RepeatedField& other);
@@ -121,25 +136,45 @@
   typedef Element* iterator;
   typedef const Element* const_iterator;
   typedef Element value_type;
+  typedef value_type& reference;
+  typedef const value_type& const_reference;
+  typedef value_type* pointer;
+  typedef const value_type* const_pointer;
+  typedef int size_type;
+  typedef ptrdiff_t difference_type;
 
   iterator begin();
   const_iterator begin() const;
   iterator end();
   const_iterator end() const;
 
+  // Reverse iterator support
+  typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
+  typedef std::reverse_iterator<iterator> reverse_iterator;
+  reverse_iterator rbegin() {
+    return reverse_iterator(end());
+  }
+  const_reverse_iterator rbegin() const {
+    return const_reverse_iterator(end());
+  }
+  reverse_iterator rend() {
+    return reverse_iterator(begin());
+  }
+  const_reverse_iterator rend() const {
+    return const_reverse_iterator(begin());
+  }
+
   // Returns the number of bytes used by the repeated field, excluding
   // sizeof(*this)
   int SpaceUsedExcludingSelf() const;
 
  private:
-  static const int kInitialSize = 4;
+  static const int kInitialSize = 0;
 
   Element* elements_;
   int      current_size_;
   int      total_size_;
 
-  Element  initial_space_[kInitialSize];
-
   // Move the contents of |from| into |to|, possibly clobbering |from| in the
   // process.  For primitive types this is just a memcpy(), but it could be
   // specialized for non-primitive types to, say, swap each element instead.
@@ -151,7 +186,21 @@
 
 namespace internal {
 template <typename It> class RepeatedPtrIterator;
-template <typename It> class RepeatedPtrOverPtrsIterator;
+template <typename It, typename VoidPtr> class RepeatedPtrOverPtrsIterator;
+}  // namespace internal
+
+namespace internal {
+
+// This is a helper template to copy an array of elements effeciently when they
+// have a trivial copy constructor, and correctly otherwise. This really
+// shouldn't be necessary, but our compiler doesn't optimize std::copy very
+// effectively.
+template <typename Element,
+          bool HasTrivialCopy = has_trivial_copy<Element>::value>
+struct ElementCopier {
+  void operator()(Element to[], const Element from[], int array_size);
+};
+
 }  // namespace internal
 
 namespace internal {
@@ -186,6 +235,10 @@
   // use of AddFromCleared(), which is not part of the public interface.
   friend class ExtensionSet;
 
+  // To parse directly into a proto2 generated class, the upb FieldAccessor
+  // needs to be able to modify a RepeatedPtrFieldBase directly.
+  friend class LIBPROTOBUF_EXPORT upb::proto2_bridge_opensource::FieldAccessor;
+
   RepeatedPtrFieldBase();
 
   // Must be called from destructor.
@@ -209,6 +262,14 @@
   template <typename TypeHandler>
   void CopyFrom(const RepeatedPtrFieldBase& other);
 
+  void CloseGap(int start, int num) {
+    // Close up a gap of "num" elements starting at offset "start".
+    for (int i = start + num; i < allocated_size_; ++i)
+      elements_[i - num] = elements_[i];
+    current_size_ -= num;
+    allocated_size_ -= num;
+  }
+
   void Reserve(int new_size);
 
   int Capacity() const;
@@ -250,15 +311,13 @@
  private:
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedPtrFieldBase);
 
-  static const int kInitialSize = 4;
+  static const int kInitialSize = 0;
 
   void** elements_;
   int    current_size_;
   int    allocated_size_;
   int    total_size_;
 
-  void*  initial_space_[kInitialSize];
-
   template <typename TypeHandler>
   static inline typename TypeHandler::Type* cast(void* element) {
     return reinterpret_cast<typename TypeHandler::Type*>(element);
@@ -280,6 +339,7 @@
     to->MergeFrom(from);
   }
   static int SpaceUsed(const GenericType& value) { return value.SpaceUsed(); }
+  static const Type& default_instance() { return Type::default_instance(); }
 };
 
 template <>
@@ -288,6 +348,25 @@
   to->CheckTypeAndMergeFrom(from);
 }
 
+template <>
+inline const MessageLite& GenericTypeHandler<MessageLite>::default_instance() {
+  // Yes, the behavior of the code is undefined, but this function is only
+  // called when we're already deep into the world of undefined, because the
+  // caller called Get(index) out of bounds.
+  MessageLite* null = NULL;
+  return *null;
+}
+
+template <>
+inline const Message& GenericTypeHandler<Message>::default_instance() {
+  // Yes, the behavior of the code is undefined, but this function is only
+  // called when we're already deep into the world of undefined, because the
+  // caller called Get(index) out of bounds.
+  Message* null = NULL;
+  return *null;
+}
+
+
 // HACK:  If a class is declared as DLL-exported in MSVC, it insists on
 //   generating copies of all its methods -- even inline ones -- to include
 //   in the DLL.  But SpaceUsed() calls StringSpaceUsedExcludingSelf() which
@@ -303,6 +382,9 @@
   static void Delete(string* value);
   static void Clear(string* value) { value->clear(); }
   static void Merge(const string& from, string* to) { *to = from; }
+  static const Type& default_instance() {
+    return ::google::protobuf::internal::kEmptyString;
+  }
 };
 
 class StringTypeHandler : public StringTypeHandlerBase {
@@ -322,6 +404,8 @@
  public:
   RepeatedPtrField();
   RepeatedPtrField(const RepeatedPtrField& other);
+  template <typename Iter>
+  RepeatedPtrField(Iter begin, const Iter& end);
   ~RepeatedPtrField();
 
   RepeatedPtrField& operator=(const RepeatedPtrField& other);
@@ -331,7 +415,16 @@
   const Element& Get(int index) const;
   Element* Mutable(int index);
   Element* Add();
-  void RemoveLast();  // Remove the last element in the array.
+
+  // Remove the last element in the array.
+  // Ownership of the element is retained by the array.
+  void RemoveLast();
+
+  // Delete elements with indices in the range [start .. start+num-1].
+  // Caution: implementation moves all elements with indices [start+num .. ].
+  // Calling this routine inside a loop can cause quadratic behavior.
+  void DeleteSubrange(int start, int num);
+
   void Clear();
   void MergeFrom(const RepeatedPtrField& other);
   void CopyFrom(const RepeatedPtrField& other);
@@ -358,42 +451,78 @@
   typedef internal::RepeatedPtrIterator<Element> iterator;
   typedef internal::RepeatedPtrIterator<const Element> const_iterator;
   typedef Element value_type;
+  typedef value_type& reference;
+  typedef const value_type& const_reference;
+  typedef value_type* pointer;
+  typedef const value_type* const_pointer;
+  typedef int size_type;
+  typedef ptrdiff_t difference_type;
 
   iterator begin();
   const_iterator begin() const;
   iterator end();
   const_iterator end() const;
 
+  // Reverse iterator support
+  typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
+  typedef std::reverse_iterator<iterator> reverse_iterator;
+  reverse_iterator rbegin() {
+    return reverse_iterator(end());
+  }
+  const_reverse_iterator rbegin() const {
+    return const_reverse_iterator(end());
+  }
+  reverse_iterator rend() {
+    return reverse_iterator(begin());
+  }
+  const_reverse_iterator rend() const {
+    return const_reverse_iterator(begin());
+  }
+
   // Custom STL-like iterator that iterates over and returns the underlying
   // pointers to Element rather than Element itself.
-  typedef internal::RepeatedPtrOverPtrsIterator<Element> pointer_iterator;
+  typedef internal::RepeatedPtrOverPtrsIterator<Element, void*>
+  pointer_iterator;
+  typedef internal::RepeatedPtrOverPtrsIterator<const Element, const void*>
+  const_pointer_iterator;
   pointer_iterator pointer_begin();
+  const_pointer_iterator pointer_begin() const;
   pointer_iterator pointer_end();
+  const_pointer_iterator pointer_end() const;
 
   // Returns (an estimate of) the number of bytes used by the repeated field,
   // excluding sizeof(*this).
   int SpaceUsedExcludingSelf() const;
 
   // Advanced memory management --------------------------------------
-  // When hardcore memory management becomes necessary -- as it often
+  // When hardcore memory management becomes necessary -- as it sometimes
   // does here at Google -- the following methods may be useful.
 
   // Add an already-allocated object, passing ownership to the
   // RepeatedPtrField.
   void AddAllocated(Element* value);
-  // Remove the last element and return it, passing ownership to the
-  // caller.
+  // Remove the last element and return it, passing ownership to the caller.
   // Requires:  size() > 0
   Element* ReleaseLast();
 
+  // Extract elements with indices in the range "[start .. start+num-1]".
+  // The caller assumes ownership of the extracted elements and is responsible
+  // for deleting them when they are no longer needed.
+  // If "elements" is non-NULL, then pointers to the extracted elements
+  // are stored in "elements[0 .. num-1]" for the convenience of the caller.
+  // If "elements" is NULL, then the caller must use some other mechanism
+  // to perform any further operations (like deletion) on these elements.
+  // Caution: implementation also moves elements with indices [start+num ..].
+  // Calling this routine inside a loop can cause quadratic behavior.
+  void ExtractSubrange(int start, int num, Element** elements);
+
   // When elements are removed by calls to RemoveLast() or Clear(), they
   // are not actually freed.  Instead, they are cleared and kept so that
   // they can be reused later.  This can save lots of CPU time when
   // repeatedly reusing a protocol message for similar purposes.
   //
-  // Really, extremely hardcore programs may actually want to manipulate
-  // these objects to better-optimize memory management.  These methods
-  // allow that.
+  // Hardcore programs may choose to manipulate these cleared objects
+  // to better optimize memory management using the following routines.
 
   // Get the number of cleared objects that are currently being kept
   // around for reuse.
@@ -420,30 +549,40 @@
 
 template <typename Element>
 inline RepeatedField<Element>::RepeatedField()
-  : elements_(initial_space_),
+  : elements_(NULL),
     current_size_(0),
     total_size_(kInitialSize) {
 }
 
 template <typename Element>
 inline RepeatedField<Element>::RepeatedField(const RepeatedField& other)
-  : elements_(initial_space_),
+  : elements_(NULL),
     current_size_(0),
     total_size_(kInitialSize) {
   CopyFrom(other);
 }
 
 template <typename Element>
-RepeatedField<Element>::~RepeatedField() {
-  if (elements_ != initial_space_) {
-    delete [] elements_;
+template <typename Iter>
+inline RepeatedField<Element>::RepeatedField(Iter begin, const Iter& end)
+  : elements_(NULL),
+    current_size_(0),
+    total_size_(kInitialSize) {
+  for (; begin != end; ++begin) {
+    Add(*begin);
   }
 }
 
 template <typename Element>
+RepeatedField<Element>::~RepeatedField() {
+  delete [] elements_;
+}
+
+template <typename Element>
 inline RepeatedField<Element>&
 RepeatedField<Element>::operator=(const RepeatedField& other) {
-  CopyFrom(other);
+  if (this != &other)
+    CopyFrom(other);
   return *this;
 }
 
@@ -506,15 +645,38 @@
 }
 
 template <typename Element>
+void RepeatedField<Element>::ExtractSubrange(
+    int start, int num, Element* elements) {
+  GOOGLE_DCHECK_GE(start, 0);
+  GOOGLE_DCHECK_GE(num, 0);
+  GOOGLE_DCHECK_LE(start + num, this->size());
+
+  // Save the values of the removed elements if requested.
+  if (elements != NULL) {
+    for (int i = 0; i < num; ++i)
+      elements[i] = this->Get(i + start);
+  }
+
+  // Slide remaining elements down to fill the gap.
+  if (num > 0) {
+    for (int i = start + num; i < this->size(); ++i)
+      this->Set(i - num, this->Get(i));
+    this->Truncate(this->size() - num);
+  }
+}
+
+template <typename Element>
 inline void RepeatedField<Element>::Clear() {
   current_size_ = 0;
 }
 
 template <typename Element>
 inline void RepeatedField<Element>::MergeFrom(const RepeatedField& other) {
-  Reserve(current_size_ + other.current_size_);
-  CopyArray(elements_ + current_size_, other.elements_, other.current_size_);
-  current_size_ += other.current_size_;
+  if (other.current_size_ != 0) {
+    Reserve(current_size_ + other.current_size_);
+    CopyArray(elements_ + current_size_, other.elements_, other.current_size_);
+    current_size_ += other.current_size_;
+  }
 }
 
 template <typename Element>
@@ -536,30 +698,18 @@
 
 template <typename Element>
 void RepeatedField<Element>::Swap(RepeatedField* other) {
+  if (this == other) return;
   Element* swap_elements     = elements_;
   int      swap_current_size = current_size_;
   int      swap_total_size   = total_size_;
-  // We may not be using initial_space_ but it's not worth checking.  Just
-  // copy it anyway.
-  Element swap_initial_space[kInitialSize];
-  MoveArray(swap_initial_space, initial_space_, kInitialSize);
 
   elements_     = other->elements_;
   current_size_ = other->current_size_;
   total_size_   = other->total_size_;
-  MoveArray(initial_space_, other->initial_space_, kInitialSize);
 
   other->elements_     = swap_elements;
   other->current_size_ = swap_current_size;
   other->total_size_   = swap_total_size;
-  MoveArray(other->initial_space_, swap_initial_space, kInitialSize);
-
-  if (elements_ == other->initial_space_) {
-    elements_ = initial_space_;
-  }
-  if (other->elements_ == initial_space_) {
-    other->elements_ = other->initial_space_;
-  }
 }
 
 template <typename Element>
@@ -590,20 +740,21 @@
 
 template <typename Element>
 inline int RepeatedField<Element>::SpaceUsedExcludingSelf() const {
-  return (elements_ != initial_space_) ? total_size_ * sizeof(elements_[0]) : 0;
+  return (elements_ != NULL) ? total_size_ * sizeof(elements_[0]) : 0;
 }
 
-// Avoid inlining of Reserve(): new, memcpy, and delete[] lead to a significant
+// Avoid inlining of Reserve(): new, copy, and delete[] lead to a significant
 // amount of code bloat.
 template <typename Element>
 void RepeatedField<Element>::Reserve(int new_size) {
   if (total_size_ >= new_size) return;
 
   Element* old_elements = elements_;
-  total_size_ = max(total_size_ * 2, new_size);
+  total_size_ = max(google::protobuf::internal::kMinRepeatedFieldAllocationSize,
+                    max(total_size_ * 2, new_size));
   elements_ = new Element[total_size_];
-  MoveArray(elements_, old_elements, current_size_);
-  if (old_elements != initial_space_) {
+  if (old_elements != NULL) {
+    MoveArray(elements_, old_elements, current_size_);
     delete [] old_elements;
   }
 }
@@ -617,22 +768,39 @@
 template <typename Element>
 inline void RepeatedField<Element>::MoveArray(
     Element to[], Element from[], int array_size) {
-  memcpy(to, from, array_size * sizeof(Element));
+  CopyArray(to, from, array_size);
 }
 
 template <typename Element>
 inline void RepeatedField<Element>::CopyArray(
     Element to[], const Element from[], int array_size) {
-  memcpy(to, from, array_size * sizeof(Element));
+  internal::ElementCopier<Element>()(to, from, array_size);
 }
 
+namespace internal {
+
+template <typename Element, bool HasTrivialCopy>
+void ElementCopier<Element, HasTrivialCopy>::operator()(
+    Element to[], const Element from[], int array_size) {
+  std::copy(from, from + array_size, to);
+}
+
+template <typename Element>
+struct ElementCopier<Element, true> {
+  void operator()(Element to[], const Element from[], int array_size) {
+    memcpy(to, from, array_size * sizeof(Element));
+  }
+};
+
+}  // namespace internal
+
 
 // -------------------------------------------------------------------
 
 namespace internal {
 
 inline RepeatedPtrFieldBase::RepeatedPtrFieldBase()
-  : elements_(initial_space_),
+  : elements_(NULL),
     current_size_(0),
     allocated_size_(0),
     total_size_(kInitialSize) {
@@ -643,16 +811,13 @@
   for (int i = 0; i < allocated_size_; i++) {
     TypeHandler::Delete(cast<TypeHandler>(elements_[i]));
   }
-  if (elements_ != initial_space_) {
-    delete [] elements_;
-  }
+  delete [] elements_;
 }
 
 inline int RepeatedPtrFieldBase::size() const {
   return current_size_;
 }
 
-
 template <typename TypeHandler>
 inline const typename TypeHandler::Type&
 RepeatedPtrFieldBase::Get(int index) const {
@@ -660,6 +825,7 @@
   return *cast<TypeHandler>(elements_[index]);
 }
 
+
 template <typename TypeHandler>
 inline typename TypeHandler::Type*
 RepeatedPtrFieldBase::Mutable(int index) {
@@ -741,7 +907,7 @@
 template <typename TypeHandler>
 inline int RepeatedPtrFieldBase::SpaceUsedExcludingSelf() const {
   int allocated_bytes =
-      (elements_ != initial_space_) ? total_size_ * sizeof(elements_[0]) : 0;
+      (elements_ != NULL) ? total_size_ * sizeof(elements_[0]) : 0;
   for (int i = 0; i < allocated_size_; ++i) {
     allocated_bytes += TypeHandler::SpaceUsed(*cast<TypeHandler>(elements_[i]));
   }
@@ -798,7 +964,6 @@
   return result;
 }
 
-
 inline int RepeatedPtrFieldBase::ClearedCount() const {
   return allocated_size_ - current_size_;
 }
@@ -822,11 +987,13 @@
 
 template <typename Element>
 class RepeatedPtrField<Element>::TypeHandler
-    : public internal::GenericTypeHandler<Element> {};
+    : public internal::GenericTypeHandler<Element> {
+};
 
 template <>
 class RepeatedPtrField<string>::TypeHandler
-    : public internal::StringTypeHandler {};
+    : public internal::StringTypeHandler {
+};
 
 
 template <typename Element>
@@ -839,6 +1006,15 @@
 }
 
 template <typename Element>
+template <typename Iter>
+inline RepeatedPtrField<Element>::RepeatedPtrField(
+    Iter begin, const Iter& end) {
+  for (; begin != end; ++begin) {
+    *Add() = *begin;
+  }
+}
+
+template <typename Element>
 RepeatedPtrField<Element>::~RepeatedPtrField() {
   Destroy<TypeHandler>();
 }
@@ -846,7 +1022,8 @@
 template <typename Element>
 inline RepeatedPtrField<Element>& RepeatedPtrField<Element>::operator=(
     const RepeatedPtrField& other) {
-  CopyFrom(other);
+  if (this != &other)
+    CopyFrom(other);
   return *this;
 }
 
@@ -860,6 +1037,7 @@
   return RepeatedPtrFieldBase::Get<TypeHandler>(index);
 }
 
+
 template <typename Element>
 inline Element* RepeatedPtrField<Element>::Mutable(int index) {
   return RepeatedPtrFieldBase::Mutable<TypeHandler>(index);
@@ -876,6 +1054,33 @@
 }
 
 template <typename Element>
+inline void RepeatedPtrField<Element>::DeleteSubrange(int start, int num) {
+  GOOGLE_DCHECK_GE(start, 0);
+  GOOGLE_DCHECK_GE(num, 0);
+  GOOGLE_DCHECK_LE(start + num, size());
+  for (int i = 0; i < num; ++i)
+    delete RepeatedPtrFieldBase::Mutable<TypeHandler>(start + i);
+  ExtractSubrange(start, num, NULL);
+}
+
+template <typename Element>
+inline void RepeatedPtrField<Element>::ExtractSubrange(
+    int start, int num, Element** elements) {
+  GOOGLE_DCHECK_GE(start, 0);
+  GOOGLE_DCHECK_GE(num, 0);
+  GOOGLE_DCHECK_LE(start + num, size());
+
+  if (num > 0) {
+    // Save the values of the removed elements if requested.
+    if (elements != NULL) {
+      for (int i = 0; i < num; ++i)
+        elements[i] = RepeatedPtrFieldBase::Mutable<TypeHandler>(i + start);
+    }
+    CloseGap(start, num);
+  }
+}
+
+template <typename Element>
 inline void RepeatedPtrField<Element>::Clear() {
   RepeatedPtrFieldBase::Clear<TypeHandler>();
 }
@@ -961,7 +1166,7 @@
 // refer to this class directly; use RepeatedPtrField<T>::iterator instead.
 //
 // The iterator for RepeatedPtrField<T>, RepeatedPtrIterator<T>, is
-// very similar to iterator_ptr<T**> in util/gtl/iterator_adaptors-inl.h,
+// very similar to iterator_ptr<T**> in util/gtl/iterator_adaptors.h,
 // but adds random-access operators and is modified to wrap a void** base
 // iterator (since RepeatedPtrField stores its array as a void* array and
 // casting void** to T** would violate C++ aliasing rules).
@@ -1057,11 +1262,14 @@
 // rather than the objects themselves as RepeatedPtrIterator does.
 // Consider using this when working with stl algorithms that change
 // the array.
-template<typename Element>
+// The VoidPtr template parameter holds the type-agnostic pointer value
+// referenced by the iterator.  It should either be "void *" for a mutable
+// iterator, or "const void *" for a constant iterator.
+template<typename Element, typename VoidPtr>
 class RepeatedPtrOverPtrsIterator
     : public std::iterator<std::random_access_iterator_tag, Element*> {
  public:
-  typedef RepeatedPtrOverPtrsIterator<Element> iterator;
+  typedef RepeatedPtrOverPtrsIterator<Element, VoidPtr> iterator;
   typedef std::iterator<
           std::random_access_iterator_tag, Element*> superclass;
 
@@ -1072,7 +1280,7 @@
   typedef typename superclass::difference_type difference_type;
 
   RepeatedPtrOverPtrsIterator() : it_(NULL) {}
-  explicit RepeatedPtrOverPtrsIterator(void** it) : it_(it) {}
+  explicit RepeatedPtrOverPtrsIterator(VoidPtr* it) : it_(it) {}
 
   // dereferenceable
   reference operator*() const { return *reinterpret_cast<Element**>(it_); }
@@ -1127,10 +1335,9 @@
   friend class RepeatedPtrIterator;
 
   // The internal iterator.
-  void** it_;
+  VoidPtr* it_;
 };
 
-
 }  // namespace internal
 
 template <typename Element>
@@ -1160,10 +1367,21 @@
   return pointer_iterator(raw_mutable_data());
 }
 template <typename Element>
+inline typename RepeatedPtrField<Element>::const_pointer_iterator
+RepeatedPtrField<Element>::pointer_begin() const {
+  return const_pointer_iterator(const_cast<const void**>(raw_mutable_data()));
+}
+template <typename Element>
 inline typename RepeatedPtrField<Element>::pointer_iterator
 RepeatedPtrField<Element>::pointer_end() {
   return pointer_iterator(raw_mutable_data() + size());
 }
+template <typename Element>
+inline typename RepeatedPtrField<Element>::const_pointer_iterator
+RepeatedPtrField<Element>::pointer_end() const {
+  return const_pointer_iterator(
+      const_cast<const void**>(raw_mutable_data() + size()));
+}
 
 
 // Iterators and helper functions that follow the spirit of the STL
@@ -1173,7 +1391,7 @@
 //   std::copy(some_sequence.begin(), some_sequence.end(),
 //             google::protobuf::RepeatedFieldBackInserter(proto.mutable_sequence()));
 //
-// Ported by johannes from util/gtl/proto-array-iterators-inl.h
+// Ported by johannes from util/gtl/proto-array-iterators.h
 
 namespace internal {
 // A back inserter for RepeatedField objects.
@@ -1194,7 +1412,7 @@
   RepeatedFieldBackInsertIterator<T>& operator++() {
     return *this;
   }
-  RepeatedFieldBackInsertIterator<T>& operator++(int ignores_parameter) {
+  RepeatedFieldBackInsertIterator<T>& operator++(int /* unused */) {
     return *this;
   }
 
@@ -1225,7 +1443,7 @@
   RepeatedPtrFieldBackInsertIterator<T>& operator++() {
     return *this;
   }
-  RepeatedPtrFieldBackInsertIterator<T>& operator++(int ignores_parameter) {
+  RepeatedPtrFieldBackInsertIterator<T>& operator++(int /* unused */) {
     return *this;
   }
 
@@ -1254,7 +1472,7 @@
     return *this;
   }
   AllocatedRepeatedPtrFieldBackInsertIterator<T>& operator++(
-      int ignores_parameter) {
+      int /* unused */) {
     return *this;
   }
 
@@ -1264,16 +1482,22 @@
 }  // namespace internal
 
 // Provides a back insert iterator for RepeatedField instances,
-// similar to std::back_inserter(). Note the identically named
-// function for RepeatedPtrField instances.
+// similar to std::back_inserter().
 template<typename T> internal::RepeatedFieldBackInsertIterator<T>
 RepeatedFieldBackInserter(RepeatedField<T>* const mutable_field) {
   return internal::RepeatedFieldBackInsertIterator<T>(mutable_field);
 }
 
 // Provides a back insert iterator for RepeatedPtrField instances,
-// similar to std::back_inserter(). Note the identically named
-// function for RepeatedField instances.
+// similar to std::back_inserter().
+template<typename T> internal::RepeatedPtrFieldBackInsertIterator<T>
+RepeatedPtrFieldBackInserter(RepeatedPtrField<T>* const mutable_field) {
+  return internal::RepeatedPtrFieldBackInsertIterator<T>(mutable_field);
+}
+
+// Special back insert iterator for RepeatedPtrField instances, just in
+// case someone wants to write generic template code that can access both
+// RepeatedFields and RepeatedPtrFields using a common name.
 template<typename T> internal::RepeatedPtrFieldBackInsertIterator<T>
 RepeatedFieldBackInserter(RepeatedPtrField<T>* const mutable_field) {
   return internal::RepeatedPtrFieldBackInsertIterator<T>(mutable_field);
diff --git a/third_party/protobuf/src/google/protobuf/repeated_field_reflection_unittest.cc b/third_party/protobuf/src/google/protobuf/repeated_field_reflection_unittest.cc
new file mode 100644
index 0000000..5fcfb00
--- /dev/null
+++ b/third_party/protobuf/src/google/protobuf/repeated_field_reflection_unittest.cc
@@ -0,0 +1,193 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 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.
+
+// Author: tgs@google.com (Tom Szymanski)
+//
+// Test reflection methods for aggregate access to Repeated[Ptr]Fields.
+// This test proto2 methods on a proto2 layout.
+
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/stringprintf.h>
+#include <google/protobuf/unittest.pb.h>
+#include <google/protobuf/test_util.h>
+#include <gtest/gtest.h>
+
+namespace google {
+namespace protobuf {
+
+using unittest::ForeignMessage;
+using unittest::TestAllTypes;
+using unittest::TestAllExtensions;
+
+namespace {
+
+static int Func(int i, int j) {
+  return i * j;
+}
+
+static string StrFunc(int i, int j) {
+  string str;
+  SStringPrintf(&str, "%d", Func(i, 4));
+  return str;
+}
+
+
+TEST(RepeatedFieldReflectionTest, RegularFields) {
+  TestAllTypes message;
+  const Reflection* refl = message.GetReflection();
+  const Descriptor* desc = message.GetDescriptor();
+
+  for (int i = 0; i < 10; ++i) {
+    message.add_repeated_int32(Func(i, 1));
+    message.add_repeated_double(Func(i, 2));
+    message.add_repeated_string(StrFunc(i, 5));
+    message.add_repeated_foreign_message()->set_c(Func(i, 6));
+  }
+
+  // Get FieldDescriptors for all the fields of interest.
+  const FieldDescriptor* fd_repeated_int32 =
+      desc->FindFieldByName("repeated_int32");
+  const FieldDescriptor* fd_repeated_double =
+      desc->FindFieldByName("repeated_double");
+  const FieldDescriptor* fd_repeated_string =
+      desc->FindFieldByName("repeated_string");
+  const FieldDescriptor* fd_repeated_foreign_message =
+      desc->FindFieldByName("repeated_foreign_message");
+
+  // Get RepeatedField objects for all fields of interest.
+  const RepeatedField<int32>& rf_int32 =
+      refl->GetRepeatedField<int32>(message, fd_repeated_int32);
+  const RepeatedField<double>& rf_double =
+      refl->GetRepeatedField<double>(message, fd_repeated_double);
+
+  // Get mutable RepeatedField objects for all fields of interest.
+  RepeatedField<int32>* mrf_int32 =
+      refl->MutableRepeatedField<int32>(&message, fd_repeated_int32);
+  RepeatedField<double>* mrf_double =
+      refl->MutableRepeatedField<double>(&message, fd_repeated_double);
+
+  // Get RepeatedPtrField objects for all fields of interest.
+  const RepeatedPtrField<string>& rpf_string =
+      refl->GetRepeatedPtrField<string>(message, fd_repeated_string);
+  const RepeatedPtrField<ForeignMessage>& rpf_foreign_message =
+      refl->GetRepeatedPtrField<ForeignMessage>(
+          message, fd_repeated_foreign_message);
+  const RepeatedPtrField<Message>& rpf_message =
+      refl->GetRepeatedPtrField<Message>(
+          message, fd_repeated_foreign_message);
+
+  // Get mutable RepeatedPtrField objects for all fields of interest.
+  RepeatedPtrField<string>* mrpf_string =
+      refl->MutableRepeatedPtrField<string>(&message, fd_repeated_string);
+  RepeatedPtrField<ForeignMessage>* mrpf_foreign_message =
+      refl->MutableRepeatedPtrField<ForeignMessage>(
+          &message, fd_repeated_foreign_message);
+  RepeatedPtrField<Message>* mrpf_message =
+      refl->MutableRepeatedPtrField<Message>(
+          &message, fd_repeated_foreign_message);
+
+  // Make sure we can do get and sets through the Repeated[Ptr]Field objects.
+  for (int i = 0; i < 10; ++i) {
+    // Check gets through const objects.
+    EXPECT_EQ(rf_int32.Get(i), Func(i, 1));
+    EXPECT_EQ(rf_double.Get(i), Func(i, 2));
+    EXPECT_EQ(rpf_string.Get(i), StrFunc(i, 5));
+    EXPECT_EQ(rpf_foreign_message.Get(i).c(), Func(i, 6));
+    EXPECT_EQ(down_cast<const ForeignMessage&>(rpf_message.Get(i)).c(),
+              Func(i, 6));
+
+    // Check gets through mutable objects.
+    EXPECT_EQ(mrf_int32->Get(i), Func(i, 1));
+    EXPECT_EQ(mrf_double->Get(i), Func(i, 2));
+    EXPECT_EQ(mrpf_string->Get(i), StrFunc(i, 5));
+    EXPECT_EQ(mrpf_foreign_message->Get(i).c(), Func(i, 6));
+    EXPECT_EQ(down_cast<const ForeignMessage&>(mrpf_message->Get(i)).c(),
+              Func(i, 6));
+
+    // Check sets through mutable objects.
+    mrf_int32->Set(i, Func(i, -1));
+    mrf_double->Set(i, Func(i, -2));
+    mrpf_string->Mutable(i)->assign(StrFunc(i, -5));
+    mrpf_foreign_message->Mutable(i)->set_c(Func(i, -6));
+    EXPECT_EQ(message.repeated_int32(i), Func(i, -1));
+    EXPECT_EQ(message.repeated_double(i), Func(i, -2));
+    EXPECT_EQ(message.repeated_string(i), StrFunc(i, -5));
+    EXPECT_EQ(message.repeated_foreign_message(i).c(), Func(i, -6));
+    down_cast<ForeignMessage*>(mrpf_message->Mutable(i))->set_c(Func(i, 7));
+    EXPECT_EQ(message.repeated_foreign_message(i).c(), Func(i, 7));
+  }
+
+  // Make sure types are checked correctly at runtime.
+  const FieldDescriptor* fd_optional_int32 =
+      desc->FindFieldByName("optional_int32");
+  EXPECT_DEATH(refl->GetRepeatedField<int32>(
+      message, fd_optional_int32), "requires a repeated field");
+  EXPECT_DEATH(refl->GetRepeatedField<double>(
+      message, fd_repeated_int32), "not the right type");
+  EXPECT_DEATH(refl->GetRepeatedPtrField<TestAllTypes>(
+      message, fd_repeated_foreign_message), "wrong submessage type");
+}
+
+
+
+
+TEST(RepeatedFieldReflectionTest, ExtensionFields) {
+  TestAllExtensions extended_message;
+  const Reflection* refl = extended_message.GetReflection();
+  const Descriptor* desc = extended_message.GetDescriptor();
+
+  for (int i = 0; i < 10; ++i) {
+    extended_message.AddExtension(
+        unittest::repeated_int64_extension, Func(i, 1));
+  }
+
+  const FieldDescriptor* fd_repeated_int64_extension =
+      desc->file()->FindExtensionByName("repeated_int64_extension");
+  GOOGLE_CHECK(fd_repeated_int64_extension != NULL);
+
+  const RepeatedField<int64>& rf_int64_extension =
+      refl->GetRepeatedField<int64>(extended_message,
+                                    fd_repeated_int64_extension);
+
+  RepeatedField<int64>* mrf_int64_extension =
+      refl->MutableRepeatedField<int64>(&extended_message,
+                                        fd_repeated_int64_extension);
+
+  for (int i = 0; i < 10; ++i) {
+    EXPECT_EQ(Func(i, 1), rf_int64_extension.Get(i));
+    mrf_int64_extension->Set(i, Func(i, -1));
+    EXPECT_EQ(Func(i, -1),
+        extended_message.GetExtension(unittest::repeated_int64_extension, i));
+  }
+}
+
+}  // namespace
+}  // namespace protobuf
+}  // namespace google
diff --git a/third_party/protobuf/src/google/protobuf/repeated_field_unittest.cc b/third_party/protobuf/src/google/protobuf/repeated_field_unittest.cc
index e7e1e99..99d5842 100644
--- a/third_party/protobuf/src/google/protobuf/repeated_field_unittest.cc
+++ b/third_party/protobuf/src/google/protobuf/repeated_field_unittest.cc
@@ -36,6 +36,7 @@
 //   other proto2 unittests.
 
 #include <algorithm>
+#include <limits>
 #include <list>
 #include <vector>
 
@@ -46,7 +47,7 @@
 #include <google/protobuf/stubs/strutil.h>
 #include <google/protobuf/testing/googletest.h>
 #include <gtest/gtest.h>
-#include <google/protobuf/stubs/stl_util-inl.h>
+#include <google/protobuf/stubs/stl_util.h>
 
 namespace google {
 using protobuf_unittest::TestAllTypes;
@@ -54,8 +55,7 @@
 namespace protobuf {
 namespace {
 
-// Test operations on a RepeatedField which is small enough that it does
-// not allocate a separate array for storage.
+// Test operations on a small RepeatedField.
 TEST(RepeatedField, Small) {
   RepeatedField<int> field;
 
@@ -77,7 +77,6 @@
   EXPECT_EQ(field.size(), 2);
   EXPECT_EQ(field.Get(0), 5);
   EXPECT_EQ(field.Get(1), 23);
-  EXPECT_EQ(field.SpaceUsedExcludingSelf(), 0);
 
   field.RemoveLast();
 
@@ -87,9 +86,11 @@
   field.Clear();
 
   EXPECT_EQ(field.size(), 0);
-  EXPECT_EQ(field.SpaceUsedExcludingSelf(), 0);
+  int expected_usage = 4 * sizeof(int);
+  EXPECT_EQ(field.SpaceUsedExcludingSelf(), expected_usage);
 }
 
+
 // Test operations on a RepeatedField which is large enough to allocate a
 // separate array.
 TEST(RepeatedField, Large) {
@@ -213,10 +214,8 @@
 
 TEST(RepeatedField, MergeFrom) {
   RepeatedField<int> source, destination;
-
   source.Add(4);
   source.Add(5);
-
   destination.Add(1);
   destination.Add(2);
   destination.Add(3);
@@ -224,7 +223,6 @@
   destination.MergeFrom(source);
 
   ASSERT_EQ(5, destination.size());
-
   EXPECT_EQ(1, destination.Get(0));
   EXPECT_EQ(2, destination.Get(1));
   EXPECT_EQ(3, destination.Get(2));
@@ -234,10 +232,8 @@
 
 TEST(RepeatedField, CopyFrom) {
   RepeatedField<int> source, destination;
-
   source.Add(4);
   source.Add(5);
-
   destination.Add(1);
   destination.Add(2);
   destination.Add(3);
@@ -245,7 +241,6 @@
   destination.CopyFrom(source);
 
   ASSERT_EQ(2, destination.size());
-
   EXPECT_EQ(4, destination.Get(0));
   EXPECT_EQ(5, destination.Get(1));
 }
@@ -262,12 +257,26 @@
   EXPECT_EQ(2, destination.Get(1));
 }
 
+TEST(RepeatedField, IteratorConstruct) {
+  vector<int> values;
+  values.push_back(1);
+  values.push_back(2);
+
+  RepeatedField<int> field(values.begin(), values.end());
+  ASSERT_EQ(values.size(), field.size());
+  EXPECT_EQ(values[0], field.Get(0));
+  EXPECT_EQ(values[1], field.Get(1));
+
+  RepeatedField<int> other(field.begin(), field.end());
+  ASSERT_EQ(values.size(), other.size());
+  EXPECT_EQ(values[0], other.Get(0));
+  EXPECT_EQ(values[1], other.Get(1));
+}
+
 TEST(RepeatedField, CopyAssign) {
   RepeatedField<int> source, destination;
-
   source.Add(4);
   source.Add(5);
-
   destination.Add(1);
   destination.Add(2);
   destination.Add(3);
@@ -275,11 +284,24 @@
   destination = source;
 
   ASSERT_EQ(2, destination.size());
-
   EXPECT_EQ(4, destination.Get(0));
   EXPECT_EQ(5, destination.Get(1));
 }
 
+TEST(RepeatedField, SelfAssign) {
+  // Verify that assignment to self does not destroy data.
+  RepeatedField<int> source, *p;
+  p = &source;
+  source.Add(7);
+  source.Add(8);
+
+  *p = source;
+
+  ASSERT_EQ(2, source.size());
+  EXPECT_EQ(7, source.Get(0));
+  EXPECT_EQ(8, source.Get(1));
+}
+
 TEST(RepeatedField, MutableDataIsMutable) {
   RepeatedField<int> field;
   field.Add(1);
@@ -315,6 +337,41 @@
 }
 
 
+TEST(RepeatedField, ExtractSubrange) {
+  // Exhaustively test every subrange in arrays of all sizes from 0 through 9.
+  for (int sz = 0; sz < 10; ++sz) {
+    for (int num = 0; num <= sz; ++num) {
+      for (int start = 0; start < sz - num; ++start) {
+        // Create RepeatedField with sz elements having values 0 through sz-1.
+        RepeatedField<int32> field;
+        for (int i = 0; i < sz; ++i)
+          field.Add(i);
+        EXPECT_EQ(field.size(), sz);
+
+        // Create a catcher array and call ExtractSubrange.
+        int32 catcher[10];
+        for (int i = 0; i < 10; ++i)
+          catcher[i] = -1;
+        field.ExtractSubrange(start, num, catcher);
+
+        // Does the resulting array have the right size?
+        EXPECT_EQ(field.size(), sz - num);
+
+        // Were the removed elements extracted into the catcher array?
+        for (int i = 0; i < num; ++i)
+          EXPECT_EQ(catcher[i], start + i);
+        EXPECT_EQ(catcher[num], -1);
+
+        // Does the resulting array contain the right values?
+        for (int i = 0; i < start; ++i)
+          EXPECT_EQ(field.Get(i), i);
+        for (int i = start; i < field.size(); ++i)
+          EXPECT_EQ(field.Get(i), i + num);
+      }
+    }
+  }
+}
+
 // ===================================================================
 // RepeatedPtrField tests.  These pretty much just mirror the RepeatedField
 // tests above.
@@ -351,6 +408,7 @@
   EXPECT_EQ(field.size(), 0);
 }
 
+
 TEST(RepeatedPtrField, Large) {
   RepeatedPtrField<string> field;
 
@@ -565,10 +623,8 @@
 
 TEST(RepeatedPtrField, MergeFrom) {
   RepeatedPtrField<string> source, destination;
-
   source.Add()->assign("4");
   source.Add()->assign("5");
-
   destination.Add()->assign("1");
   destination.Add()->assign("2");
   destination.Add()->assign("3");
@@ -576,7 +632,6 @@
   destination.MergeFrom(source);
 
   ASSERT_EQ(5, destination.size());
-
   EXPECT_EQ("1", destination.Get(0));
   EXPECT_EQ("2", destination.Get(1));
   EXPECT_EQ("3", destination.Get(2));
@@ -586,10 +641,8 @@
 
 TEST(RepeatedPtrField, CopyFrom) {
   RepeatedPtrField<string> source, destination;
-
   source.Add()->assign("4");
   source.Add()->assign("5");
-
   destination.Add()->assign("1");
   destination.Add()->assign("2");
   destination.Add()->assign("3");
@@ -597,14 +650,12 @@
   destination.CopyFrom(source);
 
   ASSERT_EQ(2, destination.size());
-
   EXPECT_EQ("4", destination.Get(0));
   EXPECT_EQ("5", destination.Get(1));
 }
 
 TEST(RepeatedPtrField, CopyConstruct) {
   RepeatedPtrField<string> source;
-
   source.Add()->assign("1");
   source.Add()->assign("2");
 
@@ -615,12 +666,45 @@
   EXPECT_EQ("2", destination.Get(1));
 }
 
+TEST(RepeatedPtrField, IteratorConstruct_String) {
+  vector<string> values;
+  values.push_back("1");
+  values.push_back("2");
+
+  RepeatedPtrField<string> field(values.begin(), values.end());
+  ASSERT_EQ(values.size(), field.size());
+  EXPECT_EQ(values[0], field.Get(0));
+  EXPECT_EQ(values[1], field.Get(1));
+
+  RepeatedPtrField<string> other(field.begin(), field.end());
+  ASSERT_EQ(values.size(), other.size());
+  EXPECT_EQ(values[0], other.Get(0));
+  EXPECT_EQ(values[1], other.Get(1));
+}
+
+TEST(RepeatedPtrField, IteratorConstruct_Proto) {
+  typedef TestAllTypes::NestedMessage Nested;
+  vector<Nested> values;
+  values.push_back(Nested());
+  values.back().set_bb(1);
+  values.push_back(Nested());
+  values.back().set_bb(2);
+
+  RepeatedPtrField<Nested> field(values.begin(), values.end());
+  ASSERT_EQ(values.size(), field.size());
+  EXPECT_EQ(values[0].bb(), field.Get(0).bb());
+  EXPECT_EQ(values[1].bb(), field.Get(1).bb());
+
+  RepeatedPtrField<Nested> other(field.begin(), field.end());
+  ASSERT_EQ(values.size(), other.size());
+  EXPECT_EQ(values[0].bb(), other.Get(0).bb());
+  EXPECT_EQ(values[1].bb(), other.Get(1).bb());
+}
+
 TEST(RepeatedPtrField, CopyAssign) {
   RepeatedPtrField<string> source, destination;
-
   source.Add()->assign("4");
   source.Add()->assign("5");
-
   destination.Add()->assign("1");
   destination.Add()->assign("2");
   destination.Add()->assign("3");
@@ -628,11 +712,24 @@
   destination = source;
 
   ASSERT_EQ(2, destination.size());
-
   EXPECT_EQ("4", destination.Get(0));
   EXPECT_EQ("5", destination.Get(1));
 }
 
+TEST(RepeatedPtrField, SelfAssign) {
+  // Verify that assignment to self does not destroy data.
+  RepeatedPtrField<string> source, *p;
+  p = &source;
+  source.Add()->assign("7");
+  source.Add()->assign("8");
+
+  *p = source;
+
+  ASSERT_EQ(2, source.size());
+  EXPECT_EQ("7", source.Get(0));
+  EXPECT_EQ("8", source.Get(1));
+}
+
 TEST(RepeatedPtrField, MutableDataIsMutable) {
   RepeatedPtrField<string> field;
   *field.Add() = "1";
@@ -644,6 +741,77 @@
   EXPECT_EQ("2", field.Get(0));
 }
 
+TEST(RepeatedPtrField, ExtractSubrange) {
+  // Exhaustively test every subrange in arrays of all sizes from 0 through 9
+  // with 0 through 3 cleared elements at the end.
+  for (int sz = 0; sz < 10; ++sz) {
+    for (int num = 0; num <= sz; ++num) {
+      for (int start = 0; start < sz - num; ++start) {
+        for (int extra = 0; extra < 4; ++extra) {
+          vector<string*> subject;
+
+          // Create an array with "sz" elements and "extra" cleared elements.
+          RepeatedPtrField<string> field;
+          for (int i = 0; i < sz + extra; ++i) {
+            subject.push_back(new string());
+            field.AddAllocated(subject[i]);
+          }
+          EXPECT_EQ(field.size(), sz + extra);
+          for (int i = 0; i < extra; ++i)
+            field.RemoveLast();
+          EXPECT_EQ(field.size(), sz);
+          EXPECT_EQ(field.ClearedCount(), extra);
+
+          // Create a catcher array and call ExtractSubrange.
+          string* catcher[10];
+          for (int i = 0; i < 10; ++i)
+            catcher[i] = NULL;
+          field.ExtractSubrange(start, num, catcher);
+
+          // Does the resulting array have the right size?
+          EXPECT_EQ(field.size(), sz - num);
+
+          // Were the removed elements extracted into the catcher array?
+          for (int i = 0; i < num; ++i)
+            EXPECT_EQ(catcher[i], subject[start + i]);
+          EXPECT_EQ(NULL, catcher[num]);
+
+          // Does the resulting array contain the right values?
+          for (int i = 0; i < start; ++i)
+            EXPECT_EQ(field.Mutable(i), subject[i]);
+          for (int i = start; i < field.size(); ++i)
+            EXPECT_EQ(field.Mutable(i), subject[i + num]);
+
+          // Reinstate the cleared elements.
+          EXPECT_EQ(field.ClearedCount(), extra);
+          for (int i = 0; i < extra; ++i)
+            field.Add();
+          EXPECT_EQ(field.ClearedCount(), 0);
+          EXPECT_EQ(field.size(), sz - num + extra);
+
+          // Make sure the extra elements are all there (in some order).
+          for (int i = sz; i < sz + extra; ++i) {
+            int count = 0;
+            for (int j = sz; j < sz + extra; ++j) {
+              if (field.Mutable(j - num) == subject[i])
+                count += 1;
+            }
+            EXPECT_EQ(count, 1);
+          }
+
+          // Release the caught elements.
+          for (int i = 0; i < num; ++i)
+            delete catcher[i];
+        }
+      }
+    }
+  }
+}
+
+TEST(RepeatedPtrField, DeleteSubrange) {
+  // DeleteSubrange is a trivial extension of ExtendSubrange.
+}
+
 // ===================================================================
 
 // Iterator tests stolen from net/proto/proto-array_unittest.
@@ -738,6 +906,30 @@
   EXPECT_EQ("baz", *(--const_proto_array.end()));
 }
 
+TEST_F(RepeatedPtrFieldIteratorTest, MutableReverseIteration) {
+  RepeatedPtrField<string>::reverse_iterator iter = proto_array_.rbegin();
+  EXPECT_EQ("baz", *iter);
+  ++iter;
+  EXPECT_EQ("bar", *(iter++));
+  EXPECT_EQ("foo", *iter);
+  ++iter;
+  EXPECT_TRUE(proto_array_.rend() == iter);
+  EXPECT_EQ("foo", *(--proto_array_.rend()));
+}
+
+TEST_F(RepeatedPtrFieldIteratorTest, ConstReverseIteration) {
+  const RepeatedPtrField<string>& const_proto_array = proto_array_;
+  RepeatedPtrField<string>::const_reverse_iterator iter
+      = const_proto_array.rbegin();
+  EXPECT_EQ("baz", *iter);
+  ++iter;
+  EXPECT_EQ("bar", *(iter++));
+  EXPECT_EQ("foo", *iter);
+  ++iter;
+  EXPECT_TRUE(const_proto_array.rend() == iter);
+  EXPECT_EQ("foo", *(--const_proto_array.rend()));
+}
+
 TEST_F(RepeatedPtrFieldIteratorTest, RandomAccess) {
   RepeatedPtrField<string>::iterator iter = proto_array_.begin();
   RepeatedPtrField<string>::iterator iter2 = iter;
@@ -805,9 +997,11 @@
     proto_array_.Add()->assign("foo");
     proto_array_.Add()->assign("bar");
     proto_array_.Add()->assign("baz");
+    const_proto_array_ = &proto_array_;
   }
 
   RepeatedPtrField<string> proto_array_;
+  const RepeatedPtrField<string>* const_proto_array_;
 };
 
 TEST_F(RepeatedPtrFieldPtrsIteratorTest, ConvertiblePtr) {
@@ -815,6 +1009,11 @@
       proto_array_.pointer_begin();
 }
 
+TEST_F(RepeatedPtrFieldPtrsIteratorTest, ConvertibleConstPtr) {
+  RepeatedPtrField<string>::const_pointer_iterator iter =
+      const_proto_array_->pointer_begin();
+}
+
 TEST_F(RepeatedPtrFieldPtrsIteratorTest, MutablePtrIteration) {
   RepeatedPtrField<string>::pointer_iterator iter =
       proto_array_.pointer_begin();
@@ -827,6 +1026,18 @@
   EXPECT_EQ("baz", **(--proto_array_.pointer_end()));
 }
 
+TEST_F(RepeatedPtrFieldPtrsIteratorTest, MutableConstPtrIteration) {
+  RepeatedPtrField<string>::const_pointer_iterator iter =
+      const_proto_array_->pointer_begin();
+  EXPECT_EQ("foo", **iter);
+  ++iter;
+  EXPECT_EQ("bar", **(iter++));
+  EXPECT_EQ("baz", **iter);
+  ++iter;
+  EXPECT_TRUE(const_proto_array_->pointer_end() == iter);
+  EXPECT_EQ("baz", **(--const_proto_array_->pointer_end()));
+}
+
 TEST_F(RepeatedPtrFieldPtrsIteratorTest, RandomPtrAccess) {
   RepeatedPtrField<string>::pointer_iterator iter =
       proto_array_.pointer_begin();
@@ -840,6 +1051,19 @@
   EXPECT_EQ(3, proto_array_.end() - proto_array_.begin());
 }
 
+TEST_F(RepeatedPtrFieldPtrsIteratorTest, RandomConstPtrAccess) {
+  RepeatedPtrField<string>::const_pointer_iterator iter =
+      const_proto_array_->pointer_begin();
+  RepeatedPtrField<string>::const_pointer_iterator iter2 = iter;
+  ++iter2;
+  ++iter2;
+  EXPECT_TRUE(iter + 2 == iter2);
+  EXPECT_TRUE(iter == iter2 - 2);
+  EXPECT_EQ("baz", *iter[2]);
+  EXPECT_EQ("baz", **(iter + 2));
+  EXPECT_EQ(3, const_proto_array_->end() - const_proto_array_->begin());
+}
+
 TEST_F(RepeatedPtrFieldPtrsIteratorTest, ComparablePtr) {
   RepeatedPtrField<string>::pointer_iterator iter =
       proto_array_.pointer_begin();
@@ -854,6 +1078,20 @@
   EXPECT_TRUE(iter >= iter);
 }
 
+TEST_F(RepeatedPtrFieldPtrsIteratorTest, ComparableConstPtr) {
+  RepeatedPtrField<string>::const_pointer_iterator iter =
+      const_proto_array_->pointer_begin();
+  RepeatedPtrField<string>::const_pointer_iterator iter2 = iter + 1;
+  EXPECT_TRUE(iter == iter);
+  EXPECT_TRUE(iter != iter2);
+  EXPECT_TRUE(iter < iter2);
+  EXPECT_TRUE(iter <= iter2);
+  EXPECT_TRUE(iter <= iter);
+  EXPECT_TRUE(iter2 > iter);
+  EXPECT_TRUE(iter2 >= iter);
+  EXPECT_TRUE(iter >= iter);
+}
+
 // Uninitialized iterator does not point to any of the RepeatedPtrOverPtrs.
 // Dereferencing an uninitialized iterator crashes the process.
 TEST_F(RepeatedPtrFieldPtrsIteratorTest, UninitializedPtrIterator) {
@@ -865,6 +1103,14 @@
   EXPECT_TRUE(iter != proto_array_.pointer_end());
 }
 
+TEST_F(RepeatedPtrFieldPtrsIteratorTest, UninitializedConstPtrIterator) {
+  RepeatedPtrField<string>::const_pointer_iterator iter;
+  EXPECT_TRUE(iter != const_proto_array_->pointer_begin());
+  EXPECT_TRUE(iter != const_proto_array_->pointer_begin() + 1);
+  EXPECT_TRUE(iter != const_proto_array_->pointer_begin() + 2);
+  EXPECT_TRUE(iter != const_proto_array_->pointer_begin() + 3);
+  EXPECT_TRUE(iter != const_proto_array_->pointer_end());
+}
 
 // This comparison functor is required by the tests for RepeatedPtrOverPtrs.
 // They operate on strings and need to compare strings as strings in
@@ -889,17 +1135,33 @@
   proto_array_.Add()->assign("x");
   proto_array_.Add()->assign("y");
 
-  RepeatedPtrField<string>::pointer_iterator iter =
-      proto_array_.pointer_begin();
-  string v = "f";
-  RepeatedPtrField<string>::pointer_iterator it =
-      lower_bound(proto_array_.pointer_begin(), proto_array_.pointer_end(),
-                  &v, StringLessThan());
+  {
+    RepeatedPtrField<string>::pointer_iterator iter =
+        proto_array_.pointer_begin();
+    string v = "f";
+    RepeatedPtrField<string>::pointer_iterator it =
+        lower_bound(proto_array_.pointer_begin(), proto_array_.pointer_end(),
+                    &v, StringLessThan());
 
-  GOOGLE_CHECK(*it != NULL);
+    GOOGLE_CHECK(*it != NULL);
 
-  EXPECT_EQ(**it, "n");
-  EXPECT_TRUE(it == proto_array_.pointer_begin() + 3);
+    EXPECT_EQ(**it, "n");
+    EXPECT_TRUE(it == proto_array_.pointer_begin() + 3);
+  }
+  {
+    RepeatedPtrField<string>::const_pointer_iterator iter =
+        const_proto_array_->pointer_begin();
+    string v = "f";
+    RepeatedPtrField<string>::const_pointer_iterator it =
+        lower_bound(const_proto_array_->pointer_begin(),
+                    const_proto_array_->pointer_end(),
+                    &v, StringLessThan());
+
+    GOOGLE_CHECK(*it != NULL);
+
+    EXPECT_EQ(**it, "n");
+    EXPECT_TRUE(it == const_proto_array_->pointer_begin() + 3);
+  }
 }
 
 TEST_F(RepeatedPtrFieldPtrsIteratorTest, PtrMutation) {
@@ -1025,13 +1287,24 @@
 
 TEST_F(RepeatedFieldInsertionIteratorsTest, Words) {
   ASSERT_EQ(words.size(), protobuffer.repeated_string_size());
-  EXPECT_EQ(words.at(0), protobuffer.repeated_string(0));
-  EXPECT_EQ(words.at(1), protobuffer.repeated_string(1));
-  EXPECT_EQ(words.at(2), protobuffer.repeated_string(2));
-  EXPECT_EQ(words.at(3), protobuffer.repeated_string(3));
-  EXPECT_EQ(words.at(4), protobuffer.repeated_string(4));
-  EXPECT_EQ(words.at(5), protobuffer.repeated_string(5));
-  EXPECT_EQ(words.at(6), protobuffer.repeated_string(6));
+  for (int i = 0; i < words.size(); ++i)
+    EXPECT_EQ(words.at(i), protobuffer.repeated_string(i));
+}
+
+TEST_F(RepeatedFieldInsertionIteratorsTest, Words2) {
+  words.clear();
+  words.push_back("sing");
+  words.push_back("a");
+  words.push_back("song");
+  words.push_back("of");
+  words.push_back("six");
+  words.push_back("pence");
+  protobuffer.mutable_repeated_string()->Clear();
+  std::copy(words.begin(), words.end(), RepeatedPtrFieldBackInserter(
+      protobuffer.mutable_repeated_string()));
+  ASSERT_EQ(words.size(), protobuffer.repeated_string_size());
+  for (int i = 0; i < words.size(); ++i)
+    EXPECT_EQ(words.at(i), protobuffer.repeated_string(i));
 }
 
 TEST_F(RepeatedFieldInsertionIteratorsTest, Nesteds) {
diff --git a/third_party/protobuf/src/google/protobuf/stubs/atomicops_internals_atomicword_compat.h b/third_party/protobuf/src/google/protobuf/stubs/atomicops_internals_atomicword_compat.h
index e9d8679..8d9a726 100644
--- a/third_party/protobuf/src/google/protobuf/stubs/atomicops_internals_atomicword_compat.h
+++ b/third_party/protobuf/src/google/protobuf/stubs/atomicops_internals_atomicword_compat.h
@@ -44,7 +44,7 @@
 // On LP64 platforms, AtomicWord and Atomic64 are both always long,
 // so this problem doesn't occur.
 
-#if !defined(GOOGLE_PROTOBUF_ARCH_64_BIT)
+#if !defined(GOOGLE_PROTOBUF_HOST_ARCH_64_BIT)
 
 namespace google {
 namespace protobuf {
@@ -117,6 +117,6 @@
 }   // namespace protobuf
 }   // namespace google
 
-#endif  // !defined(GOOGLE_PROTOBUF_ARCH_64_BIT)
+#endif  // !defined(GOOGLE_PROTOBUF_HOST_ARCH_64_BIT)
 
 #endif  // GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_ATOMICWORD_COMPAT_H_
diff --git a/third_party/protobuf/src/google/protobuf/stubs/atomicops_internals_macosx.h b/third_party/protobuf/src/google/protobuf/stubs/atomicops_internals_macosx.h
index f9b7581..9af6d63 100644
--- a/third_party/protobuf/src/google/protobuf/stubs/atomicops_internals_macosx.h
+++ b/third_party/protobuf/src/google/protobuf/stubs/atomicops_internals_macosx.h
@@ -136,7 +136,7 @@
   Atomic64 prev_value;
   do {
     if (OSAtomicCompareAndSwap64(old_value, new_value,
-                                 reinterpret_cast<volatile int64_t*>(ptr))) {
+                                 const_cast<Atomic64*>(ptr))) {
       return old_value;
     }
     prev_value = *ptr;
@@ -150,19 +150,18 @@
   do {
     old_value = *ptr;
   } while (!OSAtomicCompareAndSwap64(old_value, new_value,
-                                     reinterpret_cast<volatile int64_t*>(ptr)));
+                                     const_cast<Atomic64*>(ptr)));
   return old_value;
 }
 
 inline Atomic64 NoBarrier_AtomicIncrement(volatile Atomic64* ptr,
                                           Atomic64 increment) {
-  return OSAtomicAdd64(increment, reinterpret_cast<volatile int64_t*>(ptr));
+  return OSAtomicAdd64(increment, const_cast<Atomic64*>(ptr));
 }
 
 inline Atomic64 Barrier_AtomicIncrement(volatile Atomic64* ptr,
                                         Atomic64 increment) {
-  return OSAtomicAdd64Barrier(increment,
-                              reinterpret_cast<volatile int64_t*>(ptr));
+  return OSAtomicAdd64Barrier(increment, const_cast<Atomic64*>(ptr));
 }
 
 inline Atomic64 Acquire_CompareAndSwap(volatile Atomic64* ptr,
@@ -170,8 +169,8 @@
                                        Atomic64 new_value) {
   Atomic64 prev_value;
   do {
-    if (OSAtomicCompareAndSwap64Barrier(
-        old_value, new_value, reinterpret_cast<volatile int64_t*>(ptr))) {
+    if (OSAtomicCompareAndSwap64Barrier(old_value, new_value,
+                                        const_cast<Atomic64*>(ptr))) {
       return old_value;
     }
     prev_value = *ptr;
diff --git a/third_party/protobuf/src/google/protobuf/stubs/common.cc b/third_party/protobuf/src/google/protobuf/stubs/common.cc
index 7b15be4..16d7852 100644
--- a/third_party/protobuf/src/google/protobuf/stubs/common.cc
+++ b/third_party/protobuf/src/google/protobuf/stubs/common.cc
@@ -320,6 +320,24 @@
 #endif
 
 // ===================================================================
+// emulates google3/util/endian/endian.h
+//
+// TODO(xiaofeng): PROTOBUF_LITTLE_ENDIAN is unfortunately defined in
+// google/protobuf/io/coded_stream.h and therefore can not be used here.
+// Maybe move that macro definition here in the furture.
+uint32 ghtonl(uint32 x) {
+  union {
+    uint32 result;
+    uint8 result_array[4];
+  };
+  result_array[0] = static_cast<uint8>(x >> 24);
+  result_array[1] = static_cast<uint8>((x >> 16) & 0xFF);
+  result_array[2] = static_cast<uint8>((x >> 8) & 0xFF);
+  result_array[3] = static_cast<uint8>(x & 0xFF);
+  return result;
+}
+
+// ===================================================================
 // Shutdown support.
 
 namespace internal {
diff --git a/third_party/protobuf/src/google/protobuf/stubs/common.h b/third_party/protobuf/src/google/protobuf/stubs/common.h
index cad22fa..4c3e0cb 100644
--- a/third_party/protobuf/src/google/protobuf/stubs/common.h
+++ b/third_party/protobuf/src/google/protobuf/stubs/common.h
@@ -356,6 +356,12 @@
   return static_cast<To>(f);
 }
 
+// Simplified down_cast for reference type.
+template<typename To, typename From>
+inline To down_cast(From& f) {
+  return static_cast<To>(f);
+}
+
 }  // namespace internal
 
 // We made these internal so that they would show up as such in the docs,
@@ -701,6 +707,7 @@
 #undef GOOGLE_CHECK_LE
 #undef GOOGLE_CHECK_GT
 #undef GOOGLE_CHECK_GE
+#undef GOOGLE_CHECK_NOTNULL
 
 #undef GOOGLE_DLOG
 #undef GOOGLE_DCHECK
@@ -727,6 +734,18 @@
 #define GOOGLE_CHECK_GT(A, B) GOOGLE_CHECK((A) >  (B))
 #define GOOGLE_CHECK_GE(A, B) GOOGLE_CHECK((A) >= (B))
 
+namespace internal {
+template<typename T>
+T* CheckNotNull(const char *file, int line, const char *name, T* val) {
+  if (val == NULL) {
+    GOOGLE_LOG(FATAL) << name;
+  }
+  return val;
+}
+}  // namespace internal
+#define GOOGLE_CHECK_NOTNULL(A) \
+  internal::CheckNotNull(__FILE__, __LINE__, "'" #A "' must not be NULL", (A))
+
 #ifdef NDEBUG
 
 #define GOOGLE_DLOG GOOGLE_LOG_IF(INFO, false)
@@ -1151,20 +1170,10 @@
 using internal::MutexLockMaybe;
 
 // ===================================================================
-// from google3/base/type_traits.h
+// from google3/util/utf8/public/unilib.h
 
 namespace internal {
 
-// Specified by TR1 [4.7.4] Pointer modifications.
-template<typename T> struct remove_pointer { typedef T type; };
-template<typename T> struct remove_pointer<T*> { typedef T type; };
-template<typename T> struct remove_pointer<T* const> { typedef T type; };
-template<typename T> struct remove_pointer<T* volatile> { typedef T type; };
-template<typename T> struct remove_pointer<T* const volatile> {
-  typedef T type; };
-
-// ===================================================================
-
 // Checks if the buffer contains structurally-valid UTF-8.  Implemented in
 // structurally_valid.cc.
 LIBPROTOBUF_EXPORT bool IsStructurallyValidUTF8(const char* buf, int len);
@@ -1172,6 +1181,10 @@
 }  // namespace internal
 
 // ===================================================================
+// from google3/util/endian/endian.h
+LIBPROTOBUF_EXPORT uint32 ghtonl(uint32 x);
+
+// ===================================================================
 // Shutdown support.
 
 // Shut down the entire protocol buffers library, deleting all static-duration
diff --git a/third_party/protobuf/src/google/protobuf/stubs/hash.h b/third_party/protobuf/src/google/protobuf/stubs/hash.h
index 822d605..f7d1071 100644
--- a/third_party/protobuf/src/google/protobuf/stubs/hash.h
+++ b/third_party/protobuf/src/google/protobuf/stubs/hash.h
@@ -90,12 +90,16 @@
           typename HashFcn = hash<Key>,
           typename EqualKey = int >
 class hash_map : public std::map<Key, Data, HashFcn> {
+ public:
+  hash_map(int = 0) {}
 };
 
 template <typename Key,
           typename HashFcn = hash<Key>,
           typename EqualKey = int >
 class hash_set : public std::set<Key, HashFcn> {
+ public:
+  hash_set(int = 0) {}
 };
 
 #elif defined(_MSC_VER) && !defined(_STLPORT_VERSION)
@@ -123,6 +127,8 @@
           typename EqualKey = int >
 class hash_map : public HASH_NAMESPACE::hash_map<
     Key, Data, HashFcn> {
+ public:
+  hash_map(int = 0) {}
 };
 
 template <typename Key,
@@ -130,6 +136,8 @@
           typename EqualKey = int >
 class hash_set : public HASH_NAMESPACE::hash_set<
     Key, HashFcn> {
+ public:
+  hash_set(int = 0) {}
 };
 
 #else
@@ -163,6 +171,8 @@
           typename EqualKey = std::equal_to<Key> >
 class hash_map : public HASH_NAMESPACE::HASH_MAP_CLASS<
     Key, Data, HashFcn, EqualKey> {
+ public:
+  hash_map(int = 0) {}
 };
 
 template <typename Key,
@@ -170,6 +180,8 @@
           typename EqualKey = std::equal_to<Key> >
 class hash_set : public HASH_NAMESPACE::HASH_SET_CLASS<
     Key, HashFcn, EqualKey> {
+ public:
+  hash_set(int = 0) {}
 };
 
 #endif
diff --git a/third_party/protobuf/src/google/protobuf/stubs/map-util.h b/third_party/protobuf/src/google/protobuf/stubs/map-util.h
index f5c9d6b..775848b 100644
--- a/third_party/protobuf/src/google/protobuf/stubs/map-util.h
+++ b/third_party/protobuf/src/google/protobuf/stubs/map-util.h
@@ -68,6 +68,30 @@
   return &it->second;
 }
 
+// Perform a lookup in a map or hash_map, assuming that the key exists.
+// Crash if it does not.
+//
+// This is intended as a replacement for operator[] as an rvalue (for reading)
+// when the key is guaranteed to exist.
+//
+// operator[] is discouraged for several reasons:
+//  * It has a side-effect of inserting missing keys
+//  * It is not thread-safe (even when it is not inserting, it can still
+//      choose to resize the underlying storage)
+//  * It invalidates iterators (when it chooses to resize)
+//  * It default constructs a value object even if it doesn't need to
+//
+// This version assumes the key is printable, and includes it in the fatal log
+// message.
+template <class Collection>
+const typename Collection::value_type::second_type&
+FindOrDie(const Collection& collection,
+          const typename Collection::value_type::first_type& key) {
+  typename Collection::const_iterator it = collection.find(key);
+  GOOGLE_CHECK(it != collection.end()) << "Map key not found: " << key;
+  return it->second;
+}
+
 // Perform a lookup in a map or hash_map whose values are pointers.
 // If the key is present a const pointer to the associated value is returned,
 // otherwise a NULL pointer is returned.
diff --git a/third_party/protobuf/src/google/protobuf/stubs/stl_util.h b/third_party/protobuf/src/google/protobuf/stubs/stl_util.h
new file mode 100644
index 0000000..9021dad
--- /dev/null
+++ b/third_party/protobuf/src/google/protobuf/stubs/stl_util.h
@@ -0,0 +1,121 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 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.
+
+// from google3/util/gtl/stl_util.h
+
+#ifndef GOOGLE_PROTOBUF_STUBS_STL_UTIL_H__
+#define GOOGLE_PROTOBUF_STUBS_STL_UTIL_H__
+
+#include <google/protobuf/stubs/common.h>
+
+namespace google {
+namespace protobuf {
+
+// STLDeleteContainerPointers()
+//  For a range within a container of pointers, calls delete
+//  (non-array version) on these pointers.
+// NOTE: for these three functions, we could just implement a DeleteObject
+// functor and then call for_each() on the range and functor, but this
+// requires us to pull in all of algorithm.h, which seems expensive.
+// For hash_[multi]set, it is important that this deletes behind the iterator
+// because the hash_set may call the hash function on the iterator when it is
+// advanced, which could result in the hash function trying to deference a
+// stale pointer.
+template <class ForwardIterator>
+void STLDeleteContainerPointers(ForwardIterator begin,
+                                ForwardIterator end) {
+  while (begin != end) {
+    ForwardIterator temp = begin;
+    ++begin;
+    delete *temp;
+  }
+}
+
+// Inside Google, this function implements a horrible, disgusting hack in which
+// we reach into the string's private implementation and resize it without
+// initializing the new bytes.  In some cases doing this can significantly
+// improve performance.  However, since it's totally non-portable it has no
+// place in open source code.  Feel free to fill this function in with your
+// own disgusting hack if you want the perf boost.
+inline void STLStringResizeUninitialized(string* s, size_t new_size) {
+  s->resize(new_size);
+}
+
+// Return a mutable char* pointing to a string's internal buffer,
+// which may not be null-terminated. Writing through this pointer will
+// modify the string.
+//
+// string_as_array(&str)[i] is valid for 0 <= i < str.size() until the
+// next call to a string method that invalidates iterators.
+//
+// As of 2006-04, there is no standard-blessed way of getting a
+// mutable reference to a string's internal buffer. However, issue 530
+// (http://www.open-std.org/JTC1/SC22/WG21/docs/lwg-active.html#530)
+// proposes this as the method. According to Matt Austern, this should
+// already work on all current implementations.
+inline char* string_as_array(string* str) {
+  // DO NOT USE const_cast<char*>(str->data())! See the unittest for why.
+  return str->empty() ? NULL : &*str->begin();
+}
+
+// STLDeleteElements() deletes all the elements in an STL container and clears
+// the container.  This function is suitable for use with a vector, set,
+// hash_set, or any other STL container which defines sensible begin(), end(),
+// and clear() methods.
+//
+// If container is NULL, this function is a no-op.
+//
+// As an alternative to calling STLDeleteElements() directly, consider
+// ElementDeleter (defined below), which ensures that your container's elements
+// are deleted when the ElementDeleter goes out of scope.
+template <class T>
+void STLDeleteElements(T *container) {
+  if (!container) return;
+  STLDeleteContainerPointers(container->begin(), container->end());
+  container->clear();
+}
+
+// Given an STL container consisting of (key, value) pairs, STLDeleteValues
+// deletes all the "value" components and clears the container.  Does nothing
+// in the case it's given a NULL pointer.
+
+template <class T>
+void STLDeleteValues(T *v) {
+  if (!v) return;
+  for (typename T::iterator i = v->begin(); i != v->end(); ++i) {
+    delete i->second;
+  }
+  v->clear();
+}
+
+}  // namespace protobuf
+}  // namespace google
+
+#endif  // GOOGLE_PROTOBUF_STUBS_STL_UTIL_H__
diff --git a/third_party/protobuf/src/google/protobuf/stubs/stringprintf.cc b/third_party/protobuf/src/google/protobuf/stubs/stringprintf.cc
new file mode 100644
index 0000000..4a5b858
--- /dev/null
+++ b/third_party/protobuf/src/google/protobuf/stubs/stringprintf.cc
@@ -0,0 +1,175 @@
+// 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.
+
+// from google3/base/stringprintf.cc
+
+#include <google/protobuf/stubs/stringprintf.h>
+
+#include <errno.h>
+#include <stdarg.h> // For va_list and related operations
+#include <stdio.h> // MSVC requires this for _vsnprintf
+#include <vector>
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/testing/googletest.h>
+
+namespace google {
+namespace protobuf {
+
+#ifdef _MSC_VER
+enum { IS_COMPILER_MSVC = 1 };
+#ifndef va_copy
+// Define va_copy for MSVC. This is a hack, assuming va_list is simply a
+// pointer into the stack and is safe to copy.
+#define va_copy(dest, src) ((dest) = (src))
+#endif
+#else
+enum { IS_COMPILER_MSVC = 0 };
+#endif
+
+void StringAppendV(string* dst, const char* format, va_list ap) {
+  // First try with a small fixed size buffer
+  static const int kSpaceLength = 1024;
+  char space[kSpaceLength];
+
+  // It's possible for methods that use a va_list to invalidate
+  // the data in it upon use.  The fix is to make a copy
+  // of the structure before using it and use that copy instead.
+  va_list backup_ap;
+  va_copy(backup_ap, ap);
+  int result = vsnprintf(space, kSpaceLength, format, backup_ap);
+  va_end(backup_ap);
+
+  if (result < kSpaceLength) {
+    if (result >= 0) {
+      // Normal case -- everything fit.
+      dst->append(space, result);
+      return;
+    }
+
+    if (IS_COMPILER_MSVC) {
+      // Error or MSVC running out of space.  MSVC 8.0 and higher
+      // can be asked about space needed with the special idiom below:
+      va_copy(backup_ap, ap);
+      result = vsnprintf(NULL, 0, format, backup_ap);
+      va_end(backup_ap);
+    }
+
+    if (result < 0) {
+      // Just an error.
+      return;
+    }
+  }
+
+  // Increase the buffer size to the size requested by vsnprintf,
+  // plus one for the closing \0.
+  int length = result+1;
+  char* buf = new char[length];
+
+  // Restore the va_list before we use it again
+  va_copy(backup_ap, ap);
+  result = vsnprintf(buf, length, format, backup_ap);
+  va_end(backup_ap);
+
+  if (result >= 0 && result < length) {
+    // It fit
+    dst->append(buf, result);
+  }
+  delete[] buf;
+}
+
+
+string StringPrintf(const char* format, ...) {
+  va_list ap;
+  va_start(ap, format);
+  string result;
+  StringAppendV(&result, format, ap);
+  va_end(ap);
+  return result;
+}
+
+const string& SStringPrintf(string* dst, const char* format, ...) {
+  va_list ap;
+  va_start(ap, format);
+  dst->clear();
+  StringAppendV(dst, format, ap);
+  va_end(ap);
+  return *dst;
+}
+
+void StringAppendF(string* dst, const char* format, ...) {
+  va_list ap;
+  va_start(ap, format);
+  StringAppendV(dst, format, ap);
+  va_end(ap);
+}
+
+// Max arguments supported by StringPrintVector
+const int kStringPrintfVectorMaxArgs = 32;
+
+// An empty block of zero for filler arguments.  This is const so that if
+// printf tries to write to it (via %n) then the program gets a SIGSEGV
+// and we can fix the problem or protect against an attack.
+static const char string_printf_empty_block[256] = { '\0' };
+
+string StringPrintfVector(const char* format, const vector<string>& v) {
+  GOOGLE_CHECK_LE(v.size(), kStringPrintfVectorMaxArgs)
+      << "StringPrintfVector currently only supports up to "
+      << kStringPrintfVectorMaxArgs << " arguments. "
+      << "Feel free to add support for more if you need it.";
+
+  // Add filler arguments so that bogus format+args have a harder time
+  // crashing the program, corrupting the program (%n),
+  // or displaying random chunks of memory to users.
+
+  const char* cstr[kStringPrintfVectorMaxArgs];
+  for (int i = 0; i < v.size(); ++i) {
+    cstr[i] = v[i].c_str();
+  }
+  for (int i = v.size(); i < GOOGLE_ARRAYSIZE(cstr); ++i) {
+    cstr[i] = &string_printf_empty_block[0];
+  }
+
+  // I do not know any way to pass kStringPrintfVectorMaxArgs arguments,
+  // or any way to build a va_list by hand, or any API for printf
+  // that accepts an array of arguments.  The best I can do is stick
+  // this COMPILE_ASSERT right next to the actual statement.
+
+  GOOGLE_COMPILE_ASSERT(kStringPrintfVectorMaxArgs == 32, arg_count_mismatch);
+  return StringPrintf(format,
+                      cstr[0], cstr[1], cstr[2], cstr[3], cstr[4],
+                      cstr[5], cstr[6], cstr[7], cstr[8], cstr[9],
+                      cstr[10], cstr[11], cstr[12], cstr[13], cstr[14],
+                      cstr[15], cstr[16], cstr[17], cstr[18], cstr[19],
+                      cstr[20], cstr[21], cstr[22], cstr[23], cstr[24],
+                      cstr[25], cstr[26], cstr[27], cstr[28], cstr[29],
+                      cstr[30], cstr[31]);
+}
+}  // namespace protobuf
+}  // namespace google
diff --git a/third_party/protobuf/src/google/protobuf/stubs/stringprintf.h b/third_party/protobuf/src/google/protobuf/stubs/stringprintf.h
new file mode 100644
index 0000000..573f30f
--- /dev/null
+++ b/third_party/protobuf/src/google/protobuf/stubs/stringprintf.h
@@ -0,0 +1,76 @@
+// 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.
+
+// from google3/base/stringprintf.h
+//
+// Printf variants that place their output in a C++ string.
+//
+// Usage:
+//      string result = StringPrintf("%d %s\n", 10, "hello");
+//      SStringPrintf(&result, "%d %s\n", 10, "hello");
+//      StringAppendF(&result, "%d %s\n", 20, "there");
+
+#ifndef GOOGLE_PROTOBUF_STUBS_STRINGPRINTF_H
+#define GOOGLE_PROTOBUF_STUBS_STRINGPRINTF_H
+
+#include <stdarg.h>
+#include <string>
+#include <vector>
+
+#include <google/protobuf/stubs/common.h>
+
+namespace google {
+namespace protobuf {
+
+// Return a C++ string
+extern string StringPrintf(const char* format, ...);
+
+// Store result into a supplied string and return it
+extern const string& SStringPrintf(string* dst, const char* format, ...);
+
+// Append result to a supplied string
+extern void StringAppendF(string* dst, const char* format, ...);
+
+// Lower-level routine that takes a va_list and appends to a specified
+// string.  All other routines are just convenience wrappers around it.
+extern void StringAppendV(string* dst, const char* format, va_list ap);
+
+// The max arguments supported by StringPrintfVector
+extern const int kStringPrintfVectorMaxArgs;
+
+// You can use this version when all your arguments are strings, but
+// you don't know how many arguments you'll have at compile time.
+// StringPrintfVector will LOG(FATAL) if v.size() > kStringPrintfVectorMaxArgs
+extern string StringPrintfVector(const char* format, const vector<string>& v);
+
+}  // namespace protobuf
+}  // namespace google
+
+#endif  // GOOGLE_PROTOBUF_STUBS_STRINGPRINTF_H
diff --git a/third_party/protobuf/src/google/protobuf/stubs/stringprintf_unittest.cc b/third_party/protobuf/src/google/protobuf/stubs/stringprintf_unittest.cc
new file mode 100644
index 0000000..a78a202
--- /dev/null
+++ b/third_party/protobuf/src/google/protobuf/stubs/stringprintf_unittest.cc
@@ -0,0 +1,152 @@
+// 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.
+
+// from google3/base/stringprintf_unittest.cc
+
+#include <google/protobuf/stubs/stringprintf.h>
+
+#include <cerrno>
+#include <string>
+
+#include <google/protobuf/testing/googletest.h>
+#include <gtest/gtest.h>
+
+namespace google {
+namespace protobuf {
+namespace {
+
+TEST(StringPrintfTest, Empty) {
+#if 0
+  // gcc 2.95.3, gcc 4.1.0, and gcc 4.2.2 all warn about this:
+  // warning: zero-length printf format string.
+  // so we do not allow them in google3.
+  EXPECT_EQ("", StringPrintf(""));
+#endif
+  EXPECT_EQ("", StringPrintf("%s", string().c_str()));
+  EXPECT_EQ("", StringPrintf("%s", ""));
+}
+
+TEST(StringPrintfTest, Misc) {
+// MSVC does not support $ format specifier.
+#if !defined(_MSC_VER)
+  EXPECT_EQ("123hello w", StringPrintf("%3$d%2$s %1$c", 'w', "hello", 123));
+#endif  // !_MSC_VER
+}
+
+TEST(StringAppendFTest, Empty) {
+  string value("Hello");
+  const char* empty = "";
+  StringAppendF(&value, "%s", empty);
+  EXPECT_EQ("Hello", value);
+}
+
+TEST(StringAppendFTest, EmptyString) {
+  string value("Hello");
+  StringAppendF(&value, "%s", "");
+  EXPECT_EQ("Hello", value);
+}
+
+TEST(StringAppendFTest, String) {
+  string value("Hello");
+  StringAppendF(&value, " %s", "World");
+  EXPECT_EQ("Hello World", value);
+}
+
+TEST(StringAppendFTest, Int) {
+  string value("Hello");
+  StringAppendF(&value, " %d", 123);
+  EXPECT_EQ("Hello 123", value);
+}
+
+TEST(StringPrintfTest, Multibyte) {
+  // If we are in multibyte mode and feed invalid multibyte sequence,
+  // StringPrintf should return an empty string instead of running
+  // out of memory while trying to determine destination buffer size.
+  // see b/4194543.
+
+  char* old_locale = setlocale(LC_CTYPE, NULL);
+  // Push locale with multibyte mode
+  setlocale(LC_CTYPE, "en_US.utf8");
+
+  const char kInvalidCodePoint[] = "\375\067s";
+  string value = StringPrintf("%.*s", 3, kInvalidCodePoint);
+
+  // In some versions of glibc (e.g. eglibc-2.11.1, aka GRTEv2), snprintf
+  // returns error given an invalid codepoint. Other versions
+  // (e.g. eglibc-2.15, aka pre-GRTEv3) emit the codepoint verbatim.
+  // We test that the output is one of the above.
+  EXPECT_TRUE(value.empty() || value == kInvalidCodePoint);
+
+  // Repeat with longer string, to make sure that the dynamically
+  // allocated path in StringAppendV is handled correctly.
+  int n = 2048;
+  char* buf = new char[n+1];
+  memset(buf, ' ', n-3);
+  memcpy(buf + n - 3, kInvalidCodePoint, 4);
+  value =  StringPrintf("%.*s", n, buf);
+  // See GRTEv2 vs. GRTEv3 comment above.
+  EXPECT_TRUE(value.empty() || value == buf);
+  delete[] buf;
+
+  setlocale(LC_CTYPE, old_locale);
+}
+
+TEST(StringPrintfTest, NoMultibyte) {
+  // No multibyte handling, but the string contains funny chars.
+  char* old_locale = setlocale(LC_CTYPE, NULL);
+  setlocale(LC_CTYPE, "POSIX");
+  string value = StringPrintf("%.*s", 3, "\375\067s");
+  setlocale(LC_CTYPE, old_locale);
+  EXPECT_EQ("\375\067s", value);
+}
+
+TEST(StringPrintfTest, DontOverwriteErrno) {
+  // Check that errno isn't overwritten unless we're printing
+  // something significantly larger than what people are normally
+  // printing in their badly written PLOG() statements.
+  errno = ECHILD;
+  string value = StringPrintf("Hello, %s!", "World");
+  EXPECT_EQ(ECHILD, errno);
+}
+
+TEST(StringPrintfTest, LargeBuf) {
+  // Check that the large buffer is handled correctly.
+  int n = 2048;
+  char* buf = new char[n+1];
+  memset(buf, ' ', n);
+  buf[n] = 0;
+  string value = StringPrintf("%s", buf);
+  EXPECT_EQ(buf, value);
+  delete[] buf;
+}
+
+}  // anonymous namespace
+}  // namespace protobuf
+}  // namespace google
diff --git a/third_party/protobuf/src/google/protobuf/stubs/strutil.cc b/third_party/protobuf/src/google/protobuf/stubs/strutil.cc
index ee07ce7..917b3e9 100644
--- a/third_party/protobuf/src/google/protobuf/stubs/strutil.cc
+++ b/third_party/protobuf/src/google/protobuf/stubs/strutil.cc
@@ -189,6 +189,44 @@
   SplitStringToIteratorUsing(full, delim, it);
 }
 
+// Split a string using a character delimiter. Append the components
+// to 'result'.  If there are consecutive delimiters, this function
+// will return corresponding empty strings. The string is split into
+// at most the specified number of pieces greedily. This means that the
+// last piece may possibly be split further. To split into as many pieces
+// as possible, specify 0 as the number of pieces.
+//
+// If "full" is the empty string, yields an empty string as the only value.
+//
+// If "pieces" is negative for some reason, it returns the whole string
+// ----------------------------------------------------------------------
+template <typename StringType, typename ITR>
+static inline
+void SplitStringToIteratorAllowEmpty(const StringType& full,
+                                     const char* delim,
+                                     int pieces,
+                                     ITR& result) {
+  string::size_type begin_index, end_index;
+  begin_index = 0;
+
+  for (int i = 0; (i < pieces-1) || (pieces == 0); i++) {
+    end_index = full.find_first_of(delim, begin_index);
+    if (end_index == string::npos) {
+      *result++ = full.substr(begin_index);
+      return;
+    }
+    *result++ = full.substr(begin_index, (end_index - begin_index));
+    begin_index = end_index + 1;
+  }
+  *result++ = full.substr(begin_index);
+}
+
+void SplitStringAllowEmpty(const string& full, const char* delim,
+                           vector<string>* result) {
+  back_insert_iterator<vector<string> > it(*result);
+  SplitStringToIteratorAllowEmpty(full, delim, 0, it);
+}
+
 // ----------------------------------------------------------------------
 // JoinStrings()
 //    This merges a vector of string components with delim inserted
diff --git a/third_party/protobuf/src/google/protobuf/stubs/strutil.h b/third_party/protobuf/src/google/protobuf/stubs/strutil.h
index 4a79c22..a401c63 100644
--- a/third_party/protobuf/src/google/protobuf/stubs/strutil.h
+++ b/third_party/protobuf/src/google/protobuf/stubs/strutil.h
@@ -168,6 +168,18 @@
 LIBPROTOBUF_EXPORT void SplitStringUsing(const string& full, const char* delim,
                                          vector<string>* res);
 
+// Split a string using one or more byte delimiters, presented
+// as a nul-terminated c string. Append the components to 'result'.
+// If there are consecutive delimiters, this function will return
+// corresponding empty strings.  If you want to drop the empty
+// strings, try SplitStringUsing().
+//
+// If "full" is the empty string, yields an empty string as the only value.
+// ----------------------------------------------------------------------
+LIBPROTOBUF_EXPORT void SplitStringAllowEmpty(const string& full,
+                                              const char* delim,
+                                              vector<string>* result);
+
 // ----------------------------------------------------------------------
 // JoinStrings()
 //    These methods concatenate a vector of strings into a C++ string, using
@@ -453,5 +465,3 @@
 }  // namespace google
 
 #endif  // GOOGLE_PROTOBUF_STUBS_STRUTIL_H__
-
-
diff --git a/third_party/protobuf/src/google/protobuf/stubs/substitute.cc b/third_party/protobuf/src/google/protobuf/stubs/substitute.cc
index b542aaa..259245b 100644
--- a/third_party/protobuf/src/google/protobuf/stubs/substitute.cc
+++ b/third_party/protobuf/src/google/protobuf/stubs/substitute.cc
@@ -32,7 +32,7 @@
 
 #include <google/protobuf/stubs/substitute.h>
 #include <google/protobuf/stubs/strutil.h>
-#include <google/protobuf/stubs/stl_util-inl.h>
+#include <google/protobuf/stubs/stl_util.h>
 
 namespace google {
 namespace protobuf {
diff --git a/third_party/protobuf/src/google/protobuf/stubs/template_util.h b/third_party/protobuf/src/google/protobuf/stubs/template_util.h
new file mode 100644
index 0000000..4f30ffa
--- /dev/null
+++ b/third_party/protobuf/src/google/protobuf/stubs/template_util.h
@@ -0,0 +1,138 @@
+// Copyright 2005 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.
+
+// ----
+// Author: lar@google.com (Laramie Leavitt)
+//
+// Template metaprogramming utility functions.
+//
+// This code is compiled directly on many platforms, including client
+// platforms like Windows, Mac, and embedded systems.  Before making
+// any changes here, make sure that you're not breaking any platforms.
+//
+//
+// The names choosen here reflect those used in tr1 and the boost::mpl
+// library, there are similar operations used in the Loki library as
+// well.  I prefer the boost names for 2 reasons:
+// 1.  I think that portions of the Boost libraries are more likely to
+// be included in the c++ standard.
+// 2.  It is not impossible that some of the boost libraries will be
+// included in our own build in the future.
+// Both of these outcomes means that we may be able to directly replace
+// some of these with boost equivalents.
+//
+#ifndef GOOGLE_PROTOBUF_TEMPLATE_UTIL_H_
+#define GOOGLE_PROTOBUF_TEMPLATE_UTIL_H_
+
+namespace google {
+namespace protobuf {
+namespace internal {
+
+// Types small_ and big_ are guaranteed such that sizeof(small_) <
+// sizeof(big_)
+typedef char small_;
+
+struct big_ {
+  char dummy[2];
+};
+
+// Identity metafunction.
+template <class T>
+struct identity_ {
+  typedef T type;
+};
+
+// integral_constant, defined in tr1, is a wrapper for an integer
+// value. We don't really need this generality; we could get away
+// with hardcoding the integer type to bool. We use the fully
+// general integer_constant for compatibility with tr1.
+
+template<class T, T v>
+struct integral_constant {
+  static const T value = v;
+  typedef T value_type;
+  typedef integral_constant<T, v> type;
+};
+
+template <class T, T v> const T integral_constant<T, v>::value;
+
+
+// Abbreviations: true_type and false_type are structs that represent boolean
+// true and false values. Also define the boost::mpl versions of those names,
+// true_ and false_.
+typedef integral_constant<bool, true>  true_type;
+typedef integral_constant<bool, false> false_type;
+typedef true_type  true_;
+typedef false_type false_;
+
+// if_ is a templatized conditional statement.
+// if_<cond, A, B> is a compile time evaluation of cond.
+// if_<>::type contains A if cond is true, B otherwise.
+template<bool cond, typename A, typename B>
+struct if_{
+  typedef A type;
+};
+
+template<typename A, typename B>
+struct if_<false, A, B> {
+  typedef B type;
+};
+
+
+// type_equals_ is a template type comparator, similar to Loki IsSameType.
+// type_equals_<A, B>::value is true iff "A" is the same type as "B".
+//
+// New code should prefer base::is_same, defined in base/type_traits.h.
+// It is functionally identical, but is_same is the standard spelling.
+template<typename A, typename B>
+struct type_equals_ : public false_ {
+};
+
+template<typename A>
+struct type_equals_<A, A> : public true_ {
+};
+
+// and_ is a template && operator.
+// and_<A, B>::value evaluates "A::value && B::value".
+template<typename A, typename B>
+struct and_ : public integral_constant<bool, (A::value && B::value)> {
+};
+
+// or_ is a template || operator.
+// or_<A, B>::value evaluates "A::value || B::value".
+template<typename A, typename B>
+struct or_ : public integral_constant<bool, (A::value || B::value)> {
+};
+
+
+}  // namespace internal
+}  // namespace protobuf
+}  // namespace google
+
+#endif  // GOOGLE_PROTOBUF_TEMPLATE_UTIL_H_
diff --git a/third_party/protobuf/src/google/protobuf/stubs/template_util_unittest.cc b/third_party/protobuf/src/google/protobuf/stubs/template_util_unittest.cc
new file mode 100644
index 0000000..b1745e2
--- /dev/null
+++ b/third_party/protobuf/src/google/protobuf/stubs/template_util_unittest.cc
@@ -0,0 +1,130 @@
+// Copyright 2005 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.
+
+// ----
+// Author: lar@google.com (Laramie Leavitt)
+//
+// These tests are really compile time tests.
+// If you try to step through this in a debugger
+// you will not see any evaluations, merely that
+// value is assigned true or false sequentially.
+
+#include <google/protobuf/stubs/template_util.h>
+
+#include <google/protobuf/testing/googletest.h>
+#include <gtest/gtest.h>
+
+namespace GOOGLE_NAMESPACE = google::protobuf::internal;
+
+namespace google {
+namespace protobuf {
+namespace internal {
+namespace {
+
+TEST(TemplateUtilTest, TestSize) {
+  EXPECT_GT(sizeof(GOOGLE_NAMESPACE::big_), sizeof(GOOGLE_NAMESPACE::small_));
+}
+
+TEST(TemplateUtilTest, TestIntegralConstants) {
+  // test the built-in types.
+  EXPECT_TRUE(true_type::value);
+  EXPECT_FALSE(false_type::value);
+
+  typedef integral_constant<int, 1> one_type;
+  EXPECT_EQ(1, one_type::value);
+}
+
+TEST(TemplateUtilTest, TestTemplateIf) {
+  typedef if_<true, true_type, false_type>::type if_true;
+  EXPECT_TRUE(if_true::value);
+
+  typedef if_<false, true_type, false_type>::type if_false;
+  EXPECT_FALSE(if_false::value);
+}
+
+TEST(TemplateUtilTest, TestTemplateTypeEquals) {
+  // Check that the TemplateTypeEquals works correctly.
+  bool value = false;
+
+  // Test the same type is true.
+  value = type_equals_<int, int>::value;
+  EXPECT_TRUE(value);
+
+  // Test different types are false.
+  value = type_equals_<float, int>::value;
+  EXPECT_FALSE(value);
+
+  // Test type aliasing.
+  typedef const int foo;
+  value = type_equals_<const foo, const int>::value;
+  EXPECT_TRUE(value);
+}
+
+TEST(TemplateUtilTest, TestTemplateAndOr) {
+  // Check that the TemplateTypeEquals works correctly.
+  bool value = false;
+
+  // Yes && Yes == true.
+  value = and_<true_, true_>::value;
+  EXPECT_TRUE(value);
+  // Yes && No == false.
+  value = and_<true_, false_>::value;
+  EXPECT_FALSE(value);
+  // No && Yes == false.
+  value = and_<false_, true_>::value;
+  EXPECT_FALSE(value);
+  // No && No == false.
+  value = and_<false_, false_>::value;
+  EXPECT_FALSE(value);
+
+  // Yes || Yes == true.
+  value = or_<true_, true_>::value;
+  EXPECT_TRUE(value);
+  // Yes || No == true.
+  value = or_<true_, false_>::value;
+  EXPECT_TRUE(value);
+  // No || Yes == true.
+  value = or_<false_, true_>::value;
+  EXPECT_TRUE(value);
+  // No || No == false.
+  value = or_<false_, false_>::value;
+  EXPECT_FALSE(value);
+}
+
+TEST(TemplateUtilTest, TestIdentity) {
+  EXPECT_TRUE(
+      (type_equals_<GOOGLE_NAMESPACE::identity_<int>::type, int>::value));
+  EXPECT_TRUE(
+      (type_equals_<GOOGLE_NAMESPACE::identity_<void>::type, void>::value));
+}
+
+}  // anonymous namespace
+}  // namespace internal
+}  // namespace protobuf
+}  // namespace google
diff --git a/third_party/protobuf/src/google/protobuf/stubs/type_traits.h b/third_party/protobuf/src/google/protobuf/stubs/type_traits.h
new file mode 100644
index 0000000..997f35d
--- /dev/null
+++ b/third_party/protobuf/src/google/protobuf/stubs/type_traits.h
@@ -0,0 +1,346 @@
+// Copyright (c) 2006, 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.
+
+// ----
+// Author: Matt Austern
+//
+// This code is compiled directly on many platforms, including client
+// platforms like Windows, Mac, and embedded systems.  Before making
+// any changes here, make sure that you're not breaking any platforms.
+//
+// Define a small subset of tr1 type traits. The traits we define are:
+//   is_integral
+//   is_floating_point
+//   is_pointer
+//   is_enum
+//   is_reference
+//   is_pod
+//   has_trivial_constructor
+//   has_trivial_copy
+//   has_trivial_assign
+//   has_trivial_destructor
+//   remove_const
+//   remove_volatile
+//   remove_cv
+//   remove_reference
+//   add_reference
+//   remove_pointer
+//   is_same
+//   is_convertible
+// We can add more type traits as required.
+
+#ifndef GOOGLE_PROTOBUF_TYPE_TRAITS_H_
+#define GOOGLE_PROTOBUF_TYPE_TRAITS_H_
+
+#include <utility>                  // For pair
+
+#include <google/protobuf/stubs/template_util.h>  // For true_type and false_type
+
+namespace google {
+namespace protobuf {
+namespace internal {
+
+template <class T> struct is_integral;
+template <class T> struct is_floating_point;
+template <class T> struct is_pointer;
+// MSVC can't compile this correctly, and neither can gcc 3.3.5 (at least)
+#if !defined(_MSC_VER) && !(defined(__GNUC__) && __GNUC__ <= 3)
+// is_enum uses is_convertible, which is not available on MSVC.
+template <class T> struct is_enum;
+#endif
+template <class T> struct is_reference;
+template <class T> struct is_pod;
+template <class T> struct has_trivial_constructor;
+template <class T> struct has_trivial_copy;
+template <class T> struct has_trivial_assign;
+template <class T> struct has_trivial_destructor;
+template <class T> struct remove_const;
+template <class T> struct remove_volatile;
+template <class T> struct remove_cv;
+template <class T> struct remove_reference;
+template <class T> struct add_reference;
+template <class T> struct remove_pointer;
+template <class T, class U> struct is_same;
+#if !defined(_MSC_VER) && !(defined(__GNUC__) && __GNUC__ <= 3)
+template <class From, class To> struct is_convertible;
+#endif
+
+// is_integral is false except for the built-in integer types. A
+// cv-qualified type is integral if and only if the underlying type is.
+template <class T> struct is_integral : false_type { };
+template<> struct is_integral<bool> : true_type { };
+template<> struct is_integral<char> : true_type { };
+template<> struct is_integral<unsigned char> : true_type { };
+template<> struct is_integral<signed char> : true_type { };
+#if defined(_MSC_VER)
+// wchar_t is not by default a distinct type from unsigned short in
+// Microsoft C.
+// See http://msdn2.microsoft.com/en-us/library/dh8che7s(VS.80).aspx
+template<> struct is_integral<__wchar_t> : true_type { };
+#else
+template<> struct is_integral<wchar_t> : true_type { };
+#endif
+template<> struct is_integral<short> : true_type { };
+template<> struct is_integral<unsigned short> : true_type { };
+template<> struct is_integral<int> : true_type { };
+template<> struct is_integral<unsigned int> : true_type { };
+template<> struct is_integral<long> : true_type { };
+template<> struct is_integral<unsigned long> : true_type { };
+#ifdef HAVE_LONG_LONG
+template<> struct is_integral<long long> : true_type { };
+template<> struct is_integral<unsigned long long> : true_type { };
+#endif
+template <class T> struct is_integral<const T> : is_integral<T> { };
+template <class T> struct is_integral<volatile T> : is_integral<T> { };
+template <class T> struct is_integral<const volatile T> : is_integral<T> { };
+
+// is_floating_point is false except for the built-in floating-point types.
+// A cv-qualified type is integral if and only if the underlying type is.
+template <class T> struct is_floating_point : false_type { };
+template<> struct is_floating_point<float> : true_type { };
+template<> struct is_floating_point<double> : true_type { };
+template<> struct is_floating_point<long double> : true_type { };
+template <class T> struct is_floating_point<const T>
+    : is_floating_point<T> { };
+template <class T> struct is_floating_point<volatile T>
+    : is_floating_point<T> { };
+template <class T> struct is_floating_point<const volatile T>
+    : is_floating_point<T> { };
+
+// is_pointer is false except for pointer types. A cv-qualified type (e.g.
+// "int* const", as opposed to "int const*") is cv-qualified if and only if
+// the underlying type is.
+template <class T> struct is_pointer : false_type { };
+template <class T> struct is_pointer<T*> : true_type { };
+template <class T> struct is_pointer<const T> : is_pointer<T> { };
+template <class T> struct is_pointer<volatile T> : is_pointer<T> { };
+template <class T> struct is_pointer<const volatile T> : is_pointer<T> { };
+
+#if !defined(_MSC_VER) && !(defined(__GNUC__) && __GNUC__ <= 3)
+
+namespace internal {
+
+template <class T> struct is_class_or_union {
+  template <class U> static small_ tester(void (U::*)());
+  template <class U> static big_ tester(...);
+  static const bool value = sizeof(tester<T>(0)) == sizeof(small_);
+};
+
+// is_convertible chokes if the first argument is an array. That's why
+// we use add_reference here.
+template <bool NotUnum, class T> struct is_enum_impl
+    : is_convertible<typename add_reference<T>::type, int> { };
+
+template <class T> struct is_enum_impl<true, T> : false_type { };
+
+}  // namespace internal
+
+// Specified by TR1 [4.5.1] primary type categories.
+
+// Implementation note:
+//
+// Each type is either void, integral, floating point, array, pointer,
+// reference, member object pointer, member function pointer, enum,
+// union or class. Out of these, only integral, floating point, reference,
+// class and enum types are potentially convertible to int. Therefore,
+// if a type is not a reference, integral, floating point or class and
+// is convertible to int, it's a enum. Adding cv-qualification to a type
+// does not change whether it's an enum.
+//
+// Is-convertible-to-int check is done only if all other checks pass,
+// because it can't be used with some types (e.g. void or classes with
+// inaccessible conversion operators).
+template <class T> struct is_enum
+    : internal::is_enum_impl<
+          is_same<T, void>::value ||
+              is_integral<T>::value ||
+              is_floating_point<T>::value ||
+              is_reference<T>::value ||
+              internal::is_class_or_union<T>::value,
+          T> { };
+
+template <class T> struct is_enum<const T> : is_enum<T> { };
+template <class T> struct is_enum<volatile T> : is_enum<T> { };
+template <class T> struct is_enum<const volatile T> : is_enum<T> { };
+
+#endif
+
+// is_reference is false except for reference types.
+template<typename T> struct is_reference : false_type {};
+template<typename T> struct is_reference<T&> : true_type {};
+
+
+// We can't get is_pod right without compiler help, so fail conservatively.
+// We will assume it's false except for arithmetic types, enumerations,
+// pointers and cv-qualified versions thereof. Note that std::pair<T,U>
+// is not a POD even if T and U are PODs.
+template <class T> struct is_pod
+ : integral_constant<bool, (is_integral<T>::value ||
+                            is_floating_point<T>::value ||
+#if !defined(_MSC_VER) && !(defined(__GNUC__) && __GNUC__ <= 3)
+                            // is_enum is not available on MSVC.
+                            is_enum<T>::value ||
+#endif
+                            is_pointer<T>::value)> { };
+template <class T> struct is_pod<const T> : is_pod<T> { };
+template <class T> struct is_pod<volatile T> : is_pod<T> { };
+template <class T> struct is_pod<const volatile T> : is_pod<T> { };
+
+
+// We can't get has_trivial_constructor right without compiler help, so
+// fail conservatively. We will assume it's false except for: (1) types
+// for which is_pod is true. (2) std::pair of types with trivial
+// constructors. (3) array of a type with a trivial constructor.
+// (4) const versions thereof.
+template <class T> struct has_trivial_constructor : is_pod<T> { };
+template <class T, class U> struct has_trivial_constructor<std::pair<T, U> >
+  : integral_constant<bool,
+                      (has_trivial_constructor<T>::value &&
+                       has_trivial_constructor<U>::value)> { };
+template <class A, int N> struct has_trivial_constructor<A[N]>
+  : has_trivial_constructor<A> { };
+template <class T> struct has_trivial_constructor<const T>
+  : has_trivial_constructor<T> { };
+
+// We can't get has_trivial_copy right without compiler help, so fail
+// conservatively. We will assume it's false except for: (1) types
+// for which is_pod is true. (2) std::pair of types with trivial copy
+// constructors. (3) array of a type with a trivial copy constructor.
+// (4) const versions thereof.
+template <class T> struct has_trivial_copy : is_pod<T> { };
+template <class T, class U> struct has_trivial_copy<std::pair<T, U> >
+  : integral_constant<bool,
+                      (has_trivial_copy<T>::value &&
+                       has_trivial_copy<U>::value)> { };
+template <class A, int N> struct has_trivial_copy<A[N]>
+  : has_trivial_copy<A> { };
+template <class T> struct has_trivial_copy<const T> : has_trivial_copy<T> { };
+
+// We can't get has_trivial_assign right without compiler help, so fail
+// conservatively. We will assume it's false except for: (1) types
+// for which is_pod is true. (2) std::pair of types with trivial copy
+// constructors. (3) array of a type with a trivial assign constructor.
+template <class T> struct has_trivial_assign : is_pod<T> { };
+template <class T, class U> struct has_trivial_assign<std::pair<T, U> >
+  : integral_constant<bool,
+                      (has_trivial_assign<T>::value &&
+                       has_trivial_assign<U>::value)> { };
+template <class A, int N> struct has_trivial_assign<A[N]>
+  : has_trivial_assign<A> { };
+
+// We can't get has_trivial_destructor right without compiler help, so
+// fail conservatively. We will assume it's false except for: (1) types
+// for which is_pod is true. (2) std::pair of types with trivial
+// destructors. (3) array of a type with a trivial destructor.
+// (4) const versions thereof.
+template <class T> struct has_trivial_destructor : is_pod<T> { };
+template <class T, class U> struct has_trivial_destructor<std::pair<T, U> >
+  : integral_constant<bool,
+                      (has_trivial_destructor<T>::value &&
+                       has_trivial_destructor<U>::value)> { };
+template <class A, int N> struct has_trivial_destructor<A[N]>
+  : has_trivial_destructor<A> { };
+template <class T> struct has_trivial_destructor<const T>
+  : has_trivial_destructor<T> { };
+
+// Specified by TR1 [4.7.1]
+template<typename T> struct remove_const { typedef T type; };
+template<typename T> struct remove_const<T const> { typedef T type; };
+template<typename T> struct remove_volatile { typedef T type; };
+template<typename T> struct remove_volatile<T volatile> { typedef T type; };
+template<typename T> struct remove_cv {
+  typedef typename remove_const<typename remove_volatile<T>::type>::type type;
+};
+
+
+// Specified by TR1 [4.7.2] Reference modifications.
+template<typename T> struct remove_reference { typedef T type; };
+template<typename T> struct remove_reference<T&> { typedef T type; };
+
+template <typename T> struct add_reference { typedef T& type; };
+template <typename T> struct add_reference<T&> { typedef T& type; };
+
+// Specified by TR1 [4.7.4] Pointer modifications.
+template<typename T> struct remove_pointer { typedef T type; };
+template<typename T> struct remove_pointer<T*> { typedef T type; };
+template<typename T> struct remove_pointer<T* const> { typedef T type; };
+template<typename T> struct remove_pointer<T* volatile> { typedef T type; };
+template<typename T> struct remove_pointer<T* const volatile> {
+  typedef T type; };
+
+// Specified by TR1 [4.6] Relationships between types
+template<typename T, typename U> struct is_same : public false_type { };
+template<typename T> struct is_same<T, T> : public true_type { };
+
+// Specified by TR1 [4.6] Relationships between types
+#if !defined(_MSC_VER) && !(defined(__GNUC__) && __GNUC__ <= 3)
+namespace internal {
+
+// This class is an implementation detail for is_convertible, and you
+// don't need to know how it works to use is_convertible. For those
+// who care: we declare two different functions, one whose argument is
+// of type To and one with a variadic argument list. We give them
+// return types of different size, so we can use sizeof to trick the
+// compiler into telling us which function it would have chosen if we
+// had called it with an argument of type From.  See Alexandrescu's
+// _Modern C++ Design_ for more details on this sort of trick.
+
+template <typename From, typename To>
+struct ConvertHelper {
+  static small_ Test(To);
+  static big_ Test(...);
+  static From Create();
+};
+}  // namespace internal
+
+// Inherits from true_type if From is convertible to To, false_type otherwise.
+template <typename From, typename To>
+struct is_convertible
+    : integral_constant<bool,
+                        sizeof(internal::ConvertHelper<From, To>::Test(
+                                  internal::ConvertHelper<From, To>::Create()))
+                        == sizeof(small_)> {
+};
+#endif
+
+}  // namespace internal
+}  // namespace protobuf
+}  // namespace google
+
+// Right now these macros are no-ops, and mostly just document the fact
+// these types are PODs, for human use.  They may be made more contentful
+// later.  The typedef is just to make it legal to put a semicolon after
+// these macros.
+#define DECLARE_POD(TypeName) typedef int Dummy_Type_For_DECLARE_POD
+#define DECLARE_NESTED_POD(TypeName) DECLARE_POD(TypeName)
+#define PROPAGATE_POD_FROM_TEMPLATE_ARGUMENT(TemplateName)             \
+    typedef int Dummy_Type_For_PROPAGATE_POD_FROM_TEMPLATE_ARGUMENT
+#define ENFORCE_POD(TypeName) typedef int Dummy_Type_For_ENFORCE_POD
+
+#endif  // GOOGLE_PROTOBUF_TYPE_TRAITS_H_
diff --git a/third_party/protobuf/src/google/protobuf/stubs/type_traits_unittest.cc b/third_party/protobuf/src/google/protobuf/stubs/type_traits_unittest.cc
new file mode 100644
index 0000000..00e5a47
--- /dev/null
+++ b/third_party/protobuf/src/google/protobuf/stubs/type_traits_unittest.cc
@@ -0,0 +1,647 @@
+// Copyright (c) 2006, 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.
+
+// ----
+// Author: Matt Austern
+
+#include <google/protobuf/stubs/type_traits.h>
+
+#include <stdlib.h>   // for exit()
+#include <stdio.h>
+#include <string>
+#include <vector>
+
+#include <google/protobuf/testing/googletest.h>
+#include <gtest/gtest.h>
+
+typedef int int32;
+typedef long int64;
+
+using std::string;
+using std::vector;
+using std::pair;
+
+using google::protobuf::internal::add_reference;
+using google::protobuf::internal::has_trivial_assign;
+using google::protobuf::internal::has_trivial_constructor;
+using google::protobuf::internal::has_trivial_copy;
+using google::protobuf::internal::has_trivial_destructor;
+#if !defined(_MSC_VER) && !(defined(__GNUC__) && __GNUC__ <= 3)
+using google::protobuf::internal::is_convertible;
+using google::protobuf::internal::is_enum;
+#endif
+using google::protobuf::internal::is_floating_point;
+using google::protobuf::internal::is_integral;
+using google::protobuf::internal::is_pointer;
+using google::protobuf::internal::is_pod;
+using google::protobuf::internal::is_reference;
+using google::protobuf::internal::is_same;
+using google::protobuf::internal::remove_const;
+using google::protobuf::internal::remove_cv;
+using google::protobuf::internal::remove_pointer;
+using google::protobuf::internal::remove_reference;
+using google::protobuf::internal::remove_volatile;
+
+
+// This assertion produces errors like "error: invalid use of
+// incomplete type 'struct <unnamed>::AssertTypesEq<const int, int>'"
+// when it fails.
+template<typename T, typename U> struct AssertTypesEq;
+template<typename T> struct AssertTypesEq<T, T> {};
+#define COMPILE_ASSERT_TYPES_EQ(T, U) static_cast<void>(AssertTypesEq<T, U>())
+
+// A user-defined POD type.
+struct A {
+  int n_;
+};
+
+// A user-defined non-POD type with a trivial copy constructor.
+class B {
+ public:
+  explicit B(int n) : n_(n) { }
+ private:
+  int n_;
+};
+
+// Another user-defined non-POD type with a trivial copy constructor.
+// We will explicitly declare C to have a trivial copy constructor
+// by specializing has_trivial_copy.
+class C {
+ public:
+  explicit C(int n) : n_(n) { }
+ private:
+  int n_;
+};
+
+namespace google {
+namespace protobuf {
+namespace internal {
+template<> struct has_trivial_copy<C> : true_type { };
+}  // namespace internal
+}  // namespace protobuf
+}  // namespace google
+
+// Another user-defined non-POD type with a trivial assignment operator.
+// We will explicitly declare C to have a trivial assignment operator
+// by specializing has_trivial_assign.
+class D {
+ public:
+  explicit D(int n) : n_(n) { }
+ private:
+  int n_;
+};
+
+namespace google {
+namespace protobuf {
+namespace internal {
+template<> struct has_trivial_assign<D> : true_type { };
+}  // namespace internal
+}  // namespace protobuf
+}  // namespace google
+
+// Another user-defined non-POD type with a trivial constructor.
+// We will explicitly declare E to have a trivial constructor
+// by specializing has_trivial_constructor.
+class E {
+ public:
+  int n_;
+};
+
+namespace google {
+namespace protobuf {
+namespace internal {
+template<> struct has_trivial_constructor<E> : true_type { };
+}  // namespace internal
+}  // namespace protobuf
+}  // namespace google
+
+// Another user-defined non-POD type with a trivial destructor.
+// We will explicitly declare E to have a trivial destructor
+// by specializing has_trivial_destructor.
+class F {
+ public:
+  explicit F(int n) : n_(n) { }
+ private:
+  int n_;
+};
+
+namespace google {
+namespace protobuf {
+namespace internal {
+template<> struct has_trivial_destructor<F> : true_type { };
+}  // namespace internal
+}  // namespace protobuf
+}  // namespace google
+
+enum G {};
+
+union H {};
+
+class I {
+ public:
+  operator int() const;
+};
+
+class J {
+ private:
+  operator int() const;
+};
+
+namespace google {
+namespace protobuf {
+namespace {
+
+// A base class and a derived class that inherits from it, used for
+// testing conversion type traits.
+class Base {
+ public:
+  virtual ~Base() { }
+};
+
+class Derived : public Base {
+};
+
+TEST(TypeTraitsTest, TestIsInteger) {
+  // Verify that is_integral is true for all integer types.
+  EXPECT_TRUE(is_integral<bool>::value);
+  EXPECT_TRUE(is_integral<char>::value);
+  EXPECT_TRUE(is_integral<unsigned char>::value);
+  EXPECT_TRUE(is_integral<signed char>::value);
+  EXPECT_TRUE(is_integral<wchar_t>::value);
+  EXPECT_TRUE(is_integral<int>::value);
+  EXPECT_TRUE(is_integral<unsigned int>::value);
+  EXPECT_TRUE(is_integral<short>::value);
+  EXPECT_TRUE(is_integral<unsigned short>::value);
+  EXPECT_TRUE(is_integral<long>::value);
+  EXPECT_TRUE(is_integral<unsigned long>::value);
+
+  // Verify that is_integral is false for a few non-integer types.
+  EXPECT_FALSE(is_integral<void>::value);
+  EXPECT_FALSE(is_integral<float>::value);
+  EXPECT_FALSE(is_integral<string>::value);
+  EXPECT_FALSE(is_integral<int*>::value);
+  EXPECT_FALSE(is_integral<A>::value);
+  EXPECT_FALSE((is_integral<pair<int, int> >::value));
+
+  // Verify that cv-qualified integral types are still integral, and
+  // cv-qualified non-integral types are still non-integral.
+  EXPECT_TRUE(is_integral<const char>::value);
+  EXPECT_TRUE(is_integral<volatile bool>::value);
+  EXPECT_TRUE(is_integral<const volatile unsigned int>::value);
+  EXPECT_FALSE(is_integral<const float>::value);
+  EXPECT_FALSE(is_integral<int* volatile>::value);
+  EXPECT_FALSE(is_integral<const volatile string>::value);
+}
+
+TEST(TypeTraitsTest, TestIsFloating) {
+  // Verify that is_floating_point is true for all floating-point types.
+  EXPECT_TRUE(is_floating_point<float>::value);
+  EXPECT_TRUE(is_floating_point<double>::value);
+  EXPECT_TRUE(is_floating_point<long double>::value);
+
+  // Verify that is_floating_point is false for a few non-float types.
+  EXPECT_FALSE(is_floating_point<void>::value);
+  EXPECT_FALSE(is_floating_point<long>::value);
+  EXPECT_FALSE(is_floating_point<string>::value);
+  EXPECT_FALSE(is_floating_point<float*>::value);
+  EXPECT_FALSE(is_floating_point<A>::value);
+  EXPECT_FALSE((is_floating_point<pair<int, int> >::value));
+
+  // Verify that cv-qualified floating point types are still floating, and
+  // cv-qualified non-floating types are still non-floating.
+  EXPECT_TRUE(is_floating_point<const float>::value);
+  EXPECT_TRUE(is_floating_point<volatile double>::value);
+  EXPECT_TRUE(is_floating_point<const volatile long double>::value);
+  EXPECT_FALSE(is_floating_point<const int>::value);
+  EXPECT_FALSE(is_floating_point<volatile string>::value);
+  EXPECT_FALSE(is_floating_point<const volatile char>::value);
+}
+
+TEST(TypeTraitsTest, TestIsPointer) {
+  // Verify that is_pointer is true for some pointer types.
+  EXPECT_TRUE(is_pointer<int*>::value);
+  EXPECT_TRUE(is_pointer<void*>::value);
+  EXPECT_TRUE(is_pointer<string*>::value);
+  EXPECT_TRUE(is_pointer<const void*>::value);
+  EXPECT_TRUE(is_pointer<volatile float* const*>::value);
+
+  // Verify that is_pointer is false for some non-pointer types.
+  EXPECT_FALSE(is_pointer<void>::value);
+  EXPECT_FALSE(is_pointer<float&>::value);
+  EXPECT_FALSE(is_pointer<long>::value);
+  EXPECT_FALSE(is_pointer<vector<int*> >::value);
+  EXPECT_FALSE(is_pointer<int[5]>::value);
+
+  // A function pointer is a pointer, but a function type, or a function
+  // reference type, is not.
+  EXPECT_TRUE(is_pointer<int (*)(int x)>::value);
+  EXPECT_FALSE(is_pointer<void(char x)>::value);
+  EXPECT_FALSE(is_pointer<double (&)(string x)>::value);
+
+  // Verify that is_pointer<T> is true for some cv-qualified pointer types,
+  // and false for some cv-qualified non-pointer types.
+  EXPECT_TRUE(is_pointer<int* const>::value);
+  EXPECT_TRUE(is_pointer<const void* volatile>::value);
+  EXPECT_TRUE(is_pointer<char** const volatile>::value);
+  EXPECT_FALSE(is_pointer<const int>::value);
+  EXPECT_FALSE(is_pointer<volatile vector<int*> >::value);
+  EXPECT_FALSE(is_pointer<const volatile double>::value);
+}
+
+TEST(TypeTraitsTest, TestIsEnum) {
+// is_enum isn't supported on MSVC or gcc 3.x
+#if !defined(_MSC_VER) && !(defined(__GNUC__) && __GNUC__ <= 3)
+  // Verify that is_enum is true for enum types.
+  EXPECT_TRUE(is_enum<G>::value);
+  EXPECT_TRUE(is_enum<const G>::value);
+  EXPECT_TRUE(is_enum<volatile G>::value);
+  EXPECT_TRUE(is_enum<const volatile G>::value);
+
+  // Verify that is_enum is false for a few non-enum types.
+  EXPECT_FALSE(is_enum<void>::value);
+  EXPECT_FALSE(is_enum<G&>::value);
+  EXPECT_FALSE(is_enum<G[1]>::value);
+  EXPECT_FALSE(is_enum<const G[1]>::value);
+  EXPECT_FALSE(is_enum<G[]>::value);
+  EXPECT_FALSE(is_enum<int>::value);
+  EXPECT_FALSE(is_enum<float>::value);
+  EXPECT_FALSE(is_enum<A>::value);
+  EXPECT_FALSE(is_enum<A*>::value);
+  EXPECT_FALSE(is_enum<const A>::value);
+  EXPECT_FALSE(is_enum<H>::value);
+  EXPECT_FALSE(is_enum<I>::value);
+  EXPECT_FALSE(is_enum<J>::value);
+  EXPECT_FALSE(is_enum<void()>::value);
+  EXPECT_FALSE(is_enum<void(*)()>::value);
+  EXPECT_FALSE(is_enum<int A::*>::value);
+  EXPECT_FALSE(is_enum<void (A::*)()>::value);
+#endif
+}
+
+TEST(TypeTraitsTest, TestIsReference) {
+  // Verifies that is_reference is true for all reference types.
+  typedef float& RefFloat;
+  EXPECT_TRUE(is_reference<float&>::value);
+  EXPECT_TRUE(is_reference<const int&>::value);
+  EXPECT_TRUE(is_reference<const int*&>::value);
+  EXPECT_TRUE(is_reference<int (&)(bool)>::value);
+  EXPECT_TRUE(is_reference<RefFloat>::value);
+  EXPECT_TRUE(is_reference<const RefFloat>::value);
+  EXPECT_TRUE(is_reference<volatile RefFloat>::value);
+  EXPECT_TRUE(is_reference<const volatile RefFloat>::value);
+
+
+  // Verifies that is_reference is false for all non-reference types.
+  EXPECT_FALSE(is_reference<float>::value);
+  EXPECT_FALSE(is_reference<const float>::value);
+  EXPECT_FALSE(is_reference<volatile float>::value);
+  EXPECT_FALSE(is_reference<const volatile float>::value);
+  EXPECT_FALSE(is_reference<const int*>::value);
+  EXPECT_FALSE(is_reference<int()>::value);
+  EXPECT_FALSE(is_reference<void(*)(const char&)>::value);
+}
+
+TEST(TypeTraitsTest, TestAddReference) {
+  COMPILE_ASSERT_TYPES_EQ(int&, add_reference<int>::type);
+  COMPILE_ASSERT_TYPES_EQ(const int&, add_reference<const int>::type);
+  COMPILE_ASSERT_TYPES_EQ(volatile int&,
+                          add_reference<volatile int>::type);
+  COMPILE_ASSERT_TYPES_EQ(const volatile int&,
+                          add_reference<const volatile int>::type);
+  COMPILE_ASSERT_TYPES_EQ(int&, add_reference<int&>::type);
+  COMPILE_ASSERT_TYPES_EQ(const int&, add_reference<const int&>::type);
+  COMPILE_ASSERT_TYPES_EQ(volatile int&,
+                          add_reference<volatile int&>::type);
+  COMPILE_ASSERT_TYPES_EQ(const volatile int&,
+                          add_reference<const volatile int&>::type);
+}
+
+TEST(TypeTraitsTest, TestIsPod) {
+  // Verify that arithmetic types and pointers are marked as PODs.
+  EXPECT_TRUE(is_pod<bool>::value);
+  EXPECT_TRUE(is_pod<char>::value);
+  EXPECT_TRUE(is_pod<unsigned char>::value);
+  EXPECT_TRUE(is_pod<signed char>::value);
+  EXPECT_TRUE(is_pod<wchar_t>::value);
+  EXPECT_TRUE(is_pod<int>::value);
+  EXPECT_TRUE(is_pod<unsigned int>::value);
+  EXPECT_TRUE(is_pod<short>::value);
+  EXPECT_TRUE(is_pod<unsigned short>::value);
+  EXPECT_TRUE(is_pod<long>::value);
+  EXPECT_TRUE(is_pod<unsigned long>::value);
+  EXPECT_TRUE(is_pod<float>::value);
+  EXPECT_TRUE(is_pod<double>::value);
+  EXPECT_TRUE(is_pod<long double>::value);
+  EXPECT_TRUE(is_pod<string*>::value);
+  EXPECT_TRUE(is_pod<A*>::value);
+  EXPECT_TRUE(is_pod<const B*>::value);
+  EXPECT_TRUE(is_pod<C**>::value);
+  EXPECT_TRUE(is_pod<const int>::value);
+  EXPECT_TRUE(is_pod<char* volatile>::value);
+  EXPECT_TRUE(is_pod<const volatile double>::value);
+#if !defined(_MSC_VER) && !(defined(__GNUC__) && __GNUC__ <= 3)
+  EXPECT_TRUE(is_pod<G>::value);
+  EXPECT_TRUE(is_pod<const G>::value);
+  EXPECT_TRUE(is_pod<volatile G>::value);
+  EXPECT_TRUE(is_pod<const volatile G>::value);
+#endif
+
+  // Verify that some non-POD types are not marked as PODs.
+  EXPECT_FALSE(is_pod<void>::value);
+  EXPECT_FALSE(is_pod<string>::value);
+  EXPECT_FALSE((is_pod<pair<int, int> >::value));
+  EXPECT_FALSE(is_pod<A>::value);
+  EXPECT_FALSE(is_pod<B>::value);
+  EXPECT_FALSE(is_pod<C>::value);
+  EXPECT_FALSE(is_pod<const string>::value);
+  EXPECT_FALSE(is_pod<volatile A>::value);
+  EXPECT_FALSE(is_pod<const volatile B>::value);
+}
+
+TEST(TypeTraitsTest, TestHasTrivialConstructor) {
+  // Verify that arithmetic types and pointers have trivial constructors.
+  EXPECT_TRUE(has_trivial_constructor<bool>::value);
+  EXPECT_TRUE(has_trivial_constructor<char>::value);
+  EXPECT_TRUE(has_trivial_constructor<unsigned char>::value);
+  EXPECT_TRUE(has_trivial_constructor<signed char>::value);
+  EXPECT_TRUE(has_trivial_constructor<wchar_t>::value);
+  EXPECT_TRUE(has_trivial_constructor<int>::value);
+  EXPECT_TRUE(has_trivial_constructor<unsigned int>::value);
+  EXPECT_TRUE(has_trivial_constructor<short>::value);
+  EXPECT_TRUE(has_trivial_constructor<unsigned short>::value);
+  EXPECT_TRUE(has_trivial_constructor<long>::value);
+  EXPECT_TRUE(has_trivial_constructor<unsigned long>::value);
+  EXPECT_TRUE(has_trivial_constructor<float>::value);
+  EXPECT_TRUE(has_trivial_constructor<double>::value);
+  EXPECT_TRUE(has_trivial_constructor<long double>::value);
+  EXPECT_TRUE(has_trivial_constructor<string*>::value);
+  EXPECT_TRUE(has_trivial_constructor<A*>::value);
+  EXPECT_TRUE(has_trivial_constructor<const B*>::value);
+  EXPECT_TRUE(has_trivial_constructor<C**>::value);
+
+  // Verify that pairs and arrays of such types have trivial
+  // constructors.
+  typedef int int10[10];
+  EXPECT_TRUE((has_trivial_constructor<pair<int, char*> >::value));
+  EXPECT_TRUE(has_trivial_constructor<int10>::value);
+
+  // Verify that pairs of types without trivial constructors
+  // are not marked as trivial.
+  EXPECT_FALSE((has_trivial_constructor<pair<int, string> >::value));
+  EXPECT_FALSE((has_trivial_constructor<pair<string, int> >::value));
+
+  // Verify that types without trivial constructors are
+  // correctly marked as such.
+  EXPECT_FALSE(has_trivial_constructor<string>::value);
+  EXPECT_FALSE(has_trivial_constructor<vector<int> >::value);
+
+  // Verify that E, which we have declared to have a trivial
+  // constructor, is correctly marked as such.
+  EXPECT_TRUE(has_trivial_constructor<E>::value);
+}
+
+TEST(TypeTraitsTest, TestHasTrivialCopy) {
+  // Verify that arithmetic types and pointers have trivial copy
+  // constructors.
+  EXPECT_TRUE(has_trivial_copy<bool>::value);
+  EXPECT_TRUE(has_trivial_copy<char>::value);
+  EXPECT_TRUE(has_trivial_copy<unsigned char>::value);
+  EXPECT_TRUE(has_trivial_copy<signed char>::value);
+  EXPECT_TRUE(has_trivial_copy<wchar_t>::value);
+  EXPECT_TRUE(has_trivial_copy<int>::value);
+  EXPECT_TRUE(has_trivial_copy<unsigned int>::value);
+  EXPECT_TRUE(has_trivial_copy<short>::value);
+  EXPECT_TRUE(has_trivial_copy<unsigned short>::value);
+  EXPECT_TRUE(has_trivial_copy<long>::value);
+  EXPECT_TRUE(has_trivial_copy<unsigned long>::value);
+  EXPECT_TRUE(has_trivial_copy<float>::value);
+  EXPECT_TRUE(has_trivial_copy<double>::value);
+  EXPECT_TRUE(has_trivial_copy<long double>::value);
+  EXPECT_TRUE(has_trivial_copy<string*>::value);
+  EXPECT_TRUE(has_trivial_copy<A*>::value);
+  EXPECT_TRUE(has_trivial_copy<const B*>::value);
+  EXPECT_TRUE(has_trivial_copy<C**>::value);
+
+  // Verify that pairs and arrays of such types have trivial
+  // copy constructors.
+  typedef int int10[10];
+  EXPECT_TRUE((has_trivial_copy<pair<int, char*> >::value));
+  EXPECT_TRUE(has_trivial_copy<int10>::value);
+
+  // Verify that pairs of types without trivial copy constructors
+  // are not marked as trivial.
+  EXPECT_FALSE((has_trivial_copy<pair<int, string> >::value));
+  EXPECT_FALSE((has_trivial_copy<pair<string, int> >::value));
+
+  // Verify that types without trivial copy constructors are
+  // correctly marked as such.
+  EXPECT_FALSE(has_trivial_copy<string>::value);
+  EXPECT_FALSE(has_trivial_copy<vector<int> >::value);
+
+  // Verify that C, which we have declared to have a trivial
+  // copy constructor, is correctly marked as such.
+  EXPECT_TRUE(has_trivial_copy<C>::value);
+}
+
+TEST(TypeTraitsTest, TestHasTrivialAssign) {
+  // Verify that arithmetic types and pointers have trivial assignment
+  // operators.
+  EXPECT_TRUE(has_trivial_assign<bool>::value);
+  EXPECT_TRUE(has_trivial_assign<char>::value);
+  EXPECT_TRUE(has_trivial_assign<unsigned char>::value);
+  EXPECT_TRUE(has_trivial_assign<signed char>::value);
+  EXPECT_TRUE(has_trivial_assign<wchar_t>::value);
+  EXPECT_TRUE(has_trivial_assign<int>::value);
+  EXPECT_TRUE(has_trivial_assign<unsigned int>::value);
+  EXPECT_TRUE(has_trivial_assign<short>::value);
+  EXPECT_TRUE(has_trivial_assign<unsigned short>::value);
+  EXPECT_TRUE(has_trivial_assign<long>::value);
+  EXPECT_TRUE(has_trivial_assign<unsigned long>::value);
+  EXPECT_TRUE(has_trivial_assign<float>::value);
+  EXPECT_TRUE(has_trivial_assign<double>::value);
+  EXPECT_TRUE(has_trivial_assign<long double>::value);
+  EXPECT_TRUE(has_trivial_assign<string*>::value);
+  EXPECT_TRUE(has_trivial_assign<A*>::value);
+  EXPECT_TRUE(has_trivial_assign<const B*>::value);
+  EXPECT_TRUE(has_trivial_assign<C**>::value);
+
+  // Verify that pairs and arrays of such types have trivial
+  // assignment operators.
+  typedef int int10[10];
+  EXPECT_TRUE((has_trivial_assign<pair<int, char*> >::value));
+  EXPECT_TRUE(has_trivial_assign<int10>::value);
+
+  // Verify that pairs of types without trivial assignment operators
+  // are not marked as trivial.
+  EXPECT_FALSE((has_trivial_assign<pair<int, string> >::value));
+  EXPECT_FALSE((has_trivial_assign<pair<string, int> >::value));
+
+  // Verify that types without trivial assignment operators are
+  // correctly marked as such.
+  EXPECT_FALSE(has_trivial_assign<string>::value);
+  EXPECT_FALSE(has_trivial_assign<vector<int> >::value);
+
+  // Verify that D, which we have declared to have a trivial
+  // assignment operator, is correctly marked as such.
+  EXPECT_TRUE(has_trivial_assign<D>::value);
+}
+
+TEST(TypeTraitsTest, TestHasTrivialDestructor) {
+  // Verify that arithmetic types and pointers have trivial destructors.
+  EXPECT_TRUE(has_trivial_destructor<bool>::value);
+  EXPECT_TRUE(has_trivial_destructor<char>::value);
+  EXPECT_TRUE(has_trivial_destructor<unsigned char>::value);
+  EXPECT_TRUE(has_trivial_destructor<signed char>::value);
+  EXPECT_TRUE(has_trivial_destructor<wchar_t>::value);
+  EXPECT_TRUE(has_trivial_destructor<int>::value);
+  EXPECT_TRUE(has_trivial_destructor<unsigned int>::value);
+  EXPECT_TRUE(has_trivial_destructor<short>::value);
+  EXPECT_TRUE(has_trivial_destructor<unsigned short>::value);
+  EXPECT_TRUE(has_trivial_destructor<long>::value);
+  EXPECT_TRUE(has_trivial_destructor<unsigned long>::value);
+  EXPECT_TRUE(has_trivial_destructor<float>::value);
+  EXPECT_TRUE(has_trivial_destructor<double>::value);
+  EXPECT_TRUE(has_trivial_destructor<long double>::value);
+  EXPECT_TRUE(has_trivial_destructor<string*>::value);
+  EXPECT_TRUE(has_trivial_destructor<A*>::value);
+  EXPECT_TRUE(has_trivial_destructor<const B*>::value);
+  EXPECT_TRUE(has_trivial_destructor<C**>::value);
+
+  // Verify that pairs and arrays of such types have trivial
+  // destructors.
+  typedef int int10[10];
+  EXPECT_TRUE((has_trivial_destructor<pair<int, char*> >::value));
+  EXPECT_TRUE(has_trivial_destructor<int10>::value);
+
+  // Verify that pairs of types without trivial destructors
+  // are not marked as trivial.
+  EXPECT_FALSE((has_trivial_destructor<pair<int, string> >::value));
+  EXPECT_FALSE((has_trivial_destructor<pair<string, int> >::value));
+
+  // Verify that types without trivial destructors are
+  // correctly marked as such.
+  EXPECT_FALSE(has_trivial_destructor<string>::value);
+  EXPECT_FALSE(has_trivial_destructor<vector<int> >::value);
+
+  // Verify that F, which we have declared to have a trivial
+  // destructor, is correctly marked as such.
+  EXPECT_TRUE(has_trivial_destructor<F>::value);
+}
+
+// Tests remove_pointer.
+TEST(TypeTraitsTest, TestRemovePointer) {
+  COMPILE_ASSERT_TYPES_EQ(int, remove_pointer<int>::type);
+  COMPILE_ASSERT_TYPES_EQ(int, remove_pointer<int*>::type);
+  COMPILE_ASSERT_TYPES_EQ(const int, remove_pointer<const int*>::type);
+  COMPILE_ASSERT_TYPES_EQ(int, remove_pointer<int* const>::type);
+  COMPILE_ASSERT_TYPES_EQ(int, remove_pointer<int* volatile>::type);
+}
+
+TEST(TypeTraitsTest, TestRemoveConst) {
+  COMPILE_ASSERT_TYPES_EQ(int, remove_const<int>::type);
+  COMPILE_ASSERT_TYPES_EQ(int, remove_const<const int>::type);
+  COMPILE_ASSERT_TYPES_EQ(int *, remove_const<int * const>::type);
+  // TR1 examples.
+  COMPILE_ASSERT_TYPES_EQ(const int *, remove_const<const int *>::type);
+  COMPILE_ASSERT_TYPES_EQ(volatile int,
+                          remove_const<const volatile int>::type);
+}
+
+TEST(TypeTraitsTest, TestRemoveVolatile) {
+  COMPILE_ASSERT_TYPES_EQ(int, remove_volatile<int>::type);
+  COMPILE_ASSERT_TYPES_EQ(int, remove_volatile<volatile int>::type);
+  COMPILE_ASSERT_TYPES_EQ(int *, remove_volatile<int * volatile>::type);
+  // TR1 examples.
+  COMPILE_ASSERT_TYPES_EQ(volatile int *,
+                          remove_volatile<volatile int *>::type);
+  COMPILE_ASSERT_TYPES_EQ(const int,
+                          remove_volatile<const volatile int>::type);
+}
+
+TEST(TypeTraitsTest, TestRemoveCV) {
+  COMPILE_ASSERT_TYPES_EQ(int, remove_cv<int>::type);
+  COMPILE_ASSERT_TYPES_EQ(int, remove_cv<volatile int>::type);
+  COMPILE_ASSERT_TYPES_EQ(int, remove_cv<const int>::type);
+  COMPILE_ASSERT_TYPES_EQ(int *, remove_cv<int * const volatile>::type);
+  // TR1 examples.
+  COMPILE_ASSERT_TYPES_EQ(const volatile int *,
+                          remove_cv<const volatile int *>::type);
+  COMPILE_ASSERT_TYPES_EQ(int,
+                          remove_cv<const volatile int>::type);
+}
+
+TEST(TypeTraitsTest, TestRemoveReference) {
+  COMPILE_ASSERT_TYPES_EQ(int, remove_reference<int>::type);
+  COMPILE_ASSERT_TYPES_EQ(int, remove_reference<int&>::type);
+  COMPILE_ASSERT_TYPES_EQ(const int, remove_reference<const int&>::type);
+  COMPILE_ASSERT_TYPES_EQ(int*, remove_reference<int * &>::type);
+}
+
+TEST(TypeTraitsTest, TestIsSame) {
+  EXPECT_TRUE((is_same<int32, int32>::value));
+  EXPECT_FALSE((is_same<int32, int64>::value));
+  EXPECT_FALSE((is_same<int64, int32>::value));
+  EXPECT_FALSE((is_same<int, const int>::value));
+
+  EXPECT_TRUE((is_same<void, void>::value));
+  EXPECT_FALSE((is_same<void, int>::value));
+  EXPECT_FALSE((is_same<int, void>::value));
+
+  EXPECT_TRUE((is_same<int*, int*>::value));
+  EXPECT_TRUE((is_same<void*, void*>::value));
+  EXPECT_FALSE((is_same<int*, void*>::value));
+  EXPECT_FALSE((is_same<void*, int*>::value));
+  EXPECT_FALSE((is_same<void*, const void*>::value));
+  EXPECT_FALSE((is_same<void*, void* const>::value));
+
+  EXPECT_TRUE((is_same<Base*, Base*>::value));
+  EXPECT_TRUE((is_same<Derived*, Derived*>::value));
+  EXPECT_FALSE((is_same<Base*, Derived*>::value));
+  EXPECT_FALSE((is_same<Derived*, Base*>::value));
+}
+
+TEST(TypeTraitsTest, TestConvertible) {
+#if !defined(_MSC_VER) && !(defined(__GNUC__) && __GNUC__ <= 3)
+  EXPECT_TRUE((is_convertible<int, int>::value));
+  EXPECT_TRUE((is_convertible<int, long>::value));
+  EXPECT_TRUE((is_convertible<long, int>::value));
+
+  EXPECT_TRUE((is_convertible<int*, void*>::value));
+  EXPECT_FALSE((is_convertible<void*, int*>::value));
+
+  EXPECT_TRUE((is_convertible<Derived*, Base*>::value));
+  EXPECT_FALSE((is_convertible<Base*, Derived*>::value));
+  EXPECT_TRUE((is_convertible<Derived*, const Base*>::value));
+  EXPECT_FALSE((is_convertible<const Derived*, Base*>::value));
+#endif
+}
+
+}  // anonymous namespace
+}  // namespace protobuf
+}  // namespace google
diff --git a/third_party/protobuf/src/google/protobuf/test_util.cc b/third_party/protobuf/src/google/protobuf/test_util.cc
index af8b390..841f4b3 100644
--- a/third_party/protobuf/src/google/protobuf/test_util.cc
+++ b/third_party/protobuf/src/google/protobuf/test_util.cc
@@ -50,6 +50,13 @@
 namespace protobuf {
 
 void TestUtil::SetAllFields(unittest::TestAllTypes* message) {
+  SetOptionalFields(message);
+  AddRepeatedFields1(message);
+  AddRepeatedFields2(message);
+  SetDefaultFields(message);
+}
+
+void TestUtil::SetOptionalFields(unittest::TestAllTypes* message) {
   message->set_optional_int32   (101);
   message->set_optional_int64   (102);
   message->set_optional_uint32  (103);
@@ -66,10 +73,12 @@
   message->set_optional_string  ("115");
   message->set_optional_bytes   ("116");
 
-  message->mutable_optionalgroup           ()->set_a(117);
-  message->mutable_optional_nested_message ()->set_bb(118);
-  message->mutable_optional_foreign_message()->set_c(119);
-  message->mutable_optional_import_message ()->set_d(120);
+  message->mutable_optionalgroup                 ()->set_a(117);
+  message->mutable_optional_nested_message       ()->set_bb(118);
+  message->mutable_optional_foreign_message      ()->set_c(119);
+  message->mutable_optional_import_message       ()->set_d(120);
+  message->mutable_optional_public_import_message()->set_e(126);
+  message->mutable_optional_lazy_message         ()->set_bb(127);
 
   message->set_optional_nested_enum (unittest::TestAllTypes::BAZ);
   message->set_optional_foreign_enum(unittest::FOREIGN_BAZ      );
@@ -87,9 +96,11 @@
     message->GetDescriptor()->FindFieldByName("optional_cord"),
     "125");
 #endif  // !PROTOBUF_TEST_NO_DESCRIPTORS
+}
 
-  // -----------------------------------------------------------------
+// -------------------------------------------------------------------
 
+void TestUtil::AddRepeatedFields1(unittest::TestAllTypes* message) {
   message->add_repeated_int32   (201);
   message->add_repeated_int64   (202);
   message->add_repeated_uint32  (203);
@@ -110,6 +121,7 @@
   message->add_repeated_nested_message ()->set_bb(218);
   message->add_repeated_foreign_message()->set_c(219);
   message->add_repeated_import_message ()->set_d(220);
+  message->add_repeated_lazy_message   ()->set_bb(227);
 
   message->add_repeated_nested_enum (unittest::TestAllTypes::BAR);
   message->add_repeated_foreign_enum(unittest::FOREIGN_BAR      );
@@ -125,7 +137,9 @@
     message->GetDescriptor()->FindFieldByName("repeated_cord"),
     "225");
 #endif  // !PROTOBUF_TEST_NO_DESCRIPTORS
+}
 
+void TestUtil::AddRepeatedFields2(unittest::TestAllTypes* message) {
   // Add a second one of each field.
   message->add_repeated_int32   (301);
   message->add_repeated_int64   (302);
@@ -147,6 +161,7 @@
   message->add_repeated_nested_message ()->set_bb(318);
   message->add_repeated_foreign_message()->set_c(319);
   message->add_repeated_import_message ()->set_d(320);
+  message->add_repeated_lazy_message   ()->set_bb(327);
 
   message->add_repeated_nested_enum (unittest::TestAllTypes::BAZ);
   message->add_repeated_foreign_enum(unittest::FOREIGN_BAZ      );
@@ -162,9 +177,11 @@
     message->GetDescriptor()->FindFieldByName("repeated_cord"),
     "325");
 #endif  // !PROTOBUF_TEST_NO_DESCRIPTORS
+}
 
-  // -----------------------------------------------------------------
+// -------------------------------------------------------------------
 
+void TestUtil::SetDefaultFields(unittest::TestAllTypes* message) {
   message->set_default_int32   (401);
   message->set_default_int64   (402);
   message->set_default_uint32  (403);
@@ -220,6 +237,7 @@
   message->mutable_repeated_nested_message (1)->set_bb(518);
   message->mutable_repeated_foreign_message(1)->set_c(519);
   message->mutable_repeated_import_message (1)->set_d(520);
+  message->mutable_repeated_lazy_message   (1)->set_bb(527);
 
   message->set_repeated_nested_enum (1, unittest::TestAllTypes::FOO);
   message->set_repeated_foreign_enum(1, unittest::FOREIGN_FOO      );
@@ -256,15 +274,19 @@
   EXPECT_TRUE(message.has_optional_string  ());
   EXPECT_TRUE(message.has_optional_bytes   ());
 
-  EXPECT_TRUE(message.has_optionalgroup           ());
-  EXPECT_TRUE(message.has_optional_nested_message ());
-  EXPECT_TRUE(message.has_optional_foreign_message());
-  EXPECT_TRUE(message.has_optional_import_message ());
+  EXPECT_TRUE(message.has_optionalgroup                 ());
+  EXPECT_TRUE(message.has_optional_nested_message       ());
+  EXPECT_TRUE(message.has_optional_foreign_message      ());
+  EXPECT_TRUE(message.has_optional_import_message       ());
+  EXPECT_TRUE(message.has_optional_public_import_message());
+  EXPECT_TRUE(message.has_optional_lazy_message         ());
 
-  EXPECT_TRUE(message.optionalgroup           ().has_a());
-  EXPECT_TRUE(message.optional_nested_message ().has_bb());
-  EXPECT_TRUE(message.optional_foreign_message().has_c());
-  EXPECT_TRUE(message.optional_import_message ().has_d());
+  EXPECT_TRUE(message.optionalgroup                 ().has_a());
+  EXPECT_TRUE(message.optional_nested_message       ().has_bb());
+  EXPECT_TRUE(message.optional_foreign_message      ().has_c());
+  EXPECT_TRUE(message.optional_import_message       ().has_d());
+  EXPECT_TRUE(message.optional_public_import_message().has_e());
+  EXPECT_TRUE(message.optional_lazy_message         ().has_bb());
 
   EXPECT_TRUE(message.has_optional_nested_enum ());
   EXPECT_TRUE(message.has_optional_foreign_enum());
@@ -291,10 +313,12 @@
   EXPECT_EQ("115", message.optional_string  ());
   EXPECT_EQ("116", message.optional_bytes   ());
 
-  EXPECT_EQ(117, message.optionalgroup           ().a());
-  EXPECT_EQ(118, message.optional_nested_message ().bb());
-  EXPECT_EQ(119, message.optional_foreign_message().c());
-  EXPECT_EQ(120, message.optional_import_message ().d());
+  EXPECT_EQ(117, message.optionalgroup                  ().a());
+  EXPECT_EQ(118, message.optional_nested_message        ().bb());
+  EXPECT_EQ(119, message.optional_foreign_message       ().c());
+  EXPECT_EQ(120, message.optional_import_message        ().d());
+  EXPECT_EQ(126, message.optional_public_import_message ().e());
+  EXPECT_EQ(127, message.optional_lazy_message          ().bb());
 
   EXPECT_EQ(unittest::TestAllTypes::BAZ, message.optional_nested_enum ());
   EXPECT_EQ(unittest::FOREIGN_BAZ      , message.optional_foreign_enum());
@@ -323,6 +347,7 @@
   ASSERT_EQ(2, message.repeated_nested_message_size ());
   ASSERT_EQ(2, message.repeated_foreign_message_size());
   ASSERT_EQ(2, message.repeated_import_message_size ());
+  ASSERT_EQ(2, message.repeated_lazy_message_size   ());
   ASSERT_EQ(2, message.repeated_nested_enum_size    ());
   ASSERT_EQ(2, message.repeated_foreign_enum_size   ());
   ASSERT_EQ(2, message.repeated_import_enum_size    ());
@@ -352,6 +377,7 @@
   EXPECT_EQ(218, message.repeated_nested_message (0).bb());
   EXPECT_EQ(219, message.repeated_foreign_message(0).c());
   EXPECT_EQ(220, message.repeated_import_message (0).d());
+  EXPECT_EQ(227, message.repeated_lazy_message   (0).bb());
 
 
   EXPECT_EQ(unittest::TestAllTypes::BAR, message.repeated_nested_enum (0));
@@ -378,6 +404,7 @@
   EXPECT_EQ(318, message.repeated_nested_message (1).bb());
   EXPECT_EQ(319, message.repeated_foreign_message(1).c());
   EXPECT_EQ(320, message.repeated_import_message (1).d());
+  EXPECT_EQ(327, message.repeated_lazy_message   (1).bb());
 
   EXPECT_EQ(unittest::TestAllTypes::BAZ, message.repeated_nested_enum (1));
   EXPECT_EQ(unittest::FOREIGN_BAZ      , message.repeated_foreign_enum(1));
@@ -449,10 +476,12 @@
   EXPECT_FALSE(message.has_optional_string  ());
   EXPECT_FALSE(message.has_optional_bytes   ());
 
-  EXPECT_FALSE(message.has_optionalgroup           ());
-  EXPECT_FALSE(message.has_optional_nested_message ());
-  EXPECT_FALSE(message.has_optional_foreign_message());
-  EXPECT_FALSE(message.has_optional_import_message ());
+  EXPECT_FALSE(message.has_optionalgroup                 ());
+  EXPECT_FALSE(message.has_optional_nested_message       ());
+  EXPECT_FALSE(message.has_optional_foreign_message      ());
+  EXPECT_FALSE(message.has_optional_import_message       ());
+  EXPECT_FALSE(message.has_optional_public_import_message());
+  EXPECT_FALSE(message.has_optional_lazy_message         ());
 
   EXPECT_FALSE(message.has_optional_nested_enum ());
   EXPECT_FALSE(message.has_optional_foreign_enum());
@@ -479,15 +508,19 @@
   EXPECT_EQ(""   , message.optional_bytes   ());
 
   // Embedded messages should also be clear.
-  EXPECT_FALSE(message.optionalgroup           ().has_a());
-  EXPECT_FALSE(message.optional_nested_message ().has_bb());
-  EXPECT_FALSE(message.optional_foreign_message().has_c());
-  EXPECT_FALSE(message.optional_import_message ().has_d());
+  EXPECT_FALSE(message.optionalgroup                 ().has_a());
+  EXPECT_FALSE(message.optional_nested_message       ().has_bb());
+  EXPECT_FALSE(message.optional_foreign_message      ().has_c());
+  EXPECT_FALSE(message.optional_import_message       ().has_d());
+  EXPECT_FALSE(message.optional_public_import_message().has_e());
+  EXPECT_FALSE(message.optional_lazy_message         ().has_bb());
 
-  EXPECT_EQ(0, message.optionalgroup           ().a());
-  EXPECT_EQ(0, message.optional_nested_message ().bb());
-  EXPECT_EQ(0, message.optional_foreign_message().c());
-  EXPECT_EQ(0, message.optional_import_message ().d());
+  EXPECT_EQ(0, message.optionalgroup                 ().a());
+  EXPECT_EQ(0, message.optional_nested_message       ().bb());
+  EXPECT_EQ(0, message.optional_foreign_message      ().c());
+  EXPECT_EQ(0, message.optional_import_message       ().d());
+  EXPECT_EQ(0, message.optional_public_import_message().e());
+  EXPECT_EQ(0, message.optional_lazy_message         ().bb());
 
   // Enums without defaults are set to the first value in the enum.
   EXPECT_EQ(unittest::TestAllTypes::FOO, message.optional_nested_enum ());
@@ -516,6 +549,7 @@
   EXPECT_EQ(0, message.repeated_nested_message_size ());
   EXPECT_EQ(0, message.repeated_foreign_message_size());
   EXPECT_EQ(0, message.repeated_import_message_size ());
+  EXPECT_EQ(0, message.repeated_lazy_message_size   ());
   EXPECT_EQ(0, message.repeated_nested_enum_size    ());
   EXPECT_EQ(0, message.repeated_foreign_enum_size   ());
   EXPECT_EQ(0, message.repeated_import_enum_size    ());
@@ -595,6 +629,7 @@
   ASSERT_EQ(2, message.repeated_nested_message_size ());
   ASSERT_EQ(2, message.repeated_foreign_message_size());
   ASSERT_EQ(2, message.repeated_import_message_size ());
+  ASSERT_EQ(2, message.repeated_lazy_message_size   ());
   ASSERT_EQ(2, message.repeated_nested_enum_size    ());
   ASSERT_EQ(2, message.repeated_foreign_enum_size   ());
   ASSERT_EQ(2, message.repeated_import_enum_size    ());
@@ -624,6 +659,7 @@
   EXPECT_EQ(218, message.repeated_nested_message (0).bb());
   EXPECT_EQ(219, message.repeated_foreign_message(0).c());
   EXPECT_EQ(220, message.repeated_import_message (0).d());
+  EXPECT_EQ(227, message.repeated_lazy_message   (0).bb());
 
   EXPECT_EQ(unittest::TestAllTypes::BAR, message.repeated_nested_enum (0));
   EXPECT_EQ(unittest::FOREIGN_BAR      , message.repeated_foreign_enum(0));
@@ -651,6 +687,7 @@
   EXPECT_EQ(518, message.repeated_nested_message (1).bb());
   EXPECT_EQ(519, message.repeated_foreign_message(1).c());
   EXPECT_EQ(520, message.repeated_import_message (1).d());
+  EXPECT_EQ(527, message.repeated_lazy_message   (1).bb());
 
   EXPECT_EQ(unittest::TestAllTypes::FOO, message.repeated_nested_enum (1));
   EXPECT_EQ(unittest::FOREIGN_FOO      , message.repeated_foreign_enum(1));
@@ -953,6 +990,9 @@
   message->SetExtension(unittest::optional_string_piece_extension, "124");
   message->SetExtension(unittest::optional_cord_extension, "125");
 
+  message->MutableExtension(unittest::optional_public_import_message_extension)->set_e(126);
+  message->MutableExtension(unittest::optional_lazy_message_extension)->set_bb(127);
+
   // -----------------------------------------------------------------
 
   message->AddExtension(unittest::repeated_int32_extension   , 201);
@@ -975,6 +1015,7 @@
   message->AddExtension(unittest::repeated_nested_message_extension )->set_bb(218);
   message->AddExtension(unittest::repeated_foreign_message_extension)->set_c(219);
   message->AddExtension(unittest::repeated_import_message_extension )->set_d(220);
+  message->AddExtension(unittest::repeated_lazy_message_extension   )->set_bb(227);
 
   message->AddExtension(unittest::repeated_nested_enum_extension , unittest::TestAllTypes::BAR);
   message->AddExtension(unittest::repeated_foreign_enum_extension, unittest::FOREIGN_BAR      );
@@ -1004,6 +1045,7 @@
   message->AddExtension(unittest::repeated_nested_message_extension )->set_bb(318);
   message->AddExtension(unittest::repeated_foreign_message_extension)->set_c(319);
   message->AddExtension(unittest::repeated_import_message_extension )->set_d(320);
+  message->AddExtension(unittest::repeated_lazy_message_extension   )->set_bb(327);
 
   message->AddExtension(unittest::repeated_nested_enum_extension , unittest::TestAllTypes::BAZ);
   message->AddExtension(unittest::repeated_foreign_enum_extension, unittest::FOREIGN_BAZ      );
@@ -1073,6 +1115,7 @@
   message->MutableExtension(unittest::repeated_nested_message_extension , 1)->set_bb(518);
   message->MutableExtension(unittest::repeated_foreign_message_extension, 1)->set_c(519);
   message->MutableExtension(unittest::repeated_import_message_extension , 1)->set_d(520);
+  message->MutableExtension(unittest::repeated_lazy_message_extension   , 1)->set_bb(527);
 
   message->SetExtension(unittest::repeated_nested_enum_extension , 1, unittest::TestAllTypes::FOO);
   message->SetExtension(unittest::repeated_foreign_enum_extension, 1, unittest::FOREIGN_FOO      );
@@ -1102,15 +1145,19 @@
   EXPECT_TRUE(message.HasExtension(unittest::optional_string_extension  ));
   EXPECT_TRUE(message.HasExtension(unittest::optional_bytes_extension   ));
 
-  EXPECT_TRUE(message.HasExtension(unittest::optionalgroup_extension           ));
-  EXPECT_TRUE(message.HasExtension(unittest::optional_nested_message_extension ));
-  EXPECT_TRUE(message.HasExtension(unittest::optional_foreign_message_extension));
-  EXPECT_TRUE(message.HasExtension(unittest::optional_import_message_extension ));
+  EXPECT_TRUE(message.HasExtension(unittest::optionalgroup_extension                 ));
+  EXPECT_TRUE(message.HasExtension(unittest::optional_nested_message_extension       ));
+  EXPECT_TRUE(message.HasExtension(unittest::optional_foreign_message_extension      ));
+  EXPECT_TRUE(message.HasExtension(unittest::optional_import_message_extension       ));
+  EXPECT_TRUE(message.HasExtension(unittest::optional_public_import_message_extension));
+  EXPECT_TRUE(message.HasExtension(unittest::optional_lazy_message_extension         ));
 
-  EXPECT_TRUE(message.GetExtension(unittest::optionalgroup_extension           ).has_a());
-  EXPECT_TRUE(message.GetExtension(unittest::optional_nested_message_extension ).has_bb());
-  EXPECT_TRUE(message.GetExtension(unittest::optional_foreign_message_extension).has_c());
-  EXPECT_TRUE(message.GetExtension(unittest::optional_import_message_extension ).has_d());
+  EXPECT_TRUE(message.GetExtension(unittest::optionalgroup_extension                 ).has_a());
+  EXPECT_TRUE(message.GetExtension(unittest::optional_nested_message_extension       ).has_bb());
+  EXPECT_TRUE(message.GetExtension(unittest::optional_foreign_message_extension      ).has_c());
+  EXPECT_TRUE(message.GetExtension(unittest::optional_import_message_extension       ).has_d());
+  EXPECT_TRUE(message.GetExtension(unittest::optional_public_import_message_extension).has_e());
+  EXPECT_TRUE(message.GetExtension(unittest::optional_lazy_message_extension         ).has_bb());
 
   EXPECT_TRUE(message.HasExtension(unittest::optional_nested_enum_extension ));
   EXPECT_TRUE(message.HasExtension(unittest::optional_foreign_enum_extension));
@@ -1146,6 +1193,8 @@
 
   EXPECT_EQ("124", message.GetExtension(unittest::optional_string_piece_extension));
   EXPECT_EQ("125", message.GetExtension(unittest::optional_cord_extension));
+  EXPECT_EQ(126, message.GetExtension(unittest::optional_public_import_message_extension ).e());
+  EXPECT_EQ(127, message.GetExtension(unittest::optional_lazy_message_extension).bb());
 
   // -----------------------------------------------------------------
 
@@ -1169,6 +1218,7 @@
   ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_nested_message_extension ));
   ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_foreign_message_extension));
   ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_import_message_extension ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_lazy_message_extension   ));
   ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_nested_enum_extension    ));
   ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_foreign_enum_extension   ));
   ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_import_enum_extension    ));
@@ -1196,6 +1246,7 @@
   EXPECT_EQ(218, message.GetExtension(unittest::repeated_nested_message_extension , 0).bb());
   EXPECT_EQ(219, message.GetExtension(unittest::repeated_foreign_message_extension, 0).c());
   EXPECT_EQ(220, message.GetExtension(unittest::repeated_import_message_extension , 0).d());
+  EXPECT_EQ(227, message.GetExtension(unittest::repeated_lazy_message_extension   , 0).bb());
 
   EXPECT_EQ(unittest::TestAllTypes::BAR, message.GetExtension(unittest::repeated_nested_enum_extension , 0));
   EXPECT_EQ(unittest::FOREIGN_BAR      , message.GetExtension(unittest::repeated_foreign_enum_extension, 0));
@@ -1224,6 +1275,7 @@
   EXPECT_EQ(318, message.GetExtension(unittest::repeated_nested_message_extension , 1).bb());
   EXPECT_EQ(319, message.GetExtension(unittest::repeated_foreign_message_extension, 1).c());
   EXPECT_EQ(320, message.GetExtension(unittest::repeated_import_message_extension , 1).d());
+  EXPECT_EQ(327, message.GetExtension(unittest::repeated_lazy_message_extension   , 1).bb());
 
   EXPECT_EQ(unittest::TestAllTypes::BAZ, message.GetExtension(unittest::repeated_nested_enum_extension , 1));
   EXPECT_EQ(unittest::FOREIGN_BAZ      , message.GetExtension(unittest::repeated_foreign_enum_extension, 1));
@@ -1307,10 +1359,12 @@
   EXPECT_FALSE(message.HasExtension(unittest::optional_string_extension  ));
   EXPECT_FALSE(message.HasExtension(unittest::optional_bytes_extension   ));
 
-  EXPECT_FALSE(message.HasExtension(unittest::optionalgroup_extension           ));
-  EXPECT_FALSE(message.HasExtension(unittest::optional_nested_message_extension ));
-  EXPECT_FALSE(message.HasExtension(unittest::optional_foreign_message_extension));
-  EXPECT_FALSE(message.HasExtension(unittest::optional_import_message_extension ));
+  EXPECT_FALSE(message.HasExtension(unittest::optionalgroup_extension                 ));
+  EXPECT_FALSE(message.HasExtension(unittest::optional_nested_message_extension       ));
+  EXPECT_FALSE(message.HasExtension(unittest::optional_foreign_message_extension      ));
+  EXPECT_FALSE(message.HasExtension(unittest::optional_import_message_extension       ));
+  EXPECT_FALSE(message.HasExtension(unittest::optional_public_import_message_extension));
+  EXPECT_FALSE(message.HasExtension(unittest::optional_lazy_message_extension         ));
 
   EXPECT_FALSE(message.HasExtension(unittest::optional_nested_enum_extension ));
   EXPECT_FALSE(message.HasExtension(unittest::optional_foreign_enum_extension));
@@ -1337,15 +1391,19 @@
   EXPECT_EQ(""   , message.GetExtension(unittest::optional_bytes_extension   ));
 
   // Embedded messages should also be clear.
-  EXPECT_FALSE(message.GetExtension(unittest::optionalgroup_extension           ).has_a());
-  EXPECT_FALSE(message.GetExtension(unittest::optional_nested_message_extension ).has_bb());
-  EXPECT_FALSE(message.GetExtension(unittest::optional_foreign_message_extension).has_c());
-  EXPECT_FALSE(message.GetExtension(unittest::optional_import_message_extension ).has_d());
+  EXPECT_FALSE(message.GetExtension(unittest::optionalgroup_extension                 ).has_a());
+  EXPECT_FALSE(message.GetExtension(unittest::optional_nested_message_extension       ).has_bb());
+  EXPECT_FALSE(message.GetExtension(unittest::optional_foreign_message_extension      ).has_c());
+  EXPECT_FALSE(message.GetExtension(unittest::optional_import_message_extension       ).has_d());
+  EXPECT_FALSE(message.GetExtension(unittest::optional_public_import_message_extension).has_e());
+  EXPECT_FALSE(message.GetExtension(unittest::optional_lazy_message_extension         ).has_bb());
 
-  EXPECT_EQ(0, message.GetExtension(unittest::optionalgroup_extension           ).a());
-  EXPECT_EQ(0, message.GetExtension(unittest::optional_nested_message_extension ).bb());
-  EXPECT_EQ(0, message.GetExtension(unittest::optional_foreign_message_extension).c());
-  EXPECT_EQ(0, message.GetExtension(unittest::optional_import_message_extension ).d());
+  EXPECT_EQ(0, message.GetExtension(unittest::optionalgroup_extension                 ).a());
+  EXPECT_EQ(0, message.GetExtension(unittest::optional_nested_message_extension       ).bb());
+  EXPECT_EQ(0, message.GetExtension(unittest::optional_foreign_message_extension      ).c());
+  EXPECT_EQ(0, message.GetExtension(unittest::optional_import_message_extension       ).d());
+  EXPECT_EQ(0, message.GetExtension(unittest::optional_public_import_message_extension).e());
+  EXPECT_EQ(0, message.GetExtension(unittest::optional_lazy_message_extension         ).bb());
 
   // Enums without defaults are set to the first value in the enum.
   EXPECT_EQ(unittest::TestAllTypes::FOO, message.GetExtension(unittest::optional_nested_enum_extension ));
@@ -1376,6 +1434,7 @@
   EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_nested_message_extension ));
   EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_foreign_message_extension));
   EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_import_message_extension ));
+  EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_lazy_message_extension   ));
   EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_nested_enum_extension    ));
   EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_foreign_enum_extension   ));
   EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_import_enum_extension    ));
@@ -1459,6 +1518,7 @@
   ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_nested_message_extension ));
   ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_foreign_message_extension));
   ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_import_message_extension ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_lazy_message_extension   ));
   ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_nested_enum_extension    ));
   ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_foreign_enum_extension   ));
   ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_import_enum_extension    ));
@@ -1486,6 +1546,7 @@
   EXPECT_EQ(218, message.GetExtension(unittest::repeated_nested_message_extension , 0).bb());
   EXPECT_EQ(219, message.GetExtension(unittest::repeated_foreign_message_extension, 0).c());
   EXPECT_EQ(220, message.GetExtension(unittest::repeated_import_message_extension , 0).d());
+  EXPECT_EQ(227, message.GetExtension(unittest::repeated_lazy_message_extension   , 0).bb());
 
   EXPECT_EQ(unittest::TestAllTypes::BAR, message.GetExtension(unittest::repeated_nested_enum_extension , 0));
   EXPECT_EQ(unittest::FOREIGN_BAR      , message.GetExtension(unittest::repeated_foreign_enum_extension, 0));
@@ -1515,6 +1576,7 @@
   EXPECT_EQ(518, message.GetExtension(unittest::repeated_nested_message_extension , 1).bb());
   EXPECT_EQ(519, message.GetExtension(unittest::repeated_foreign_message_extension, 1).c());
   EXPECT_EQ(520, message.GetExtension(unittest::repeated_import_message_extension , 1).d());
+  EXPECT_EQ(527, message.GetExtension(unittest::repeated_lazy_message_extension   , 1).bb());
 
   EXPECT_EQ(unittest::TestAllTypes::FOO, message.GetExtension(unittest::repeated_nested_enum_extension , 1));
   EXPECT_EQ(unittest::FOREIGN_FOO      , message.GetExtension(unittest::repeated_foreign_enum_extension, 1));
@@ -1750,6 +1812,7 @@
   ASSERT_EQ(1, message.repeated_nested_message_size ());
   ASSERT_EQ(1, message.repeated_foreign_message_size());
   ASSERT_EQ(1, message.repeated_import_message_size ());
+  ASSERT_EQ(1, message.repeated_import_message_size ());
   ASSERT_EQ(1, message.repeated_nested_enum_size    ());
   ASSERT_EQ(1, message.repeated_foreign_enum_size   ());
   ASSERT_EQ(1, message.repeated_import_enum_size    ());
@@ -1780,6 +1843,7 @@
   EXPECT_EQ(218, message.repeated_nested_message (0).bb());
   EXPECT_EQ(219, message.repeated_foreign_message(0).c());
   EXPECT_EQ(220, message.repeated_import_message (0).d());
+  EXPECT_EQ(220, message.repeated_import_message (0).d());
 
   EXPECT_EQ(unittest::TestAllTypes::BAR, message.repeated_nested_enum (0));
   EXPECT_EQ(unittest::FOREIGN_BAR      , message.repeated_foreign_enum(0));
@@ -1810,6 +1874,7 @@
   ASSERT_EQ(1, message.ExtensionSize(unittest::repeated_nested_message_extension ));
   ASSERT_EQ(1, message.ExtensionSize(unittest::repeated_foreign_message_extension));
   ASSERT_EQ(1, message.ExtensionSize(unittest::repeated_import_message_extension ));
+  ASSERT_EQ(1, message.ExtensionSize(unittest::repeated_lazy_message_extension   ));
   ASSERT_EQ(1, message.ExtensionSize(unittest::repeated_nested_enum_extension    ));
   ASSERT_EQ(1, message.ExtensionSize(unittest::repeated_foreign_enum_extension   ));
   ASSERT_EQ(1, message.ExtensionSize(unittest::repeated_import_enum_extension    ));
@@ -1838,6 +1903,7 @@
   EXPECT_EQ(218, message.GetExtension(unittest::repeated_nested_message_extension , 0).bb());
   EXPECT_EQ(219, message.GetExtension(unittest::repeated_foreign_message_extension, 0).c());
   EXPECT_EQ(220, message.GetExtension(unittest::repeated_import_message_extension , 0).d());
+  EXPECT_EQ(227, message.GetExtension(unittest::repeated_lazy_message_extension   , 0).bb());
 
   EXPECT_EQ(unittest::TestAllTypes::BAR, message.GetExtension(unittest::repeated_nested_enum_extension , 0));
   EXPECT_EQ(unittest::FOREIGN_BAR      , message.GetExtension(unittest::repeated_foreign_enum_extension, 0));
@@ -1847,6 +1913,36 @@
   EXPECT_EQ("225", message.GetExtension(unittest::repeated_cord_extension, 0));
 }
 
+void TestUtil::ExpectLastRepeatedsReleased(
+    const unittest::TestAllTypes& message) {
+  ASSERT_EQ(1, message.repeatedgroup_size           ());
+  ASSERT_EQ(1, message.repeated_nested_message_size ());
+  ASSERT_EQ(1, message.repeated_foreign_message_size());
+  ASSERT_EQ(1, message.repeated_import_message_size ());
+  ASSERT_EQ(1, message.repeated_import_message_size ());
+
+  EXPECT_EQ(217, message.repeatedgroup           (0).a());
+  EXPECT_EQ(218, message.repeated_nested_message (0).bb());
+  EXPECT_EQ(219, message.repeated_foreign_message(0).c());
+  EXPECT_EQ(220, message.repeated_import_message (0).d());
+  EXPECT_EQ(220, message.repeated_import_message (0).d());
+}
+
+void TestUtil::ExpectLastRepeatedExtensionsReleased(
+    const unittest::TestAllExtensions& message) {
+  ASSERT_EQ(1, message.ExtensionSize(unittest::repeatedgroup_extension           ));
+  ASSERT_EQ(1, message.ExtensionSize(unittest::repeated_nested_message_extension ));
+  ASSERT_EQ(1, message.ExtensionSize(unittest::repeated_foreign_message_extension));
+  ASSERT_EQ(1, message.ExtensionSize(unittest::repeated_import_message_extension ));
+  ASSERT_EQ(1, message.ExtensionSize(unittest::repeated_lazy_message_extension   ));
+
+  EXPECT_EQ(217, message.GetExtension(unittest::repeatedgroup_extension           , 0).a());
+  EXPECT_EQ(218, message.GetExtension(unittest::repeated_nested_message_extension , 0).bb());
+  EXPECT_EQ(219, message.GetExtension(unittest::repeated_foreign_message_extension, 0).c());
+  EXPECT_EQ(220, message.GetExtension(unittest::repeated_import_message_extension , 0).d());
+  EXPECT_EQ(227, message.GetExtension(unittest::repeated_lazy_message_extension   , 0).bb());
+}
+
 void TestUtil::ExpectRepeatedsSwapped(
     const unittest::TestAllTypes& message) {
   ASSERT_EQ(2, message.repeated_int32_size   ());
@@ -1869,6 +1965,7 @@
   ASSERT_EQ(2, message.repeated_nested_message_size ());
   ASSERT_EQ(2, message.repeated_foreign_message_size());
   ASSERT_EQ(2, message.repeated_import_message_size ());
+  ASSERT_EQ(2, message.repeated_import_message_size ());
   ASSERT_EQ(2, message.repeated_nested_enum_size    ());
   ASSERT_EQ(2, message.repeated_foreign_enum_size   ());
   ASSERT_EQ(2, message.repeated_import_enum_size    ());
@@ -1899,6 +1996,7 @@
   EXPECT_EQ(218, message.repeated_nested_message (1).bb());
   EXPECT_EQ(219, message.repeated_foreign_message(1).c());
   EXPECT_EQ(220, message.repeated_import_message (1).d());
+  EXPECT_EQ(220, message.repeated_import_message (1).d());
 
   EXPECT_EQ(unittest::TestAllTypes::BAR, message.repeated_nested_enum (1));
   EXPECT_EQ(unittest::FOREIGN_BAR      , message.repeated_foreign_enum(1));
@@ -1924,6 +2022,7 @@
   EXPECT_EQ(318, message.repeated_nested_message (0).bb());
   EXPECT_EQ(319, message.repeated_foreign_message(0).c());
   EXPECT_EQ(320, message.repeated_import_message (0).d());
+  EXPECT_EQ(320, message.repeated_import_message (0).d());
 
   EXPECT_EQ(unittest::TestAllTypes::BAZ, message.repeated_nested_enum (0));
   EXPECT_EQ(unittest::FOREIGN_BAZ      , message.repeated_foreign_enum(0));
@@ -1953,6 +2052,7 @@
   ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_nested_message_extension ));
   ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_foreign_message_extension));
   ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_import_message_extension ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_lazy_message_extension   ));
   ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_nested_enum_extension    ));
   ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_foreign_enum_extension   ));
   ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_import_enum_extension    ));
@@ -1980,6 +2080,7 @@
   EXPECT_EQ(218, message.GetExtension(unittest::repeated_nested_message_extension , 1).bb());
   EXPECT_EQ(219, message.GetExtension(unittest::repeated_foreign_message_extension, 1).c());
   EXPECT_EQ(220, message.GetExtension(unittest::repeated_import_message_extension , 1).d());
+  EXPECT_EQ(227, message.GetExtension(unittest::repeated_lazy_message_extension   , 1).bb());
 
   EXPECT_EQ(unittest::TestAllTypes::BAR, message.GetExtension(unittest::repeated_nested_enum_extension , 1));
   EXPECT_EQ(unittest::FOREIGN_BAR      , message.GetExtension(unittest::repeated_foreign_enum_extension, 1));
@@ -2008,6 +2109,7 @@
   EXPECT_EQ(318, message.GetExtension(unittest::repeated_nested_message_extension , 0).bb());
   EXPECT_EQ(319, message.GetExtension(unittest::repeated_foreign_message_extension, 0).c());
   EXPECT_EQ(320, message.GetExtension(unittest::repeated_import_message_extension , 0).d());
+  EXPECT_EQ(327, message.GetExtension(unittest::repeated_lazy_message_extension   , 0).bb());
 
   EXPECT_EQ(unittest::TestAllTypes::BAZ, message.GetExtension(unittest::repeated_nested_enum_extension , 0));
   EXPECT_EQ(unittest::FOREIGN_BAZ      , message.GetExtension(unittest::repeated_foreign_enum_extension, 0));
@@ -2031,6 +2133,8 @@
     pool->FindFieldByName("protobuf_unittest.ForeignMessage.c");
   import_d_ =
     pool->FindFieldByName("protobuf_unittest_import.ImportMessage.d");
+  import_e_ =
+    pool->FindFieldByName("protobuf_unittest_import.PublicImportMessage.e");
   nested_foo_ =
     pool->FindEnumValueByName("protobuf_unittest.TestAllTypes.FOO");
   nested_bar_ =
@@ -2067,6 +2171,7 @@
   EXPECT_TRUE(nested_b_         != NULL);
   EXPECT_TRUE(foreign_c_        != NULL);
   EXPECT_TRUE(import_d_         != NULL);
+  EXPECT_TRUE(import_e_         != NULL);
   EXPECT_TRUE(nested_foo_       != NULL);
   EXPECT_TRUE(nested_bar_       != NULL);
   EXPECT_TRUE(nested_baz_       != NULL);
@@ -2129,6 +2234,12 @@
   reflection->SetString(message, F("optional_string_piece"), "124");
   reflection->SetString(message, F("optional_cord"), "125");
 
+  sub_message = reflection->MutableMessage(message, F("optional_public_import_message"));
+  sub_message->GetReflection()->SetInt32(sub_message, import_e_, 126);
+
+  sub_message = reflection->MutableMessage(message, F("optional_lazy_message"));
+  sub_message->GetReflection()->SetInt32(sub_message, nested_b_, 127);
+
   // -----------------------------------------------------------------
 
   reflection->AddInt32 (message, F("repeated_int32"   ), 201);
@@ -2155,6 +2266,8 @@
   sub_message->GetReflection()->SetInt32(sub_message, foreign_c_, 219);
   sub_message = reflection->AddMessage(message, F("repeated_import_message"));
   sub_message->GetReflection()->SetInt32(sub_message, import_d_, 220);
+  sub_message = reflection->AddMessage(message, F("repeated_lazy_message"));
+  sub_message->GetReflection()->SetInt32(sub_message, nested_b_, 227);
 
   reflection->AddEnum(message, F("repeated_nested_enum" ),  nested_bar_);
   reflection->AddEnum(message, F("repeated_foreign_enum"), foreign_bar_);
@@ -2188,6 +2301,8 @@
   sub_message->GetReflection()->SetInt32(sub_message, foreign_c_, 319);
   sub_message = reflection->AddMessage(message, F("repeated_import_message"));
   sub_message->GetReflection()->SetInt32(sub_message, import_d_, 320);
+  sub_message = reflection->AddMessage(message, F("repeated_lazy_message"));
+  sub_message->GetReflection()->SetInt32(sub_message, nested_b_, 327);
 
   reflection->AddEnum(message, F("repeated_nested_enum" ),  nested_baz_);
   reflection->AddEnum(message, F("repeated_foreign_enum"), foreign_baz_);
@@ -2289,10 +2404,12 @@
   EXPECT_TRUE(reflection->HasField(message, F("optional_string"  )));
   EXPECT_TRUE(reflection->HasField(message, F("optional_bytes"   )));
 
-  EXPECT_TRUE(reflection->HasField(message, F("optionalgroup"           )));
-  EXPECT_TRUE(reflection->HasField(message, F("optional_nested_message" )));
-  EXPECT_TRUE(reflection->HasField(message, F("optional_foreign_message")));
-  EXPECT_TRUE(reflection->HasField(message, F("optional_import_message" )));
+  EXPECT_TRUE(reflection->HasField(message, F("optionalgroup"                 )));
+  EXPECT_TRUE(reflection->HasField(message, F("optional_nested_message"       )));
+  EXPECT_TRUE(reflection->HasField(message, F("optional_foreign_message"      )));
+  EXPECT_TRUE(reflection->HasField(message, F("optional_import_message"       )));
+  EXPECT_TRUE(reflection->HasField(message, F("optional_public_import_message")));
+  EXPECT_TRUE(reflection->HasField(message, F("optional_lazy_message"         )));
 
   sub_message = &reflection->GetMessage(message, F("optionalgroup"));
   EXPECT_TRUE(sub_message->GetReflection()->HasField(*sub_message, group_a_));
@@ -2302,6 +2419,10 @@
   EXPECT_TRUE(sub_message->GetReflection()->HasField(*sub_message, foreign_c_));
   sub_message = &reflection->GetMessage(message, F("optional_import_message"));
   EXPECT_TRUE(sub_message->GetReflection()->HasField(*sub_message, import_d_));
+  sub_message = &reflection->GetMessage(message, F("optional_public_import_message"));
+  EXPECT_TRUE(sub_message->GetReflection()->HasField(*sub_message, import_e_));
+  sub_message = &reflection->GetMessage(message, F("optional_lazy_message"));
+  EXPECT_TRUE(sub_message->GetReflection()->HasField(*sub_message, nested_b_));
 
   EXPECT_TRUE(reflection->HasField(message, F("optional_nested_enum" )));
   EXPECT_TRUE(reflection->HasField(message, F("optional_foreign_enum")));
@@ -2337,6 +2458,10 @@
   EXPECT_EQ(119, sub_message->GetReflection()->GetInt32(*sub_message, foreign_c_));
   sub_message = &reflection->GetMessage(message, F("optional_import_message"));
   EXPECT_EQ(120, sub_message->GetReflection()->GetInt32(*sub_message, import_d_));
+  sub_message = &reflection->GetMessage(message, F("optional_public_import_message"));
+  EXPECT_EQ(126, sub_message->GetReflection()->GetInt32(*sub_message, import_e_));
+  sub_message = &reflection->GetMessage(message, F("optional_lazy_message"));
+  EXPECT_EQ(127, sub_message->GetReflection()->GetInt32(*sub_message, nested_b_));
 
   EXPECT_EQ( nested_baz_, reflection->GetEnum(message, F("optional_nested_enum" )));
   EXPECT_EQ(foreign_baz_, reflection->GetEnum(message, F("optional_foreign_enum")));
@@ -2347,6 +2472,7 @@
 
   EXPECT_EQ("125", reflection->GetString(message, F("optional_cord")));
   EXPECT_EQ("125", reflection->GetStringReference(message, F("optional_cord"), &scratch));
+
 }
 
 void TestUtil::ReflectionTester::ExpectAllFieldsSetViaReflection2(
@@ -2377,6 +2503,7 @@
   ASSERT_EQ(2, reflection->FieldSize(message, F("repeated_nested_message" )));
   ASSERT_EQ(2, reflection->FieldSize(message, F("repeated_foreign_message")));
   ASSERT_EQ(2, reflection->FieldSize(message, F("repeated_import_message" )));
+  ASSERT_EQ(2, reflection->FieldSize(message, F("repeated_lazy_message"   )));
   ASSERT_EQ(2, reflection->FieldSize(message, F("repeated_nested_enum"    )));
   ASSERT_EQ(2, reflection->FieldSize(message, F("repeated_foreign_enum"   )));
   ASSERT_EQ(2, reflection->FieldSize(message, F("repeated_import_enum"    )));
@@ -2411,6 +2538,8 @@
   EXPECT_EQ(219, sub_message->GetReflection()->GetInt32(*sub_message, foreign_c_));
   sub_message = &reflection->GetRepeatedMessage(message, F("repeated_import_message"), 0);
   EXPECT_EQ(220, sub_message->GetReflection()->GetInt32(*sub_message, import_d_));
+  sub_message = &reflection->GetRepeatedMessage(message, F("repeated_lazy_message"), 0);
+  EXPECT_EQ(227, sub_message->GetReflection()->GetInt32(*sub_message, nested_b_));
 
   EXPECT_EQ( nested_bar_, reflection->GetRepeatedEnum(message, F("repeated_nested_enum" ),0));
   EXPECT_EQ(foreign_bar_, reflection->GetRepeatedEnum(message, F("repeated_foreign_enum"),0));
@@ -2453,6 +2582,8 @@
   EXPECT_EQ(319, sub_message->GetReflection()->GetInt32(*sub_message, foreign_c_));
   sub_message = &reflection->GetRepeatedMessage(message, F("repeated_import_message"), 1);
   EXPECT_EQ(320, sub_message->GetReflection()->GetInt32(*sub_message, import_d_));
+  sub_message = &reflection->GetRepeatedMessage(message, F("repeated_lazy_message"), 1);
+  EXPECT_EQ(327, sub_message->GetReflection()->GetInt32(*sub_message, nested_b_));
 
   EXPECT_EQ( nested_baz_, reflection->GetRepeatedEnum(message, F("repeated_nested_enum" ),1));
   EXPECT_EQ(foreign_baz_, reflection->GetRepeatedEnum(message, F("repeated_foreign_enum"),1));
@@ -2609,6 +2740,8 @@
   EXPECT_FALSE(reflection->HasField(message, F("optional_nested_message" )));
   EXPECT_FALSE(reflection->HasField(message, F("optional_foreign_message")));
   EXPECT_FALSE(reflection->HasField(message, F("optional_import_message" )));
+  EXPECT_FALSE(reflection->HasField(message, F("optional_public_import_message")));
+  EXPECT_FALSE(reflection->HasField(message, F("optional_lazy_message")));
 
   EXPECT_FALSE(reflection->HasField(message, F("optional_nested_enum" )));
   EXPECT_FALSE(reflection->HasField(message, F("optional_foreign_enum")));
@@ -2650,6 +2783,12 @@
   sub_message = &reflection->GetMessage(message, F("optional_import_message"));
   EXPECT_FALSE(sub_message->GetReflection()->HasField(*sub_message, import_d_));
   EXPECT_EQ(0, sub_message->GetReflection()->GetInt32(*sub_message, import_d_));
+  sub_message = &reflection->GetMessage(message, F("optional_public_import_message"));
+  EXPECT_FALSE(sub_message->GetReflection()->HasField(*sub_message, import_e_));
+  EXPECT_EQ(0, sub_message->GetReflection()->GetInt32(*sub_message, import_e_));
+  sub_message = &reflection->GetMessage(message, F("optional_lazy_message"));
+  EXPECT_FALSE(sub_message->GetReflection()->HasField(*sub_message, nested_b_));
+  EXPECT_EQ(0, sub_message->GetReflection()->GetInt32(*sub_message, nested_b_));
 
   // Enums without defaults are set to the first value in the enum.
   EXPECT_EQ( nested_foo_, reflection->GetEnum(message, F("optional_nested_enum" )));
@@ -2683,6 +2822,7 @@
   EXPECT_EQ(0, reflection->FieldSize(message, F("repeated_nested_message" )));
   EXPECT_EQ(0, reflection->FieldSize(message, F("repeated_foreign_message")));
   EXPECT_EQ(0, reflection->FieldSize(message, F("repeated_import_message" )));
+  EXPECT_EQ(0, reflection->FieldSize(message, F("repeated_lazy_message"   )));
   EXPECT_EQ(0, reflection->FieldSize(message, F("repeated_nested_enum"    )));
   EXPECT_EQ(0, reflection->FieldSize(message, F("repeated_foreign_enum"   )));
   EXPECT_EQ(0, reflection->FieldSize(message, F("repeated_import_enum"    )));
@@ -2796,6 +2936,8 @@
   sub_message->GetReflection()->SetInt32(sub_message, foreign_c_, 519);
   sub_message = reflection->MutableRepeatedMessage(message, F("repeated_import_message"), 1);
   sub_message->GetReflection()->SetInt32(sub_message, import_d_, 520);
+  sub_message = reflection->MutableRepeatedMessage(message, F("repeated_lazy_message"), 1);
+  sub_message->GetReflection()->SetInt32(sub_message, nested_b_, 527);
 
   reflection->SetRepeatedEnum(message, F("repeated_nested_enum" ), 1,  nested_foo_);
   reflection->SetRepeatedEnum(message, F("repeated_foreign_enum"), 1, foreign_foo_);
@@ -2824,7 +2966,8 @@
   reflection->SetRepeatedEnum  (message, F("packed_enum"    ), 1, foreign_foo_);
 }
 
-void TestUtil::ReflectionTester::RemoveLastRepeatedsViaReflection(Message* message) {
+void TestUtil::ReflectionTester::RemoveLastRepeatedsViaReflection(
+    Message* message) {
   const Reflection* reflection = message->GetReflection();
 
   vector<const FieldDescriptor*> output;
@@ -2837,6 +2980,26 @@
   }
 }
 
+void TestUtil::ReflectionTester::ReleaseLastRepeatedsViaReflection(
+    Message* message, bool expect_extensions_notnull) {
+  const Reflection* reflection = message->GetReflection();
+
+  vector<const FieldDescriptor*> output;
+  reflection->ListFields(*message, &output);
+  for (int i=0; i<output.size(); ++i) {
+    const FieldDescriptor* field = output[i];
+    if (!field->is_repeated()) continue;
+    if (field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE) continue;
+
+    Message* released = reflection->ReleaseLast(message, field);
+    if (!field->is_extension() || expect_extensions_notnull) {
+      ASSERT_TRUE(released != NULL) << "ReleaseLast returned NULL for: "
+                                    << field->name();
+    }
+    delete released;
+  }
+}
+
 void TestUtil::ReflectionTester::SwapRepeatedsViaReflection(Message* message) {
   const Reflection* reflection = message->GetReflection();
 
@@ -2850,5 +3013,35 @@
   }
 }
 
+void TestUtil::ReflectionTester::ExpectMessagesReleasedViaReflection(
+    Message* message,
+    TestUtil::ReflectionTester::MessageReleaseState expected_release_state) {
+  const Reflection* reflection = message->GetReflection();
+
+  static const char* fields[] = {
+    "optionalgroup",
+    "optional_nested_message",
+    "optional_foreign_message",
+    "optional_import_message",
+  };
+  for (int i = 0; i < GOOGLE_ARRAYSIZE(fields); i++) {
+    const Message& sub_message = reflection->GetMessage(*message, F(fields[i]));
+    Message* released = reflection->ReleaseMessage(message, F(fields[i]));
+    switch (expected_release_state) {
+      case IS_NULL:
+        EXPECT_TRUE(released == NULL);
+        break;
+      case NOT_NULL:
+        EXPECT_TRUE(released != NULL);
+        EXPECT_EQ(&sub_message, released);
+        break;
+      case CAN_BE_NULL:
+        break;
+    }
+    delete released;
+    EXPECT_FALSE(reflection->HasField(*message, F(fields[i])));
+  }
+}
+
 }  // namespace protobuf
 }  // namespace google
diff --git a/third_party/protobuf/src/google/protobuf/test_util.h b/third_party/protobuf/src/google/protobuf/test_util.h
index 25165f3..4551957 100644
--- a/third_party/protobuf/src/google/protobuf/test_util.h
+++ b/third_party/protobuf/src/google/protobuf/test_util.h
@@ -43,13 +43,17 @@
 namespace google {
 namespace protobuf {
 
-namespace unittest = protobuf_unittest;
+namespace unittest = ::protobuf_unittest;
 namespace unittest_import = protobuf_unittest_import;
 
 class TestUtil {
  public:
   // Set every field in the message to a unique value.
   static void SetAllFields(unittest::TestAllTypes* message);
+  static void SetOptionalFields(unittest::TestAllTypes* message);
+  static void AddRepeatedFields1(unittest::TestAllTypes* message);
+  static void AddRepeatedFields2(unittest::TestAllTypes* message);
+  static void SetDefaultFields(unittest::TestAllTypes* message);
   static void SetAllExtensions(unittest::TestAllExtensions* message);
   static void SetAllFieldsAndExtensions(unittest::TestFieldOrderings* message);
   static void SetPackedFields(unittest::TestPackedTypes* message);
@@ -104,6 +108,10 @@
       const unittest::TestAllTypes& message);
   static void ExpectLastRepeatedExtensionsRemoved(
       const unittest::TestAllExtensions& message);
+  static void ExpectLastRepeatedsReleased(
+      const unittest::TestAllTypes& message);
+  static void ExpectLastRepeatedExtensionsReleased(
+      const unittest::TestAllExtensions& message);
 
   // Check that all repeated fields have had their first and last elements
   // swapped.
@@ -132,8 +140,18 @@
     void ExpectPackedClearViaReflection(const Message& message);
 
     void RemoveLastRepeatedsViaReflection(Message* message);
+    void ReleaseLastRepeatedsViaReflection(
+        Message* message, bool expect_extensions_notnull);
     void SwapRepeatedsViaReflection(Message* message);
 
+    enum MessageReleaseState {
+      IS_NULL,
+      CAN_BE_NULL,
+      NOT_NULL,
+    };
+    void ExpectMessagesReleasedViaReflection(
+        Message* message, MessageReleaseState expected_release_state);
+
    private:
     const FieldDescriptor* F(const string& name);
 
@@ -144,6 +162,7 @@
     const FieldDescriptor* nested_b_;
     const FieldDescriptor* foreign_c_;
     const FieldDescriptor* import_d_;
+    const FieldDescriptor* import_e_;
 
     const EnumValueDescriptor* nested_foo_;
     const EnumValueDescriptor* nested_bar_;
diff --git a/third_party/protobuf/src/google/protobuf/test_util_lite.cc b/third_party/protobuf/src/google/protobuf/test_util_lite.cc
index d7140e0..9099292 100644
--- a/third_party/protobuf/src/google/protobuf/test_util_lite.cc
+++ b/third_party/protobuf/src/google/protobuf/test_util_lite.cc
@@ -62,10 +62,12 @@
   message->set_optional_string  ("115");
   message->set_optional_bytes   ("116");
 
-  message->mutable_optionalgroup           ()->set_a(117);
-  message->mutable_optional_nested_message ()->set_bb(118);
-  message->mutable_optional_foreign_message()->set_c(119);
-  message->mutable_optional_import_message ()->set_d(120);
+  message->mutable_optionalgroup                 ()->set_a(117);
+  message->mutable_optional_nested_message       ()->set_bb(118);
+  message->mutable_optional_foreign_message      ()->set_c(119);
+  message->mutable_optional_import_message       ()->set_d(120);
+  message->mutable_optional_public_import_message()->set_e(126);
+  message->mutable_optional_lazy_message         ()->set_bb(127);
 
   message->set_optional_nested_enum (unittest::TestAllTypesLite::BAZ );
   message->set_optional_foreign_enum(unittest::FOREIGN_LITE_BAZ      );
@@ -94,6 +96,7 @@
   message->add_repeated_nested_message ()->set_bb(218);
   message->add_repeated_foreign_message()->set_c(219);
   message->add_repeated_import_message ()->set_d(220);
+  message->add_repeated_lazy_message   ()->set_bb(227);
 
   message->add_repeated_nested_enum (unittest::TestAllTypesLite::BAR );
   message->add_repeated_foreign_enum(unittest::FOREIGN_LITE_BAR      );
@@ -121,6 +124,7 @@
   message->add_repeated_nested_message ()->set_bb(318);
   message->add_repeated_foreign_message()->set_c(319);
   message->add_repeated_import_message ()->set_d(320);
+  message->add_repeated_lazy_message   ()->set_bb(327);
 
   message->add_repeated_nested_enum (unittest::TestAllTypesLite::BAZ );
   message->add_repeated_foreign_enum(unittest::FOREIGN_LITE_BAZ      );
@@ -174,6 +178,7 @@
   message->mutable_repeated_nested_message (1)->set_bb(518);
   message->mutable_repeated_foreign_message(1)->set_c(519);
   message->mutable_repeated_import_message (1)->set_d(520);
+  message->mutable_repeated_lazy_message   (1)->set_bb(527);
 
   message->set_repeated_nested_enum (1, unittest::TestAllTypesLite::FOO );
   message->set_repeated_foreign_enum(1, unittest::FOREIGN_LITE_FOO      );
@@ -201,15 +206,19 @@
   EXPECT_TRUE(message.has_optional_string  ());
   EXPECT_TRUE(message.has_optional_bytes   ());
 
-  EXPECT_TRUE(message.has_optionalgroup           ());
-  EXPECT_TRUE(message.has_optional_nested_message ());
-  EXPECT_TRUE(message.has_optional_foreign_message());
-  EXPECT_TRUE(message.has_optional_import_message ());
+  EXPECT_TRUE(message.has_optionalgroup                 ());
+  EXPECT_TRUE(message.has_optional_nested_message       ());
+  EXPECT_TRUE(message.has_optional_foreign_message      ());
+  EXPECT_TRUE(message.has_optional_import_message       ());
+  EXPECT_TRUE(message.has_optional_public_import_message());
+  EXPECT_TRUE(message.has_optional_lazy_message         ());
 
-  EXPECT_TRUE(message.optionalgroup           ().has_a());
-  EXPECT_TRUE(message.optional_nested_message ().has_bb());
-  EXPECT_TRUE(message.optional_foreign_message().has_c());
-  EXPECT_TRUE(message.optional_import_message ().has_d());
+  EXPECT_TRUE(message.optionalgroup                 ().has_a());
+  EXPECT_TRUE(message.optional_nested_message       ().has_bb());
+  EXPECT_TRUE(message.optional_foreign_message      ().has_c());
+  EXPECT_TRUE(message.optional_import_message       ().has_d());
+  EXPECT_TRUE(message.optional_public_import_message().has_e());
+  EXPECT_TRUE(message.optional_lazy_message         ().has_bb());
 
   EXPECT_TRUE(message.has_optional_nested_enum ());
   EXPECT_TRUE(message.has_optional_foreign_enum());
@@ -232,10 +241,12 @@
   EXPECT_EQ("115", message.optional_string  ());
   EXPECT_EQ("116", message.optional_bytes   ());
 
-  EXPECT_EQ(117, message.optionalgroup           ().a());
-  EXPECT_EQ(118, message.optional_nested_message ().bb());
-  EXPECT_EQ(119, message.optional_foreign_message().c());
-  EXPECT_EQ(120, message.optional_import_message ().d());
+  EXPECT_EQ(117, message.optionalgroup                 ().a());
+  EXPECT_EQ(118, message.optional_nested_message       ().bb());
+  EXPECT_EQ(119, message.optional_foreign_message      ().c());
+  EXPECT_EQ(120, message.optional_import_message       ().d());
+  EXPECT_EQ(126, message.optional_public_import_message().e());
+  EXPECT_EQ(127, message.optional_lazy_message         ().bb());
 
   EXPECT_EQ(unittest::TestAllTypesLite::BAZ , message.optional_nested_enum ());
   EXPECT_EQ(unittest::FOREIGN_LITE_BAZ      , message.optional_foreign_enum());
@@ -264,6 +275,7 @@
   ASSERT_EQ(2, message.repeated_nested_message_size ());
   ASSERT_EQ(2, message.repeated_foreign_message_size());
   ASSERT_EQ(2, message.repeated_import_message_size ());
+  ASSERT_EQ(2, message.repeated_lazy_message_size   ());
   ASSERT_EQ(2, message.repeated_nested_enum_size    ());
   ASSERT_EQ(2, message.repeated_foreign_enum_size   ());
   ASSERT_EQ(2, message.repeated_import_enum_size    ());
@@ -289,6 +301,7 @@
   EXPECT_EQ(218, message.repeated_nested_message (0).bb());
   EXPECT_EQ(219, message.repeated_foreign_message(0).c());
   EXPECT_EQ(220, message.repeated_import_message (0).d());
+  EXPECT_EQ(227, message.repeated_lazy_message   (0).bb());
 
 
   EXPECT_EQ(unittest::TestAllTypesLite::BAR , message.repeated_nested_enum (0));
@@ -315,6 +328,7 @@
   EXPECT_EQ(318, message.repeated_nested_message (1).bb());
   EXPECT_EQ(319, message.repeated_foreign_message(1).c());
   EXPECT_EQ(320, message.repeated_import_message (1).d());
+  EXPECT_EQ(327, message.repeated_lazy_message   (1).bb());
 
   EXPECT_EQ(unittest::TestAllTypesLite::BAZ , message.repeated_nested_enum (1));
   EXPECT_EQ(unittest::FOREIGN_LITE_BAZ      , message.repeated_foreign_enum(1));
@@ -386,10 +400,12 @@
   EXPECT_FALSE(message.has_optional_string  ());
   EXPECT_FALSE(message.has_optional_bytes   ());
 
-  EXPECT_FALSE(message.has_optionalgroup           ());
-  EXPECT_FALSE(message.has_optional_nested_message ());
-  EXPECT_FALSE(message.has_optional_foreign_message());
-  EXPECT_FALSE(message.has_optional_import_message ());
+  EXPECT_FALSE(message.has_optionalgroup                 ());
+  EXPECT_FALSE(message.has_optional_nested_message       ());
+  EXPECT_FALSE(message.has_optional_foreign_message      ());
+  EXPECT_FALSE(message.has_optional_import_message       ());
+  EXPECT_FALSE(message.has_optional_public_import_message());
+  EXPECT_FALSE(message.has_optional_lazy_message         ());
 
   EXPECT_FALSE(message.has_optional_nested_enum ());
   EXPECT_FALSE(message.has_optional_foreign_enum());
@@ -414,10 +430,12 @@
   EXPECT_EQ(""   , message.optional_bytes   ());
 
   // Embedded messages should also be clear.
-  EXPECT_FALSE(message.optionalgroup           ().has_a());
-  EXPECT_FALSE(message.optional_nested_message ().has_bb());
-  EXPECT_FALSE(message.optional_foreign_message().has_c());
-  EXPECT_FALSE(message.optional_import_message ().has_d());
+  EXPECT_FALSE(message.optionalgroup                 ().has_a());
+  EXPECT_FALSE(message.optional_nested_message       ().has_bb());
+  EXPECT_FALSE(message.optional_foreign_message      ().has_c());
+  EXPECT_FALSE(message.optional_import_message       ().has_d());
+  EXPECT_FALSE(message.optional_public_import_message().has_e());
+  EXPECT_FALSE(message.optional_lazy_message         ().has_bb());
 
   EXPECT_EQ(0, message.optionalgroup           ().a());
   EXPECT_EQ(0, message.optional_nested_message ().bb());
@@ -451,6 +469,7 @@
   EXPECT_EQ(0, message.repeated_nested_message_size ());
   EXPECT_EQ(0, message.repeated_foreign_message_size());
   EXPECT_EQ(0, message.repeated_import_message_size ());
+  EXPECT_EQ(0, message.repeated_lazy_message_size   ());
   EXPECT_EQ(0, message.repeated_nested_enum_size    ());
   EXPECT_EQ(0, message.repeated_foreign_enum_size   ());
   EXPECT_EQ(0, message.repeated_import_enum_size    ());
@@ -528,6 +547,7 @@
   ASSERT_EQ(2, message.repeated_nested_message_size ());
   ASSERT_EQ(2, message.repeated_foreign_message_size());
   ASSERT_EQ(2, message.repeated_import_message_size ());
+  ASSERT_EQ(2, message.repeated_lazy_message_size   ());
   ASSERT_EQ(2, message.repeated_nested_enum_size    ());
   ASSERT_EQ(2, message.repeated_foreign_enum_size   ());
   ASSERT_EQ(2, message.repeated_import_enum_size    ());
@@ -553,6 +573,7 @@
   EXPECT_EQ(218, message.repeated_nested_message (0).bb());
   EXPECT_EQ(219, message.repeated_foreign_message(0).c());
   EXPECT_EQ(220, message.repeated_import_message (0).d());
+  EXPECT_EQ(227, message.repeated_lazy_message   (0).bb());
 
   EXPECT_EQ(unittest::TestAllTypesLite::BAR , message.repeated_nested_enum (0));
   EXPECT_EQ(unittest::FOREIGN_LITE_BAR      , message.repeated_foreign_enum(0));
@@ -580,6 +601,7 @@
   EXPECT_EQ(518, message.repeated_nested_message (1).bb());
   EXPECT_EQ(519, message.repeated_foreign_message(1).c());
   EXPECT_EQ(520, message.repeated_import_message (1).d());
+  EXPECT_EQ(527, message.repeated_lazy_message   (1).bb());
 
   EXPECT_EQ(unittest::TestAllTypesLite::FOO , message.repeated_nested_enum (1));
   EXPECT_EQ(unittest::FOREIGN_LITE_FOO      , message.repeated_foreign_enum(1));
@@ -787,10 +809,12 @@
   message->SetExtension(unittest::optional_string_extension_lite  , "115");
   message->SetExtension(unittest::optional_bytes_extension_lite   , "116");
 
-  message->MutableExtension(unittest::optionalgroup_extension_lite           )->set_a(117);
-  message->MutableExtension(unittest::optional_nested_message_extension_lite )->set_bb(118);
-  message->MutableExtension(unittest::optional_foreign_message_extension_lite)->set_c(119);
-  message->MutableExtension(unittest::optional_import_message_extension_lite )->set_d(120);
+  message->MutableExtension(unittest::optionalgroup_extension_lite                 )->set_a(117);
+  message->MutableExtension(unittest::optional_nested_message_extension_lite       )->set_bb(118);
+  message->MutableExtension(unittest::optional_foreign_message_extension_lite      )->set_c(119);
+  message->MutableExtension(unittest::optional_import_message_extension_lite       )->set_d(120);
+  message->MutableExtension(unittest::optional_public_import_message_extension_lite)->set_e(126);
+  message->MutableExtension(unittest::optional_lazy_message_extension_lite         )->set_bb(127);
 
   message->SetExtension(unittest::optional_nested_enum_extension_lite , unittest::TestAllTypesLite::BAZ );
   message->SetExtension(unittest::optional_foreign_enum_extension_lite, unittest::FOREIGN_LITE_BAZ      );
@@ -819,6 +843,7 @@
   message->AddExtension(unittest::repeated_nested_message_extension_lite )->set_bb(218);
   message->AddExtension(unittest::repeated_foreign_message_extension_lite)->set_c(219);
   message->AddExtension(unittest::repeated_import_message_extension_lite )->set_d(220);
+  message->AddExtension(unittest::repeated_lazy_message_extension_lite   )->set_bb(227);
 
   message->AddExtension(unittest::repeated_nested_enum_extension_lite , unittest::TestAllTypesLite::BAR );
   message->AddExtension(unittest::repeated_foreign_enum_extension_lite, unittest::FOREIGN_LITE_BAR      );
@@ -846,6 +871,7 @@
   message->AddExtension(unittest::repeated_nested_message_extension_lite )->set_bb(318);
   message->AddExtension(unittest::repeated_foreign_message_extension_lite)->set_c(319);
   message->AddExtension(unittest::repeated_import_message_extension_lite )->set_d(320);
+  message->AddExtension(unittest::repeated_lazy_message_extension_lite   )->set_bb(327);
 
   message->AddExtension(unittest::repeated_nested_enum_extension_lite , unittest::TestAllTypesLite::BAZ );
   message->AddExtension(unittest::repeated_foreign_enum_extension_lite, unittest::FOREIGN_LITE_BAZ      );
@@ -900,6 +926,7 @@
   message->MutableExtension(unittest::repeated_nested_message_extension_lite , 1)->set_bb(518);
   message->MutableExtension(unittest::repeated_foreign_message_extension_lite, 1)->set_c(519);
   message->MutableExtension(unittest::repeated_import_message_extension_lite , 1)->set_d(520);
+  message->MutableExtension(unittest::repeated_lazy_message_extension_lite   , 1)->set_bb(527);
 
   message->SetExtension(unittest::repeated_nested_enum_extension_lite , 1, unittest::TestAllTypesLite::FOO );
   message->SetExtension(unittest::repeated_foreign_enum_extension_lite, 1, unittest::FOREIGN_LITE_FOO      );
@@ -927,15 +954,19 @@
   EXPECT_TRUE(message.HasExtension(unittest::optional_string_extension_lite  ));
   EXPECT_TRUE(message.HasExtension(unittest::optional_bytes_extension_lite   ));
 
-  EXPECT_TRUE(message.HasExtension(unittest::optionalgroup_extension_lite           ));
-  EXPECT_TRUE(message.HasExtension(unittest::optional_nested_message_extension_lite ));
-  EXPECT_TRUE(message.HasExtension(unittest::optional_foreign_message_extension_lite));
-  EXPECT_TRUE(message.HasExtension(unittest::optional_import_message_extension_lite ));
+  EXPECT_TRUE(message.HasExtension(unittest::optionalgroup_extension_lite                 ));
+  EXPECT_TRUE(message.HasExtension(unittest::optional_nested_message_extension_lite       ));
+  EXPECT_TRUE(message.HasExtension(unittest::optional_foreign_message_extension_lite      ));
+  EXPECT_TRUE(message.HasExtension(unittest::optional_import_message_extension_lite       ));
+  EXPECT_TRUE(message.HasExtension(unittest::optional_public_import_message_extension_lite));
+  EXPECT_TRUE(message.HasExtension(unittest::optional_lazy_message_extension_lite         ));
 
-  EXPECT_TRUE(message.GetExtension(unittest::optionalgroup_extension_lite           ).has_a());
-  EXPECT_TRUE(message.GetExtension(unittest::optional_nested_message_extension_lite ).has_bb());
-  EXPECT_TRUE(message.GetExtension(unittest::optional_foreign_message_extension_lite).has_c());
-  EXPECT_TRUE(message.GetExtension(unittest::optional_import_message_extension_lite ).has_d());
+  EXPECT_TRUE(message.GetExtension(unittest::optionalgroup_extension_lite                 ).has_a());
+  EXPECT_TRUE(message.GetExtension(unittest::optional_nested_message_extension_lite       ).has_bb());
+  EXPECT_TRUE(message.GetExtension(unittest::optional_foreign_message_extension_lite      ).has_c());
+  EXPECT_TRUE(message.GetExtension(unittest::optional_import_message_extension_lite       ).has_d());
+  EXPECT_TRUE(message.GetExtension(unittest::optional_public_import_message_extension_lite).has_e());
+  EXPECT_TRUE(message.GetExtension(unittest::optional_lazy_message_extension_lite         ).has_bb());
 
   EXPECT_TRUE(message.HasExtension(unittest::optional_nested_enum_extension_lite ));
   EXPECT_TRUE(message.HasExtension(unittest::optional_foreign_enum_extension_lite));
@@ -958,10 +989,12 @@
   EXPECT_EQ("115", message.GetExtension(unittest::optional_string_extension_lite  ));
   EXPECT_EQ("116", message.GetExtension(unittest::optional_bytes_extension_lite   ));
 
-  EXPECT_EQ(117, message.GetExtension(unittest::optionalgroup_extension_lite           ).a());
-  EXPECT_EQ(118, message.GetExtension(unittest::optional_nested_message_extension_lite ).bb());
-  EXPECT_EQ(119, message.GetExtension(unittest::optional_foreign_message_extension_lite).c());
-  EXPECT_EQ(120, message.GetExtension(unittest::optional_import_message_extension_lite ).d());
+  EXPECT_EQ(117, message.GetExtension(unittest::optionalgroup_extension_lite                 ).a());
+  EXPECT_EQ(118, message.GetExtension(unittest::optional_nested_message_extension_lite       ).bb());
+  EXPECT_EQ(119, message.GetExtension(unittest::optional_foreign_message_extension_lite      ).c());
+  EXPECT_EQ(120, message.GetExtension(unittest::optional_import_message_extension_lite       ).d());
+  EXPECT_EQ(126, message.GetExtension(unittest::optional_public_import_message_extension_lite).e());
+  EXPECT_EQ(127, message.GetExtension(unittest::optional_lazy_message_extension_lite         ).bb());
 
   EXPECT_EQ(unittest::TestAllTypesLite::BAZ , message.GetExtension(unittest::optional_nested_enum_extension_lite ));
   EXPECT_EQ(unittest::FOREIGN_LITE_BAZ      , message.GetExtension(unittest::optional_foreign_enum_extension_lite));
@@ -990,6 +1023,7 @@
   ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_nested_message_extension_lite ));
   ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_foreign_message_extension_lite));
   ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_import_message_extension_lite ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_lazy_message_extension_lite   ));
   ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_nested_enum_extension_lite    ));
   ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_foreign_enum_extension_lite   ));
   ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_import_enum_extension_lite    ));
@@ -1015,6 +1049,7 @@
   EXPECT_EQ(218, message.GetExtension(unittest::repeated_nested_message_extension_lite , 0).bb());
   EXPECT_EQ(219, message.GetExtension(unittest::repeated_foreign_message_extension_lite, 0).c());
   EXPECT_EQ(220, message.GetExtension(unittest::repeated_import_message_extension_lite , 0).d());
+  EXPECT_EQ(227, message.GetExtension(unittest::repeated_lazy_message_extension_lite   , 0).bb());
 
   EXPECT_EQ(unittest::TestAllTypesLite::BAR , message.GetExtension(unittest::repeated_nested_enum_extension_lite , 0));
   EXPECT_EQ(unittest::FOREIGN_LITE_BAR      , message.GetExtension(unittest::repeated_foreign_enum_extension_lite, 0));
@@ -1041,6 +1076,7 @@
   EXPECT_EQ(318, message.GetExtension(unittest::repeated_nested_message_extension_lite , 1).bb());
   EXPECT_EQ(319, message.GetExtension(unittest::repeated_foreign_message_extension_lite, 1).c());
   EXPECT_EQ(320, message.GetExtension(unittest::repeated_import_message_extension_lite , 1).d());
+  EXPECT_EQ(327, message.GetExtension(unittest::repeated_lazy_message_extension_lite   , 1).bb());
 
   EXPECT_EQ(unittest::TestAllTypesLite::BAZ , message.GetExtension(unittest::repeated_nested_enum_extension_lite , 1));
   EXPECT_EQ(unittest::FOREIGN_LITE_BAZ      , message.GetExtension(unittest::repeated_foreign_enum_extension_lite, 1));
@@ -1118,10 +1154,12 @@
   EXPECT_FALSE(message.HasExtension(unittest::optional_string_extension_lite  ));
   EXPECT_FALSE(message.HasExtension(unittest::optional_bytes_extension_lite   ));
 
-  EXPECT_FALSE(message.HasExtension(unittest::optionalgroup_extension_lite           ));
-  EXPECT_FALSE(message.HasExtension(unittest::optional_nested_message_extension_lite ));
-  EXPECT_FALSE(message.HasExtension(unittest::optional_foreign_message_extension_lite));
-  EXPECT_FALSE(message.HasExtension(unittest::optional_import_message_extension_lite ));
+  EXPECT_FALSE(message.HasExtension(unittest::optionalgroup_extension_lite                 ));
+  EXPECT_FALSE(message.HasExtension(unittest::optional_nested_message_extension_lite       ));
+  EXPECT_FALSE(message.HasExtension(unittest::optional_foreign_message_extension_lite      ));
+  EXPECT_FALSE(message.HasExtension(unittest::optional_import_message_extension_lite       ));
+  EXPECT_FALSE(message.HasExtension(unittest::optional_public_import_message_extension_lite));
+  EXPECT_FALSE(message.HasExtension(unittest::optional_lazy_message_extension_lite         ));
 
   EXPECT_FALSE(message.HasExtension(unittest::optional_nested_enum_extension_lite ));
   EXPECT_FALSE(message.HasExtension(unittest::optional_foreign_enum_extension_lite));
@@ -1146,15 +1184,19 @@
   EXPECT_EQ(""   , message.GetExtension(unittest::optional_bytes_extension_lite   ));
 
   // Embedded messages should also be clear.
-  EXPECT_FALSE(message.GetExtension(unittest::optionalgroup_extension_lite           ).has_a());
-  EXPECT_FALSE(message.GetExtension(unittest::optional_nested_message_extension_lite ).has_bb());
-  EXPECT_FALSE(message.GetExtension(unittest::optional_foreign_message_extension_lite).has_c());
-  EXPECT_FALSE(message.GetExtension(unittest::optional_import_message_extension_lite ).has_d());
+  EXPECT_FALSE(message.GetExtension(unittest::optionalgroup_extension_lite                 ).has_a());
+  EXPECT_FALSE(message.GetExtension(unittest::optional_nested_message_extension_lite       ).has_bb());
+  EXPECT_FALSE(message.GetExtension(unittest::optional_foreign_message_extension_lite      ).has_c());
+  EXPECT_FALSE(message.GetExtension(unittest::optional_import_message_extension_lite       ).has_d());
+  EXPECT_FALSE(message.GetExtension(unittest::optional_public_import_message_extension_lite).has_e());
+  EXPECT_FALSE(message.GetExtension(unittest::optional_lazy_message_extension_lite         ).has_bb());
 
-  EXPECT_EQ(0, message.GetExtension(unittest::optionalgroup_extension_lite           ).a());
-  EXPECT_EQ(0, message.GetExtension(unittest::optional_nested_message_extension_lite ).bb());
-  EXPECT_EQ(0, message.GetExtension(unittest::optional_foreign_message_extension_lite).c());
-  EXPECT_EQ(0, message.GetExtension(unittest::optional_import_message_extension_lite ).d());
+  EXPECT_EQ(0, message.GetExtension(unittest::optionalgroup_extension_lite                 ).a());
+  EXPECT_EQ(0, message.GetExtension(unittest::optional_nested_message_extension_lite       ).bb());
+  EXPECT_EQ(0, message.GetExtension(unittest::optional_foreign_message_extension_lite      ).c());
+  EXPECT_EQ(0, message.GetExtension(unittest::optional_import_message_extension_lite       ).d());
+  EXPECT_EQ(0, message.GetExtension(unittest::optional_public_import_message_extension_lite).e());
+  EXPECT_EQ(0, message.GetExtension(unittest::optional_lazy_message_extension_lite         ).bb());
 
   // Enums without defaults are set to the first value in the enum.
   EXPECT_EQ(unittest::TestAllTypesLite::FOO , message.GetExtension(unittest::optional_nested_enum_extension_lite ));
@@ -1183,6 +1225,7 @@
   EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_nested_message_extension_lite ));
   EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_foreign_message_extension_lite));
   EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_import_message_extension_lite ));
+  EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_lazy_message_extension_lite   ));
   EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_nested_enum_extension_lite    ));
   EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_foreign_enum_extension_lite   ));
   EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_import_enum_extension_lite    ));
@@ -1260,6 +1303,7 @@
   ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_nested_message_extension_lite ));
   ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_foreign_message_extension_lite));
   ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_import_message_extension_lite ));
+  ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_lazy_message_extension_lite   ));
   ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_nested_enum_extension_lite    ));
   ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_foreign_enum_extension_lite   ));
   ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_import_enum_extension_lite    ));
@@ -1285,6 +1329,7 @@
   EXPECT_EQ(218, message.GetExtension(unittest::repeated_nested_message_extension_lite , 0).bb());
   EXPECT_EQ(219, message.GetExtension(unittest::repeated_foreign_message_extension_lite, 0).c());
   EXPECT_EQ(220, message.GetExtension(unittest::repeated_import_message_extension_lite , 0).d());
+  EXPECT_EQ(227, message.GetExtension(unittest::repeated_lazy_message_extension_lite   , 0).bb());
 
   EXPECT_EQ(unittest::TestAllTypesLite::BAR , message.GetExtension(unittest::repeated_nested_enum_extension_lite , 0));
   EXPECT_EQ(unittest::FOREIGN_LITE_BAR      , message.GetExtension(unittest::repeated_foreign_enum_extension_lite, 0));
@@ -1312,6 +1357,7 @@
   EXPECT_EQ(518, message.GetExtension(unittest::repeated_nested_message_extension_lite , 1).bb());
   EXPECT_EQ(519, message.GetExtension(unittest::repeated_foreign_message_extension_lite, 1).c());
   EXPECT_EQ(520, message.GetExtension(unittest::repeated_import_message_extension_lite , 1).d());
+  EXPECT_EQ(527, message.GetExtension(unittest::repeated_lazy_message_extension_lite   , 1).bb());
 
   EXPECT_EQ(unittest::TestAllTypesLite::FOO , message.GetExtension(unittest::repeated_nested_enum_extension_lite , 1));
   EXPECT_EQ(unittest::FOREIGN_LITE_FOO      , message.GetExtension(unittest::repeated_foreign_enum_extension_lite, 1));
diff --git a/third_party/protobuf/src/google/protobuf/testdata/text_format_unittest_data.txt b/third_party/protobuf/src/google/protobuf/testdata/text_format_unittest_data.txt
index feea8f7..bbe5882 100644
--- a/third_party/protobuf/src/google/protobuf/testdata/text_format_unittest_data.txt
+++ b/third_party/protobuf/src/google/protobuf/testdata/text_format_unittest_data.txt
@@ -30,6 +30,12 @@
 optional_import_enum: IMPORT_BAZ
 optional_string_piece: "124"
 optional_cord: "125"
+optional_public_import_message {
+  e: 126
+}
+optional_lazy_message {
+  bb: 127
+}
 repeated_int32: 201
 repeated_int32: 301
 repeated_int64: 202
@@ -94,6 +100,12 @@
 repeated_string_piece: "324"
 repeated_cord: "225"
 repeated_cord: "325"
+repeated_lazy_message {
+  bb: 227
+}
+repeated_lazy_message {
+  bb: 327
+}
 default_int32: 401
 default_int64: 402
 default_uint32: 403
diff --git a/third_party/protobuf/src/google/protobuf/testdata/text_format_unittest_extensions_data.txt b/third_party/protobuf/src/google/protobuf/testdata/text_format_unittest_extensions_data.txt
index 057beae..0a217f0 100644
--- a/third_party/protobuf/src/google/protobuf/testdata/text_format_unittest_extensions_data.txt
+++ b/third_party/protobuf/src/google/protobuf/testdata/text_format_unittest_extensions_data.txt
@@ -30,6 +30,12 @@
 [protobuf_unittest.optional_import_enum_extension]: IMPORT_BAZ
 [protobuf_unittest.optional_string_piece_extension]: "124"
 [protobuf_unittest.optional_cord_extension]: "125"
+[protobuf_unittest.optional_public_import_message_extension] {
+  e: 126
+}
+[protobuf_unittest.optional_lazy_message_extension] {
+  bb: 127
+}
 [protobuf_unittest.repeated_int32_extension]: 201
 [protobuf_unittest.repeated_int32_extension]: 301
 [protobuf_unittest.repeated_int64_extension]: 202
@@ -94,6 +100,12 @@
 [protobuf_unittest.repeated_string_piece_extension]: "324"
 [protobuf_unittest.repeated_cord_extension]: "225"
 [protobuf_unittest.repeated_cord_extension]: "325"
+[protobuf_unittest.repeated_lazy_message_extension] {
+  bb: 227
+}
+[protobuf_unittest.repeated_lazy_message_extension] {
+  bb: 327
+}
 [protobuf_unittest.default_int32_extension]: 401
 [protobuf_unittest.default_int64_extension]: 402
 [protobuf_unittest.default_uint32_extension]: 403
diff --git a/third_party/protobuf/src/google/protobuf/testing/googletest.cc b/third_party/protobuf/src/google/protobuf/testing/googletest.cc
index cd094d0..a8da6b1 100644
--- a/third_party/protobuf/src/google/protobuf/testing/googletest.cc
+++ b/third_party/protobuf/src/google/protobuf/testing/googletest.cc
@@ -223,16 +223,17 @@
   active_log_ = NULL;
 }
 
-const vector<string>& ScopedMemoryLog::GetMessages(LogLevel dummy) const {
-  GOOGLE_CHECK_EQ(dummy, ERROR);
-  return messages_;
+const vector<string>& ScopedMemoryLog::GetMessages(LogLevel level) {
+  GOOGLE_CHECK(level == ERROR ||
+               level == WARNING);
+  return messages_[level];
 }
 
 void ScopedMemoryLog::HandleLog(LogLevel level, const char* filename,
                                 int line, const string& message) {
   GOOGLE_CHECK(active_log_ != NULL);
-  if (level == ERROR) {
-    active_log_->messages_.push_back(message);
+  if (level == ERROR || level == WARNING) {
+    active_log_->messages_[level].push_back(message);
   }
 }
 
diff --git a/third_party/protobuf/src/google/protobuf/testing/googletest.h b/third_party/protobuf/src/google/protobuf/testing/googletest.h
index 71444c9..6b17ae4 100644
--- a/third_party/protobuf/src/google/protobuf/testing/googletest.h
+++ b/third_party/protobuf/src/google/protobuf/testing/googletest.h
@@ -34,6 +34,7 @@
 #ifndef GOOGLE_PROTOBUF_GOOGLETEST_H__
 #define GOOGLE_PROTOBUF_GOOGLETEST_H__
 
+#include <map>
 #include <vector>
 #include <google/protobuf/stubs/common.h>
 
@@ -60,6 +61,7 @@
 // ScopedMemoryLog refers to LOGLEVEL_ERROR as just ERROR.
 #undef ERROR  // defend against promiscuous windows.h
 static const LogLevel ERROR = LOGLEVEL_ERROR;
+static const LogLevel WARNING = LOGLEVEL_WARNING;
 
 // Receives copies of all LOG(ERROR) messages while in scope.  Sample usage:
 //   {
@@ -74,14 +76,11 @@
   ScopedMemoryLog();
   virtual ~ScopedMemoryLog();
 
-  // Fetches all messages logged.  The internal version of this class
-  // would only fetch messages at the given security level, but the protobuf
-  // open source version ignores the argument since we always pass ERROR
-  // anyway.
-  const vector<string>& GetMessages(LogLevel dummy) const;
+  // Fetches all messages with the given severity level.
+  const vector<string>& GetMessages(LogLevel error);
 
  private:
-  vector<string> messages_;
+  map<LogLevel, vector<string> > messages_;
   LogHandler* old_handler_;
 
   static void HandleLog(LogLevel level, const char* filename, int line,
diff --git a/third_party/protobuf/src/google/protobuf/text_format.cc b/third_party/protobuf/src/google/protobuf/text_format.cc
index 1494ebd..1ee3df5 100644
--- a/third_party/protobuf/src/google/protobuf/text_format.cc
+++ b/third_party/protobuf/src/google/protobuf/text_format.cc
@@ -49,6 +49,8 @@
 #include <google/protobuf/descriptor.pb.h>
 #include <google/protobuf/io/tokenizer.h>
 #include <google/protobuf/stubs/strutil.h>
+#include <google/protobuf/stubs/map-util.h>
+#include <google/protobuf/stubs/stl_util.h>
 
 namespace google {
 namespace protobuf {
@@ -94,6 +96,73 @@
 
 
 // ===========================================================================
+// Implementation of the parse information tree class.
+TextFormat::ParseInfoTree::ParseInfoTree() { }
+
+TextFormat::ParseInfoTree::~ParseInfoTree() {
+  // Remove any nested information trees, as they are owned by this tree.
+  for (NestedMap::iterator it = nested_.begin(); it != nested_.end(); ++it) {
+    STLDeleteElements(&(it->second));
+  }
+}
+
+void TextFormat::ParseInfoTree::RecordLocation(
+    const FieldDescriptor* field,
+    TextFormat::ParseLocation location) {
+  locations_[field].push_back(location);
+}
+
+TextFormat::ParseInfoTree* TextFormat::ParseInfoTree::CreateNested(
+    const FieldDescriptor* field) {
+  // Owned by us in the map.
+  TextFormat::ParseInfoTree* instance = new TextFormat::ParseInfoTree();
+  vector<TextFormat::ParseInfoTree*>* trees = &nested_[field];
+  GOOGLE_CHECK(trees);
+  trees->push_back(instance);
+  return instance;
+}
+
+void CheckFieldIndex(const FieldDescriptor* field, int index) {
+  if (field == NULL) { return; }
+
+  if (field->is_repeated() && index == -1) {
+    GOOGLE_LOG(DFATAL) << "Index must be in range of repeated field values. "
+                << "Field: " << field->name();
+  } else if (!field->is_repeated() && index != -1) {
+    GOOGLE_LOG(DFATAL) << "Index must be -1 for singular fields."
+                << "Field: " << field->name();
+  }
+}
+
+TextFormat::ParseLocation TextFormat::ParseInfoTree::GetLocation(
+    const FieldDescriptor* field, int index) const {
+  CheckFieldIndex(field, index);
+  if (index == -1) { index = 0; }
+
+  const vector<TextFormat::ParseLocation>* locations =
+      FindOrNull(locations_, field);
+  if (locations == NULL || index >= locations->size()) {
+    return TextFormat::ParseLocation();
+  }
+
+  return (*locations)[index];
+}
+
+TextFormat::ParseInfoTree* TextFormat::ParseInfoTree::GetTreeForNested(
+    const FieldDescriptor* field, int index) const {
+  CheckFieldIndex(field, index);
+  if (index == -1) { index = 0; }
+
+  const vector<TextFormat::ParseInfoTree*>* trees = FindOrNull(nested_, field);
+  if (trees == NULL || index >= trees->size()) {
+    return NULL;
+  }
+
+  return (*trees)[index];
+}
+
+
+// ===========================================================================
 // Internal class for parsing an ASCII representation of a Protocol Message.
 // This class makes use of the Protocol Message compiler's tokenizer found
 // in //google/protobuf/io/tokenizer.h. Note that class's Parse
@@ -120,13 +189,17 @@
              io::ZeroCopyInputStream* input_stream,
              io::ErrorCollector* error_collector,
              TextFormat::Finder* finder,
-             SingularOverwritePolicy singular_overwrite_policy)
+             ParseInfoTree* parse_info_tree,
+             SingularOverwritePolicy singular_overwrite_policy,
+             bool allow_unknown_field)
     : error_collector_(error_collector),
       finder_(finder),
+      parse_info_tree_(parse_info_tree),
       tokenizer_error_collector_(this),
       tokenizer_(input_stream, &tokenizer_error_collector_),
       root_message_type_(root_message_type),
       singular_overwrite_policy_(singular_overwrite_policy),
+      allow_unknown_field_(allow_unknown_field),
       had_errors_(false) {
     // For backwards-compatibility with proto1, we need to allow the 'f' suffix
     // for floats.
@@ -240,6 +313,8 @@
     string field_name;
 
     const FieldDescriptor* field = NULL;
+    int start_line = tokenizer_.current().line;
+    int start_column = tokenizer_.current().column;
 
     if (TryConsume("[")) {
       // Extension.
@@ -257,10 +332,16 @@
                : reflection->FindKnownExtensionByName(field_name));
 
       if (field == NULL) {
-        ReportError("Extension \"" + field_name + "\" is not defined or "
-                    "is not an extension of \"" +
-                    descriptor->full_name() + "\".");
-        return false;
+        if (!allow_unknown_field_) {
+          ReportError("Extension \"" + field_name + "\" is not defined or "
+                      "is not an extension of \"" +
+                      descriptor->full_name() + "\".");
+          return false;
+        } else {
+          ReportWarning("Extension \"" + field_name + "\" is not defined or "
+                        "is not an extension of \"" +
+                        descriptor->full_name() + "\".");
+        }
       }
     } else {
       DO(ConsumeIdentifier(&field_name));
@@ -285,9 +366,30 @@
       }
 
       if (field == NULL) {
-        ReportError("Message type \"" + descriptor->full_name() +
-                    "\" has no field named \"" + field_name + "\".");
-        return false;
+        if (!allow_unknown_field_) {
+          ReportError("Message type \"" + descriptor->full_name() +
+                      "\" has no field named \"" + field_name + "\".");
+          return false;
+        } else {
+          ReportWarning("Message type \"" + descriptor->full_name() +
+                        "\" has no field named \"" + field_name + "\".");
+        }
+      }
+    }
+
+    // Skips unknown field.
+    if (field == NULL) {
+      GOOGLE_CHECK(allow_unknown_field_);
+      // Try to guess the type of this field.
+      // If this field is not a message, there should be a ":" between the
+      // field name and the field value and also the field value should not
+      // start with "{" or "<" which indicates the begining of a message body.
+      // If there is no ":" or there is a "{" or "<" after ":", this field has
+      // to be a message or the input is ill-formed.
+      if (TryConsume(":") && !LookingAt("{") && !LookingAt("<")) {
+        return SkipFieldValue();
+      } else {
+        return SkipFieldMessage();
       }
     }
 
@@ -329,12 +431,61 @@
                     + field_name + "\"");
     }
 
+    // If a parse info tree exists, add the location for the parsed
+    // field.
+    if (parse_info_tree_ != NULL) {
+      parse_info_tree_->RecordLocation(field,
+                                       ParseLocation(start_line, start_column));
+    }
+
+    return true;
+  }
+
+  // Skips the next field including the field's name and value.
+  bool SkipField() {
+    string field_name;
+    if (TryConsume("[")) {
+      // Extension name.
+      DO(ConsumeIdentifier(&field_name));
+      while (TryConsume(".")) {
+        string part;
+        DO(ConsumeIdentifier(&part));
+        field_name += ".";
+        field_name += part;
+      }
+      DO(Consume("]"));
+    } else {
+      DO(ConsumeIdentifier(&field_name));
+    }
+
+    // Try to guess the type of this field.
+    // If this field is not a message, there should be a ":" between the
+    // field name and the field value and also the field value should not
+    // start with "{" or "<" which indicates the begining of a message body.
+    // If there is no ":" or there is a "{" or "<" after ":", this field has
+    // to be a message or the input is ill-formed.
+    if (TryConsume(":") && !LookingAt("{") && !LookingAt("<")) {
+      DO(SkipFieldValue());
+    } else {
+      DO(SkipFieldMessage());
+    }
+    // For historical reasons, fields may optionally be separated by commas or
+    // semicolons.
+    TryConsume(";") || TryConsume(",");
     return true;
   }
 
   bool ConsumeFieldMessage(Message* message,
                            const Reflection* reflection,
                            const FieldDescriptor* field) {
+
+    // If the parse information tree is not NULL, create a nested one
+    // for the nested message.
+    ParseInfoTree* parent = parse_info_tree_;
+    if (parent != NULL) {
+      parse_info_tree_ = parent->CreateNested(field);
+    }
+
     string delimeter;
     if (TryConsume("<")) {
       delimeter = ">";
@@ -349,6 +500,26 @@
       DO(ConsumeMessage(reflection->MutableMessage(message, field),
                         delimeter));
     }
+
+    // Reset the parse information tree.
+    parse_info_tree_ = parent;
+    return true;
+  }
+
+  // Skips the whole body of a message including the begining delimeter and
+  // the ending delimeter.
+  bool SkipFieldMessage() {
+    string delimeter;
+    if (TryConsume("<")) {
+      delimeter = ">";
+    } else {
+      DO(Consume("{"));
+      delimeter = "}";
+    }
+    while (!LookingAt(">") &&  !LookingAt("}")) {
+      DO(SkipField());
+    }
+    DO(Consume(delimeter));
     return true;
   }
 
@@ -479,6 +650,60 @@
     return true;
   }
 
+  bool SkipFieldValue() {
+    if (LookingAtType(io::Tokenizer::TYPE_STRING)) {
+      while (LookingAtType(io::Tokenizer::TYPE_STRING)) {
+        tokenizer_.Next();
+      }
+      return true;
+    }
+    // Possible field values other than string:
+    //   12345        => TYPE_INTEGER
+    //   -12345       => TYPE_SYMBOL + TYPE_INTEGER
+    //   1.2345       => TYPE_FLOAT
+    //   -1.2345      => TYPE_SYMBOL + TYPE_FLOAT
+    //   inf          => TYPE_IDENTIFIER
+    //   -inf         => TYPE_SYMBOL + TYPE_IDENTIFIER
+    //   TYPE_INTEGER => TYPE_IDENTIFIER
+    // Divides them into two group, one with TYPE_SYMBOL
+    // and the other without:
+    //   Group one:
+    //     12345        => TYPE_INTEGER
+    //     1.2345       => TYPE_FLOAT
+    //     inf          => TYPE_IDENTIFIER
+    //     TYPE_INTEGER => TYPE_IDENTIFIER
+    //   Group two:
+    //     -12345       => TYPE_SYMBOL + TYPE_INTEGER
+    //     -1.2345      => TYPE_SYMBOL + TYPE_FLOAT
+    //     -inf         => TYPE_SYMBOL + TYPE_IDENTIFIER
+    // As we can see, the field value consists of an optional '-' and one of
+    // TYPE_INTEGER, TYPE_FLOAT and TYPE_IDENTIFIER.
+    bool has_minus = TryConsume("-");
+    if (!LookingAtType(io::Tokenizer::TYPE_INTEGER) &&
+        !LookingAtType(io::Tokenizer::TYPE_FLOAT) &&
+        !LookingAtType(io::Tokenizer::TYPE_IDENTIFIER)) {
+      return false;
+    }
+    // Combination of '-' and TYPE_IDENTIFIER may result in an invalid field
+    // value while other combinations all generate valid values.
+    // We check if the value of this combination is valid here.
+    // TYPE_IDENTIFIER after a '-' should be one of the float values listed
+    // below:
+    //   inf, inff, infinity, nan
+    if (has_minus && LookingAtType(io::Tokenizer::TYPE_IDENTIFIER)) {
+      string text = tokenizer_.current().text;
+      LowerString(&text);
+      if (text != "inf" &&
+          text != "infinity" &&
+          text != "nan") {
+        ReportError("Invalid float number: " + text);
+        return false;
+      }
+    }
+    tokenizer_.Next();
+    return true;
+  }
+
   // Returns true if the current token's text is equal to that specified.
   bool LookingAt(const string& text) {
     return tokenizer_.current().text == text;
@@ -596,7 +821,8 @@
     } else if (LookingAtType(io::Tokenizer::TYPE_IDENTIFIER)) {
       string text = tokenizer_.current().text;
       LowerString(&text);
-      if (text == "inf" || text == "infinity") {
+      if (text == "inf" ||
+          text == "infinity") {
         *value = std::numeric_limits<double>::infinity();
         tokenizer_.Next();
       } else if (text == "nan") {
@@ -670,10 +896,12 @@
 
   io::ErrorCollector* error_collector_;
   TextFormat::Finder* finder_;
+  ParseInfoTree* parse_info_tree_;
   ParserErrorCollector tokenizer_error_collector_;
   io::Tokenizer tokenizer_;
   const Descriptor* root_message_type_;
   SingularOverwritePolicy singular_overwrite_policy_;
+  bool allow_unknown_field_;
   bool had_errors_;
 };
 
@@ -699,7 +927,7 @@
   ~TextGenerator() {
     // Only BackUp() if we're sure we've successfully called Next() at least
     // once.
-    if (buffer_size_ > 0) {
+    if (!failed_ && buffer_size_ > 0) {
       output_->BackUp(buffer_size_);
     }
   }
@@ -809,7 +1037,9 @@
 TextFormat::Parser::Parser()
   : error_collector_(NULL),
     finder_(NULL),
-    allow_partial_(false) {
+    parse_info_tree_(NULL),
+    allow_partial_(false),
+    allow_unknown_field_(false) {
 }
 
 TextFormat::Parser::~Parser() {}
@@ -818,7 +1048,9 @@
                                Message* output) {
   output->Clear();
   ParserImpl parser(output->GetDescriptor(), input, error_collector_,
-                    finder_, ParserImpl::FORBID_SINGULAR_OVERWRITES);
+                    finder_, parse_info_tree_,
+                    ParserImpl::FORBID_SINGULAR_OVERWRITES,
+                    allow_unknown_field_);
   return MergeUsingImpl(input, output, &parser);
 }
 
@@ -831,7 +1063,9 @@
 bool TextFormat::Parser::Merge(io::ZeroCopyInputStream* input,
                                Message* output) {
   ParserImpl parser(output->GetDescriptor(), input, error_collector_,
-                    finder_, ParserImpl::ALLOW_SINGULAR_OVERWRITES);
+                    finder_, parse_info_tree_,
+                    ParserImpl::ALLOW_SINGULAR_OVERWRITES,
+                    allow_unknown_field_);
   return MergeUsingImpl(input, output, &parser);
 }
 
@@ -861,7 +1095,9 @@
     Message* output) {
   io::ArrayInputStream input_stream(input.data(), input.size());
   ParserImpl parser(output->GetDescriptor(), &input_stream, error_collector_,
-                    finder_, ParserImpl::ALLOW_SINGULAR_OVERWRITES);
+                    finder_, parse_info_tree_,
+                    ParserImpl::ALLOW_SINGULAR_OVERWRITES,
+                    allow_unknown_field_);
   return parser.ParseField(field, output);
 }
 
diff --git a/third_party/protobuf/src/google/protobuf/text_format.h b/third_party/protobuf/src/google/protobuf/text_format.h
index 03c0491..0974139 100644
--- a/third_party/protobuf/src/google/protobuf/text_format.h
+++ b/third_party/protobuf/src/google/protobuf/text_format.h
@@ -38,7 +38,10 @@
 #ifndef GOOGLE_PROTOBUF_TEXT_FORMAT_H__
 #define GOOGLE_PROTOBUF_TEXT_FORMAT_H__
 
+#include <map>
 #include <string>
+#include <vector>
+#include <google/protobuf/stubs/common.h>
 #include <google/protobuf/message.h>
 #include <google/protobuf/descriptor.h>
 
@@ -220,6 +223,57 @@
         const string& name) const = 0;
   };
 
+  // A location in the parsed text.
+  struct ParseLocation {
+    int line;
+    int column;
+
+    ParseLocation() : line(-1), column(-1) {}
+    ParseLocation(int line_param, int column_param)
+        : line(line_param), column(column_param) {}
+  };
+
+  // Data structure which is populated with the locations of each field
+  // value parsed from the text.
+  class LIBPROTOBUF_EXPORT ParseInfoTree {
+   public:
+    ParseInfoTree();
+    ~ParseInfoTree();
+
+    // Returns the parse location for index-th value of the field in the parsed
+    // text. If none exists, returns a location with line = -1. Index should be
+    // -1 for not-repeated fields.
+    ParseLocation GetLocation(const FieldDescriptor* field, int index) const;
+
+    // Returns the parse info tree for the given field, which must be a message
+    // type. The nested information tree is owned by the root tree and will be
+    // deleted when it is deleted.
+    ParseInfoTree* GetTreeForNested(const FieldDescriptor* field,
+                                    int index) const;
+
+   private:
+    // Allow the text format parser to record information into the tree.
+    friend class TextFormat;
+
+    // Records the starting location of a single value for a field.
+    void RecordLocation(const FieldDescriptor* field, ParseLocation location);
+
+    // Create and records a nested tree for a nested message field.
+    ParseInfoTree* CreateNested(const FieldDescriptor* field);
+
+    // Defines the map from the index-th field descriptor to its parse location.
+    typedef map<const FieldDescriptor*, vector<ParseLocation> > LocationMap;
+
+    // Defines the map from the index-th field descriptor to the nested parse
+    // info tree.
+    typedef map<const FieldDescriptor*, vector<ParseInfoTree*> > NestedMap;
+
+    LocationMap locations_;
+    NestedMap nested_;
+
+    GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ParseInfoTree);
+  };
+
   // For more control over parsing, use this class.
   class LIBPROTOBUF_EXPORT Parser {
    public:
@@ -248,6 +302,12 @@
       finder_ = finder;
     }
 
+    // Sets where location information about the parse will be written. If NULL
+    // (the default), then no location will be written.
+    void WriteLocationsTo(ParseInfoTree* tree) {
+      parse_info_tree_ = tree;
+    }
+
     // Normally parsing fails if, after parsing, output->IsInitialized()
     // returns false.  Call AllowPartialMessage(true) to skip this check.
     void AllowPartialMessage(bool allow) {
@@ -259,6 +319,7 @@
                                    const FieldDescriptor* field,
                                    Message* output);
 
+
    private:
     // Forward declaration of an internal class used to parse text
     // representations (see text_format.cc for implementation).
@@ -272,7 +333,9 @@
 
     io::ErrorCollector* error_collector_;
     Finder* finder_;
+    ParseInfoTree* parse_info_tree_;
     bool allow_partial_;
+    bool allow_unknown_field_;
   };
 
  private:
diff --git a/third_party/protobuf/src/google/protobuf/text_format_unittest.cc b/third_party/protobuf/src/google/protobuf/text_format_unittest.cc
index 00ea8c3..353a5e4 100644
--- a/third_party/protobuf/src/google/protobuf/text_format_unittest.cc
+++ b/third_party/protobuf/src/google/protobuf/text_format_unittest.cc
@@ -339,6 +339,21 @@
     text);
 }
 
+TEST_F(TextFormatTest, PrintBufferTooSmall) {
+  // Test printing a message to a buffer that is too small.
+
+  protobuf_unittest::TestAllTypes message;
+
+  message.add_repeated_string("abc");
+  message.add_repeated_string("def");
+
+  char buffer[1] = "";
+  io::ArrayOutputStream output_stream(buffer, 1);
+  EXPECT_FALSE(TextFormat::Print(message, &output_stream));
+  EXPECT_EQ(buffer[0], 'r');
+  EXPECT_EQ(output_stream.ByteCount(), 1);
+}
+
 TEST_F(TextFormatTest, ParseBasic) {
   io::ArrayInputStream input_stream(proto_debug_string_.data(),
                                     proto_debug_string_.size());
@@ -728,6 +743,25 @@
               error_collector.text_);
   }
 
+  void ExpectSuccessAndTree(const string& input, Message* proto,
+                            TextFormat::ParseInfoTree* info_tree) {
+    TextFormat::Parser parser;
+    MockErrorCollector error_collector;
+    parser.RecordErrorsTo(&error_collector);
+    parser.WriteLocationsTo(info_tree);
+
+    EXPECT_TRUE(parser.ParseFromString(input, proto));
+  }
+
+  void ExpectLocation(TextFormat::ParseInfoTree* tree,
+                      const Descriptor* d, const string& field_name,
+                      int index, int line, int column) {
+    TextFormat::ParseLocation location = tree->GetLocation(
+        d->FindFieldByName(field_name), index);
+    EXPECT_EQ(line, location.line);
+    EXPECT_EQ(column, location.column);
+  }
+
   // An error collector which simply concatenates all its errors into a big
   // block of text which can be checked.
   class MockErrorCollector : public io::ErrorCollector {
@@ -749,6 +783,71 @@
   };
 };
 
+TEST_F(TextFormatParserTest, ParseInfoTreeBuilding) {
+  scoped_ptr<unittest::TestAllTypes> message(new unittest::TestAllTypes);
+  const Descriptor* d = message->GetDescriptor();
+
+  string stringData =
+      "optional_int32: 1\n"
+      "optional_int64: 2\n"
+      "  optional_double: 2.4\n"
+      "repeated_int32: 5\n"
+      "repeated_int32: 10\n"
+      "optional_nested_message <\n"
+      "  bb: 78\n"
+      ">\n"
+      "repeated_nested_message <\n"
+      "  bb: 79\n"
+      ">\n"
+      "repeated_nested_message <\n"
+      "  bb: 80\n"
+      ">";
+
+
+  TextFormat::ParseInfoTree tree;
+  ExpectSuccessAndTree(stringData, message.get(), &tree);
+
+  // Verify that the tree has the correct positions.
+  ExpectLocation(&tree, d, "optional_int32", -1, 0, 0);
+  ExpectLocation(&tree, d, "optional_int64", -1, 1, 0);
+  ExpectLocation(&tree, d, "optional_double", -1, 2, 2);
+
+  ExpectLocation(&tree, d, "repeated_int32", 0, 3, 0);
+  ExpectLocation(&tree, d, "repeated_int32", 1, 4, 0);
+
+  ExpectLocation(&tree, d, "optional_nested_message", -1, 5, 0);
+  ExpectLocation(&tree, d, "repeated_nested_message", 0, 8, 0);
+  ExpectLocation(&tree, d, "repeated_nested_message", 1, 11, 0);
+
+  // Check for fields not set. For an invalid field, the location returned
+  // should be -1, -1.
+  ExpectLocation(&tree, d, "repeated_int64", 0, -1, -1);
+  ExpectLocation(&tree, d, "repeated_int32", 6, -1, -1);
+  ExpectLocation(&tree, d, "some_unknown_field", -1, -1, -1);
+
+  // Verify inside the nested message.
+  const FieldDescriptor* nested_field =
+      d->FindFieldByName("optional_nested_message");
+
+  TextFormat::ParseInfoTree* nested_tree =
+      tree.GetTreeForNested(nested_field, -1);
+  ExpectLocation(nested_tree, nested_field->message_type(), "bb", -1, 6, 2);
+
+  // Verify inside another nested message.
+  nested_field = d->FindFieldByName("repeated_nested_message");
+  nested_tree = tree.GetTreeForNested(nested_field, 0);
+  ExpectLocation(nested_tree, nested_field->message_type(), "bb", -1, 9, 2);
+
+  nested_tree = tree.GetTreeForNested(nested_field, 1);
+  ExpectLocation(nested_tree, nested_field->message_type(), "bb", -1, 12, 2);
+
+  // Verify a NULL tree for an unknown nested field.
+  TextFormat::ParseInfoTree* unknown_nested_tree =
+      tree.GetTreeForNested(nested_field, 2);
+
+  EXPECT_EQ(NULL, unknown_nested_tree);
+}
+
 TEST_F(TextFormatParserTest, ParseFieldValueFromString) {
   scoped_ptr<unittest::TestAllTypes> message(new unittest::TestAllTypes);
   const Descriptor* d = message->GetDescriptor();
@@ -921,10 +1020,10 @@
                 1, 16);
   ExpectFailure("optional_int32: 0x80000000\n",
                 "Integer out of range.", 1, 17);
-  ExpectFailure("optional_int32: -0x80000001\n",
-                "Integer out of range.", 1, 18);
   ExpectFailure("optional_int64: 0x8000000000000000\n",
                 "Integer out of range.", 1, 17);
+  ExpectFailure("optional_int32: -0x80000001\n",
+                "Integer out of range.", 1, 18);
   ExpectFailure("optional_int64: -0x8000000000000001\n",
                 "Integer out of range.", 1, 18);
 
@@ -1136,6 +1235,7 @@
   EXPECT_EQ(2, descriptors.size());
 }
 
+
 }  // namespace text_format_unittest
 }  // namespace protobuf
 }  // namespace google
diff --git a/third_party/protobuf/src/google/protobuf/unittest.proto b/third_party/protobuf/src/google/protobuf/unittest.proto
index 97ec674..0305be6 100644
--- a/third_party/protobuf/src/google/protobuf/unittest.proto
+++ b/third_party/protobuf/src/google/protobuf/unittest.proto
@@ -103,6 +103,12 @@
   optional string optional_string_piece = 24 [ctype=STRING_PIECE];
   optional string optional_cord = 25 [ctype=CORD];
 
+  // Defined in unittest_import_public.proto
+  optional protobuf_unittest_import.PublicImportMessage
+      optional_public_import_message = 26;
+
+  optional NestedMessage optional_lazy_message = 27 [lazy=true];
+
   // Repeated
   repeated    int32 repeated_int32    = 31;
   repeated    int64 repeated_int64    = 32;
@@ -135,6 +141,8 @@
   repeated string repeated_string_piece = 54 [ctype=STRING_PIECE];
   repeated string repeated_cord = 55 [ctype=CORD];
 
+  repeated NestedMessage repeated_lazy_message = 57 [lazy=true];
+
   // Singular with defaults
   optional    int32 default_int32    = 61 [default =  41    ];
   optional    int64 default_int64    = 62 [default =  42    ];
@@ -216,6 +224,12 @@
   optional string optional_string_piece_extension = 24 [ctype=STRING_PIECE];
   optional string optional_cord_extension = 25 [ctype=CORD];
 
+  optional protobuf_unittest_import.PublicImportMessage
+    optional_public_import_message_extension = 26;
+
+  optional TestAllTypes.NestedMessage
+    optional_lazy_message_extension = 27 [lazy=true];
+
   // Repeated
   repeated    int32 repeated_int32_extension    = 31;
   repeated    int64 repeated_int64_extension    = 32;
@@ -250,6 +264,9 @@
   repeated string repeated_string_piece_extension = 54 [ctype=STRING_PIECE];
   repeated string repeated_cord_extension = 55 [ctype=CORD];
 
+  repeated TestAllTypes.NestedMessage
+    repeated_lazy_message_extension = 57 [lazy=true];
+
   // Singular with defaults
   optional    int32 default_int32_extension    = 61 [default =  41    ];
   optional    int64 default_int64_extension    = 62 [default =  42    ];
@@ -397,6 +414,13 @@
   optional group Bar = 3 { optional int32 a = 1; }  // NO_PROTO1
 }                                                   // NO_PROTO1
 
+// Additional messages for testing lazy fields.
+message TestEagerMessage {
+  optional TestAllTypes sub_message = 1 [lazy=false];
+}
+message TestLazyMessage {
+  optional TestAllTypes sub_message = 1 [lazy=true];
+}
 
 // Needed for a Python test.
 message TestNestedMessageHasBits {
@@ -470,6 +494,8 @@
   optional uint64 large_uint64 = 3 [default = 0xFFFFFFFFFFFFFFFF];
   optional  int32 small_int32  = 4 [default = -0x7FFFFFFF];
   optional  int64 small_int64  = 5 [default = -0x7FFFFFFFFFFFFFFF];
+  optional  int32 really_small_int32 = 21 [default = -0x80000000];
+  optional  int64 really_small_int64 = 22 [default = -0x8000000000000000];
 
   // The default value here is UTF-8 for "\u1234".  (We could also just type
   // the UTF-8 text directly into this text file rather than escape it, but
@@ -500,6 +526,14 @@
   // Note that in .proto file, "\?" is a valid way to escape ? in string
   // literals.
   optional string cpp_trigraph = 20 [default = "? \? ?? \?? \??? ??/ ?\?-"];
+
+  // String defaults containing the character '\000'
+  optional string string_with_zero       = 23 [default = "hel\000lo"];
+  optional  bytes bytes_with_zero        = 24 [default = "wor\000ld"];
+  optional string string_piece_with_zero = 25 [ctype=STRING_PIECE,
+                                               default="ab\000c"];
+  optional string cord_with_zero         = 26 [ctype=CORD,
+                                               default="12\0003"];
 }
 
 message SparseEnumMessage {
@@ -511,10 +545,19 @@
   optional string data = 1;
 }
 
+message MoreString {
+  repeated string data = 1;
+}
+
 message OneBytes {
   optional bytes data = 1;
 }
 
+message MoreBytes {
+  repeated bytes data = 1;
+}
+
+
 // Test messages for packed fields
 
 message TestPackedTypes {
@@ -615,11 +658,56 @@
   repeated uint64  repeated_uint64  = 262143;
 }
 
+// Test that if an optional or required message/group field appears multiple
+// times in the input, they need to be merged.
+message TestParsingMerge {
+  // RepeatedFieldsGenerator defines matching field types as TestParsingMerge,
+  // except that all fields are repeated. In the tests, we will serialize the
+  // RepeatedFieldsGenerator to bytes, and parse the bytes to TestParsingMerge.
+  // Repeated fields in RepeatedFieldsGenerator are expected to be merged into
+  // the corresponding required/optional fields in TestParsingMerge.
+  message RepeatedFieldsGenerator {
+    repeated TestAllTypes field1 = 1;
+    repeated TestAllTypes field2 = 2;
+    repeated TestAllTypes field3 = 3;
+    repeated group Group1 = 10 {
+      optional TestAllTypes field1 = 11;
+    }
+    repeated group Group2 = 20 {
+      optional TestAllTypes field1 = 21;
+    }
+    repeated TestAllTypes ext1 = 1000;
+    repeated TestAllTypes ext2 = 1001;
+  }
+  required TestAllTypes required_all_types = 1;
+  optional TestAllTypes optional_all_types = 2;
+  repeated TestAllTypes repeated_all_types = 3;
+  optional group OptionalGroup = 10 {
+    optional TestAllTypes optional_group_all_types = 11;
+  }
+  repeated group RepeatedGroup = 20 {
+    optional TestAllTypes repeated_group_all_types = 21;
+  }
+  extensions 1000 to max;
+  extend TestParsingMerge {
+    optional TestAllTypes optional_ext = 1000;
+    repeated TestAllTypes repeated_ext = 1001;
+  }
+}
+
+message TestCommentInjectionMessage {
+  // */ <- This should not close the generated doc comment
+  optional string a = 1 [default="*/ <- Neither should this."];
+}
+
 
 // Test that RPC services work.
 message FooRequest  {}
 message FooResponse {}
 
+message FooClientMessage {}
+message FooServerMessage{}
+
 service TestService {
   rpc Foo(FooRequest) returns (FooResponse);
   rpc Bar(BarRequest) returns (BarResponse);
diff --git a/third_party/protobuf/src/google/protobuf/unittest_custom_options.proto b/third_party/protobuf/src/google/protobuf/unittest_custom_options.proto
index a610785..e591d29 100644
--- a/third_party/protobuf/src/google/protobuf/unittest_custom_options.proto
+++ b/third_party/protobuf/src/google/protobuf/unittest_custom_options.proto
@@ -116,6 +116,12 @@
 message CustomOptionFooResponse {
 }
 
+message CustomOptionFooClientMessage {
+}
+
+message CustomOptionFooServerMessage {
+}
+
 service TestServiceWithCustomOptions {
   option (service_opt1) = -9876543210;
 
@@ -364,3 +370,18 @@
   option (enumopt) = { s:'EnumAnnotation' };
   VALUE = 1 [(enumvalopt) = { s:'EnumValueAnnotation' }];
 }
+
+// Test custom options for nested type.
+message NestedOptionType {
+  message NestedMessage {
+    option (message_opt1) = 1001;
+    optional int32 nested_field = 1 [(field_opt1) = 1002];
+  }
+  enum NestedEnum {
+    option (enum_opt1) = 1003;
+    NESTED_ENUM_VALUE = 1 [(enum_value_opt1) = 1004];
+  }
+  extend google.protobuf.FileOptions {
+    optional int32 nested_extension = 7912573 [(field_opt2) = 1005];
+  }
+}
diff --git a/third_party/protobuf/src/google/protobuf/unittest_import.proto b/third_party/protobuf/src/google/protobuf/unittest_import.proto
index cd533ec..c115b11 100644
--- a/third_party/protobuf/src/google/protobuf/unittest_import.proto
+++ b/third_party/protobuf/src/google/protobuf/unittest_import.proto
@@ -49,6 +49,9 @@
 // Do not set a java_outer_classname here to verify that Proto2 works without
 // one.
 
+// Test public import
+import public "google/protobuf/unittest_import_public.proto";
+
 message ImportMessage {
   optional int32 d = 1;
 }
diff --git a/third_party/protobuf/src/google/protobuf/unittest_import_lite.proto b/third_party/protobuf/src/google/protobuf/unittest_import_lite.proto
index ebaab5c..81b117f 100644
--- a/third_party/protobuf/src/google/protobuf/unittest_import_lite.proto
+++ b/third_party/protobuf/src/google/protobuf/unittest_import_lite.proto
@@ -38,6 +38,8 @@
 
 option java_package = "com.google.protobuf";
 
+import public "google/protobuf/unittest_import_public_lite.proto";
+
 message ImportMessageLite {
   optional int32 d = 1;
 }
diff --git a/third_party/protobuf/src/google/protobuf/unittest_import_public.proto b/third_party/protobuf/src/google/protobuf/unittest_import_public.proto
new file mode 100644
index 0000000..ea5d1b1
--- /dev/null
+++ b/third_party/protobuf/src/google/protobuf/unittest_import_public.proto
@@ -0,0 +1,40 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 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.
+
+// Author: liujisi@google.com (Pherl Liu)
+
+
+package protobuf_unittest_import;
+
+option java_package = "com.google.protobuf.test";
+
+message PublicImportMessage {
+  optional int32 e = 1;
+}
diff --git a/third_party/protobuf/src/google/protobuf/unittest_import_public_lite.proto b/third_party/protobuf/src/google/protobuf/unittest_import_public_lite.proto
new file mode 100644
index 0000000..d077563
--- /dev/null
+++ b/third_party/protobuf/src/google/protobuf/unittest_import_public_lite.proto
@@ -0,0 +1,42 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 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.
+
+// Author: liujisi@google.com (Pherl Liu)
+
+
+package protobuf_unittest_import;
+
+option optimize_for = LITE_RUNTIME;
+
+option java_package = "com.google.protobuf";
+
+message PublicImportMessageLite {
+  optional int32 e = 1;
+}
diff --git a/third_party/protobuf/src/google/protobuf/unittest_lite.proto b/third_party/protobuf/src/google/protobuf/unittest_lite.proto
index cca6b49..a1764aa 100644
--- a/third_party/protobuf/src/google/protobuf/unittest_lite.proto
+++ b/third_party/protobuf/src/google/protobuf/unittest_lite.proto
@@ -85,6 +85,12 @@
   optional string optional_string_piece = 24 [ctype=STRING_PIECE];
   optional string optional_cord = 25 [ctype=CORD];
 
+  // Defined in unittest_import_public.proto
+  optional protobuf_unittest_import.PublicImportMessageLite
+      optional_public_import_message = 26;
+
+  optional NestedMessage optional_lazy_message = 27 [lazy=true];
+
   // Repeated
   repeated    int32 repeated_int32    = 31;
   repeated    int64 repeated_int64    = 32;
@@ -118,6 +124,8 @@
   repeated string repeated_string_piece = 54 [ctype=STRING_PIECE];
   repeated string repeated_cord = 55 [ctype=CORD];
 
+  repeated NestedMessage repeated_lazy_message = 57 [lazy=true];
+
   // Singular with defaults
   optional    int32 default_int32    = 61 [default =  41    ];
   optional    int64 default_int64    = 62 [default =  42    ];
@@ -213,6 +221,12 @@
       [ctype=STRING_PIECE];
   optional string optional_cord_extension_lite = 25 [ctype=CORD];
 
+  optional protobuf_unittest_import.PublicImportMessageLite
+    optional_public_import_message_extension_lite = 26;
+
+  optional TestAllTypesLite.NestedMessage
+    optional_lazy_message_extension_lite = 27 [lazy=true];
+
   // Repeated
   repeated    int32 repeated_int32_extension_lite    = 31;
   repeated    int64 repeated_int64_extension_lite    = 32;
@@ -249,6 +263,9 @@
       [ctype=STRING_PIECE];
   repeated string repeated_cord_extension_lite = 55 [ctype=CORD];
 
+  repeated TestAllTypesLite.NestedMessage
+    repeated_lazy_message_extension_lite = 57 [lazy=true];
+
   // Singular with defaults
   optional    int32 default_int32_extension_lite    = 61 [default =  41    ];
   optional    int64 default_int64_extension_lite    = 62 [default =  42    ];
@@ -310,3 +327,34 @@
 message TestDeprecatedLite {
   optional int32 deprecated_field = 1 [deprecated = true];
 }
+
+// See the comments of the same type in unittest.proto.
+message TestParsingMergeLite {
+  message RepeatedFieldsGenerator {
+    repeated TestAllTypesLite field1 = 1;
+    repeated TestAllTypesLite field2 = 2;
+    repeated TestAllTypesLite field3 = 3;
+    repeated group Group1 = 10 {
+      optional TestAllTypesLite field1 = 11;
+    }
+    repeated group Group2 = 20 {
+      optional TestAllTypesLite field1 = 21;
+    }
+    repeated TestAllTypesLite ext1 = 1000;
+    repeated TestAllTypesLite ext2 = 1001;
+  }
+  required TestAllTypesLite required_all_types = 1;
+  optional TestAllTypesLite optional_all_types = 2;
+  repeated TestAllTypesLite repeated_all_types = 3;
+  optional group OptionalGroup = 10 {
+    optional TestAllTypesLite optional_group_all_types = 11;
+  }
+  repeated group RepeatedGroup = 20 {
+    optional TestAllTypesLite repeated_group_all_types = 21;
+  }
+  extensions 1000 to max;
+  extend TestParsingMergeLite {
+    optional TestAllTypesLite optional_ext = 1000;
+    repeated TestAllTypesLite repeated_ext = 1001;
+  }
+}
diff --git a/third_party/protobuf/src/google/protobuf/unknown_field_set.cc b/third_party/protobuf/src/google/protobuf/unknown_field_set.cc
index 38a36d5..b6aaa18 100644
--- a/third_party/protobuf/src/google/protobuf/unknown_field_set.cc
+++ b/third_party/protobuf/src/google/protobuf/unknown_field_set.cc
@@ -32,13 +32,14 @@
 //  Based on original Protocol Buffers design by
 //  Sanjay Ghemawat, Jeff Dean, and others.
 
-#include <google/protobuf/stubs/common.h>
 #include <google/protobuf/unknown_field_set.h>
-#include <google/protobuf/stubs/stl_util-inl.h>
+
+#include <google/protobuf/stubs/common.h>
 #include <google/protobuf/io/coded_stream.h>
 #include <google/protobuf/io/zero_copy_stream.h>
 #include <google/protobuf/io/zero_copy_stream_impl_lite.h>
 #include <google/protobuf/wire_format_lite.h>
+#include <google/protobuf/stubs/stl_util.h>
 
 namespace google {
 namespace protobuf {
@@ -75,6 +76,14 @@
   fields_->clear();
 }
 
+void UnknownFieldSet::ClearAndFreeMemory() {
+  if (fields_ != NULL) {
+    Clear();
+    delete fields_;
+    fields_ = NULL;
+  }
+}
+
 void UnknownFieldSet::MergeFrom(const UnknownFieldSet& other) {
   for (int i = 0; i < other.field_count(); i++) {
     AddField(other.field(i));
@@ -89,8 +98,9 @@
     const UnknownField& field = (*fields_)[i];
     switch (field.type()) {
       case UnknownField::TYPE_LENGTH_DELIMITED:
-        total_size += sizeof(*field.length_delimited_) +
-          internal::StringSpaceUsedExcludingSelf(*field.length_delimited_);
+        total_size += sizeof(*field.length_delimited_.string_value_) +
+                      internal::StringSpaceUsedExcludingSelf(
+                          *field.length_delimited_.string_value_);
         break;
       case UnknownField::TYPE_GROUP:
         total_size += field.group_->SpaceUsed();
@@ -138,11 +148,12 @@
   UnknownField field;
   field.number_ = number;
   field.type_ = UnknownField::TYPE_LENGTH_DELIMITED;
-  field.length_delimited_ = new string;
+  field.length_delimited_.string_value_ = new string;
   fields_->push_back(field);
-  return field.length_delimited_;
+  return field.length_delimited_.string_value_;
 }
 
+
 UnknownFieldSet* UnknownFieldSet::AddGroup(int number) {
   if (fields_ == NULL) fields_ = new vector<UnknownField>;
   UnknownField field;
@@ -159,6 +170,39 @@
   fields_->back().DeepCopy();
 }
 
+void UnknownFieldSet::DeleteSubrange(int start, int num) {
+  GOOGLE_DCHECK(fields_ != NULL);
+  // Delete the specified fields.
+  for (int i = 0; i < num; ++i) {
+    (*fields_)[i + start].Delete();
+  }
+  // Slide down the remaining fields.
+  for (int i = start + num; i < fields_->size(); ++i) {
+    (*fields_)[i - num] = (*fields_)[i];
+  }
+  // Pop off the # of deleted fields.
+  for (int i = 0; i < num; ++i) {
+    fields_->pop_back();
+  }
+}
+
+void UnknownFieldSet::DeleteByNumber(int number) {
+  if (fields_ == NULL) return;
+  int left = 0;  // The number of fields left after deletion.
+  for (int i = 0; i < fields_->size(); ++i) {
+    UnknownField* field = &(*fields_)[i];
+    if (field->number() == number) {
+      field->Delete();
+    } else {
+      if (i != left) {
+        (*fields_)[left] = (*fields_)[i];
+      }
+      ++left;
+    }
+  }
+  fields_->resize(left);
+}
+
 bool UnknownFieldSet::MergeFromCodedStream(io::CodedInputStream* input) {
 
   UnknownFieldSet other;
@@ -190,7 +234,7 @@
 void UnknownField::Delete() {
   switch (type()) {
     case UnknownField::TYPE_LENGTH_DELIMITED:
-      delete length_delimited_;
+      delete length_delimited_.string_value_;
       break;
     case UnknownField::TYPE_GROUP:
       delete group_;
@@ -203,7 +247,8 @@
 void UnknownField::DeepCopy() {
   switch (type()) {
     case UnknownField::TYPE_LENGTH_DELIMITED:
-      length_delimited_ = new string(*length_delimited_);
+      length_delimited_.string_value_ = new string(
+          *length_delimited_.string_value_);
       break;
     case UnknownField::TYPE_GROUP: {
       UnknownFieldSet* group = new UnknownFieldSet;
@@ -216,5 +261,22 @@
   }
 }
 
+
+void UnknownField::SerializeLengthDelimitedNoTag(
+    io::CodedOutputStream* output) const {
+  GOOGLE_DCHECK_EQ(TYPE_LENGTH_DELIMITED, type_);
+  const string& data = *length_delimited_.string_value_;
+  output->WriteVarint32(data.size());
+  output->WriteString(data);
+}
+
+uint8* UnknownField::SerializeLengthDelimitedNoTagToArray(uint8* target) const {
+  GOOGLE_DCHECK_EQ(TYPE_LENGTH_DELIMITED, type_);
+  const string& data = *length_delimited_.string_value_;
+  target = io::CodedOutputStream::WriteVarint32ToArray(data.size(), target);
+  target = io::CodedOutputStream::WriteStringToArray(data, target);
+  return target;
+}
+
 }  // namespace protobuf
 }  // namespace google
diff --git a/third_party/protobuf/src/google/protobuf/unknown_field_set.h b/third_party/protobuf/src/google/protobuf/unknown_field_set.h
index 84c2e2b..825bba8 100644
--- a/third_party/protobuf/src/google/protobuf/unknown_field_set.h
+++ b/third_party/protobuf/src/google/protobuf/unknown_field_set.h
@@ -38,12 +38,24 @@
 #ifndef GOOGLE_PROTOBUF_UNKNOWN_FIELD_SET_H__
 #define GOOGLE_PROTOBUF_UNKNOWN_FIELD_SET_H__
 
+#include <assert.h>
 #include <string>
 #include <vector>
-#include <google/protobuf/repeated_field.h>
+#include <google/protobuf/stubs/common.h>
+// TODO(jasonh): some people seem to rely on protobufs to include this for them!
 
 namespace google {
 namespace protobuf {
+  namespace io {
+    class CodedInputStream;         // coded_stream.h
+    class CodedOutputStream;        // coded_stream.h
+    class ZeroCopyInputStream;      // zero_copy_stream.h
+  }
+  namespace internal {
+    class WireFormat;               // wire_format.h
+    class UnknownFieldSetFieldSkipperUsingCord;
+                                    // extension_set_heavy.cc
+  }
 
 class Message;                      // message.h
 class UnknownField;                 // below
@@ -68,6 +80,9 @@
   // Remove all fields.
   inline void Clear();
 
+  // Remove all fields and deallocate internal data objects
+  void ClearAndFreeMemory();
+
   // Is this set empty?
   inline bool empty() const;
 
@@ -107,6 +122,15 @@
   // Adds an unknown field from another set.
   void AddField(const UnknownField& field);
 
+  // Delete fields with indices in the range [start .. start+num-1].
+  // Caution: implementation moves all fields with indices [start+num .. ].
+  void DeleteSubrange(int start, int num);
+
+  // Delete all fields with a specific field number. The order of left fields
+  // is preserved.
+  // Caution: implementation moves all fields after the first deleted field.
+  void DeleteByNumber(int number);
+
   // Parsing helpers -------------------------------------------------
   // These work exactly like the similarly-named methods of Message.
 
@@ -119,6 +143,7 @@
   }
 
  private:
+
   void ClearFallback();
 
   vector<UnknownField>* fields_;
@@ -159,6 +184,15 @@
   inline string* mutable_length_delimited();
   inline UnknownFieldSet* mutable_group();
 
+  // Serialization API.
+  // These methods can take advantage of the underlying implementation and may
+  // archieve a better performance than using getters to retrieve the data and
+  // do the serialization yourself.
+  void SerializeLengthDelimitedNoTag(io::CodedOutputStream* output) const;
+  uint8* SerializeLengthDelimitedNoTagToArray(uint8* target) const;
+
+  inline int GetLengthDelimitedSize() const;
+
  private:
   friend class UnknownFieldSet;
 
@@ -168,13 +202,16 @@
   // Make a deep copy of any pointers in this UnknownField.
   void DeepCopy();
 
+
   unsigned int number_ : 29;
   unsigned int type_   : 3;
   union {
     uint64 varint_;
     uint32 fixed32_;
     uint64 fixed64_;
-    string* length_delimited_;
+    mutable union {
+      string* string_value_;
+    } length_delimited_;
     UnknownFieldSet* group_;
   };
 };
@@ -211,57 +248,63 @@
   AddLengthDelimited(number)->assign(value);
 }
 
+
 inline int UnknownField::number() const { return number_; }
 inline UnknownField::Type UnknownField::type() const {
   return static_cast<Type>(type_);
 }
 
 inline uint64 UnknownField::varint () const {
-  GOOGLE_DCHECK_EQ(type_, TYPE_VARINT);
+  assert(type_ == TYPE_VARINT);
   return varint_;
 }
 inline uint32 UnknownField::fixed32() const {
-  GOOGLE_DCHECK_EQ(type_, TYPE_FIXED32);
+  assert(type_ == TYPE_FIXED32);
   return fixed32_;
 }
 inline uint64 UnknownField::fixed64() const {
-  GOOGLE_DCHECK_EQ(type_, TYPE_FIXED64);
+  assert(type_ == TYPE_FIXED64);
   return fixed64_;
 }
 inline const string& UnknownField::length_delimited() const {
-  GOOGLE_DCHECK_EQ(type_, TYPE_LENGTH_DELIMITED);
-  return *length_delimited_;
+  assert(type_ == TYPE_LENGTH_DELIMITED);
+  return *length_delimited_.string_value_;
 }
 inline const UnknownFieldSet& UnknownField::group() const {
-  GOOGLE_DCHECK_EQ(type_, TYPE_GROUP);
+  assert(type_ == TYPE_GROUP);
   return *group_;
 }
 
 inline void UnknownField::set_varint(uint64 value) {
-  GOOGLE_DCHECK_EQ(type_, TYPE_VARINT);
+  assert(type_ == TYPE_VARINT);
   varint_ = value;
 }
 inline void UnknownField::set_fixed32(uint32 value) {
-  GOOGLE_DCHECK_EQ(type_, TYPE_FIXED32);
+  assert(type_ == TYPE_FIXED32);
   fixed32_ = value;
 }
 inline void UnknownField::set_fixed64(uint64 value) {
-  GOOGLE_DCHECK_EQ(type_, TYPE_FIXED64);
+  assert(type_ == TYPE_FIXED64);
   fixed64_ = value;
 }
 inline void UnknownField::set_length_delimited(const string& value) {
-  GOOGLE_DCHECK_EQ(type_, TYPE_LENGTH_DELIMITED);
-  length_delimited_->assign(value);
+  assert(type_ == TYPE_LENGTH_DELIMITED);
+  length_delimited_.string_value_->assign(value);
 }
 inline string* UnknownField::mutable_length_delimited() {
-  GOOGLE_DCHECK_EQ(type_, TYPE_LENGTH_DELIMITED);
-  return length_delimited_;
+  assert(type_ == TYPE_LENGTH_DELIMITED);
+  return length_delimited_.string_value_;
 }
 inline UnknownFieldSet* UnknownField::mutable_group() {
-  GOOGLE_DCHECK_EQ(type_, TYPE_GROUP);
+  assert(type_ == TYPE_GROUP);
   return group_;
 }
 
+inline int UnknownField::GetLengthDelimitedSize() const {
+  GOOGLE_DCHECK_EQ(TYPE_LENGTH_DELIMITED, type_);
+  return length_delimited_.string_value_->size();
+}
+
 }  // namespace protobuf
 
 }  // namespace google
diff --git a/third_party/protobuf/src/google/protobuf/unknown_field_set_unittest.cc b/third_party/protobuf/src/google/protobuf/unknown_field_set_unittest.cc
index 1235c9e..c6b8769 100644
--- a/third_party/protobuf/src/google/protobuf/unknown_field_set_unittest.cc
+++ b/third_party/protobuf/src/google/protobuf/unknown_field_set_unittest.cc
@@ -46,15 +46,13 @@
 #include <google/protobuf/stubs/common.h>
 #include <google/protobuf/testing/googletest.h>
 #include <gtest/gtest.h>
-#include <google/protobuf/stubs/stl_util-inl.h>
+#include <google/protobuf/stubs/stl_util.h>
 
 namespace google {
 namespace protobuf {
 
 using internal::WireFormat;
 
-namespace {
-
 class UnknownFieldSetTest : public testing::Test {
  protected:
   virtual void SetUp() {
@@ -107,6 +105,8 @@
   UnknownFieldSet* unknown_fields_;
 };
 
+namespace {
+
 TEST_F(UnknownFieldSetTest, AllFieldsPresent) {
   // All fields of TestAllTypes should be present, in numeric order (because
   // that's the order we parsed them in).  Fields that are not valid field
@@ -297,12 +297,21 @@
     destination.DebugString());
 }
 
+
 TEST_F(UnknownFieldSetTest, Clear) {
   // Clear the set.
   empty_message_.Clear();
   EXPECT_EQ(0, unknown_fields_->field_count());
 }
 
+TEST_F(UnknownFieldSetTest, ClearAndFreeMemory) {
+  EXPECT_GT(unknown_fields_->field_count(), 0);
+  unknown_fields_->ClearAndFreeMemory();
+  EXPECT_EQ(0, unknown_fields_->field_count());
+  unknown_fields_->AddVarint(123456, 654321);
+  EXPECT_EQ(1, unknown_fields_->field_count());
+}
+
 TEST_F(UnknownFieldSetTest, ParseKnownAndUnknown) {
   // Test mixing known and unknown fields when parsing.
 
@@ -498,6 +507,7 @@
   EXPECT_LT(base_size, empty_message.SpaceUsed());
 }
 
+
 TEST_F(UnknownFieldSetTest, Empty) {
   UnknownFieldSet unknown_fields;
   EXPECT_TRUE(unknown_fields.empty());
@@ -507,6 +517,78 @@
   EXPECT_TRUE(unknown_fields.empty());
 }
 
+TEST_F(UnknownFieldSetTest, DeleteSubrange) {
+  // Exhaustively test the deletion of every possible subrange in arrays of all
+  // sizes from 0 through 9.
+  for (int size = 0; size < 10; ++size) {
+    for (int num = 0; num <= size; ++num) {
+      for (int start = 0; start < size - num; ++start) {
+        // Create a set with "size" fields.
+        UnknownFieldSet unknown;
+        for (int i = 0; i < size; ++i) {
+          unknown.AddFixed32(i, i);
+        }
+        // Delete the specified subrange.
+        unknown.DeleteSubrange(start, num);
+        // Make sure the resulting field values are still correct.
+        EXPECT_EQ(size - num, unknown.field_count());
+        for (int i = 0; i < unknown.field_count(); ++i) {
+          if (i < start) {
+            EXPECT_EQ(i, unknown.field(i).fixed32());
+          } else {
+            EXPECT_EQ(i + num, unknown.field(i).fixed32());
+          }
+        }
+      }
+    }
+  }
+}
+
+void CheckDeleteByNumber(const vector<int>& field_numbers, int deleted_number,
+                        const vector<int>& expected_field_nubmers) {
+  UnknownFieldSet unknown_fields;
+  for (int i = 0; i < field_numbers.size(); ++i) {
+    unknown_fields.AddFixed32(field_numbers[i], i);
+  }
+  unknown_fields.DeleteByNumber(deleted_number);
+  ASSERT_EQ(expected_field_nubmers.size(), unknown_fields.field_count());
+  for (int i = 0; i < expected_field_nubmers.size(); ++i) {
+    EXPECT_EQ(expected_field_nubmers[i],
+              unknown_fields.field(i).number());
+  }
+}
+
+#define MAKE_VECTOR(x) vector<int>(x, x + GOOGLE_ARRAYSIZE(x))
+TEST_F(UnknownFieldSetTest, DeleteByNumber) {
+  CheckDeleteByNumber(vector<int>(), 1, vector<int>());
+  static const int kTestFieldNumbers1[] = {1, 2, 3};
+  static const int kFieldNumberToDelete1 = 1;
+  static const int kExpectedFieldNumbers1[] = {2, 3};
+  CheckDeleteByNumber(MAKE_VECTOR(kTestFieldNumbers1), kFieldNumberToDelete1,
+                      MAKE_VECTOR(kExpectedFieldNumbers1));
+  static const int kTestFieldNumbers2[] = {1, 2, 3};
+  static const int kFieldNumberToDelete2 = 2;
+  static const int kExpectedFieldNumbers2[] = {1, 3};
+  CheckDeleteByNumber(MAKE_VECTOR(kTestFieldNumbers2), kFieldNumberToDelete2,
+                      MAKE_VECTOR(kExpectedFieldNumbers2));
+  static const int kTestFieldNumbers3[] = {1, 2, 3};
+  static const int kFieldNumberToDelete3 = 3;
+  static const int kExpectedFieldNumbers3[] = {1, 2};
+  CheckDeleteByNumber(MAKE_VECTOR(kTestFieldNumbers3), kFieldNumberToDelete3,
+                      MAKE_VECTOR(kExpectedFieldNumbers3));
+  static const int kTestFieldNumbers4[] = {1, 2, 1, 4, 1};
+  static const int kFieldNumberToDelete4 = 1;
+  static const int kExpectedFieldNumbers4[] = {2, 4};
+  CheckDeleteByNumber(MAKE_VECTOR(kTestFieldNumbers4), kFieldNumberToDelete4,
+                      MAKE_VECTOR(kExpectedFieldNumbers4));
+  static const int kTestFieldNumbers5[] = {1, 2, 3, 4, 5};
+  static const int kFieldNumberToDelete5 = 6;
+  static const int kExpectedFieldNumbers5[] = {1, 2, 3, 4, 5};
+  CheckDeleteByNumber(MAKE_VECTOR(kTestFieldNumbers5), kFieldNumberToDelete5,
+                      MAKE_VECTOR(kExpectedFieldNumbers5));
+}
+#undef MAKE_VECTOR
 }  // namespace
+
 }  // namespace protobuf
 }  // namespace google
diff --git a/third_party/protobuf/src/google/protobuf/wire_format.cc b/third_party/protobuf/src/google/protobuf/wire_format.cc
index d07f633..491eede 100644
--- a/third_party/protobuf/src/google/protobuf/wire_format.cc
+++ b/third_party/protobuf/src/google/protobuf/wire_format.cc
@@ -48,12 +48,11 @@
 #include <google/protobuf/unknown_field_set.h>
 
 
+
 namespace google {
 namespace protobuf {
 namespace internal {
 
-using internal::WireFormatLite;
-
 namespace {
 
 // This function turns out to be convenient when using some macros later.
@@ -340,10 +339,7 @@
   const FieldDescriptor* field = NULL;
 
   // If we see message data before the type_id, we'll append it to this so
-  // we can parse it later.  This will probably never happen in practice,
-  // as no MessageSet encoder I know of writes the message before the type ID.
-  // But, it's technically valid so we should allow it.
-  // TODO(kenton):  Use a Cord instead?  Do I care?
+  // we can parse it later.
   string message_data;
 
   while (true) {
@@ -381,7 +377,10 @@
           uint32 length;
           if (!input->ReadVarint32(&length)) return false;
           if (!input->ReadString(&temp, length)) return false;
-          message_data.append(temp);
+          io::StringOutputStream output_stream(&message_data);
+          io::CodedOutputStream coded_output(&output_stream);
+          coded_output.WriteVarint32(length);
+          coded_output.WriteString(temp);
         } else {
           // Already saw type_id, so we can parse this directly.
           if (!ParseAndMergeField(fake_tag, field, message, input)) {
@@ -754,10 +753,10 @@
         break;
       // no default case: have the compiler warn if a case is not covered.
     }
-    GOOGLE_LOG(ERROR) << "Encountered string containing invalid UTF-8 data while "
+    GOOGLE_LOG(ERROR) << "String field contains invalid UTF-8 data when "
                << operation_str
-               << " protocol buffer. Strings must contain only UTF-8; "
-                  "use the 'bytes' type for raw bytes.";
+               << " a protocol buffer. Use the 'bytes' type if you intend to "
+                  "send raw bytes.";
   }
 }
 
diff --git a/third_party/protobuf/src/google/protobuf/wire_format.h b/third_party/protobuf/src/google/protobuf/wire_format.h
index d52bc4a..8a89881 100644
--- a/third_party/protobuf/src/google/protobuf/wire_format.h
+++ b/third_party/protobuf/src/google/protobuf/wire_format.h
@@ -40,6 +40,7 @@
 #define GOOGLE_PROTOBUF_WIRE_FORMAT_H__
 
 #include <string>
+#include <google/protobuf/stubs/common.h>
 #include <google/protobuf/descriptor.pb.h>
 #include <google/protobuf/descriptor.h>
 #include <google/protobuf/message.h>
diff --git a/third_party/protobuf/src/google/protobuf/wire_format_lite.cc b/third_party/protobuf/src/google/protobuf/wire_format_lite.cc
index 3bf9268..6c21478 100644
--- a/third_party/protobuf/src/google/protobuf/wire_format_lite.cc
+++ b/third_party/protobuf/src/google/protobuf/wire_format_lite.cc
@@ -40,7 +40,7 @@
 #include <google/protobuf/stubs/common.h>
 #include <google/protobuf/io/coded_stream_inl.h>
 #include <google/protobuf/io/zero_copy_stream.h>
-#include <google/protobuf/io/zero_copy_stream_impl.h>
+#include <google/protobuf/io/zero_copy_stream_impl_lite.h>
 #include <google/protobuf/unknown_field_set.h>
 
 namespace google {
@@ -506,12 +506,14 @@
                                  io::CodedOutputStream* output) {
   // String is for UTF-8 text only
   WriteTag(field_number, WIRETYPE_LENGTH_DELIMITED, output);
+  GOOGLE_CHECK(value.size() <= kint32max);
   output->WriteVarint32(value.size());
   output->WriteString(value);
 }
 void WireFormatLite::WriteBytes(int field_number, const string& value,
                                 io::CodedOutputStream* output) {
   WriteTag(field_number, WIRETYPE_LENGTH_DELIMITED, output);
+  GOOGLE_CHECK(value.size() <= kint32max);
   output->WriteVarint32(value.size());
   output->WriteString(value);
 }
diff --git a/third_party/protobuf/src/google/protobuf/wire_format_lite.h b/third_party/protobuf/src/google/protobuf/wire_format_lite.h
index 5f9f2a3..98d8004 100644
--- a/third_party/protobuf/src/google/protobuf/wire_format_lite.h
+++ b/third_party/protobuf/src/google/protobuf/wire_format_lite.h
@@ -41,16 +41,14 @@
 #define GOOGLE_PROTOBUF_WIRE_FORMAT_LITE_H__
 
 #include <string>
+#include <google/protobuf/stubs/common.h>
 #include <google/protobuf/message_lite.h>
+#include <google/protobuf/io/coded_stream.h>  // for CodedOutputStream::Varint32Size
 
 namespace google {
 
 namespace protobuf {
   template <typename T> class RepeatedField;  // repeated_field.h
-  namespace io {
-    class CodedInputStream;             // coded_stream.h
-    class CodedOutputStream;            // coded_stream.h
-  }
   class UnknownFieldSet;
 }
 
@@ -521,6 +519,10 @@
   template<typename MessageType>
   static inline int MessageSizeNoVirtual(const MessageType& value);
 
+  // Given the length of data, calculate the byte size of the data on the
+  // wire if we encode the data as a length delimited field.
+  static inline int LengthDelimitedSize(int length);
+
  private:
   // A helper method for the repeated primitive reader. This method has
   // optimizations for primitive types that have fixed size on the wire, and
@@ -556,7 +558,7 @@
   // saves it as an unknown varint.
   void SkipUnknownEnum(int field_number, int value);
 
- private:
+ protected:
   UnknownFieldSet* unknown_fields_;
 };
 
diff --git a/third_party/protobuf/src/google/protobuf/wire_format_lite_inl.h b/third_party/protobuf/src/google/protobuf/wire_format_lite_inl.h
index 103b0bd..0f97386 100644
--- a/third_party/protobuf/src/google/protobuf/wire_format_lite_inl.h
+++ b/third_party/protobuf/src/google/protobuf/wire_format_lite_inl.h
@@ -41,7 +41,6 @@
 #include <google/protobuf/message_lite.h>
 #include <google/protobuf/repeated_field.h>
 #include <google/protobuf/wire_format_lite.h>
-#include <google/protobuf/generated_message_util.h>
 #include <google/protobuf/io/coded_stream.h>
 
 
@@ -749,8 +748,7 @@
   return value.ByteSize();
 }
 inline int WireFormatLite::MessageSize(const MessageLite& value) {
-  int size = value.ByteSize();
-  return io::CodedOutputStream::VarintSize32(size) + size;
+  return LengthDelimitedSize(value.ByteSize());
 }
 
 // See comment on ReadGroupNoVirtual to understand the need for this template
@@ -763,8 +761,12 @@
 template<typename MessageType_WorkAroundCppLookupDefect>
 inline int WireFormatLite::MessageSizeNoVirtual(
     const MessageType_WorkAroundCppLookupDefect& value) {
-  int size = value.MessageType_WorkAroundCppLookupDefect::ByteSize();
-  return io::CodedOutputStream::VarintSize32(size) + size;
+  return LengthDelimitedSize(
+      value.MessageType_WorkAroundCppLookupDefect::ByteSize());
+}
+
+inline int WireFormatLite::LengthDelimitedSize(int length) {
+  return io::CodedOutputStream::VarintSize32(length) + length;
 }
 
 }  // namespace internal
diff --git a/third_party/protobuf/src/google/protobuf/wire_format_unittest.cc b/third_party/protobuf/src/google/protobuf/wire_format_unittest.cc
index 867970c..9822828 100644
--- a/third_party/protobuf/src/google/protobuf/wire_format_unittest.cc
+++ b/third_party/protobuf/src/google/protobuf/wire_format_unittest.cc
@@ -44,7 +44,7 @@
 #include <google/protobuf/stubs/common.h>
 #include <google/protobuf/testing/googletest.h>
 #include <gtest/gtest.h>
-#include <google/protobuf/stubs/stl_util-inl.h>
+#include <google/protobuf/stubs/stl_util.h>
 
 namespace google {
 namespace protobuf {
@@ -480,6 +480,54 @@
   EXPECT_EQ(message_set.DebugString(), dynamic_message_set.DebugString());
 }
 
+TEST(WireFormatTest, ParseMessageSetWithReverseTagOrder) {
+  string data;
+  {
+    unittest::TestMessageSetExtension1 message;
+    message.set_i(123);
+    // Build a MessageSet manually with its message content put before its
+    // type_id.
+    io::StringOutputStream output_stream(&data);
+    io::CodedOutputStream coded_output(&output_stream);
+    coded_output.WriteTag(WireFormatLite::kMessageSetItemStartTag);
+    // Write the message content first.
+    WireFormatLite::WriteTag(WireFormatLite::kMessageSetMessageNumber,
+                             WireFormatLite::WIRETYPE_LENGTH_DELIMITED,
+                             &coded_output);
+    coded_output.WriteVarint32(message.ByteSize());
+    message.SerializeWithCachedSizes(&coded_output);
+    // Write the type id.
+    uint32 type_id = message.GetDescriptor()->extension(0)->number();
+    WireFormatLite::WriteUInt32(WireFormatLite::kMessageSetTypeIdNumber,
+                                type_id, &coded_output);
+    coded_output.WriteTag(WireFormatLite::kMessageSetItemEndTag);
+  }
+  {
+    unittest::TestMessageSet message_set;
+    ASSERT_TRUE(message_set.ParseFromString(data));
+
+    EXPECT_EQ(123, message_set.GetExtension(
+        unittest::TestMessageSetExtension1::message_set_extension).i());
+  }
+  {
+    // Test parse the message via Reflection.
+    unittest::TestMessageSet message_set;
+    io::CodedInputStream input(
+        reinterpret_cast<const uint8*>(data.data()), data.size());
+    EXPECT_TRUE(WireFormat::ParseAndMergePartial(&input, &message_set));
+    EXPECT_TRUE(input.ConsumedEntireMessage());
+
+    EXPECT_EQ(123, message_set.GetExtension(
+        unittest::TestMessageSetExtension1::message_set_extension).i());
+  }
+}
+
+TEST(WireFormatTest, ParseBrokenMessageSet) {
+  unittest::TestMessageSet message_set;
+  string input("goodbye");  // Invalid wire format data.
+  EXPECT_FALSE(message_set.ParseFromString(input));
+}
+
 TEST(WireFormatTest, RecursionLimit) {
   unittest::TestRecursiveMessage message;
   message.mutable_a()->mutable_a()->mutable_a()->mutable_a()->set_i(1);
@@ -800,6 +848,10 @@
   return message->ParseFromArray(wire_buffer.data(), wire_buffer.size());
 }
 
+bool StartsWith(const string& s, const string& prefix) {
+  return s.substr(0, prefix.length()) == prefix;
+}
+
 TEST(Utf8ValidationTest, WriteInvalidUTF8String) {
   string wire_buffer;
   protobuf_unittest::OneString input;
@@ -811,11 +863,10 @@
   }
 #ifdef GOOGLE_PROTOBUF_UTF8_VALIDATION_ENABLED
   ASSERT_EQ(1, errors.size());
-  EXPECT_EQ("Encountered string containing invalid UTF-8 data while "
-            "serializing protocol buffer. Strings must contain only UTF-8; "
-            "use the 'bytes' type for raw bytes.",
-            errors[0]);
-
+  EXPECT_TRUE(StartsWith(errors[0],
+                         "String field contains invalid UTF-8 data when "
+                         "serializing a protocol buffer. Use the "
+                         "'bytes' type if you intend to send raw bytes."));
 #else
   ASSERT_EQ(0, errors.size());
 #endif  // GOOGLE_PROTOBUF_UTF8_VALIDATION_ENABLED
@@ -834,10 +885,10 @@
   }
 #ifdef GOOGLE_PROTOBUF_UTF8_VALIDATION_ENABLED
   ASSERT_EQ(1, errors.size());
-  EXPECT_EQ("Encountered string containing invalid UTF-8 data while "
-            "parsing protocol buffer. Strings must contain only UTF-8; "
-            "use the 'bytes' type for raw bytes.",
-            errors[0]);
+  EXPECT_TRUE(StartsWith(errors[0],
+                         "String field contains invalid UTF-8 data when "
+                         "parsing a protocol buffer. Use the "
+                         "'bytes' type if you intend to send raw bytes."));
 
 #else
   ASSERT_EQ(0, errors.size());
@@ -899,6 +950,28 @@
   EXPECT_EQ(input.data(), output.data());
 }
 
+TEST(Utf8ValidationTest, ParseRepeatedString) {
+  protobuf_unittest::MoreBytes input;
+  input.add_data(kValidUTF8String);
+  input.add_data(kInvalidUTF8String);
+  input.add_data(kInvalidUTF8String);
+  string wire_buffer = input.SerializeAsString();
+
+  protobuf_unittest::MoreString output;
+  vector<string> errors;
+  {
+    ScopedMemoryLog log;
+    ReadMessage(wire_buffer, &output);
+    errors = log.GetMessages(ERROR);
+  }
+#ifdef GOOGLE_PROTOBUF_UTF8_VALIDATION_ENABLED
+  ASSERT_EQ(2, errors.size());
+#else
+  ASSERT_EQ(0, errors.size());
+#endif  // GOOGLE_PROTOBUF_UTF8_VALIDATION_ENABLED
+  EXPECT_EQ(wire_buffer, output.SerializeAsString());
+}
+
 }  // namespace
 }  // namespace internal
 }  // namespace protobuf
diff --git a/third_party/protobuf/vsprojects/extract_includes.bat b/third_party/protobuf/vsprojects/extract_includes.bat
index 70fdf73..4dcb4e1 100755
--- a/third_party/protobuf/vsprojects/extract_includes.bat
+++ b/third_party/protobuf/vsprojects/extract_includes.bat
@@ -17,6 +17,7 @@
 copy ..\src\google\protobuf\descriptor_database.h include\google\protobuf\descriptor_database.h

 copy ..\src\google\protobuf\dynamic_message.h include\google\protobuf\dynamic_message.h

 copy ..\src\google\protobuf\extension_set.h include\google\protobuf\extension_set.h

+copy ..\src\google\protobuf\generated_enum_reflection.h include\google\protobuf\generated_enum_reflection.h

 copy ..\src\google\protobuf\generated_message_util.h include\google\protobuf\generated_message_util.h

 copy ..\src\google\protobuf\generated_message_reflection.h include\google\protobuf\generated_message_reflection.h

 copy ..\src\google\protobuf\message.h include\google\protobuf\message.h

diff --git a/third_party/widevine/cdm/widevine_cdm.gyp b/third_party/widevine/cdm/widevine_cdm.gyp
index 0d08bc6..a4185e6 100644
--- a/third_party/widevine/cdm/widevine_cdm.gyp
+++ b/third_party/widevine/cdm/widevine_cdm.gyp
@@ -56,9 +56,9 @@
             'widevine_cdm_binaries',
           ],
           'sources': [
-            '<(DEPTH)/webkit/renderer/media/crypto/ppapi/cdm_wrapper.cc',
-            '<(DEPTH)/webkit/renderer/media/crypto/ppapi/cdm/content_decryption_module.h',
-            '<(DEPTH)/webkit/renderer/media/crypto/ppapi/linked_ptr.h',
+            '<(DEPTH)/media/cdm/ppapi/api/content_decryption_module.h',
+            '<(DEPTH)/media/cdm/ppapi/cdm_wrapper.cc',
+            '<(DEPTH)/media/cdm/ppapi/linked_ptr.h',
           ],
           'conditions': [
             [ 'os_posix == 1 and OS != "mac"', {
diff --git a/tools/bisect_utils.py b/tools/bisect_utils.py
index 2847c2c..37869df 100644
--- a/tools/bisect_utils.py
+++ b/tools/bisect_utils.py
@@ -22,6 +22,8 @@
                               "chrome/data/page_cycler/.git",
       "src/data/dom_perf": "https://chrome-internal.googlesource.com/"
                            "chrome/data/dom_perf/.git",
+      "src/data/mach_ports": "https://chrome-internal.googlesource.com/"
+                           "chrome/data/mach_ports/.git",
       "src/tools/perf/data": "https://chrome-internal.googlesource.com/"
                              "chrome/tools/perf/data/.git",
       "src/third_party/adobe/flash/binaries/ppapi/linux":
diff --git a/tools/checklicenses/checklicenses.py b/tools/checklicenses/checklicenses.py
index 9c27256..25dedc2 100755
--- a/tools/checklicenses/checklicenses.py
+++ b/tools/checklicenses/checklicenses.py
@@ -128,10 +128,6 @@
     'data/tab_switching': [
         'UNKNOWN',
     ],
-    'googleurl': [  # http://code.google.com/p/google-url/issues/detail?id=15
-        'UNKNOWN',
-    ],
-
     'native_client': [  # http://crbug.com/98099
         'UNKNOWN',
     ],
diff --git a/tools/clang/plugins/ChromeClassTester.cpp b/tools/clang/plugins/ChromeClassTester.cpp
index 5784334..ee8452d 100644
--- a/tools/clang/plugins/ChromeClassTester.cpp
+++ b/tools/clang/plugins/ChromeClassTester.cpp
@@ -151,7 +151,6 @@
   banned_directories_.push_back("ppapi/");
   banned_directories_.push_back("usr/");
   banned_directories_.push_back("testing/");
-  banned_directories_.push_back("googleurl/");
   banned_directories_.push_back("v8/");
   banned_directories_.push_back("dart/");
   banned_directories_.push_back("sdch/");
diff --git a/tools/deep_memory_profiler/lib/sorter.py b/tools/deep_memory_profiler/lib/sorter.py
index db50c70..64e0851 100644
--- a/tools/deep_memory_profiler/lib/sorter.py
+++ b/tools/deep_memory_profiler/lib/sorter.py
@@ -20,6 +20,8 @@
     os.path.join(BASE_PATH, 'sorter.vm-sharing.json'),
     ]
 
+DEFAULT_TEMPLATES = os.path.join(BASE_PATH, 'templates.json')
+
 
 class Unit(object):
   """Represents a minimum unit of memory usage categorization.
@@ -152,7 +154,7 @@
   def __init__(self, dct):
     self._name = dct['name']
     self._hidden = dct.get('hidden', False)
-    self._subworlds = dct.get('subworlds', [])
+    self._subs = dct.get('subs', [])
 
   def match(self, unit):
     raise NotImplementedError()
@@ -165,9 +167,9 @@
   def hidden(self):
     return self._hidden
 
-  def iter_subworld(self):
-    for subworld in self._subworlds:
-      yield subworld
+  def iter_subs(self):
+    for sub in self._subs:
+      yield sub
 
 
 class VMRule(AbstractRule):
@@ -328,6 +330,7 @@
     self._version = dct['version']
     self._world = dct['world']
     self._name = dct['name']
+    self._root = dct.get('root', False)
     self._order = dct['order']
 
     self._rules = []
@@ -368,6 +371,10 @@
   def name(self):
     return self._name
 
+  @property
+  def root(self):
+    return self._root
+
   def find(self, unit):
     raise NotImplementedError()
 
@@ -414,6 +421,21 @@
     assert False
 
 
+class SorterTemplates(object):
+  """Represents a template for sorters."""
+  def __init__(self, dct):
+    self._dict = dct
+
+  def as_dict(self):
+    return self._dict
+
+  @staticmethod
+  def load(filename):
+    with open(filename) as templates_f:
+      templates_dict = json.load(templates_f)
+    return SorterTemplates(templates_dict)
+
+
 class SorterSet(object):
   """Represents an iterable set of Sorters."""
   def __init__(self, additional=None, default=None):
@@ -427,6 +449,7 @@
       if sorter.world not in self._sorters:
         self._sorters[sorter.world] = []
       self._sorters[sorter.world].append(sorter)
+    self._templates = SorterTemplates.load(DEFAULT_TEMPLATES)
 
   def __repr__(self):
     result = cStringIO.StringIO()
@@ -441,3 +464,7 @@
   def iter_world(self, world):
     for sorter in self._sorters.get(world, []):
       yield sorter
+
+  @property
+  def templates(self):
+    return self._templates
diff --git a/tools/deep_memory_profiler/sorter.vm-map.json b/tools/deep_memory_profiler/sorter.vm-map.json
index f26e866..7fc4d27 100644
--- a/tools/deep_memory_profiler/sorter.vm-map.json
+++ b/tools/deep_memory_profiler/sorter.vm-map.json
@@ -3,6 +3,7 @@
   "version": 1,
   "world": "vm",
   "name": "map",
+  "root": true,
   "order": {},
   "rules": [
     {
@@ -46,8 +47,11 @@
     {
       "name": "mmap-tcmalloc",
       "backtrace_function": ".*(DoAllocWithArena|SbrkSysAllocator::Alloc|MmapSysAllocator::Alloc|LowLevelAlloc::Alloc|LowLevelAlloc::AllocWithArena).*",
-      "mmap": true,
-      "subworlds": [ "malloc" ]
+      "subs": [
+        [ "malloc", "component" ],
+        [ "malloc", "type" ]
+      ],
+      "mmap": true
     },
     {
       "name": "mmap-v8-heap-newspace",
diff --git a/tools/deep_memory_profiler/sorter.vm-sharing.json b/tools/deep_memory_profiler/sorter.vm-sharing.json
index 788a5c3..4cb52a6 100644
--- a/tools/deep_memory_profiler/sorter.vm-sharing.json
+++ b/tools/deep_memory_profiler/sorter.vm-sharing.json
@@ -3,6 +3,7 @@
   "version": 1,
   "world": "vm",
   "name": "sharing",
+  "root": true,
   "order": {},
   "rules": [
     {
diff --git a/tools/deep_memory_profiler/subcommands/cat.py b/tools/deep_memory_profiler/subcommands/cat.py
index b7783b9..1e9e5b3 100644
--- a/tools/deep_memory_profiler/subcommands/cat.py
+++ b/tools/deep_memory_profiler/subcommands/cat.py
@@ -37,6 +37,9 @@
     (bucket_set, dumps) = SubCommand.load_basic_files(
         dump_path, True, alternative_dirs=alternative_dirs_dict)
 
+    # Load all sorters.
+    sorters = SorterSet()
+
     json_root = OrderedDict()
     json_root['version'] = 1
     json_root['run_id'] = None
@@ -46,10 +49,14 @@
         json_root['run_id'] = ''
         break
       json_root['run_id'] = dump.run_id
-    json_root['snapshots'] = []
+    json_root['roots'] = []
+    for sorter in sorters:
+      if sorter.root:
+        json_root['roots'].append([sorter.world, sorter.name])
+    json_root['default_template'] = 'l2'
+    json_root['templates'] = sorters.templates.as_dict()
 
-    # Load all sorters.
-    sorters = SorterSet()
+    json_root['snapshots'] = []
 
     for dump in dumps:
       json_root['snapshots'].append(
@@ -76,9 +83,9 @@
   def _fill_world(dump, bucket_set, sorters, world):
     root = OrderedDict()
 
-    root['name'] = 'world'
+    root['name'] = world
     if world == 'vm':
-      root['unit_fields'] = ['committed', 'reserved']
+      root['unit_fields'] = ['size', 'reserved']
     elif world == 'malloc':
       root['unit_fields'] = ['size', 'alloc_count', 'free_count']
 
@@ -107,11 +114,11 @@
           category = OrderedDict()
           category['name'] = found.name
           category['color'] = 'random'
-          subworlds = {}
-          for subworld in found.iter_subworld():
-            subworlds[subworld] = False
-          if subworlds:
-            category['subworlds'] = subworlds
+          subs = []
+          for sub_world, sub_breakdown in found.iter_subs():
+            subs.append([sub_world, sub_breakdown])
+          if subs:
+            category['subs'] = subs
           if found.hidden:
             category['hidden'] = True
           category['units'] = []
diff --git a/tools/deep_memory_profiler/templates.json b/tools/deep_memory_profiler/templates.json
new file mode 100644
index 0000000..b4d9a4e
--- /dev/null
+++ b/tools/deep_memory_profiler/templates.json
@@ -0,0 +1,12 @@
+{
+  "l2": ["vm", "map", {
+    "mmap-tcmalloc": ["malloc", "component", {}]
+  }],
+  "details": ["vm", "map", {
+    "mmap-tcmalloc": ["malloc", "component", {
+      "webkit": ["malloc", "webkit-details", {}],
+      "skia": ["malloc", "skia-details", {}]
+    }],
+    "mmap-v8-heap": ["javascript", "type", {}]
+  }]
+}
diff --git a/tools/heapcheck/suppressions.txt b/tools/heapcheck/suppressions.txt
index 5f767c1..5d03b7b 100644
--- a/tools/heapcheck/suppressions.txt
+++ b/tools/heapcheck/suppressions.txt
@@ -640,20 +640,6 @@
   fun:chromeos::input_method::InputMethodConfigurationTest_TestInitialize_Test::TestBody
 }
 {
-   bug_181691
-   Heapcheck:Leak
-   ...
-   fun:InitThread
-   fun:ShCompile
-   fun:gpu::gles2::ShaderTranslator::Translate
-   fun:gpu::gles2::ProgramManager::ForceCompileShader
-   fun:gpu::gles2::ProgramManager::DoCompileShader
-   fun:gpu::gles2::GLES2DecoderImpl::DoCompileShader
-   fun:gpu::gles2::GLES2DecoderImpl::HandleCompileShader
-   fun:gpu::gles2::GLES2DecoderImpl::DoCommand
-   fun:gpu::CommandParser::ProcessCommand
-}
-{
    bug_233532
    Heapcheck:Leak
    ...
@@ -855,3 +841,11 @@
    fun:net::NSSCertDatabase::DeleteCertAndKey
    fun:chromeos::NetworkCertMigratorTest::CleanupTestCert
 }
+{
+   bug_270312
+   Heapcheck:Leak
+   ...
+   fun:MessageCenterButtonBar
+   fun:MessageCenterView
+   fun:message_center::MessageCenterViewTest::SetUp
+}
diff --git a/tools/licenses.py b/tools/licenses.py
index 4d1cb01..d2c535b 100755
--- a/tools/licenses.py
+++ b/tools/licenses.py
@@ -82,7 +82,6 @@
     os.path.join('chrome', 'common', 'extensions', 'docs', 'examples'),
     os.path.join('chrome', 'test', 'chromeos', 'autotest'),
     os.path.join('chrome', 'test', 'data'),
-    os.path.join('googleurl'),
     os.path.join('native_client'),
     os.path.join('native_client_sdk'),
     os.path.join('net', 'tools', 'spdyshark'),
@@ -97,6 +96,7 @@
     os.path.join('tools', 'grit'),
     os.path.join('tools', 'gyp'),
     os.path.join('tools', 'page_cycler', 'acid3'),
+    os.path.join('url', 'third_party', 'mozilla'),
     os.path.join('v8'),
     # Fake directory so we can include the strongtalk license.
     os.path.join('v8', 'strongtalk'),
@@ -107,12 +107,6 @@
 # can't provide a README.chromium.  Please prefer a README.chromium
 # wherever possible.
 SPECIAL_CASES = {
-    os.path.join('googleurl'): {
-        "Name": "google-url",
-        "URL": "http://code.google.com/p/google-url/",
-        "License": "BSD and MPL 1.1/GPL 2.0/LGPL 2.1",
-        "License File": "LICENSE.txt",
-    },
     os.path.join('native_client'): {
         "Name": "native client",
         "URL": "http://code.google.com/p/nativeclient",
diff --git a/tools/metrics/actions/chromeactions.txt b/tools/metrics/actions/chromeactions.txt
index f8c62b7..3970b94 100644
--- a/tools/metrics/actions/chromeactions.txt
+++ b/tools/metrics/actions/chromeactions.txt
@@ -1071,6 +1071,7 @@
 0x9e77fb06de21d0b4	MobileContextMenuOpenLinkInIncognito
 0xa024c8dce2320bb1	MobileContextMenuOpenLinkInNewTab
 0xde20f676a6805404	MobileContextMenuSaveImage
+0xf123d71a7f1df18a	MobileContextMenuSearchByImage
 0x470fb8fde85c094b	MobileContextMenuShareLink
 0xb177bc454b6a2105	MobileContextMenuText
 0xac284cf4338f8a66	MobileContextMenuViewImage
@@ -1129,6 +1130,10 @@
 0x3deff4b1d1a6c795	MobileToolbarShowStackView
 0xa358306810cb78c4	MobileToolbarStackViewNewTab
 0x001b06917446ac95	MobileToolbarToggleBookmark
+0xfe5d7732799048fd	MobileUsingMenuByHwButtonDragging
+0xb25fb65d8d767718	MobileUsingMenuByHwButtonTap
+0xaf60773aea14a7b5	MobileUsingMenuBySwButtonDragging
+0x15fd6bb5bff45129	MobileUsingMenuBySwButtonTap
 0x409a073e57298782	MostVisited0
 0xaf4909be766297ab	MostVisited1
 0x6028c57529e1608f	MostVisited2
diff --git a/tools/metrics/actions/extract_actions.py b/tools/metrics/actions/extract_actions.py
index a1ea213..f6819af 100755
--- a/tools/metrics/actions/extract_actions.py
+++ b/tools/metrics/actions/extract_actions.py
@@ -212,6 +212,7 @@
   actions.add('MobileContextMenuOpenLinkInIncognito')
   actions.add('MobileContextMenuOpenLinkInNewTab')
   actions.add('MobileContextMenuSaveImage')
+  actions.add('MobileContextMenuSearchByImage')
   actions.add('MobileContextMenuShareLink')
   actions.add('MobileContextMenuText')
   actions.add('MobileContextMenuViewImage')
@@ -270,6 +271,10 @@
   actions.add('MobileToolbarShowStackView')
   actions.add('MobileToolbarStackViewNewTab')
   actions.add('MobileToolbarToggleBookmark')
+  actions.add('MobileUsingMenuByHwButtonDragging')
+  actions.add('MobileUsingMenuByHwButtonTap')
+  actions.add('MobileUsingMenuBySwButtonDragging')
+  actions.add('MobileUsingMenuBySwButtonTap')
   actions.add('SystemBack')
   actions.add('SystemBackForNavigation')
 
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml
index 3e7fe9d..f0c5161 100644
--- a/tools/metrics/histograms/histograms.xml
+++ b/tools/metrics/histograms/histograms.xml
@@ -1140,6 +1140,14 @@
 </histogram>
 
 <histogram name="CertificateType">
+  <obsolete>
+    Deprecated as of 8/2013. This histogram only considered the leaf certificate
+    expiry date as a proxy for whether a certificate was in-scope for the BRs,
+    but did not consider the issuance date. As some CAs have issued long-lived
+    certs prior to the BRs, this disproportionately reported those certs as
+    being subject to the BRs, but non-compliant, when in reality they're not
+    subject.
+  </obsolete>
   <summary>
     Information about the certificate algorithms and sizes in use on the web, to
     examine compliance with the CA/Browser Forum requirements and security best
@@ -1147,6 +1155,15 @@
   </summary>
 </histogram>
 
+<histogram name="CertificateType2">
+  <summary>
+    Information about the certificate algorithms and sizes in use on the web, to
+    examine compliance with the CA/Browser Forum requirements and security best
+    practice. This histogram considers the notBefore as the issuance date, for
+    purposes of what requirements apply.
+  </summary>
+</histogram>
+
 <histogram name="Chrome.SearchSelectExempt" enum="SearchEngine">
   <obsolete>
     Deprecated 8/2013. No longer tracked.
@@ -4056,6 +4073,14 @@
   </summary>
 </histogram>
 
+<histogram name="HistoryPage.ClickPositionSubset">
+  <summary>
+    Subset of the Click Position histogram. Contains only the first smaller
+    subset of entries on the page. Number of entries that the clicked entry is
+    older than in History page. Last bucket is entries of that value or higher.
+  </summary>
+</histogram>
+
 <histogram name="HistoryPage.OtherDevicesMenu" enum="NtpOtherSessionsType">
   <summary>
     Histogram for usage of the section in the history page that allows the user
@@ -4071,6 +4096,16 @@
   </summary>
 </histogram>
 
+<histogram name="HistoryPage.RemoveEntryPositionSubset">
+  <summary>
+    Subset of Remove Entry Position histogram. Contains only the first smaller
+    subset of entries on the page. Number of entries that the deleted entry is
+    older than in History page. Last bucket is any entry of that value or
+    higher. Confirmed removal is not guaranteed, just an initiation of 'Remove
+    selected items'.
+  </summary>
+</histogram>
+
 <histogram name="HttpCache.EntryLockWait" units="milliseconds">
   <summary>
     The time spent waiting for write lock on a disk cache entry.
@@ -7110,6 +7145,10 @@
   </summary>
 </histogram>
 
+<histogram name="Net.QuicSession.QuicVersion">
+  <summary>Version of the QUIC protocol used for this connection.</summary>
+</histogram>
+
 <histogram name="Net.RenegotiationExtensionSupported">
   <summary>
     True if the HTTP request was sent to a server which supports the TLS
@@ -7117,6 +7156,13 @@
   </summary>
 </histogram>
 
+<histogram name="Net.ResourceLoader.ReadDeferral" units="milliseconds">
+  <summary>
+    When starting a cross-site navigation, the time between reading the headers
+    and body of the response.
+  </summary>
+</histogram>
+
 <histogram name="Net.SocketIdleTimeBeforeNextUse_ReusedSocket">
   <summary>The time an already used socket sat idle before being used.</summary>
 </histogram>
@@ -9653,6 +9699,13 @@
   </summary>
 </histogram>
 
+<histogram name="Platform.DiskUsage.NumUserHomeDirectories"
+    units="home directories">
+  <summary>
+    Number of users home directories on the device. Logged once a day.
+  </summary>
+</histogram>
+
 <histogram name="Platform.DiskUsage.OldestUserOnDevice">
   <summary>
     Days since last login of the least recently user on device. Logged once a
@@ -13233,6 +13286,20 @@
   </summary>
 </histogram>
 
+<histogram name="Settings.HomePageIsNewTabPage.PulledFromSync" enum="Boolean">
+  <summary>
+    The value of the home-page-is-new-tab-page pref when pulled down from sync
+    to update an out-of-sync local pref store.
+  </summary>
+</histogram>
+
+<histogram name="Settings.HomePageIsNewTabPage.PushedToSync" enum="Boolean">
+  <summary>
+    The value of the home-page-is-new-tab-page pref when pushed up to sync from
+    a change made locally.
+  </summary>
+</histogram>
+
 <histogram name="Settings.ShowHomeButton" enum="BooleanEnabled">
   <summary>
     Whether or not the home button is enabled in user preferences when a profile
@@ -13240,10 +13307,39 @@
   </summary>
 </histogram>
 
+<histogram name="Settings.ShowHomeButton.PulledFromSync" enum="BooleanEnabled">
+  <summary>
+    The enabled state of the Home button pref when pulled down from sync to
+    update an out-of-sync local pref store.
+  </summary>
+</histogram>
+
+<histogram name="Settings.ShowHomeButton.PushedToSync" enum="BooleanEnabled">
+  <summary>
+    The enabled state of the Home button pref when pushed up to sync from a
+    change made locally.
+  </summary>
+</histogram>
+
 <histogram name="Settings.StartupPageLoadSettings" enum="SessionStartupPref">
   <summary>The startup page settings when a profile is loaded.</summary>
 </histogram>
 
+<histogram name="Settings.StartupPageLoadSettings.PulledFromSync"
+    enum="SessionStartupPref">
+  <summary>
+    The startup page setting when pulled down from sync to update an out-of-sync
+    local pref store.
+  </summary>
+</histogram>
+
+<histogram name="Settings.StartupPageLoadSettings.PushedToSync"
+    enum="SessionStartupPref">
+  <summary>
+    The startup page setting when pushed up to sync from a change made locally.
+  </summary>
+</histogram>
+
 <histogram name="Settings.StartupPageLoadURLs">
   <summary>
     The number of URLs to be loaded on startup when a profile is loaded, if the
@@ -14573,6 +14669,21 @@
   </summary>
 </histogram>
 
+<histogram name="UserManager.LoginUserType" enum="UserType">
+  <summary>
+    The number of users of different types that log in to the system (Chrome
+    OS).
+  </summary>
+</histogram>
+
+<histogram name="UserManager.LogoutToLoginDelay" units="seconds">
+  <summary>
+    The time between one regular user logging out and a different regular user
+    logging in (Chrome OS). Delays above thirty minutes or which span system
+    reboots or non-regular-user logins are not reported.
+  </summary>
+</histogram>
+
 <histogram name="Variations.DisabledNoEntropyProvider" enum="BooleanHit">
   <obsolete>
     Deprecated 1/2013. No longer tracked.
@@ -15052,7 +15163,52 @@
   </summary>
 </histogram>
 
+<histogram name="WebFont.DownloadTime.0.Under10KB" units="milliseconds">
+  <summary>
+    The time it takes for a webfont download to finish, for webfonts of under
+    10KB.
+  </summary>
+</histogram>
+
+<histogram name="WebFont.DownloadTime.1.10KBTo50KB" units="milliseconds">
+  <summary>
+    The time it takes for a webfont download to finish, for webfonts of
+    10KB-50KB.
+  </summary>
+</histogram>
+
+<histogram name="WebFont.DownloadTime.2.50KBTo100KB" units="milliseconds">
+  <summary>
+    The time it takes for a webfont download to finish, for webfonts of
+    50KB-100KB.
+  </summary>
+</histogram>
+
+<histogram name="WebFont.DownloadTime.3.100KBTo1MB" units="milliseconds">
+  <summary>
+    The time it takes for a webfont download to finish, for webfonts of
+    100KB-1MB.
+  </summary>
+</histogram>
+
+<histogram name="WebFont.DownloadTime.4.Over1MB" units="milliseconds">
+  <summary>
+    The time it takes for a webfont download to finish, for webfonts of over
+    1MB.
+  </summary>
+</histogram>
+
+<histogram name="WebFont.DownloadTime.LoadError" units="milliseconds">
+  <summary>
+    The time taken for a webfont download that failed. Includes aborted
+    requests.
+  </summary>
+</histogram>
+
 <histogram name="WebFont.LoadTime.0.Under10KB" units="milliseconds">
+  <obsolete>
+    Deprecated as of 8/2013, replaced by WebFont.DownloadTime.0.Under10KB.
+  </obsolete>
   <summary>
     The time it takes for a webfont download to finish, for webfonts of under
     10KB.
@@ -15060,6 +15216,9 @@
 </histogram>
 
 <histogram name="WebFont.LoadTime.1.10KBTo50KB" units="milliseconds">
+  <obsolete>
+    Deprecated as of 8/2013, replaced by WebFont.DownloadTime.1.10KBTo50KB.
+  </obsolete>
   <summary>
     The time it takes for a webfont download to finish, for webfonts of
     10KB-50KB.
@@ -15067,6 +15226,9 @@
 </histogram>
 
 <histogram name="WebFont.LoadTime.2.50KBTo100KB" units="milliseconds">
+  <obsolete>
+    Deprecated as of 8/2013, replaced by WebFont.DownloadTime.2.50KBTo100KB.
+  </obsolete>
   <summary>
     The time it takes for a webfont download to finish, for webfonts of
     50KB-100KB.
@@ -15074,6 +15236,9 @@
 </histogram>
 
 <histogram name="WebFont.LoadTime.3.100KBTo1MB" units="milliseconds">
+  <obsolete>
+    Deprecated as of 8/2013, replaced by WebFont.DownloadTime.3.100KBTo1MB.
+  </obsolete>
   <summary>
     The time it takes for a webfont download to finish, for webfonts of
     100KB-1MB.
@@ -15081,6 +15246,9 @@
 </histogram>
 
 <histogram name="WebFont.LoadTime.4.Over1MB" units="milliseconds">
+  <obsolete>
+    Deprecated as of 8/2013, replaced by WebFont.DownloadTime.4.Over1MB.
+  </obsolete>
   <summary>
     The time it takes for a webfont download to finish, for webfonts of over
     1MB.
@@ -15088,6 +15256,9 @@
 </histogram>
 
 <histogram name="WebFont.LoadTime.LoadError" units="milliseconds">
+  <obsolete>
+    Deprecated as of 8/2013, replaced by WebFont.DownloadTime.LoadError.
+  </obsolete>
   <summary>
     The time taken for a webfont download that failed. Includes aborted
     requests.
@@ -16182,8 +16353,8 @@
   <int value="7" label="Cancelled"/>
   <int value="8" label="Started"/>
   <int value="9" label="Interrupted"/>
-  <int value="10" label="Calls to AppendDataToFile (Size)"/>
-  <int value="11" label="Calls to AppendDataToFile (Count)"/>
+  <int value="10" label="Calls to AppendDataToFile (Size) (Obsolete)"/>
+  <int value="11" label="Calls to AppendDataToFile (Count) (Obsolete)"/>
   <int value="12" label="Interrupted at End of Download"/>
   <int value="13" label="Attempt to Append to Detached File"/>
   <int value="14" label="File Missing After Successful Scan"/>
@@ -17450,6 +17621,7 @@
   <int value="514" label="SYSTEM_STORAGE_GETALLAVAILABLECAPACITYWATCHES"/>
   <int value="515" label="SYSTEM_STORAGE_REMOVEALLAVAILABLECAPACITYWATCHES"/>
   <int value="516" label="INFOBARS_SHOW"/>
+  <int value="517" label="EXPERIMENTAL_INPUT_VIRTUALKEYBOARD_MOVECURSOR"/>
 </enum>
 
 <enum name="ExtensionInstallCause" type="int">
@@ -21980,6 +22152,8 @@
   <int value="11" label="SHOW_UNDERSTAND"/>
   <int value="12" label="SHOW_INTERNAL_HOSTNAME"/>
   <int value="13" label="PROCEED_INTERNAL_HOSTNAME"/>
+  <int value="14" label="SHOW_NEW_SITE"/>
+  <int value="15" label="PROCEED_NEW_SITE"/>
 </enum>
 
 <enum name="SuspendStatus" type="int">
@@ -22002,6 +22176,8 @@
   <int value="3" label="Partially evicted"/>
   <int value="4" label="Reloaded due to backgrounding"/>
   <int value="5" label="Reloaded due to incognito"/>
+  <int value="6" label="Reloaded due to cold start (fg tab on start)"/>
+  <int value="7" label="Reloaded due to cold start (bg tab on switch)"/>
 </enum>
 
 <enum name="TabSwitchedToForegroundLaunchedWithURL" type="int">
@@ -22241,6 +22417,15 @@
   <int value="10" label="kFileSystemScheme"/>
 </enum>
 
+<enum name="UserType" type="int">
+  <int value="0" label="Regular"/>
+  <int value="1" label="Guest"/>
+  <int value="2" label="Retail Mode"/>
+  <int value="3" label="Public Account"/>
+  <int value="4" label="Locally Managed"/>
+  <int value="5" label="Kiosk App"/>
+</enum>
+
 <enum name="VariationsResourceRequestsAllowedState" type="int">
   <int value="0" label="Resource requests allowed"/>
   <int value="1" label="Resource requests not allowed"/>
@@ -22375,6 +22560,9 @@
   <int value="8" label="Spending limit exceeded"/>
   <int value="9" label="Unsupported API version"/>
   <int value="10" label="Unknown error"/>
+  <int value="11" label="Unsupported merchant"/>
+  <int value="12" label="Unsupported buyer legal address"/>
+  <int value="13" label="Unverified know your customer status"/>
 </enum>
 
 <enum name="WalletRequiredActions" type="int">
@@ -22613,9 +22801,23 @@
   <affected-histogram name="CertificateType.NonBR.Intermediate"/>
   <affected-histogram name="CertificateType.NonBR.Leaf"/>
   <affected-histogram name="CertificateType.NonBR.Root"/>
+  <affected-histogram name="CertificateType2.BR.Intermediate"/>
+  <affected-histogram name="CertificateType2.BR.Leaf"/>
+  <affected-histogram name="CertificateType2.BR.Root"/>
+  <affected-histogram name="CertificateType2.NonBR.Intermediate"/>
+  <affected-histogram name="CertificateType2.NonBR.Leaf"/>
+  <affected-histogram name="CertificateType2.NonBR.Root"/>
 </fieldtrial>
 
 <fieldtrial name="CertificateTypeBRValidity" separator=".">
+  <obsolete>
+    Deprecated as of 8/2013. This histogram only considered the leaf certificate
+    expiry date as a proxy for whether a certificate was in-scope for the BRs,
+    but did not consider the issuance date. As some CAs have issued long-lived
+    certs prior to the BRs, this disproportionately reported those certs as
+    being subject to the BRs, but non-compliant, when in reality they're not
+    subject.
+  </obsolete>
   <group name="BR"
       label="The *leaf* certificate of the chain expires after 2013-12-31,
              meaning that it should be in scope for the Baseline
@@ -22626,12 +22828,26 @@
   <affected-histogram name="CertificateType"/>
 </fieldtrial>
 
+<fieldtrial name="CertificateTypeBRValidity2" separator=".">
+  <group name="BR"
+      label="The *leaf* certificate of the chain expires after 2013-12-31 and
+             was issued on or after 2012-07-01, as judged by the notBefore,
+             meaning that it should be in scope for the Baseline
+             Requirement's key size requirements"/>
+  <group name="NonBR"
+      label="The *leaf* certificate of the chain expires on or before
+             2013-12-31 or was issued before 2012-07-01"/>
+  <affected-histogram name="CertificateType2"/>
+</fieldtrial>
+
 <fieldtrial name="CertificateTypeChainPosition" separator=".">
   <group name="Intermediate" label="Intermediate's SPKI"/>
   <group name="Leaf" label="Leaf's SPKI"/>
   <group name="Root" label="Root's SPKI"/>
   <affected-histogram name="CertificateType.BR"/>
   <affected-histogram name="CertificateType.NonBR"/>
+  <affected-histogram name="CertificateType2.BR"/>
+  <affected-histogram name="CertificateType2.NonBR"/>
 </fieldtrial>
 
 <fieldtrial name="ConnCountImpact">
diff --git a/tools/perf/benchmarks/pica.py b/tools/perf/benchmarks/pica.py
index fed16b6..01920bd 100644
--- a/tools/perf/benchmarks/pica.py
+++ b/tools/perf/benchmarks/pica.py
@@ -2,45 +2,15 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-import os
-
 from telemetry import test
-from telemetry.core import util
 from telemetry.page import page_measurement
-from telemetry.page import page_set
-
 
 class PicaMeasurement(page_measurement.PageMeasurement):
-  def WillNavigateToPage(self, page, tab):
-    page.script_to_evaluate_on_commit = """
-      document.addEventListener('WebComponentsReady', function() {
-        var unused = document.body.offsetHeight; // force layout
-        window.__pica_load_time = performance.now();
-      });
-    """
-
   def MeasurePage(self, _, tab, results):
-    def _IsDone():
-      return tab.EvaluateJavaScript('window.__pica_load_time != undefined')
-    util.WaitFor(_IsDone, 60)
-
     result = int(tab.EvaluateJavaScript('__pica_load_time'))
     results.Add('Total', 'ms', result)
 
 
 class Pica(test.Test):
   test = PicaMeasurement
-
-  def CreatePageSet(self, options):
-    return page_set.PageSet.FromDict({
-        'archive_data_file': '../data/pica.json',
-        # Pica requires non-deterministic Date and Math.random calls
-        # See http://crbug.com/255641
-        'make_javascript_deterministic': False,
-        'pages': [
-          {
-            'url': 'http://www.polymer-project.org/'
-                   'polymer-all/projects/pica/index.html'
-          }
-        ]
-      }, os.path.abspath(__file__))
+  page_set = 'page_sets/pica.json'
diff --git a/tools/perf/measurements/smoothness.py b/tools/perf/measurements/smoothness.py
index a553e95..4bdbe07 100644
--- a/tools/perf/measurements/smoothness.py
+++ b/tools/perf/measurements/smoothness.py
@@ -3,6 +3,7 @@
 # found in the LICENSE file.
 from metrics import loading
 from metrics import smoothness
+from metrics.gpu_rendering_stats import GpuRenderingStats
 from telemetry.page import page_measurement
 
 class DidNotScrollException(page_measurement.MeasurementFailure):
@@ -59,11 +60,9 @@
     loading.LoadingMetric().AddResults(tab, results)
 
     smoothness.CalcFirstPaintTimeResults(results, tab)
-    smoothness.CalcScrollResults(rendering_stats_deltas, results)
-    smoothness.CalcTextureUploadResults(rendering_stats_deltas, results)
-    smoothness.CalcImageDecodingResults(rendering_stats_deltas, results)
-    smoothness.CalcAnalysisResults(rendering_stats_deltas, results)
-    smoothness.CalcLatencyResults(rendering_stats_deltas, results)
+
+    benchmark_stats = GpuRenderingStats(rendering_stats_deltas)
+    smoothness.CalcResults(benchmark_stats, results)
 
     if self.options.report_all_results:
       for k, v in rendering_stats_deltas.iteritems():
diff --git a/tools/perf/metrics/gpu_rendering_stats.py b/tools/perf/metrics/gpu_rendering_stats.py
new file mode 100644
index 0000000..9af9f9e
--- /dev/null
+++ b/tools/perf/metrics/gpu_rendering_stats.py
@@ -0,0 +1,47 @@
+# 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.
+
+class GpuRenderingStats(object):
+  def __init__(self, rendering_stats_deltas):
+    rs = rendering_stats_deltas
+
+    # Scroll Stats
+    self.total_time = rs.get('totalTimeInSeconds', 0)
+    self.screen_frame_count = rs.get('numFramesSentToScreen', 0)
+    self.dropped_frame_count = rs.get('droppedFrameCount', 0)
+    self.impl_thread_scroll_count = rs.get('numImplThreadScrolls', 0)
+    self.main_thread_scroll_count = rs.get('numMainThreadScrolls', 0)
+    self.drawn_layers_count = rs.get('numLayersDrawn', 0)
+    self.missing_tile_count = rs.get('numMissingTiles', 0)
+
+    # Texture Upload Stats
+    self.texture_upload_count = rs.get('textureUploadCount', 0)
+    self.texture_upload_time = rs.get('totalTextureUploadTimeInSeconds', 0)
+    self.commit_count = rs.get('totalCommitCount', 0)
+    self.commit_time = rs.get('totalCommitTimeInSeconds', 0)
+
+    # Image Decoding Stats
+    self.deferred_image_decode_count = rs.get(
+        'totalDeferredImageDecodeCount', 0)
+    self.deferred_image_decode_time = rs.get(
+        'totalDeferredImageDecodeTimeInSeconds', 0)
+    self.deferred_image_cache_hits = rs.get(
+        'totalDeferredImageCacheHitCount', 0)
+    self.image_gathering_count = rs.get('totalImageGatheringCount', 0)
+    self.image_gathering_time = rs.get('totalImageGatheringTimeInSeconds', 0)
+
+    # Tile Analysis Stats
+    self.tile_analysis_count = rs.get('totalTilesAnalyzed', 0)
+    self.tile_analysis_time = rs.get('totalTileAnalysisTimeInSeconds', 0)
+    self.solid_color_tile_analysis_count = rs.get('solidColorTilesAnalyzed', 0)
+
+    # Latency Stats
+    self.input_event_count = rs.get('inputEventCount', 0)
+    self.input_event_latency = rs.get('totalInputLatency', 0)
+    self.touch_ui_count = rs.get('touchUICount', 0)
+    self.touch_ui_latency = rs.get('totalTouchUILatency', 0)
+    self.touch_acked_count = rs.get('touchAckedCount', 0)
+    self.touch_acked_latency = rs.get('totalTouchAckedLatency', 0)
+    self.scroll_update_count = rs.get('scrollUpdateCount', 0)
+    self.scroll_update_latency = rs.get('totalScrollUpdateLatency', 0)
diff --git a/tools/perf/metrics/smoothness.py b/tools/perf/metrics/smoothness.py
index f4ebfbc..c4ec7bc 100644
--- a/tools/perf/metrics/smoothness.py
+++ b/tools/perf/metrics/smoothness.py
@@ -51,66 +51,15 @@
     return self._tab.EvaluateJavaScript(
       'window.__renderingStats.getDeltas()')
 
-
-def DivideIfPossibleOrZero(numerator, denominator):
+def Average(numerator, denominator, scale = None, precision = None):
   if denominator == 0:
     return 0
-  return numerator / denominator
-
-def CalcScrollResults(rendering_stats_deltas, results):
-  num_frames_sent_to_screen = rendering_stats_deltas['numFramesSentToScreen']
-
-  mean_frame_time_seconds = (
-    rendering_stats_deltas['totalTimeInSeconds'] /
-      float(num_frames_sent_to_screen))
-
-  dropped_percent = (
-    rendering_stats_deltas['droppedFrameCount'] /
-    float(num_frames_sent_to_screen))
-
-  num_impl_thread_scrolls = rendering_stats_deltas.get(
-    'numImplThreadScrolls', 0)
-  num_main_thread_scrolls = rendering_stats_deltas.get(
-    'numMainThreadScrolls', 0)
-
-  percent_impl_scrolled = DivideIfPossibleOrZero(
-    float(num_impl_thread_scrolls),
-    num_impl_thread_scrolls + num_main_thread_scrolls)
-
-  num_layers = (
-      rendering_stats_deltas.get('numLayersDrawn', 0) /
-      float(num_frames_sent_to_screen))
-
-  num_missing_tiles = (
-      rendering_stats_deltas.get('numMissingTiles', 0) /
-      float(num_frames_sent_to_screen))
-
-  results.Add('mean_frame_time', 'ms', round(mean_frame_time_seconds * 1000, 3))
-  results.Add('dropped_percent', '%', round(dropped_percent * 100, 1),
-              data_type='unimportant')
-  results.Add('percent_impl_scrolled', '%',
-              round(percent_impl_scrolled * 100, 1),
-              data_type='unimportant')
-  results.Add('average_num_layers_drawn', '', round(num_layers, 1),
-              data_type='unimportant')
-  results.Add('average_num_missing_tiles', '', round(num_missing_tiles, 1),
-              data_type='unimportant')
-
-def CalcTextureUploadResults(rendering_stats_deltas, results):
-  if (('totalCommitCount' not in rendering_stats_deltas)
-      or rendering_stats_deltas['totalCommitCount'] == 0) :
-    averageCommitTimeMs = 0
-  else :
-    averageCommitTimeMs = (
-        1000 * rendering_stats_deltas['totalCommitTimeInSeconds'] /
-        rendering_stats_deltas['totalCommitCount'])
-
-  results.Add('texture_upload_count', 'count',
-              rendering_stats_deltas.get('textureUploadCount', 0))
-  results.Add('total_texture_upload_time', 'seconds',
-              rendering_stats_deltas.get('totalTextureUploadTimeInSeconds', 0))
-  results.Add('average_commit_time', 'ms', averageCommitTimeMs,
-              data_type='unimportant')
+  avg = float(numerator) / float(denominator)
+  if scale:
+    avg *= scale
+  if precision:
+    avg = round(avg, precision)
+  return avg
 
 def CalcFirstPaintTimeResults(results, tab):
   if tab.browser.is_content_shell:
@@ -131,72 +80,78 @@
 
   results.Add('first_paint', 'ms', round(first_paint_secs * 1000, 1))
 
-def CalcImageDecodingResults(rendering_stats_deltas, results):
-  totalDeferredImageDecodeCount = rendering_stats_deltas.get(
-      'totalDeferredImageDecodeCount', 0)
-  totalDeferredImageCacheHitCount = rendering_stats_deltas.get(
-      'totalDeferredImageCacheHitCount', 0)
-  totalImageGatheringCount = rendering_stats_deltas.get(
-      'totalImageGatheringCount', 0)
-  totalDeferredImageDecodeTimeInSeconds = rendering_stats_deltas.get(
-      'totalDeferredImageDecodeTimeInSeconds', 0)
-  totalImageGatheringTimeInSeconds = rendering_stats_deltas.get(
-      'totalImageGatheringTimeInSeconds', 0)
+def CalcResults(benchmark_stats, results):
+  s = benchmark_stats
 
-  averageImageGatheringTime = DivideIfPossibleOrZero(
-      (totalImageGatheringTimeInSeconds * 1000), totalImageGatheringCount)
+  # Scroll Results
+  results.Add('mean_frame_time', 'ms',
+              Average(s.total_time, s.screen_frame_count, 1000, 3))
+  results.Add('dropped_percent', '%',
+              Average(s.dropped_frame_count, s.screen_frame_count,
+                      100, 1),
+              data_type='unimportant')
+  results.Add('percent_impl_scrolled', '%',
+              Average(s.impl_thread_scroll_count,
+                      s.impl_thread_scroll_count +
+                      s.main_thread_scroll_count,
+                      100, 1),
+              data_type='unimportant')
+  results.Add('average_num_layers_drawn', '',
+              Average(s.drawn_layers_count, s.screen_frame_count, 1, 1),
+              data_type='unimportant')
+  results.Add('average_num_missing_tiles', '',
+              Average(s.missing_tile_count, s.screen_frame_count, 1, 1),
+              data_type='unimportant')
 
+  # Texture Upload Results
+  results.Add('average_commit_time', 'ms',
+              Average(s.commit_time, s.commit_count, 1000, 3),
+              data_type='unimportant')
+  results.Add('texture_upload_count', 'count',
+              s.texture_upload_count)
+  results.Add('total_texture_upload_time', 'seconds',
+              s.texture_upload_time)
+
+  # Image Decoding Results
   results.Add('total_deferred_image_decode_count', 'count',
-              totalDeferredImageDecodeCount,
+              s.deferred_image_decode_count,
               data_type='unimportant')
   results.Add('total_image_cache_hit_count', 'count',
-              totalDeferredImageCacheHitCount,
+              s.deferred_image_cache_hits,
               data_type='unimportant')
-  results.Add('average_image_gathering_time', 'ms', averageImageGatheringTime,
+  results.Add('average_image_gathering_time', 'ms',
+              Average(s.image_gathering_time, s.image_gathering_count,
+                      1000, 3),
               data_type='unimportant')
   results.Add('total_deferred_image_decoding_time', 'seconds',
-              totalDeferredImageDecodeTimeInSeconds,
+              s.deferred_image_decode_time,
               data_type='unimportant')
 
-def CalcAnalysisResults(rendering_stats_deltas, results):
-  totalTilesAnalyzed = rendering_stats_deltas.get(
-      'totalTilesAnalyzed', 0)
-  solidColorTilesAnalyzed = rendering_stats_deltas.get(
-      'solidColorTilesAnalyzed', 0)
-  totalTileAnalysisTimeInSeconds = rendering_stats_deltas.get(
-      'totalTileAnalysisTimeInSeconds', 0)
-
-  averageAnalysisTimeMS = \
-      1000 * DivideIfPossibleOrZero(totalTileAnalysisTimeInSeconds,
-                                    totalTilesAnalyzed)
-
+  # Tile Analysis Results
   results.Add('total_tiles_analyzed', 'count',
-              totalTilesAnalyzed,
+              s.tile_analysis_count,
               data_type='unimportant')
   results.Add('solid_color_tiles_analyzed', 'count',
-              solidColorTilesAnalyzed,
+              s.solid_color_tile_analysis_count,
               data_type='unimportant')
   results.Add('average_tile_analysis_time', 'ms',
-              averageAnalysisTimeMS,
+              Average(s.tile_analysis_time, s.tile_analysis_count,
+                      1000, 3),
               data_type='unimportant')
 
-def CalcLatency(rendering_stats_deltas, count_name, total_latency_name,
-                result_name, results):
-  eventCount = rendering_stats_deltas.get(count_name, 0)
-  totalLatencyInSeconds = rendering_stats_deltas.get(total_latency_name, 0)
-  averageLatency = DivideIfPossibleOrZero(
-      (totalLatencyInSeconds * 1000), eventCount)
-  results.Add(result_name, 'ms', averageLatency, data_type='unimportant')
-
-def CalcLatencyResults(rendering_stats_deltas, results):
-  CalcLatency(rendering_stats_deltas, 'inputEventCount', 'totalInputLatency',
-              'average_latency', results)
-  CalcLatency(rendering_stats_deltas, 'touchUICount', 'totalTouchUILatency',
-              'average_touch_ui_latency', results)
-  CalcLatency(rendering_stats_deltas, 'touchAckedCount',
-              'totalTouchAckedLatency',
-              'average_touch_acked_latency',
-              results)
-  CalcLatency(rendering_stats_deltas, 'scrollUpdateCount',
-              'totalScrollUpdateLatency',
-              'average_scroll_update_latency', results)
+  # Latency Results
+  results.Add('average_latency', 'ms',
+              Average(s.input_event_latency, s.input_event_count,
+                      1000, 3),
+              data_type='unimportant')
+  results.Add('average_touch_ui_latency', 'ms',
+              Average(s.touch_ui_latency, s.touch_ui_count, 1000, 3),
+              data_type='unimportant')
+  results.Add('average_touch_acked_latency', 'ms',
+              Average(s.touch_acked_latency, s.touch_acked_count,
+                      1000, 3),
+              data_type='unimportant')
+  results.Add('average_scroll_update_latency', 'ms',
+              Average(s.scroll_update_latency, s.scroll_update_count,
+                      1000, 3),
+              data_type='unimportant')
diff --git a/tools/perf/metrics/smoothness_unittest.py b/tools/perf/metrics/smoothness_unittest.py
index e7b8778..2a42f9d 100644
--- a/tools/perf/metrics/smoothness_unittest.py
+++ b/tools/perf/metrics/smoothness_unittest.py
@@ -4,43 +4,110 @@
 import unittest
 
 from metrics import smoothness
+from metrics.gpu_rendering_stats import GpuRenderingStats
 from telemetry.page import page
 from telemetry.page.page_measurement_results import PageMeasurementResults
 
 class SmoothnessMetricsUnitTest(unittest.TestCase):
-
-  def testCalcResultsFromRAFRenderStats(self):
-    rendering_stats = {'droppedFrameCount': 5,
-                       'totalTimeInSeconds': 1,
-                       'numAnimationFrames': 10,
-                       'numFramesSentToScreen': 10}
-    res = PageMeasurementResults()
-    res.WillMeasurePage(page.Page('http://foo.com/', None))
-    smoothness.CalcScrollResults(rendering_stats, res)
-    res.DidMeasurePage()
-    self.assertEquals(50, res.page_results[0]['dropped_percent'].value)
-    self.assertAlmostEquals(
-      100,
-      res.page_results[0]['mean_frame_time'].value, 2)
-
   def testCalcResultsRealRenderStats(self):
-    rendering_stats = {'numFramesSentToScreen': 60,
-                       'globalTotalTextureUploadTimeInSeconds': 0,
-                       'totalProcessingCommandsTimeInSeconds': 0,
-                       'globalTextureUploadCount': 0,
-                       'droppedFrameCount': 0,
-                       'textureUploadCount': 0,
-                       'numAnimationFrames': 10,
-                       'totalPaintTimeInSeconds': 0.35374299999999986,
-                       'globalTotalProcessingCommandsTimeInSeconds': 0,
-                       'totalTextureUploadTimeInSeconds': 0,
-                       'totalRasterizeTimeInSeconds': 0,
-                       'totalTimeInSeconds': 1.0}
+    mock_rendering_stats_deltas = {
+        'totalTimeInSeconds': 1.0,
+        'numFramesSentToScreen': 100,
+        'droppedFrameCount': 20,
+        'numImplThreadScrolls': 50,
+        'numMainThreadScrolls': 50,
+        'numLayersDrawn': 240,
+        'numMissingTiles': 10,
+        'textureUploadCount': 120,
+        'totalTextureUploadTimeInSeconds': 1.2,
+        'totalCommitCount': 130,
+        'totalCommitTimeInSeconds': 1.3,
+        'totalDeferredImageDecodeCount': 140,
+        'totalDeferredImageDecodeTimeInSeconds': 1.4,
+        'totalDeferredImageCacheHitCount': 30,
+        'totalImageGatheringCount': 150,
+        'totalImageGatheringTimeInSeconds': 1.5,
+        'totalTilesAnalyzed': 160,
+        'totalTileAnalysisTimeInSeconds': 1.6,
+        'solidColorTilesAnalyzed': 40,
+        'inputEventCount': 170,
+        'totalInputLatency': 1.7,
+        'touchUICount': 180,
+        'totalTouchUILatency': 1.8,
+        'touchAckedCount': 190,
+        'totalTouchAckedLatency': 1.9,
+        'scrollUpdateCount': 200,
+        'totalScrollUpdateLatency': 2.0}
+    stats = GpuRenderingStats(mock_rendering_stats_deltas)
+
     res = PageMeasurementResults()
     res.WillMeasurePage(page.Page('http://foo.com/', None))
-    smoothness.CalcScrollResults(rendering_stats, res)
+    smoothness.CalcResults(stats, res)
     res.DidMeasurePage()
-    self.assertEquals(0, res.page_results[0]['dropped_percent'].value)
+
+    # Scroll Results
     self.assertAlmostEquals(
-      1000 / 60.,
-      res.page_results[0]['mean_frame_time'].value, 2)
+        1.0 / 100.0 * 1000.0,
+        res.page_results[0]['mean_frame_time'].value, 2)
+    self.assertAlmostEquals(
+        20.0 / 100.0 * 100.0,
+        res.page_results[0]['dropped_percent'].value)
+    self.assertAlmostEquals(
+        50.0 / (50.0 + 50.0) * 100.0,
+        res.page_results[0]['percent_impl_scrolled'].value)
+    self.assertAlmostEquals(
+        240.0 / 100.0,
+        res.page_results[0]['average_num_layers_drawn'].value)
+    self.assertAlmostEquals(
+        10.0 / 100.0,
+        res.page_results[0]['average_num_missing_tiles'].value)
+
+    # Texture Upload Results
+    self.assertAlmostEquals(
+        1.3 / 130.0 * 1000.0,
+        res.page_results[0]['average_commit_time'].value)
+    self.assertEquals(
+        120,
+        res.page_results[0]['texture_upload_count'].value)
+    self.assertEquals(
+        1.2,
+        res.page_results[0]['total_texture_upload_time'].value)
+
+    # Image Decoding Results
+    self.assertEquals(
+        140,
+        res.page_results[0]['total_deferred_image_decode_count'].value)
+    self.assertEquals(
+        30,
+        res.page_results[0]['total_image_cache_hit_count'].value)
+    self.assertAlmostEquals(
+        1.5 / 150.0 * 1000.0,
+        res.page_results[0]['average_image_gathering_time'].value)
+    self.assertEquals(
+        1.4,
+        res.page_results[0]['total_deferred_image_decoding_time'].value)
+
+    # Tile Analysis Results
+    self.assertEquals(
+        160,
+        res.page_results[0]['total_tiles_analyzed'].value)
+    self.assertEquals(
+        40,
+        res.page_results[0]['solid_color_tiles_analyzed'].value)
+    self.assertAlmostEquals(
+        1.6 / 160.0 * 1000.0,
+        res.page_results[0]['average_tile_analysis_time'].value)
+
+    # Latency Results
+    self.assertAlmostEquals(
+        1.7 / 170.0 * 1000.0,
+        res.page_results[0]['average_latency'].value)
+    self.assertAlmostEquals(
+        1.8 / 180.0 * 1000.0,
+        res.page_results[0]['average_touch_ui_latency'].value)
+    self.assertAlmostEquals(
+        1.9 / 190.0 * 1000.0,
+        res.page_results[0]['average_touch_acked_latency'].value)
+    self.assertAlmostEquals(
+        2.0 / 200.0 * 1000.0,
+        res.page_results[0]['average_scroll_update_latency'].value)
diff --git a/tools/perf/page_sets/PRESUBMIT.py b/tools/perf/page_sets/PRESUBMIT.py
index 5fae0e8..f161443 100644
--- a/tools/perf/page_sets/PRESUBMIT.py
+++ b/tools/perf/page_sets/PRESUBMIT.py
@@ -1,4 +1,4 @@
-# Copyright 2013 The Chromium Authors. All rights reserved.
+# 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.
 import os
@@ -6,9 +6,6 @@
 import sys
 
 
-DEFAULT_BUCKET = 'chromium-wpr'
-
-
 def _SyncFilesToCloud(input_api, output_api):
   """Searches for .sha1 files and uploads them to Cloud Storage.
 
@@ -23,7 +20,7 @@
   finally:
     sys.path = old_sys_path
 
-  hashes_in_cloud_storage = cloud_storage.List(DEFAULT_BUCKET)
+  hashes_in_cloud_storage = cloud_storage.List(cloud_storage.DEFAULT_BUCKET)
 
   results = []
   for hash_path in input_api.AbsoluteLocalPaths():
@@ -52,7 +49,7 @@
       continue
 
     try:
-      cloud_storage.Insert(DEFAULT_BUCKET, file_hash, file_path)
+      cloud_storage.Insert(cloud_storage.DEFAULT_BUCKET, file_hash, file_path)
     except cloud_storage.CloudStorageError:
       results.append(output_api.PresubmitError(
           'Unable to upload to Cloud Storage: %s' % hash_path))
diff --git a/tools/perf/page_sets/pica.json b/tools/perf/page_sets/pica.json
new file mode 100644
index 0000000..2315276
--- /dev/null
+++ b/tools/perf/page_sets/pica.json
@@ -0,0 +1,16 @@
+{
+  "description": "Pica demo app for the Polymer UI toolkit",
+  "archive_data_file": "../data/pica.json",
+  "pages": [
+    { "url": "http://www.polymer-project.org/polymer-all/projects/pica/index.html",
+      "script_to_evaluate_on_commit":
+          "document.addEventListener('WebComponentsReady', function(){var unused = document.body.offsetHeight; window.__pica_load_time = performance.now(); setTimeout(function(){window.__web_components_ready=true}, 1000)})",
+      "wait_for_javascript_expression": "window.__web_components_ready",
+      "smoothness": {
+        "action": "tap_element",
+        "find_element_expression": "document.querySelector('pi-app').$.Topics.$.topics.$.container.querySelector('.item > .card')",
+        "wait_for_event": "g-panels-select"
+      }
+    }
+  ]
+}
diff --git a/tools/perf/page_sets/tough_video_cases/crowd.ogg b/tools/perf/page_sets/tough_video_cases/crowd.ogg
deleted file mode 100644
index e69de29..0000000
--- a/tools/perf/page_sets/tough_video_cases/crowd.ogg
+++ /dev/null
diff --git a/tools/perf/page_sets/tough_video_cases/crowd.wav b/tools/perf/page_sets/tough_video_cases/crowd.wav
deleted file mode 100644
index e69de29..0000000
--- a/tools/perf/page_sets/tough_video_cases/crowd.wav
+++ /dev/null
diff --git a/tools/perf/page_sets/tough_video_cases/crowd1080.mp4 b/tools/perf/page_sets/tough_video_cases/crowd1080.mp4
deleted file mode 100644
index e4cf00c..0000000
--- a/tools/perf/page_sets/tough_video_cases/crowd1080.mp4
+++ /dev/null
Binary files differ
diff --git a/tools/perf/page_sets/tough_video_cases/crowd1080.ogv b/tools/perf/page_sets/tough_video_cases/crowd1080.ogv
deleted file mode 100644
index e4cf00c..0000000
--- a/tools/perf/page_sets/tough_video_cases/crowd1080.ogv
+++ /dev/null
Binary files differ
diff --git a/tools/perf/page_sets/tough_video_cases/crowd1080.webm b/tools/perf/page_sets/tough_video_cases/crowd1080.webm
deleted file mode 100644
index e4cf00c..0000000
--- a/tools/perf/page_sets/tough_video_cases/crowd1080.webm
+++ /dev/null
Binary files differ
diff --git a/tools/perf/page_sets/tough_video_cases/crowd2160.mp4 b/tools/perf/page_sets/tough_video_cases/crowd2160.mp4
deleted file mode 100644
index a5a8a5f..0000000
--- a/tools/perf/page_sets/tough_video_cases/crowd2160.mp4
+++ /dev/null
Binary files differ
diff --git a/tools/perf/page_sets/tough_video_cases/crowd2160.ogv b/tools/perf/page_sets/tough_video_cases/crowd2160.ogv
deleted file mode 100644
index e4cf00c..0000000
--- a/tools/perf/page_sets/tough_video_cases/crowd2160.ogv
+++ /dev/null
Binary files differ
diff --git a/tools/perf/page_sets/tough_video_cases/crowd2160.webm b/tools/perf/page_sets/tough_video_cases/crowd2160.webm
deleted file mode 100644
index a5a8a5f..0000000
--- a/tools/perf/page_sets/tough_video_cases/crowd2160.webm
+++ /dev/null
Binary files differ
diff --git a/tools/perf/page_sets/tough_video_cases/crowd360.mp4 b/tools/perf/page_sets/tough_video_cases/crowd360.mp4
deleted file mode 100644
index e69de29..0000000
--- a/tools/perf/page_sets/tough_video_cases/crowd360.mp4
+++ /dev/null
diff --git a/tools/perf/page_sets/tough_video_cases/crowd360.ogv b/tools/perf/page_sets/tough_video_cases/crowd360.ogv
deleted file mode 100644
index e69de29..0000000
--- a/tools/perf/page_sets/tough_video_cases/crowd360.ogv
+++ /dev/null
diff --git a/tools/perf/page_sets/tough_video_cases/crowd360.webm b/tools/perf/page_sets/tough_video_cases/crowd360.webm
deleted file mode 100644
index e69de29..0000000
--- a/tools/perf/page_sets/tough_video_cases/crowd360.webm
+++ /dev/null
diff --git a/tools/perf/page_sets/tough_video_cases/crowd480.webm b/tools/perf/page_sets/tough_video_cases/crowd480.webm
deleted file mode 100644
index e69de29..0000000
--- a/tools/perf/page_sets/tough_video_cases/crowd480.webm
+++ /dev/null
diff --git a/tools/perf/page_sets/tough_video_cases/crowd720.webm b/tools/perf/page_sets/tough_video_cases/crowd720.webm
deleted file mode 100644
index e69de29..0000000
--- a/tools/perf/page_sets/tough_video_cases/crowd720.webm
+++ /dev/null
diff --git a/tools/perf/page_sets/tough_video_cases/tulip2.m4a b/tools/perf/page_sets/tough_video_cases/tulip2.m4a
deleted file mode 100644
index e69de29..0000000
--- a/tools/perf/page_sets/tough_video_cases/tulip2.m4a
+++ /dev/null
diff --git a/tools/perf/page_sets/tough_video_cases/tulip2.mp3 b/tools/perf/page_sets/tough_video_cases/tulip2.mp3
deleted file mode 100644
index e69de29..0000000
--- a/tools/perf/page_sets/tough_video_cases/tulip2.mp3
+++ /dev/null
diff --git a/tools/perf/page_sets/tough_video_cases/tulip2.mp4 b/tools/perf/page_sets/tough_video_cases/tulip2.mp4
deleted file mode 100644
index e69de29..0000000
--- a/tools/perf/page_sets/tough_video_cases/tulip2.mp4
+++ /dev/null
diff --git a/tools/perf/page_sets/tough_video_cases/tulip2.ogg b/tools/perf/page_sets/tough_video_cases/tulip2.ogg
deleted file mode 100644
index e69de29..0000000
--- a/tools/perf/page_sets/tough_video_cases/tulip2.ogg
+++ /dev/null
diff --git a/tools/perf/page_sets/tough_video_cases/tulip2.ogv b/tools/perf/page_sets/tough_video_cases/tulip2.ogv
deleted file mode 100644
index e69de29..0000000
--- a/tools/perf/page_sets/tough_video_cases/tulip2.ogv
+++ /dev/null
diff --git a/tools/perf/page_sets/tough_video_cases/tulip2.wav b/tools/perf/page_sets/tough_video_cases/tulip2.wav
deleted file mode 100644
index e69de29..0000000
--- a/tools/perf/page_sets/tough_video_cases/tulip2.wav
+++ /dev/null
diff --git a/tools/perf/page_sets/tough_video_cases/tulip2.webm b/tools/perf/page_sets/tough_video_cases/tulip2.webm
deleted file mode 100644
index e69de29..0000000
--- a/tools/perf/page_sets/tough_video_cases/tulip2.webm
+++ /dev/null
diff --git a/tools/perf/run_measurement b/tools/perf/run_measurement
index 8893fcd..dd5ecc8 100755
--- a/tools/perf/run_measurement
+++ b/tools/perf/run_measurement
@@ -11,6 +11,7 @@
 BOOTSTRAPPED_FILES_DIR = 'support/bootstrap_files'
 PERF_DIR = 'src/tools/perf'
 DEPS_FILE = 'bootstrap_deps'
+BASE_DIR = os.path.dirname(os.path.abspath(__file__))
 
 def BootstrapIfNeeded(module_name, module_path, module_deps_url):
   """Ensures that the given module_name is available, grab from URL if not."""
@@ -18,9 +19,7 @@
     imp.find_module(module_name)
     return
   except ImportError:
-    sys.path.append(os.path.join(os.path.dirname(__file__),
-                                 BOOTSTRAPPED_FILES_DIR,
-                                 module_path))
+    sys.path.append(os.path.join(BASE_DIR, BOOTSTRAPPED_FILES_DIR, module_path))
     try:
       imp.find_module(module_name)
       return
@@ -30,8 +29,7 @@
                                      'telemetry_bootstrap.py').read()
       bootstrap = imp.new_module('bootstrap')
       exec bootstrap_txt in bootstrap.__dict__
-      bootstrap.DownloadDepsURL(os.path.join(os.path.dirname(__file__),
-                                             BOOTSTRAPPED_FILES_DIR),
+      bootstrap.DownloadDepsURL(os.path.join(BASE_DIR, BOOTSTRAPPED_FILES_DIR),
                                 module_deps_url)
       return
 
@@ -41,14 +39,12 @@
   Returns: a list of telemetry deps.
   """
   # Add telemetry_tools to sys.path for the import below
-  telemetry_tools_path = os.path.join(os.path.dirname(__file__),
-                                      os.pardir, 'telemetry_tools')
+  telemetry_tools_path = os.path.join(BASE_DIR, os.pardir, 'telemetry_tools')
   sys.path.append(telemetry_tools_path)
 
   import perf_tools
   import telemetry_bootstrap
-  deps_file = os.path.join(os.path.dirname(perf_tools.__file__),
-                           DEPS_FILE)
+  deps_file = os.path.join(os.path.dirname(perf_tools.__file__), DEPS_FILE)
   return telemetry_bootstrap.ListAllDepsPaths(open(deps_file).read())
 
 def main():
@@ -57,8 +53,7 @@
                     '/perf/perf_tools/' + DEPS_FILE)
 
   # Add telemetry to sys.path for the import below
-  telemetry_path = os.path.join(os.path.dirname(__file__),
-                                os.pardir, 'telemetry')
+  telemetry_path = os.path.join(BASE_DIR, os.pardir, 'telemetry')
   sys.path.append(telemetry_path)
 
   if '--print-bootstrap-deps' in sys.argv:
@@ -101,7 +96,7 @@
       return old_benchmark_names[arg]
 
   runner = MeasurementRunner()
-  sys.exit(runner.Run(os.path.dirname(__file__), page_set_filenames))
+  sys.exit(runner.Run(BASE_DIR, page_set_filenames))
 
 if __name__ == '__main__':
   sys.exit(main())
diff --git a/tools/perf/run_tests b/tools/perf/run_tests
index 275e064..36eefbb 100755
--- a/tools/perf/run_tests
+++ b/tools/perf/run_tests
@@ -25,6 +25,9 @@
   start_dir = 'perf_tools'
   ret += run_tests.Main(sys.argv[1:], start_dir, top_level_dir, runner)
 
+  start_dir = 'metrics'
+  ret += run_tests.Main(sys.argv[1:], start_dir, top_level_dir, runner)
+
   if runner.result:
     runner.result.PrintSummary()
     sys.exit(min(ret + runner.result.num_errors, 255))
diff --git a/tools/perf/test-info.json b/tools/perf/test-info.json
index 8f56e9b..79caaad 100644
--- a/tools/perf/test-info.json
+++ b/tools/perf/test-info.json
@@ -30,9 +30,7 @@
   },
   "dom_perf": {
     "description": "Performance of DOM operations.",
-    "code": [
-      "chrome/src/tools/perf/benchmarks/dom_perf.py"
-    ]
+    "code": ["chrome/src/tools/perf/benchmarks/dom_perf.py"]
   },
   "dromaeo_domcoreattr": {
     "description": "Setting and getting DOM node attributes.",
@@ -143,7 +141,7 @@
     "description": "Milliseconds to decode a large image of various formats (gif, jpg, png, webp).",
     "code": [
       "chrome/src/tools/perf/measurements/image_decoding.py",
-      "chrome/src/chrome/test/data/image_decoding/"
+      "chrome/src/tools/perf/page_sets/image_decoding_measurement.json"
     ]
   },
   "indexeddb": {
@@ -204,7 +202,10 @@
   },
   "memory_measurement": {
     "description": "Use (recorded versions of) real world web sites and measure memory consumption.",
-    "code": ["chrome/src/tools/perf/measurements/memory.py"]
+    "code": [
+      "chrome/src/tools/perf/measurements/memory.py",
+      "chrome/src/tools/perf/page_sets/top_25.json"
+    ]
   },
   "memory_test": {
     "description": "Loads a number of URLs across tabs and windows and measures the memory usage.",
@@ -246,7 +247,10 @@
   },
   "smoothness_measurement": {
     "description": "Measures frame rate and a variety of other statistics while scrolling down the top 25 web pages. [Documentation](http://www.chromium.org/developers/design-documents/rendering-benchmarks).",
-    "code": ["chrome/src/tools/perf/measurements/smoothness.py"]
+    "code": [
+      "chrome/src/tools/perf/measurements/smoothness.py",
+      "chrome/src/tools/perf/page_sets/top_25.json"
+    ]
   },
   "spaceport": {
     "description": "Performance on [spaceport.io's perfmarks benchmark](http://spaceport.io/community/perfmarks). This test performs 3 animations (rotate, translate, scale) using a variety of methods (css, webgl, canvas, etc) and reports the number of objects that can be simultaneously animated while still achieving 30FPS.",
@@ -254,7 +258,10 @@
   },
   "startup_measurement": {
     "description": "Measures startup time under various scenarios. This is a port of our old startup_test target to Telemetry.",
-    "code": ["chrome/src/tools/perf/measurements/startup.py"]
+    "code": [
+      "chrome/src/tools/perf/measurements/startup.py",
+      "src/tools/perf/page_sets/blank_page.json"
+    ]
   },
   "startup_test": {
     "description": "Measures startup and shutdown time for 1 tab, 5 tabs, and 10 tabs under a several different user profiles. These tests are in the process of being ported to Telemetry - see the startup_measurement test.",
diff --git a/tools/perf_expectations/perf_expectations.json b/tools/perf_expectations/perf_expectations.json
index d3d4cc8..52088ac 100644
--- a/tools/perf_expectations/perf_expectations.json
+++ b/tools/perf_expectations/perf_expectations.json
@@ -1,6 +1,6 @@
-{"linux-release-64/sizes/chrome-bss/bss": {"reva": 206130, "revb": 206207, "type": "absolute", "better": "lower", "improve": 490741, "regress": 542601, "sha1": "902edbc8"},
+{"linux-release-64/sizes/chrome-bss/bss": {"reva": 216421, "revb": 216430, "type": "absolute", "better": "lower", "improve": 523892, "regress": 579040, "sha1": "0b0195e2"},
  "linux-release-64/sizes/chrome-data/data": {"reva": 203454, "revb": 203474, "type": "absolute", "better": "lower", "improve": 3570183, "regress": 3946094, "sha1": "b0d5e0fc"},
- "linux-release-64/sizes/chrome-si/initializers": {"reva": 196313, "revb": 196318, "type": "absolute", "better": "lower", "improve": 34, "regress": 34, "tolerance": 0, "sha1": "cd47eda1"},
+ "linux-release-64/sizes/chrome-si/initializers": {"reva": 216959, "revb": 216961, "type": "absolute", "better": "lower", "improve": 33, "regress": 33, "tolerance": 0, "sha1": "ebd8c26b"},
  "linux-release-64/sizes/chrome-text/text": {"reva": 203454, "revb": 203474, "type": "absolute", "better": "lower", "improve": 94012670, "regress": 103908994, "sha1": "a8dc15a3"},
  "linux-release-64/sizes/chrome.pak/chrome.pak": {"reva": 214295, "revb": 214296, "type": "absolute", "better": "lower", "improve": 4578193, "regress": 5060109, "sha1": "0785f1c1"},
  "linux-release-64/sizes/chrome/chrome": {"reva": 203454, "revb": 203474, "type": "absolute", "better": "lower", "improve": 128793270, "regress": 142351155, "sha1": "193926f5"},
@@ -365,7 +365,7 @@
  "linux-release/media_tests_av_perf/ttp/Wifi_roller.webm": {"reva": 175328, "revb": 176157, "type": "absolute", "better": "lower", "improve": 867.35, "regress": 1041.075, "sha1": "d99ce51c"},
  "linux-release/sizes/chrome-bss/bss": {"reva": 205093, "revb": 206368, "type": "absolute", "better": "lower", "improve": 316939, "regress": 389240, "sha1": "8d78343e"},
  "linux-release/sizes/chrome-data/data": {"reva": 203454, "revb": 203474, "type": "absolute", "better": "lower", "improve": 1936814, "regress": 2140724, "sha1": "915f9e72"},
- "linux-release/sizes/chrome-si/initializers": {"reva": 196188, "revb": 197308, "type": "absolute", "better": "lower", "improve": 35, "regress": 35, "tolerance": 0, "sha1": "86b46a4e"},
+ "linux-release/sizes/chrome-si/initializers": {"reva": 216959, "revb": 216961, "type": "absolute", "better": "lower", "improve": 34, "regress": 34, "tolerance": 0, "sha1": "69a4e038"},
  "linux-release/sizes/chrome-text/text": {"reva": 203454, "revb": 203474, "type": "absolute", "better": "lower", "improve": 79833368, "regress": 88237335, "sha1": "e1b38def"},
  "linux-release/sizes/chrome-textrel/textrel": {"reva": 135570, "revb": 135664, "type": "absolute", "better": "lower", "improve": 0, "regress": 0, "sha1": "832078e7"},
  "linux-release/sizes/chrome.pak/chrome.pak": {"reva": 214295, "revb": 214296, "type": "absolute", "better": "lower", "improve": 4578193, "regress": 5060109, "sha1": "a95a611b"},
diff --git a/tools/telemetry/examples/rendering_microbenchmark_test.py b/tools/telemetry/examples/rendering_microbenchmark_test.py
deleted file mode 100755
index 59e452a..0000000
--- a/tools/telemetry/examples/rendering_microbenchmark_test.py
+++ /dev/null
@@ -1,77 +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 os
-import re
-import sys
-
-sys.path.append(os.path.join(os.path.dirname(__file__), '..'))
-
-from telemetry.core import browser_finder
-from telemetry.core import browser_options
-
-def Main(args):
-  options = browser_options.BrowserOptions()
-  parser = options.CreateParser('rendering_microbenchmark_test.py <sitelist>')
-  # TODO(nduca): Add test specific options here, if any.
-  options, args = parser.parse_args(args)
-  if len(args) != 1:
-    parser.print_usage()
-    return 255
-
-  urls = []
-  with open(args[0], 'r') as f:
-    for url in f.readlines():
-      url = url.strip()
-      if not re.match('(.+)://', url):
-        url = 'http://%s' % url
-      urls.append(url)
-
-  options.extra_browser_args.append('--enable-gpu-benchmarking')
-  browser_to_create = browser_finder.FindBrowser(options)
-  if not browser_to_create:
-    sys.stderr.write('No browser found! Supported types: %s' %
-        browser_finder.GetAllAvailableBrowserTypes(options))
-    return 255
-  with browser_to_create.Create() as b:
-    tab = b.tabs[0]
-    # Check browser for benchmark API. Can only be done on non-chrome URLs.
-    tab.Navigate('http://www.google.com')
-    import time
-    time.sleep(2)
-    tab.WaitForDocumentReadyStateToBeComplete()
-    if tab.EvaluateJavaScript('window.chrome.gpuBenchmarking === undefined'):
-      print 'Browser does not support gpu benchmarks API.'
-      return 255
-
-    if tab.EvaluateJavaScript(
-        'window.chrome.gpuBenchmarking.runRenderingBenchmarks === undefined'):
-      print 'Browser does not support rendering benchmarks API.'
-      return 255
-
-    # Run the test. :)
-    first_line = []
-    def DumpResults(url, results):
-      if len(first_line) == 0:
-        cols = ['url']
-        for r in results:
-          cols.append(r['benchmark'])
-        print ','.join(cols)
-        first_line.append(0)
-      cols = [url]
-      for r in results:
-        cols.append(str(r['result']))
-      print ','.join(cols)
-
-    for u in urls:
-      tab.Navigate(u)
-      tab.WaitForDocumentReadyStateToBeInteractiveOrBetter()
-      results = tab.EvaluateJavaScript(
-          'window.chrome.gpuBenchmarking.runRenderingBenchmarks();')
-      DumpResults(url, results)
-
-  return 0
-
-if __name__ == '__main__':
-  sys.exit(Main(sys.argv[1:]))
diff --git a/tools/telemetry/support/html_output/results-template.html b/tools/telemetry/support/html_output/results-template.html
index b0b84c7..898d057 100644
--- a/tools/telemetry/support/html_output/results-template.html
+++ b/tools/telemetry/support/html_output/results-template.html
@@ -211,7 +211,9 @@
         return (unit == 'kb' ||
                 unit == 'KB' ||
                 unit == 'MB' ||
-                unit == 'bytes');
+                unit == 'bytes' ||
+                !metric.indexOf('V8.') ||
+                metric == 'processes');
     }
     this.addResult = function (newResult) {
         testResults.push(newResult);
diff --git a/tools/telemetry/telemetry/core/browser_options.py b/tools/telemetry/telemetry/core/browser_options.py
index c27d158..69f3048 100644
--- a/tools/telemetry/telemetry/core/browser_options.py
+++ b/tools/telemetry/telemetry/core/browser_options.py
@@ -89,11 +89,15 @@
         '--remote',
         dest='cros_remote',
         help='The IP address of a remote ChromeOS device to use.')
+    identity = None
+    testing_rsa = os.path.join(
+        util.GetChromiumSrcDir(),
+        'third_party', 'chromite', 'ssh_keys', 'testing_rsa')
+    if os.path.exists(testing_rsa):
+      identity = testing_rsa
     group.add_option('--identity',
         dest='cros_ssh_identity',
-        default=os.path.join(
-            util.GetChromiumSrcDir(),
-            'third_party', 'chromite', 'ssh_keys', 'testing_rsa'),
+        default=identity,
         help='The identity file to use when ssh\'ing into the ChromeOS device')
     parser.add_option_group(group)
 
@@ -107,6 +111,10 @@
         choices=profile_choices,
         help=('The user profile to use. A clean profile is used by default. '
               'Supported values: ' + ', '.join(profile_choices)))
+    group.add_option('--profile-dir',
+        dest='profile_dir',
+        help='Profile directory to launch the browser with. '
+             'A clean profile is used by default')
     group.add_option('--extra-browser-args',
         dest='extra_browser_args_as_string',
         help='Additional arguments to pass to the browser when it starts')
@@ -214,7 +222,12 @@
       # Parse repeat options
       self.repeat_options.UpdateFromParseResults(self, parser)
 
-      self.profile_dir = profile_types.GetProfileDir(self.profile_type)
+      # TODO(jeremy): I'm in the process of adding explicit knowledge of profile
+      # directories to Telemetry. As part of this work profile_type needs to be
+      # reworked to not override profile_dir.
+      if not self.profile_dir:
+        self.profile_dir = profile_types.GetProfileDir(self.profile_type)
+
       return ret
     parser.parse_args = ParseArgs
     return parser
@@ -222,3 +235,7 @@
   def AppendExtraBrowserArg(self, arg):
     if arg not in self.extra_browser_args:
       self.extra_browser_args.append(arg)
+
+  def MergeDefaultValues(self, defaults):
+    for k, v in defaults.__dict__.items():
+      self.ensure_value(k, v)
diff --git a/tools/telemetry/telemetry/core/browser_options_unittest.py b/tools/telemetry/telemetry/core/browser_options_unittest.py
index df22b93..9f016fa 100644
--- a/tools/telemetry/telemetry/core/browser_options_unittest.py
+++ b/tools/telemetry/telemetry/core/browser_options_unittest.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 optparse
 import unittest
 
 from telemetry.core import browser_options
@@ -58,3 +59,41 @@
     options_ret, _ = parser.parse_args(['--browser', 'any'])
     self.assertEquals(options_ret, options)
     self.assertFalse(options.verbosity)
+
+  def testProfileDirDefault(self):
+    options = browser_options.BrowserOptions()
+    parser = options.CreateParser()
+    parser.parse_args(['--browser', 'any'])
+    self.assertEquals(options.profile_dir, None)
+
+  def testProfileDir(self):
+    options = browser_options.BrowserOptions()
+    parser = options.CreateParser()
+    parser.parse_args(['--browser', 'any', '--profile-dir', 'foo'])
+    self.assertEquals(options.profile_dir, 'foo')
+
+  def testMergeDefaultValues(self):
+    options = browser_options.BrowserOptions()
+    options.already_true = True
+    options.already_false = False
+    options.override_to_true = False
+    options.override_to_false = True
+
+    parser = optparse.OptionParser()
+    parser.add_option('--already_true', action='store_true')
+    parser.add_option('--already_false', action='store_true')
+    parser.add_option('--unset', action='store_true')
+    parser.add_option('--default_true', action='store_true', default=True)
+    parser.add_option('--default_false', action='store_true', default=False)
+    parser.add_option('--override_to_true', action='store_true', default=False)
+    parser.add_option('--override_to_false', action='store_true', default=True)
+
+    options.MergeDefaultValues(parser.get_default_values())
+
+    self.assertTrue(options.already_true)
+    self.assertFalse(options.already_false)
+    self.assertTrue(options.unset is None)
+    self.assertTrue(options.default_true)
+    self.assertFalse(options.default_false)
+    self.assertFalse(options.override_to_true)
+    self.assertTrue(options.override_to_false)
diff --git a/tools/telemetry/telemetry/core/chrome/cros_browser_backend.py b/tools/telemetry/telemetry/core/chrome/cros_browser_backend.py
index bad383c..c5dede5 100644
--- a/tools/telemetry/telemetry/core/chrome/cros_browser_backend.py
+++ b/tools/telemetry/telemetry/core/chrome/cros_browser_backend.py
@@ -87,6 +87,8 @@
             '--login-screen=login',
             # Skip user image selection screen, and post login screens.
             '--oobe-skip-postlogin',
+            # Skip hwid check, for VMs and pre-MP lab devices.
+            '--skip-hwid-check',
             # Allow devtools to connect to chrome.
             '--remote-debugging-port=%i' % self._remote_debugging_port,
             # Open a maximized window.
@@ -99,10 +101,6 @@
       # This extension bypasses gaia and logs us in.
       args.append('--auth-ext-path=%s' % self._login_ext_dir)
 
-    # Skip hwid check on systems that don't have a hwid set, eg VMs.
-    if not self.hwid:
-      args.append('--skip-hwid-check')
-
     return args
 
   def _GetSessionManagerPid(self, procs):
diff --git a/tools/telemetry/telemetry/page/actions/scroll.py b/tools/telemetry/telemetry/page/actions/scroll.py
index f132bf9..f7df4ad 100644
--- a/tools/telemetry/telemetry/page/actions/scroll.py
+++ b/tools/telemetry/telemetry/page/actions/scroll.py
@@ -72,7 +72,7 @@
     return True
 
   def CustomizeBrowserOptions(self, options):
-    options.extra_browser_args.append('--enable-gpu-benchmarking')
+    options.AppendExtraBrowserArg('--enable-gpu-benchmarking')
 
   def BindMeasurementJavaScript(self, tab, start_js, stop_js):
     # Make the scroll action start and stop measurement automatically.
diff --git a/tools/telemetry/telemetry/page/actions/tap_element.py b/tools/telemetry/telemetry/page/actions/tap_element.py
new file mode 100644
index 0000000..f3a4734
--- /dev/null
+++ b/tools/telemetry/telemetry/page/actions/tap_element.py
@@ -0,0 +1,45 @@
+# 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.
+
+from telemetry.core import exceptions
+from telemetry.core import util
+from telemetry.page import page as page_module
+from telemetry.page.actions import page_action
+
+class TapElementAction(page_action.PageAction):
+  """Page action that dispatches a custom 'tap' event at an element.
+
+  For pages that don't respond to 'click' events, this action offers
+  an alternative to ClickElementAction.
+
+  Configuration options:
+    find_element_expression: a JavaScript expression that should yield
+                             the element to tap.
+    wait_for_event: an event name that will be listened for on the Document.
+  """
+  def __init__(self, attributes=None):
+    super(TapElementAction, self).__init__(attributes)
+
+  def RunAction(self, page, tab, previous_action):
+    def DoTap():
+      assert hasattr(self, 'find_element_expression')
+      event = 'new CustomEvent("tap", {bubbles: true})'
+      code = '(%s).dispatchEvent(%s)' % (self.find_element_expression, event)
+      try:
+        tab.ExecuteJavaScript(code)
+      except exceptions.EvaluateException:
+        raise page_action.PageActionFailed(
+            'Cannot find element with code ' + self.find_element_javascript)
+
+    if hasattr(self, 'wait_for_event'):
+      code = ('document.addEventListener("%s", '
+              'function(){window.__tap_event_finished=true})')
+      tab.ExecuteJavaScript(code % self.wait_for_event)
+      DoTap()
+      util.WaitFor(lambda: tab.EvaluateJavaScript(
+          'window.__tap_event_finished'), 60)
+    else:
+      DoTap()
+
+    page_module.Page.WaitForPageToLoad(self, tab, 60)
diff --git a/tools/telemetry/telemetry/page/cloud_storage.py b/tools/telemetry/telemetry/page/cloud_storage.py
index 3d4d2e5..d52c622 100644
--- a/tools/telemetry/telemetry/page/cloud_storage.py
+++ b/tools/telemetry/telemetry/page/cloud_storage.py
@@ -16,6 +16,9 @@
 from telemetry.core import util
 
 
+DEFAULT_BUCKET = 'chromium-wpr'
+
+
 _GSUTIL_URL = 'http://storage.googleapis.com/pub/gsutil.tar.gz'
 _DOWNLOAD_PATH = os.path.join(util.GetTelemetryDir(), 'third_party', 'gsutil')
 
@@ -73,23 +76,36 @@
 
 def Delete(bucket, remote_path):
   url = 'gs://%s/%s' % (bucket, remote_path)
-  logging.debug('Deleting %s' % url)
+  logging.info('Deleting %s' % url)
   _RunCommand(['rm', url])
 
 
 def Get(bucket, remote_path, local_path):
   url = 'gs://%s/%s' % (bucket, remote_path)
-  logging.debug('Downloading %s to %s' % (url, local_path))
+  logging.info('Downloading %s to %s' % (url, local_path))
   _RunCommand(['cp', url, local_path])
 
 
 def Insert(bucket, remote_path, local_path):
   url = 'gs://%s/%s' % (bucket, remote_path)
-  logging.debug('Uploading %s to %s' % (local_path, url))
+  logging.info('Uploading %s to %s' % (local_path, url))
   _RunCommand(['cp', local_path, url])
 
 
+def GetIfChanged(bucket, file_path):
+  """Gets the file at file_path if it has a hash file that doesn't match."""
+  hash_path = file_path + '.sha1'
+  if not os.path.exists(hash_path):
+    return
+
+  with open(hash_path, 'rb') as f:
+    expected_hash = f.read(1024).rstrip()
+  if not os.path.exists(file_path) or GetHash(file_path) != expected_hash:
+    Get(bucket, expected_hash, file_path)
+
+
 def GetHash(file_path):
+  """Calculates and returns the hash of the file at file_path."""
   sha1 = hashlib.sha1()
   with open(file_path, 'rb') as f:
     while True:
diff --git a/tools/telemetry/telemetry/page/page.py b/tools/telemetry/telemetry/page/page.py
index 63bfd69..5d06076 100644
--- a/tools/telemetry/telemetry/page/page.py
+++ b/tools/telemetry/telemetry/page/page.py
@@ -67,6 +67,16 @@
     raise AttributeError()
 
   @property
+  def is_file(self):
+    parsed_url = urlparse.urlparse(self.url)
+    return parsed_url.scheme == 'file'
+
+  @property
+  def is_local(self):
+    parsed_url = urlparse.urlparse(self.url)
+    return parsed_url.scheme == 'file' or parsed_url.scheme == 'chrome'
+
+  @property
   def serving_dirs_and_file(self):
     parsed_url = urlparse.urlparse(self.url)
     path = _UrlPathJoin(self.base_dir, parsed_url.netloc, parsed_url.path)
@@ -88,11 +98,10 @@
 
   @property
   def display_url(self):
-    if self.url.startswith('http'):
+    if not self.is_local:
       return self.url
     url_paths = ['/'.join(p.url.strip('/').split('/')[:-1])
-                 for p in self.page_set
-                 if p.url.startswith('file://')]
+                 for p in self.page_set if p.is_file]
     common_prefix = os.path.commonprefix(url_paths)
     return self.url[len(common_prefix):].strip('/')
 
diff --git a/tools/telemetry/telemetry/page/page_runner.py b/tools/telemetry/telemetry/page/page_runner.py
index 423f07a..1df51de 100644
--- a/tools/telemetry/telemetry/page/page_runner.py
+++ b/tools/telemetry/telemetry/page/page_runner.py
@@ -9,7 +9,6 @@
 import tempfile
 import time
 import traceback
-import urlparse
 import random
 
 from telemetry.core import browser_finder
@@ -18,6 +17,7 @@
 from telemetry.core import wpr_modes
 from telemetry.core.platform.profiler import profiler_finder
 from telemetry.page import page_filter as page_filter_module
+from telemetry.page import page_measurement_results
 from telemetry.page import page_runner_repeat
 from telemetry.page import page_test
 
@@ -109,8 +109,7 @@
     self._did_login = False
 
   def PreparePage(self, page, tab, test=None):
-    parsed_url = urlparse.urlparse(page.url)
-    if parsed_url[0] == 'file':
+    if page.is_file:
       serving_dirs, filename = page.serving_dirs_and_file
       if tab.browser.SetHTTPServerDirectories(serving_dirs) and test:
         test.DidStartHTTPServer(tab)
@@ -165,7 +164,7 @@
   results_for_current_run = results
   if state.first_page[page] and test.discard_first_result:
     # If discarding results, substitute a dummy object.
-    results_for_current_run = type(results)()
+    results_for_current_run = page_measurement_results.PageMeasurementResults()
   results_for_current_run.StartTest(page)
   tries = 3
   while tries:
@@ -264,7 +263,7 @@
   try:
     test.WillRunTest(state.tab)
     repeat_state = page_runner_repeat.PageRunnerRepeatState(
-                       options.repeat_options)
+        options.repeat_options)
 
     repeat_state.WillRunPageSet()
     while repeat_state.ShouldRepeatPageSet():
@@ -307,8 +306,7 @@
   Logs warnings if any are missing."""
   page_set_has_live_sites = False
   for page in pages:
-    parsed_url = urlparse.urlparse(page.url)
-    if parsed_url.scheme != 'chrome' and parsed_url.scheme != 'file':
+    if not page.is_local:
       page_set_has_live_sites = True
       break
 
@@ -329,8 +327,7 @@
   pages_missing_archive_data = []
 
   for page in pages:
-    parsed_url = urlparse.urlparse(page.url)
-    if parsed_url.scheme == 'chrome' or parsed_url.scheme == 'file':
+    if page.is_local:
       continue
 
     if not page.archive_path:
diff --git a/tools/telemetry/telemetry/page/page_runner_unittest.py b/tools/telemetry/telemetry/page/page_runner_unittest.py
index dfce72d..2ff1cfc 100644
--- a/tools/telemetry/telemetry/page/page_runner_unittest.py
+++ b/tools/telemetry/telemetry/page/page_runner_unittest.py
@@ -9,6 +9,7 @@
 from telemetry.core import user_agent
 from telemetry.core import util
 from telemetry.page import page as page_module
+from telemetry.page import page_measurement
 from telemetry.page import page_set
 from telemetry.page import page_test
 from telemetry.page import page_runner
@@ -72,34 +73,42 @@
         ps,
         base_dir=os.path.dirname(__file__)))
 
-    class Test(page_test.PageTest):
+    class Measurement(page_measurement.PageMeasurement):
       @property
       def discard_first_result(self):
         return True
-      def RunTest(self, *args):
+      def MeasurePage(self, *args):
         pass
 
     options = options_for_unittests.GetCopy()
     options.output_format = 'none'
+    options.reset_html_results = None
 
     options.repeat_options.page_repeat_iters = 1
     options.repeat_options.pageset_repeat_iters = 1
-    results = page_runner.Run(Test('RunTest'), ps, expectations, options)
+    results = page_runner.Run(Measurement(), ps, expectations, options)
     self.assertEquals(0, len(results.successes))
     self.assertEquals(0, len(results.failures))
 
     options.repeat_options.page_repeat_iters = 1
     options.repeat_options.pageset_repeat_iters = 2
-    results = page_runner.Run(Test('RunTest'), ps, expectations, options)
+    results = page_runner.Run(Measurement(), ps, expectations, options)
     self.assertEquals(2, len(results.successes))
     self.assertEquals(0, len(results.failures))
 
     options.repeat_options.page_repeat_iters = 2
     options.repeat_options.pageset_repeat_iters = 1
-    results = page_runner.Run(Test('RunTest'), ps, expectations, options)
+    results = page_runner.Run(Measurement(), ps, expectations, options)
     self.assertEquals(2, len(results.successes))
     self.assertEquals(0, len(results.failures))
 
+    options.output_format = 'html'
+    options.repeat_options.page_repeat_iters = 1
+    options.repeat_options.pageset_repeat_iters = 1
+    results = page_runner.Run(Measurement(), ps, expectations, options)
+    self.assertEquals(0, len(results.successes))
+    self.assertEquals(0, len(results.failures))
+
   def testCredentialsWhenLoginFails(self):
     credentials_backend = StubCredentialsBackend(login_return_value=False)
     did_run = self.runCredentialsTest(credentials_backend)
diff --git a/tools/telemetry/telemetry/page/page_set.py b/tools/telemetry/telemetry/page/page_set.py
index 558b5c6..807c365 100644
--- a/tools/telemetry/telemetry/page/page_set.py
+++ b/tools/telemetry/telemetry/page/page_set.py
@@ -4,8 +4,8 @@
 import csv
 import json
 import os
-import urlparse
 
+from telemetry.page import cloud_storage
 from telemetry.page import page as page_module
 from telemetry.page import page_set_archive_info
 
@@ -25,12 +25,8 @@
     self.pages = []
 
     if self.archive_data_file:
-      if os.path.isdir(file_path):
-        base_dir = file_path
-      else:
-        base_dir = os.path.dirname(file_path)
       self.wpr_archive_info = page_set_archive_info.PageSetArchiveInfo.FromFile(
-          os.path.join(base_dir, self.archive_data_file), file_path)
+          os.path.join(self._base_dir, self.archive_data_file), file_path)
     else:
       self.wpr_archive_info = None
 
@@ -38,29 +34,49 @@
   def FromFile(cls, file_path):
     with open(file_path, 'r') as f:
       contents = f.read()
-      data = json.loads(contents)
-      return cls.FromDict(data, file_path)
+    data = json.loads(contents)
+    return cls.FromDict(data, file_path)
 
   @classmethod
   def FromDict(cls, data, file_path):
     page_set = cls(file_path, data)
-    if os.path.isdir(file_path):
-      base_dir = file_path
-    else:
-      base_dir = os.path.dirname(file_path)
 
     for page_attributes in data['pages']:
       url = page_attributes.pop('url')
 
       page = page_module.Page(url, page_set, attributes=page_attributes,
-                              base_dir=base_dir)
+          base_dir=page_set._base_dir)  # pylint: disable=W0212
       page_set.pages.append(page)
+
+    all_serving_dirs = set()
+    for page in page_set:
+      if page.is_file:
+        serving_dirs, _ = page.serving_dirs_and_file
+        if isinstance(serving_dirs, list):
+          all_serving_dirs |= set(serving_dirs)
+        else:
+          all_serving_dirs.add(serving_dirs)
+    for serving_dir in all_serving_dirs:
+      for dirpath, _, filenames in os.walk(serving_dir):
+        for filename in filenames:
+          file_path, extension = os.path.splitext(
+              os.path.join(dirpath, filename))
+          if extension != '.sha1':
+            continue
+          cloud_storage.GetIfChanged(cloud_storage.DEFAULT_BUCKET, file_path)
+
     return page_set
 
+  @property
+  def _base_dir(self):
+    if os.path.isdir(self.file_path):
+      return self.file_path
+    else:
+      return os.path.dirname(self.file_path)
+
   def ContainsOnlyFileURLs(self):
     for page in self.pages:
-      parsed_url = urlparse.urlparse(page.url)
-      if parsed_url.scheme != 'file':
+      if not page.is_file:
         return False
     return True
 
diff --git a/tools/telemetry/telemetry/page/page_set_archive_info.py b/tools/telemetry/telemetry/page/page_set_archive_info.py
index 33502d8..adb7625 100644
--- a/tools/telemetry/telemetry/page/page_set_archive_info.py
+++ b/tools/telemetry/telemetry/page/page_set_archive_info.py
@@ -23,6 +23,9 @@
     # Back pointer to the page set file.
     self._page_set_file_path = page_set_file_path
 
+    for archive_path in data['archives']:
+      cloud_storage.GetIfChanged(cloud_storage.DEFAULT_BUCKET, archive_path)
+
     # Map from the relative path (as it appears in the metadata file) of the
     # .wpr file to a list of urls it supports.
     self._wpr_file_to_urls = data['archives']
@@ -39,6 +42,8 @@
 
   @classmethod
   def FromFile(cls, file_path, page_set_file_path):
+    cloud_storage.GetIfChanged(cloud_storage.DEFAULT_BUCKET, file_path)
+
     if os.path.exists(file_path):
       with open(file_path, 'r') as f:
         data = json.load(f)
diff --git a/tools/telemetry/telemetry/test.py b/tools/telemetry/telemetry/test.py
index df74a2a..3b5bcf3 100644
--- a/tools/telemetry/telemetry/test.py
+++ b/tools/telemetry/telemetry/test.py
@@ -1,6 +1,7 @@
 # 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.
+import optparse
 import os
 
 from telemetry.core import repeat_options
@@ -33,6 +34,12 @@
     test = self.test()
     ps = self.CreatePageSet(options)
     expectations = self.CreateExpectations(ps)
+
+    # Ensure the test's default options are set if needed.
+    parser = optparse.OptionParser()
+    test.AddCommandLineOptions(parser)
+    options.MergeDefaultValues(parser.get_default_values())
+
     results = page_runner.Run(test, ps, expectations, options)
     results.PrintSummary()
     return len(results.failures) + len(results.errors)
diff --git a/tools/valgrind/gtest_exclude/content_unittests.gtest_mac.txt b/tools/valgrind/gtest_exclude/content_unittests.gtest_mac.txt
index dfbd75f..562c242 100644
--- a/tools/valgrind/gtest_exclude/content_unittests.gtest_mac.txt
+++ b/tools/valgrind/gtest_exclude/content_unittests.gtest_mac.txt
@@ -49,4 +49,7 @@
 MacSandboxTest.FontLoadingTest
 
 # http://crbug.com/247685
-ScreenCaptureDeviceTest.Capture
+DesktopCaptureDeviceTest.Capture
+
+# http://crbug.com/270254
+DeviceOrientationEventPumpTest.*
diff --git a/tools/valgrind/memcheck/suppressions.txt b/tools/valgrind/memcheck/suppressions.txt
index 6d773b7..da72868 100644
--- a/tools/valgrind/memcheck/suppressions.txt
+++ b/tools/valgrind/memcheck/suppressions.txt
@@ -6276,17 +6276,6 @@
    fun:_ZN2v88internal8Debugger18CallCEventCallbackENS_10DebugEventENS0_6HandleINS0_6ObjectEEES5_PNS_5Debug10ClientDataE
 }
 {
-   bug_181691
-   Memcheck:Leak
-   fun:_Znw*
-   ...
-   fun:_Z10InitThreadv
-   fun:ShCompile
-   fun:_ZN3gpu5gles216ShaderTranslator9TranslateEPKc
-   fun:_ZN3gpu5gles214ProgramManager18ForceCompileShaderEPKSsPNS0_6ShaderEPNS0_16ShaderTranslatorEPNS0_11FeatureInfoE
-   fun:_ZN3gpu5gles214ProgramManager15DoCompileShaderEPNS0_6ShaderEPNS0_16ShaderTranslatorEPNS0_11FeatureInfoE
-}
-{
    bug_184264
    Memcheck:Leak
    fun:_Znw*
@@ -6547,44 +6536,6 @@
    fun:_ZN7testing4Test11DeleteSelf_Ev
 }
 {
-   bug_230366a
-   Memcheck:Leak
-   fun:_Znw*
-   fun:_Z28InitializeGlobalParseContextv
-   fun:_Z10InitThreadv
-   fun:ShCompile
-   fun:_ZN6webkit3gpu33WebGraphicsContext3DInProcessImpl25AngleValidateShaderSourceEPNS1_17ShaderSourceEntryE
-   fun:_ZN6webkit3gpu33WebGraphicsContext3DInProcessImpl13compileShaderEj
-   fun:_ZN2cc18ProgramBindingBase10LoadShaderEPN6WebKit20WebGraphicsContext3DEjRKSs
-   fun:_ZN2cc18ProgramBindingBase4InitEPN6WebKit20WebGraphicsContext3DERKSsS5_
-   fun:_ZN2cc14ProgramBindingINS_26VertexShaderPosTexIdentityENS_21FragmentShaderRGBATexEEC1EPN6WebKit20WebGraphicsContext3DENS_17TexCoordPrecisionE
-   fun:_ZN2cc24AcceleratedTextureCopierC1EPN6WebKit20WebGraphicsContext3DEbi
-   fun:_ZN2cc24AcceleratedTextureCopier6CreateEPN6WebKit20WebGraphicsContext3DEbi
-   fun:_ZN2cc16ResourceProvider10InitializeEi
-   fun:_ZN2cc16ResourceProvider6CreateEPNS_13OutputSurfaceEi
-   fun:_ZN2cc17LayerTreeHostImpl18InitializeRendererE10scoped_ptrINS_13OutputSurfaceEN4base14DefaultDeleterIS2_EEE
-   fun:_ZN2cc11ThreadProxy30InitializeRendererOnImplThreadEPNS_15CompletionEventEPbPNS_20RendererCapabilitiesE
-}
-{
-   bug_230366b
-   Memcheck:Leak
-   fun:_Znw*
-   fun:_Z21InitializeGlobalPoolsv
-   fun:_Z10InitThreadv
-   fun:ShCompile
-   fun:_ZN6webkit3gpu33WebGraphicsContext3DInProcessImpl25AngleValidateShaderSourceEPNS1_17ShaderSourceEntryE
-   fun:_ZN6webkit3gpu33WebGraphicsContext3DInProcessImpl13compileShaderEj
-   fun:_ZN2cc18ProgramBindingBase10LoadShaderEPN6WebKit20WebGraphicsContext3DEjRKSs
-   fun:_ZN2cc18ProgramBindingBase4InitEPN6WebKit20WebGraphicsContext3DERKSsS5_
-   fun:_ZN2cc14ProgramBindingINS_26VertexShaderPosTexIdentityENS_21FragmentShaderRGBATexEEC1EPN6WebKit20WebGraphicsContext3DENS_17TexCoordPrecisionE
-   fun:_ZN2cc24AcceleratedTextureCopierC1EPN6WebKit20WebGraphicsContext3DEbi
-   fun:_ZN2cc24AcceleratedTextureCopier6CreateEPN6WebKit20WebGraphicsContext3DEbi
-   fun:_ZN2cc16ResourceProvider10InitializeEi
-   fun:_ZN2cc16ResourceProvider6CreateEPNS_13OutputSurfaceEi
-   fun:_ZN2cc17LayerTreeHostImpl18InitializeRendererE10scoped_ptrINS_13OutputSurfaceEN4base14DefaultDeleterIS2_EEE
-   fun:_ZN2cc11ThreadProxy30InitializeRendererOnImplThreadEPNS_15CompletionEventEPbPNS_20RendererCapabilitiesE
-}
-{
    bug_233541
    Memcheck:Leak
    fun:_Znw*
@@ -6719,7 +6670,6 @@
    fun:_ZN7WebCore6V8Node23appendChildMethodCustomERKN2v820FunctionCallbackInfoINS1_5ValueEEE
    fun:_ZN7WebCore14NodeV8InternalL37appendChildMethodCallbackForMainWorldERKN2v820FunctionCallbackInfoINS1_5ValueEEE
 }
-
 {
    bug_241932
    Memcheck:Leak
@@ -7040,16 +6990,25 @@
    fun:_ZN7content11ContentMainEiPPKcPNS_19ContentMainDelegateE
 }
 {
-   bug_252641
+   bug_252641_a
    Memcheck:Uninitialized
    fun:pthread_rwlock_init$UNIX2003
    fun:_ZN3re25MutexC2Ev
    fun:_ZN3re25MutexC1Ev
    ...
    fun:_ZN11leveldb_env19ParseMethodAndErrorEPKcPNS_8MethodIDEPi
-   fun:_ZN7contentL21HistogramLevelDBErrorERKSsRKN7leveldb6StatusE
-   fun:_ZN7content15LevelDBDatabase4OpenERKN4base8FilePathEPKNS_17LevelDBComparatorEPb
-   fun:_ZN7content12_GLOBAL__N_139LevelDBDatabaseTest_CorruptionTest_Test8TestBodyEv
+}
+{
+   bug_252641_b
+   Memcheck:Uninitialized
+   fun:pthread_rwlock_init$UNIX2003
+   fun:_ZN3re25MutexC2Ev
+   fun:_ZN3re25MutexC1Ev
+   ...
+   fun:_ZN11leveldb_env19ParseMethodAndErrorEPKcPNS_8MethodIDEPi
+   fun:_ZN7content23RecoveryCouldBeFruitfulEN7leveldb6StatusE
+   fun:_ZN7content21IndexedDBBackingStore4OpenERKSsRKN4base8FilePathES2_PN6WebKit15WebIDBCallbacks8DataLossEPNS_14LevelDBFactoryE
+   fun:_ZN12_GLOBAL__N_137IndexedDBIOErrorTest_CleanUpTest_Test8TestBodyEv
 }
 {
    bug_253797
@@ -7230,4 +7189,42 @@
    fun:_ZN4base11MessageLoop8PostTaskERKN15tracked_objects8LocationERKNS_8CallbackIFvvEEE
    fun:_ZN8printing8PrintJob21UpdatePrintedDocumentEPNS_15PrintedDocumentE
    fun:_ZN8printing8PrintJob4StopEv
- }
+}
+{
+   bug_269844
+   Memcheck:Leak
+   fun:_Znw*
+   fun:_ZN9__gnu_cxx13new_allocatorIPN4base11PendingTaskEE8allocateEmPKv
+   fun:_ZNSt11_Deque_baseIN4base11PendingTaskESaIS1_EE15_M_allocate_mapEm
+   fun:_ZNSt5dequeIN4base11PendingTaskESaIS1_EE17_M_reallocate_mapEmb
+   ...
+   fun:_ZN4base8internal17IncomingTaskQueue15PostPendingTaskEPNS_11PendingTaskE
+   fun:_ZN4base8internal17IncomingTaskQueue18AddToIncomingQueueERKN15tracked_objects8LocationERKNS_8CallbackIFvvEEENS_9TimeDeltaEb
+   fun:_ZN4base11MessageLoop8PostTaskERKN15tracked_objects8LocationERKNS_8CallbackIFvvEEE
+}
+{
+   bug_269884a
+   Memcheck:Leak
+   fun:_Znw*
+   fun:_ZN24SkColorFilterImageFilter6CreateEP13SkColorFilterP13SkImageFilterPK7SkIRect
+   fun:_ZN7WebCore22SkiaImageFilterBuilder19transformColorSpaceEP13SkImageFilterNS_10ColorSpaceES3_
+   fun:_ZN7WebCore22SkiaImageFilterBuilder5buildERKNS_16FilterOperationsE
+}
+{
+   bug_269884b
+   Memcheck:Leak
+   fun:_Znw*
+   fun:_ZN19SkPerlinNoiseShader15CreateTubulenceEffifPK7SkTSizeIiE
+   fun:_ZN7WebCore12FETurbulence12createShaderERKNS_7IntRectE
+   fun:_ZN7WebCore12FETurbulence17createImageFilterEPNS_22SkiaImageFilterBuilderE
+   fun:_ZN7WebCore22SkiaImageFilterBuilder5buildEPNS_12FilterEffectENS_10ColorSpaceE
+   fun:_ZN7WebCore22SkiaImageFilterBuilder5buildERKNS_16FilterOperationsE
+}
+{
+   bug_270312
+   Memcheck:Leak
+   fun:_Znw*
+   fun:_ZN14message_center22MessageCenterButtonBarC1EPNS_17MessageCenterViewEPNS_13MessageCenterEPNS_24NotifierSettingsProviderEb
+   fun:_ZN14message_center17MessageCenterViewC1EPNS_13MessageCenterEPNS_17MessageCenterTrayEibb
+   fun:_ZN14message_center21MessageCenterViewTest5SetUpEv
+}
diff --git a/tools/valgrind/tsan_v2/suppressions.txt b/tools/valgrind/tsan_v2/suppressions.txt
index c1c586d..682d33c 100644
--- a/tools/valgrind/tsan_v2/suppressions.txt
+++ b/tools/valgrind/tsan_v2/suppressions.txt
@@ -12,6 +12,9 @@
 # Races in libevent, http://crbug.com/23244
 race:libevent/event.c
 
+# http://crbug.com/46840
+race:history::HistoryBackend::DeleteFTSIndexDatabases
+
 # http://crbug.com/84094
 race:sqlite3StatusSet
 race:pcache1EnforceMaxPage
@@ -93,5 +96,16 @@
 # http://crbug.com/257543
 race:*GetObjectFromEntryAddress
 
+# http://crbug.com/268924
+race:base::g_power_monitor
+race:base::PowerMonitor::PowerMonitor
+race:base::PowerMonitor::AddObserver
+
 # http://crbug.com/268941
 race:tracked_objects::ThreadData::tls_index_
+
+# http://crbug.com/269965
+race:DesktopMediaPickerModelTest_UpdateThumbnail_Test
+
+# http://crbug.com/270037
+race:gLibCleanupFunctions
diff --git a/ui/android/java/src/org/chromium/ui/ViewAndroid.java b/ui/android/java/src/org/chromium/ui/ViewAndroid.java
index 0f0ca11..97c8e1d 100644
--- a/ui/android/java/src/org/chromium/ui/ViewAndroid.java
+++ b/ui/android/java/src/org/chromium/ui/ViewAndroid.java
@@ -4,6 +4,8 @@
 
 package org.chromium.ui;
 
+import android.view.View;
+
 import org.chromium.base.JNINamespace;
 import org.chromium.ui.ViewAndroidDelegate;
 import org.chromium.ui.WindowAndroid;
@@ -23,6 +25,8 @@
     private int mNativeViewAndroid = 0;
     private final ViewAndroidDelegate mViewAndroidDelegate;
     private final WindowAndroid mWindowAndroid;
+    private int mKeepScreenOnCount;
+    private View mKeepScreenOnView;
 
     /**
      * Constructs a View object.
@@ -55,6 +59,29 @@
         return mNativeViewAndroid;
     }
 
+    /**
+     * Set KeepScreenOn flag. If the flag already set, increase mKeepScreenOnCount.
+     */
+    public void incrementKeepScreenOnCount() {
+        mKeepScreenOnCount++;
+        if (mKeepScreenOnCount == 1) {
+            mKeepScreenOnView = mViewAndroidDelegate.acquireAnchorView();
+            mKeepScreenOnView.setKeepScreenOn(true);
+        }
+    }
+
+    /**
+     * Decrease mKeepScreenOnCount, if it is decreased to 0, remove the flag.
+     */
+    public void decrementKeepScreenOnCount() {
+        assert mKeepScreenOnCount > 0;
+        mKeepScreenOnCount--;
+        if (mKeepScreenOnCount == 0) {
+            mViewAndroidDelegate.releaseAnchorView(mKeepScreenOnView);
+            mKeepScreenOnView = null;
+        }
+    }
+
     private native int nativeInit(int windowPtr);
     private native void nativeDestroy(int nativeViewAndroid);
 }
diff --git a/ui/android/java/src/org/chromium/ui/WindowAndroid.java b/ui/android/java/src/org/chromium/ui/WindowAndroid.java
index 316690b..3fec600 100644
--- a/ui/android/java/src/org/chromium/ui/WindowAndroid.java
+++ b/ui/android/java/src/org/chromium/ui/WindowAndroid.java
@@ -11,7 +11,6 @@
 import android.content.Intent;
 import android.os.Bundle;
 import android.util.SparseArray;
-import android.view.WindowManager;
 import android.widget.Toast;
 
 import java.util.HashMap;
@@ -201,14 +200,6 @@
         return mNativeWindowAndroid;
     }
 
-    public void keepScreenOn(boolean screenOn) {
-        if (screenOn) {
-            mActivity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
-        } else {
-            mActivity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
-        }
-    }
-
     private native int nativeInit();
     private native void nativeDestroy(int nativeWindowAndroid);
 
diff --git a/ui/app_list/cocoa/app_list_view_controller.mm b/ui/app_list/cocoa/app_list_view_controller.mm
index 37b6bf8..e464721 100644
--- a/ui/app_list/cocoa/app_list_view_controller.mm
+++ b/ui/app_list/cocoa/app_list_view_controller.mm
@@ -317,6 +317,7 @@
 }
 
 - (void)onSigninStatusChanged {
+  [appsSearchBoxController_ rebuildMenu];
   app_list::SigninDelegate* signinDelegate = [self signinDelegate];
   BOOL needsSignin = signinDelegate && signinDelegate->NeedSignin();
   if (!needsSignin) {
diff --git a/ui/app_list/cocoa/apps_search_box_controller.h b/ui/app_list/cocoa/apps_search_box_controller.h
index 3e9b4b2..d28c67a 100644
--- a/ui/app_list/cocoa/apps_search_box_controller.h
+++ b/ui/app_list/cocoa/apps_search_box_controller.h
@@ -49,6 +49,9 @@
 - (id)initWithFrame:(NSRect)frame;
 - (void)clearSearch;
 
+// Rebuild the menu due to changes from the AppListViewDelegate.
+- (void)rebuildMenu;
+
 @end
 
 @interface AppsSearchBoxController (TestingAPI)
diff --git a/ui/app_list/cocoa/apps_search_box_controller.mm b/ui/app_list/cocoa/apps_search_box_controller.mm
index 6d38f94..4f02a20 100644
--- a/ui/app_list/cocoa/apps_search_box_controller.mm
+++ b/ui/app_list/cocoa/apps_search_box_controller.mm
@@ -30,8 +30,9 @@
 // Size of the menu button on the right.
 const CGFloat kMenuButtonDimension = 29;
 
-// Vertical offset that the menu should appear below the menu button.
-const CGFloat kMenuOffsetFromButton = 2;
+// Menu offset relative to the bottom-right corner of the menu button.
+const CGFloat kMenuYOffsetFromButton = -4;
+const CGFloat kMenuXOffsetFromButton = -7;
 
 }
 
@@ -153,6 +154,15 @@
   [self controlTextDidChange:nil];
 }
 
+- (void)rebuildMenu {
+  if (![delegate_ appListDelegate])
+    return;
+
+  menuController_.reset([[AppListMenuController alloc]
+      initWithSearchBoxController:self]);
+  [menuButton_ setMenu:[menuController_ menu]];  // Menu will populate here.
+}
+
 - (void)setDelegate:(id<AppsSearchBoxDelegate>)delegate {
   [[menuButton_ menu] removeAllItems];
   menuController_.reset();
@@ -167,9 +177,7 @@
     return;
 
   appListMenu_.reset(new app_list::AppListMenu([delegate_ appListDelegate]));
-  menuController_.reset([[AppListMenuController alloc]
-      initWithSearchBoxController:self]);
-  [menuButton_ setMenu:[menuController_ menu]];  // Menu will populate here.
+  [self rebuildMenu];
 }
 
 - (NSTextField*)searchTextField {
@@ -385,8 +393,8 @@
   NSRect anchorRect = [menuButton convertRect:[menuButton bounds]
                                        toView:nil];
   NSPoint anchorPoint = [[menuButton window] convertBaseToScreen:NSMakePoint(
-      NSMaxX(anchorRect),
-      NSMinY(anchorRect) - kMenuOffsetFromButton)];
+      NSMaxX(anchorRect) + kMenuXOffsetFromButton,
+      NSMinY(anchorRect) - kMenuYOffsetFromButton)];
   NSRect confinementRect = [[menuButton window] frame];
   confinementRect.size = NSMakeSize(anchorPoint.x - NSMinX(confinementRect),
                                     anchorPoint.y - NSMinY(confinementRect));
diff --git a/ui/app_list/cocoa/apps_search_results_model_bridge.mm b/ui/app_list/cocoa/apps_search_results_model_bridge.mm
index 41e3fd6..d56c5fd 100644
--- a/ui/app_list/cocoa/apps_search_results_model_bridge.mm
+++ b/ui/app_list/cocoa/apps_search_results_model_bridge.mm
@@ -44,6 +44,7 @@
   virtual void OnIsInstallingChanged() OVERRIDE {}
   virtual void OnPercentDownloadedChanged() OVERRIDE {}
   virtual void OnItemInstalled() OVERRIDE {}
+  virtual void OnItemUninstalled() OVERRIDE {}
 
  private:
   AppsSearchResultsModelBridge* bridge_;  // Weak. Owns us.
diff --git a/ui/app_list/search_result.cc b/ui/app_list/search_result.cc
index ab40d31..cf90830 100644
--- a/ui/app_list/search_result.cc
+++ b/ui/app_list/search_result.cc
@@ -63,9 +63,11 @@
 }
 
 void SearchResult::NotifyItemInstalled() {
-  FOR_EACH_OBSERVER(SearchResultObserver,
-                    observers_,
-                    OnItemInstalled());
+  FOR_EACH_OBSERVER(SearchResultObserver, observers_, OnItemInstalled());
+}
+
+void SearchResult::NotifyItemUninstalled() {
+  FOR_EACH_OBSERVER(SearchResultObserver, observers_, OnItemUninstalled());
 }
 
 void SearchResult::AddObserver(SearchResultObserver* observer) {
diff --git a/ui/app_list/search_result.h b/ui/app_list/search_result.h
index f2e94b2..5baa50f 100644
--- a/ui/app_list/search_result.h
+++ b/ui/app_list/search_result.h
@@ -101,6 +101,7 @@
   void SetPercentDownloaded(int percent_downloaded);
 
   void NotifyItemInstalled();
+  void NotifyItemUninstalled();
 
   void AddObserver(SearchResultObserver* observer);
   void RemoveObserver(SearchResultObserver* observer);
diff --git a/ui/app_list/search_result_list_view_delegate.h b/ui/app_list/search_result_list_view_delegate.h
index 7b64448..e45ac4b 100644
--- a/ui/app_list/search_result_list_view_delegate.h
+++ b/ui/app_list/search_result_list_view_delegate.h
@@ -28,6 +28,9 @@
   // Called when the app represented by |result| is installed.
   virtual void OnResultInstalled(SearchResult* result) = 0;
 
+  // Called when the app represented by |result| is uninstalled.
+  virtual void OnResultUninstalled(SearchResult* result) = 0;
+
  protected:
   virtual ~SearchResultListViewDelegate() {}
 };
diff --git a/ui/app_list/search_result_observer.h b/ui/app_list/search_result_observer.h
index 6a2b1a5..bef7564 100644
--- a/ui/app_list/search_result_observer.h
+++ b/ui/app_list/search_result_observer.h
@@ -26,6 +26,9 @@
   // Invoked when the item represented by the SearchResult is installed.
   virtual void OnItemInstalled() = 0;
 
+  // Invoked when the item represented by the SearchResult is uninstalled.
+  virtual void OnItemUninstalled() = 0;
+
  protected:
   virtual ~SearchResultObserver() {}
 };
diff --git a/ui/app_list/views/app_list_main_view.cc b/ui/app_list/views/app_list_main_view.cc
index 8874410..fa0de27 100644
--- a/ui/app_list/views/app_list_main_view.cc
+++ b/ui/app_list/views/app_list_main_view.cc
@@ -229,4 +229,8 @@
   search_box_view_->ClearSearch();
 }
 
+void AppListMainView::OnResultUninstalled(SearchResult* result) {
+  QueryChanged(search_box_view_);
+}
+
 }  // namespace app_list
diff --git a/ui/app_list/views/app_list_main_view.h b/ui/app_list/views/app_list_main_view.h
index dc73e8b..1909d97 100644
--- a/ui/app_list/views/app_list_main_view.h
+++ b/ui/app_list/views/app_list_main_view.h
@@ -85,6 +85,7 @@
                                   int action_index,
                                   int event_flags) OVERRIDE;
   virtual void OnResultInstalled(SearchResult* result) OVERRIDE;
+  virtual void OnResultUninstalled(SearchResult* result) OVERRIDE;
 
   AppListViewDelegate* delegate_;
   AppListModel* model_;
diff --git a/ui/app_list/views/app_list_view.cc b/ui/app_list/views/app_list_view.cc
index 863e25e..118ab2b 100644
--- a/ui/app_list/views/app_list_view.cc
+++ b/ui/app_list/views/app_list_view.cc
@@ -27,6 +27,7 @@
 
 #if defined(USE_AURA)
 #include "ui/aura/window.h"
+#include "ui/aura/root_window.h"
 #if defined(OS_WIN)
 #include "ui/base/win/shell.h"
 #endif
@@ -182,6 +183,18 @@
   app_list_main_view_->search_box_view()->InvalidateMenu();
 }
 
+#if defined(OS_WIN)
+HWND AppListView::GetHWND() const {
+#if defined(USE_AURA)
+  gfx::NativeWindow window =
+      GetWidget()->GetTopLevelWidget()->GetNativeWindow();
+  return window->GetRootWindow()->GetAcceleratedWidget();
+#else
+  return GetWidget()->GetTopLevelWidget()->GetNativeWindow();
+#endif
+}
+#endif
+
 views::View* AppListView::GetInitiallyFocusedView() {
   return app_list_main_view_->search_box_view()->search_box();
 }
diff --git a/ui/app_list/views/app_list_view.h b/ui/app_list/views/app_list_view.h
index eb21ceb..fff4815 100644
--- a/ui/app_list/views/app_list_view.h
+++ b/ui/app_list/views/app_list_view.h
@@ -70,6 +70,10 @@
   // Invoked when the sign-in status is changed to switch on/off sign-in view.
   void OnSigninStatusChanged();
 
+#if defined(OS_WIN)
+  HWND GetHWND() const;
+#endif
+
  private:
   // Overridden from views::WidgetDelegateView:
   virtual views::View* GetInitiallyFocusedView() OVERRIDE;
diff --git a/ui/app_list/views/search_box_view.cc b/ui/app_list/views/search_box_view.cc
index 12d166a..1d997e5 100644
--- a/ui/app_list/views/search_box_view.cc
+++ b/ui/app_list/views/search_box_view.cc
@@ -29,6 +29,10 @@
 
 const SkColor kHintTextColor = SkColorSetRGB(0xA0, 0xA0, 0xA0);
 
+// Menu offset relative to the bottom-right corner of the menu button.
+const int kMenuYOffsetFromButton = -4;
+const int kMenuXOffsetFromButton = -7;
+
 }  // namespace
 
 SearchBoxView::SearchBoxView(SearchBoxViewDelegate* delegate,
@@ -158,8 +162,10 @@
   if (!menu_)
     menu_.reset(new AppListMenuViews(view_delegate_));
 
-  menu_->RunMenuAt(menu_button_,
-                   menu_button_->GetBoundsInScreen().bottom_right());
+  const gfx::Point menu_location =
+      menu_button_->GetBoundsInScreen().bottom_right() +
+      gfx::Vector2d(kMenuXOffsetFromButton, kMenuYOffsetFromButton);
+  menu_->RunMenuAt(menu_button_, menu_location);
 }
 
 void SearchBoxView::IconChanged() {
diff --git a/ui/app_list/views/search_result_list_view.cc b/ui/app_list/views/search_result_list_view.cc
index 48c9157..5eaad3c 100644
--- a/ui/app_list/views/search_result_list_view.cc
+++ b/ui/app_list/views/search_result_list_view.cc
@@ -173,4 +173,9 @@
     delegate_->OnResultInstalled(view->result());
 }
 
+void SearchResultListView::OnSearchResultUninstalled(SearchResultView* view) {
+  if (delegate_ && view->result())
+    delegate_->OnResultUninstalled(view->result());
+}
+
 }  // namespace app_list
diff --git a/ui/app_list/views/search_result_list_view.h b/ui/app_list/views/search_result_list_view.h
index d6b0396..5b3fa48 100644
--- a/ui/app_list/views/search_result_list_view.h
+++ b/ui/app_list/views/search_result_list_view.h
@@ -59,6 +59,7 @@
                                            size_t action_index,
                                            int event_flags) OVERRIDE;
   virtual void OnSearchResultInstalled(SearchResultView* view) OVERRIDE;
+  virtual void OnSearchResultUninstalled(SearchResultView* view) OVERRIDE;
 
   SearchResultListViewDelegate* delegate_;  // Not owned.
   AppListModel::SearchResults* results_;  // Owned by AppListModel.
diff --git a/ui/app_list/views/search_result_view.cc b/ui/app_list/views/search_result_view.cc
index 0361591..55b9e0b 100644
--- a/ui/app_list/views/search_result_view.cc
+++ b/ui/app_list/views/search_result_view.cc
@@ -279,6 +279,10 @@
   delegate_->OnSearchResultInstalled(this);
 }
 
+void SearchResultView::OnItemUninstalled() {
+  delegate_->OnSearchResultUninstalled(this);
+}
+
 void SearchResultView::OnSearchResultActionActivated(size_t index,
                                                      int event_flags) {
   DCHECK(result_);
diff --git a/ui/app_list/views/search_result_view.h b/ui/app_list/views/search_result_view.h
index 4d830e7..dde3669 100644
--- a/ui/app_list/views/search_result_view.h
+++ b/ui/app_list/views/search_result_view.h
@@ -80,6 +80,7 @@
   virtual void OnIsInstallingChanged() OVERRIDE;
   virtual void OnPercentDownloadedChanged() OVERRIDE;
   virtual void OnItemInstalled() OVERRIDE;
+  virtual void OnItemUninstalled() OVERRIDE;
 
   // SearchResultActionsViewDelegate overrides:
   virtual void OnSearchResultActionActivated(size_t index,
diff --git a/ui/app_list/views/search_result_view_delegate.h b/ui/app_list/views/search_result_view_delegate.h
index 16b87ef..e86ccc8 100644
--- a/ui/app_list/views/search_result_view_delegate.h
+++ b/ui/app_list/views/search_result_view_delegate.h
@@ -24,6 +24,9 @@
   // Called when the app represented by the search result is installed.
   virtual void OnSearchResultInstalled(SearchResultView* view) = 0;
 
+  // Called when the app represented by the search result is uninstalled.
+  virtual void OnSearchResultUninstalled(SearchResultView* view) = 0;
+
  protected:
   virtual ~SearchResultViewDelegate() {}
 };
diff --git a/ui/aura/demo/demo_main.cc b/ui/aura/demo/demo_main.cc
index aea286e..06938d8 100644
--- a/ui/aura/demo/demo_main.cc
+++ b/ui/aura/demo/demo_main.cc
@@ -11,6 +11,7 @@
 #include "ui/aura/client/default_capture_client.h"
 #include "ui/aura/client/stacking_client.h"
 #include "ui/aura/env.h"
+#include "ui/aura/focus_manager.h"
 #include "ui/aura/root_window.h"
 #include "ui/aura/test/test_screen.h"
 #include "ui/aura/window.h"
@@ -116,6 +117,8 @@
       test_screen->CreateRootWindowForPrimaryDisplay());
   scoped_ptr<DemoStackingClient> stacking_client(new DemoStackingClient(
       root_window.get()));
+  aura::FocusManager focus_manager;
+  aura::client::SetFocusClient(root_window.get(), &focus_manager);
 
   // Create a hierarchy of test windows.
   DemoWindowDelegate window_delegate1(SK_ColorBLUE);
diff --git a/ui/aura/root_window_host_x11.cc b/ui/aura/root_window_host_x11.cc
index ad1b957..f69a54a 100644
--- a/ui/aura/root_window_host_x11.cc
+++ b/ui/aura/root_window_host_x11.cc
@@ -822,12 +822,16 @@
 bool RootWindowHostX11::CopyAreaToSkCanvas(const gfx::Rect& source_bounds,
                                              const gfx::Point& dest_offset,
                                              SkCanvas* canvas) {
-  scoped_ptr<ui::XScopedImage> scoped_image(GetXImage(source_bounds));
-  if (!scoped_image)
+  ui::XScopedImage scoped_image(
+      XGetImage(xdisplay_, xwindow_,
+                source_bounds.x(), source_bounds.y(),
+                source_bounds.width(), source_bounds.height(),
+                AllPlanes, ZPixmap));
+  XImage* image = scoped_image.get();
+  if (!image) {
+    LOG(ERROR) << "XGetImage failed";
     return false;
-
-  XImage* image = scoped_image->get();
-  DCHECK(image);
+  }
 
   if (image->bits_per_pixel == 32) {
     if ((0xff << SK_R32_SHIFT) != image->red_mask ||
@@ -1085,20 +1089,6 @@
   delegate_->OnHostMouseEvent(event);
 }
 
-scoped_ptr<ui::XScopedImage> RootWindowHostX11::GetXImage(
-    const gfx::Rect& snapshot_bounds) {
-  scoped_ptr<ui::XScopedImage> image(new ui::XScopedImage(
-      XGetImage(xdisplay_, xwindow_,
-                snapshot_bounds.x(), snapshot_bounds.y(),
-                snapshot_bounds.width(), snapshot_bounds.height(),
-                AllPlanes, ZPixmap)));
-  if (!image) {
-    LOG(ERROR) << "XGetImage failed";
-    image.reset();
-  }
-  return image.Pass();
-}
-
 void RootWindowHostX11::UpdateIsInternalDisplay() {
   RootWindow* root_window = GetRootWindow();
   gfx::Screen* screen = gfx::Screen::GetScreenFor(root_window);
diff --git a/ui/aura/root_window_host_x11.h b/ui/aura/root_window_host_x11.h
index b3b2788..c38002d 100644
--- a/ui/aura/root_window_host_x11.h
+++ b/ui/aura/root_window_host_x11.h
@@ -96,10 +96,6 @@
   // dispatches the event to RootWindowHostDelegate.
   void TranslateAndDispatchMouseEvent(ui::MouseEvent* event);
 
-  // Copies and returns |snapshot_bounds| from |xwindow_|.  Helper method for
-  // CopyAreaToSkCanvas() and GrabSnapshot().
-  scoped_ptr<ui::XScopedImage> GetXImage(const gfx::Rect& snapshot_bounds);
-
   // Update is_internal_display_ based on delegate_ state
   void UpdateIsInternalDisplay();
 
diff --git a/ui/base/dragdrop/drag_utils_win.cc b/ui/base/dragdrop/drag_utils_win.cc
index b760fa8..0bed7ea 100644
--- a/ui/base/dragdrop/drag_utils_win.cc
+++ b/ui/base/dragdrop/drag_utils_win.cc
@@ -9,6 +9,7 @@
 #include <shobjidl.h>
 
 #include "base/win/scoped_comptr.h"
+#include "base/win/scoped_hdc.h"
 #include "third_party/skia/include/core/SkBitmap.h"
 #include "ui/base/dragdrop/os_exchange_data.h"
 #include "ui/base/dragdrop/os_exchange_data_provider_win.h"
@@ -39,18 +40,19 @@
 // Blit the contents of the canvas to a new HBITMAP. It is the caller's
 // responsibility to release the |bits| buffer.
 static HBITMAP CreateHBITMAPFromSkBitmap(const SkBitmap& sk_bitmap) {
-  HDC screen_dc = GetDC(NULL);
+  base::win::ScopedGetDC screen_dc(NULL);
   BITMAPINFOHEADER header;
   gfx::CreateBitmapHeader(sk_bitmap.width(), sk_bitmap.height(), &header);
   void* bits;
   HBITMAP bitmap =
       CreateDIBSection(screen_dc, reinterpret_cast<BITMAPINFO*>(&header),
                        DIB_RGB_COLORS, &bits, NULL, 0);
+  if (!bitmap || !bits)
+    return NULL;
   DCHECK_EQ(sk_bitmap.rowBytes(), static_cast<size_t>(sk_bitmap.width() * 4));
   SkAutoLockPixels lock(sk_bitmap);
   memcpy(
       bits, sk_bitmap.getPixels(), sk_bitmap.height() * sk_bitmap.rowBytes());
-  ReleaseDC(NULL, screen_dc);
   return bitmap;
 }
 
@@ -64,10 +66,11 @@
   // SetDragImageOnDataObject(HBITMAP) takes ownership of the bitmap.
   HBITMAP bitmap = CreateHBITMAPFromSkBitmap(
       SkBitmapOperations::UnPreMultiply(*image_skia.bitmap()));
-
-  // Attach 'bitmap' to the data_object.
-  SetDragImageOnDataObject(bitmap, size, cursor_offset,
-      ui::OSExchangeDataProviderWin::GetIDataObject(*data_object));
+  if (bitmap) {
+    // Attach 'bitmap' to the data_object.
+    SetDragImageOnDataObject(bitmap, size, cursor_offset,
+        ui::OSExchangeDataProviderWin::GetIDataObject(*data_object));
+  }
 
 #if defined(USE_AURA)
   // TODO: the above code is used in non-Ash, while below is used in Ash. If we
diff --git a/ui/base/ime/input_method_ibus_unittest.cc b/ui/base/ime/input_method_ibus_unittest.cc
index bd84738..99accfa 100644
--- a/ui/base/ime/input_method_ibus_unittest.cc
+++ b/ui/base/ime/input_method_ibus_unittest.cc
@@ -402,6 +402,9 @@
   virtual TextInputType GetTextInputType() const OVERRIDE {
     return input_type_;
   }
+  virtual TextInputMode GetTextInputMode() const OVERRIDE {
+    return TEXT_INPUT_MODE_DEFAULT;
+  }
   virtual bool CanComposeInline() const OVERRIDE {
     return can_compose_inline_;
   }
diff --git a/ui/base/ime/text_input_client.h b/ui/base/ime/text_input_client.h
index 82d0585..2fd14a2 100644
--- a/ui/base/ime/text_input_client.h
+++ b/ui/base/ime/text_input_client.h
@@ -9,6 +9,7 @@
 #include "base/i18n/rtl.h"
 #include "base/strings/string16.h"
 #include "ui/base/ime/composition_text.h"
+#include "ui/base/ime/text_input_mode.h"
 #include "ui/base/ime/text_input_type.h"
 #include "ui/base/range/range.h"
 #include "ui/base/ui_export.h"
@@ -63,6 +64,10 @@
   // TEXT_INPUT_TYPE_NONE at runtime.
   virtual ui::TextInputType GetTextInputType() const = 0;
 
+  // Returns current text input mode. It could be changed and even becomes
+  // TEXT_INPUT_MODE_DEFAULT at runtime.
+  virtual ui::TextInputMode GetTextInputMode() const = 0;
+
   // Returns if the client supports inline composition currently.
   virtual bool CanComposeInline() const = 0;
 
diff --git a/ui/base/ime/win/imm32_manager.h b/ui/base/ime/win/imm32_manager.h
index 08776ab..17892cb 100644
--- a/ui/base/ime/win/imm32_manager.h
+++ b/ui/base/ime/win/imm32_manager.h
@@ -77,7 +77,7 @@
 class UI_EXPORT IMM32Manager {
  public:
   IMM32Manager();
-  ~IMM32Manager();
+  virtual ~IMM32Manager();
 
   // Retrieves whether or not there is an ongoing composition.
   bool is_composing() const { return is_composing_; }
@@ -241,7 +241,7 @@
   base::i18n::TextDirection GetTextDirection() const;
 
   // Sets conversion status corresponding to |input_mode|.
-  void SetTextInputMode(HWND window_handle, TextInputMode input_mode);
+  virtual void SetTextInputMode(HWND window_handle, TextInputMode input_mode);
 
   // Helper functions ----------------------------------------------------------
 
diff --git a/ui/base/ime/win/tsf_text_store_unittest.cc b/ui/base/ime/win/tsf_text_store_unittest.cc
index baa4c8d..62772f2 100644
--- a/ui/base/ime/win/tsf_text_store_unittest.cc
+++ b/ui/base/ime/win/tsf_text_store_unittest.cc
@@ -28,6 +28,7 @@
   MOCK_METHOD2(InsertChar, void(char16, int));
   MOCK_CONST_METHOD0(GetAttachedWindow, gfx::NativeWindow());
   MOCK_CONST_METHOD0(GetTextInputType, ui::TextInputType());
+  MOCK_CONST_METHOD0(GetTextInputMode, ui::TextInputMode());
   MOCK_CONST_METHOD0(CanComposeInline, bool());
   MOCK_METHOD0(GetCaretBounds, gfx::Rect());
   MOCK_METHOD2(GetCompositionCharacterBounds, bool(uint32, gfx::Rect*));
diff --git a/ui/base/strings/ui_strings.grd b/ui/base/strings/ui_strings.grd
index 1a243e5..ec198ad 100644
--- a/ui/base/strings/ui_strings.grd
+++ b/ui/base/strings/ui_strings.grd
@@ -1530,16 +1530,12 @@
       <message name="IDS_MESSAGE_CENTER_SETTINGS_GO_BACK_BUTTON_TOOLTIP" desc="The tooltip on back button that returns from settings to the notification list.">
         Go back to notifications
       </message>
-      <if expr="is_macosx">
-        <message name="IDS_MESSAGE_CENTER_SETTINGS_DIALOG_DESCRIPTION" desc="The label to describe the settings dialog.">
-          Allow notifications from the following:
-        </message>
-      </if>
-      <if expr="not is_macosx">
-        <message name="IDS_MESSAGE_CENTER_SETTINGS_DIALOG_DESCRIPTION" desc="The label to describe the settings dialog.">
-          Manage notifications per profile:
-        </message>
-      </if>
+      <message name="IDS_MESSAGE_CENTER_SETTINGS_DIALOG_DESCRIPTION" desc="The label to describe the settings dialog.">
+        Allow notifications from the following:
+      </message>
+      <message name="IDS_MESSAGE_CENTER_SETTINGS_DESCRIPTION_MULTIUSER" desc="The label to describe the settings dialog if there is more than one user.">
+        Allow notifications from the following for each user:
+      </message>
       <message name="IDS_MESSAGE_CENTER_SETTINGS" desc="The menu entry or button for visiting the appropriate settings page.">
         Settings...
       </message>
diff --git a/ui/base/touch/touch_device_win.cc b/ui/base/touch/touch_device_win.cc
index 4eba353..c07fbe9 100644
--- a/ui/base/touch/touch_device_win.cc
+++ b/ui/base/touch/touch_device_win.cc
@@ -10,8 +10,8 @@
 
 bool IsTouchDevicePresent() {
   int value = GetSystemMetrics(SM_DIGITIZER);
-  return (value & (NID_READY | NID_INTEGRATED_TOUCH)) ==
-             (NID_READY | NID_INTEGRATED_TOUCH);
+  return (value & NID_READY) &&
+      ((value & NID_INTEGRATED_TOUCH) || (value & NID_EXTERNAL_TOUCH));
 }
 
 }  // namespace ui
diff --git a/ui/gfx/box_f.cc b/ui/gfx/box_f.cc
new file mode 100644
index 0000000..107c5d6
--- /dev/null
+++ b/ui/gfx/box_f.cc
@@ -0,0 +1,52 @@
+// 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/gfx/box_f.h"
+
+#include "base/strings/stringprintf.h"
+
+namespace gfx {
+
+std::string BoxF::ToString() const {
+  return base::StringPrintf("%s %fx%fx%f",
+                            origin().ToString().c_str(),
+                            width_,
+                            height_,
+                            depth_);
+}
+
+bool BoxF::IsEmpty() const {
+  return (width_ == 0 && height_ == 0) ||
+         (width_ == 0 && depth_ == 0) ||
+         (height_ == 0 && depth_ == 0);
+}
+
+void BoxF::Union(const BoxF& box) {
+  if (IsEmpty()) {
+    *this = box;
+    return;
+  }
+  if (box.IsEmpty())
+    return;
+
+  float min_x = std::min(x(), box.x());
+  float min_y = std::min(y(), box.y());
+  float min_z = std::min(z(), box.z());
+  float max_x = std::max(right(), box.right());
+  float max_y = std::max(bottom(), box.bottom());
+  float max_z = std::max(front(), box.front());
+
+  origin_.SetPoint(min_x, min_y, min_z);
+  width_ = max_x - min_x;
+  height_ = max_y - min_y;
+  depth_ = max_z - min_z;
+}
+
+BoxF UnionBoxes(const BoxF& a, const BoxF& b) {
+  BoxF result = a;
+  result.Union(b);
+  return result;
+}
+
+}  // namespace gfx
diff --git a/ui/gfx/box_f.h b/ui/gfx/box_f.h
new file mode 100644
index 0000000..01063b1
--- /dev/null
+++ b/ui/gfx/box_f.h
@@ -0,0 +1,142 @@
+// 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_GFX_BOX_F_H_
+#define UI_GFX_BOX_F_H_
+
+#include "ui/gfx/point3_f.h"
+#include "ui/gfx/vector3d_f.h"
+
+namespace gfx {
+
+// A 3d version of gfx::RectF, with the positive z-axis pointed towards
+// the camera.
+class UI_EXPORT BoxF {
+ public:
+  BoxF()
+      : width_(0.f),
+        height_(0.f),
+        depth_(0.f) {}
+
+  BoxF(float width, float height, float depth)
+      : width_(width < 0 ? 0 : width),
+        height_(height < 0 ? 0 : height),
+        depth_(depth < 0 ? 0 : depth) {}
+
+  BoxF(float x, float y, float z, float width, float height, float depth)
+      : origin_(x, y, z),
+        width_(width < 0 ? 0 : width),
+        height_(height < 0 ? 0 : height),
+        depth_(depth < 0 ? 0 : depth) {}
+
+  BoxF(const Point3F& origin, float width, float height, float depth)
+      : origin_(origin),
+        width_(width < 0 ? 0 : width),
+        height_(height < 0 ? 0 : height),
+        depth_(depth < 0 ? 0 : depth) {}
+
+  ~BoxF() {}
+
+  // Scales all three axes by the given scale.
+  void Scale(float scale) {
+    Scale(scale, scale, scale);
+  }
+
+  // Scales each axis by the corresponding given scale.
+  void Scale(float x_scale, float y_scale, float z_scale) {
+    origin_.Scale(x_scale, y_scale, z_scale);
+    set_size(width_ * x_scale, height_ * y_scale, depth_ * z_scale);
+  }
+
+  // Moves the box by the specified distance in each dimension.
+  void operator+=(const Vector3dF& offset) {
+    origin_ += offset;
+  }
+
+  // Returns true if the box has no interior points.
+  bool IsEmpty() const;
+
+  // Computes the union of this box with the given box. The union is the
+  // smallest box that contains both boxes.
+  void Union(const BoxF& box);
+
+  std::string ToString() const;
+
+  float x() const { return origin_.x(); }
+  void set_x(float x) { origin_.set_x(x); }
+
+  float y() const { return origin_.y(); }
+  void set_y(float y) { origin_.set_y(y); }
+
+  float z() const { return origin_.z(); }
+  void set_z(float z) { origin_.set_z(z); }
+
+  float width() const { return width_; }
+  void set_width(float width) { width_ = width < 0 ? 0 : width; }
+
+  float height() const { return height_; }
+  void set_height(float height) { height_ = height < 0 ? 0 : height; }
+
+  float depth() const { return depth_; }
+  void set_depth(float depth) { depth_ = depth < 0 ? 0 : depth; }
+
+  float right() const { return x() + width(); }
+  float bottom() const { return y() + height(); }
+  float front() const { return z() + depth(); }
+
+  void set_size(float width, float height, float depth) {
+    width_ = width < 0 ? 0 : width;
+    height_ = height < 0 ? 0 : height;
+    depth_ = depth < 0 ? 0 : depth;
+  }
+
+  const Point3F& origin() const { return origin_; }
+  void set_origin(const Point3F& origin) { origin_ = origin; }
+
+ private:
+  Point3F origin_;
+  float width_;
+  float height_;
+  float depth_;
+};
+
+UI_EXPORT BoxF UnionBoxes(const BoxF& a, const BoxF& b);
+
+inline BoxF ScaleBox(const BoxF& b,
+                     float x_scale,
+                     float y_scale,
+                     float z_scale) {
+  return BoxF(b.x() * x_scale,
+              b.y() * y_scale,
+              b.z() * z_scale,
+              b.width() * x_scale,
+              b.height() * y_scale,
+              b.depth() * z_scale);
+}
+
+inline BoxF ScaleBox(const BoxF& b, float scale) {
+  return ScaleBox(b, scale, scale, scale);
+}
+
+inline bool operator==(const BoxF& a, const BoxF& b) {
+  return a.origin() == b.origin() && a.width() == b.width() &&
+         a.height() == b.height() && a.depth() == b.depth();
+}
+
+inline bool operator!=(const BoxF& a, const BoxF& b) {
+  return !(a == b);
+}
+
+inline BoxF operator+(const BoxF& b, const Vector3dF& v) {
+  return BoxF(b.x() + v.x(),
+              b.y() + v.y(),
+              b.z() + v.z(),
+              b.width(),
+              b.height(),
+              b.depth());
+}
+
+}  // namespace gfx
+
+#endif  // UI_GFX_BOX_F_H_
diff --git a/ui/gfx/box_unittest.cc b/ui/gfx/box_unittest.cc
new file mode 100644
index 0000000..0e944ec
--- /dev/null
+++ b/ui/gfx/box_unittest.cc
@@ -0,0 +1,143 @@
+// 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/basictypes.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/gfx/box_f.h"
+
+namespace gfx {
+
+TEST(BoxTest, Constructors) {
+  EXPECT_EQ(BoxF(0.f, 0.f, 0.f, 0.f, 0.f, 0.f).ToString(),
+            BoxF().ToString());
+  EXPECT_EQ(BoxF(0.f, 0.f, 0.f, -3.f, -5.f, -7.f).ToString(),
+            BoxF().ToString());
+
+  EXPECT_EQ(BoxF(0.f, 0.f, 0.f, 3.f, 5.f, 7.f).ToString(),
+            BoxF(3.f, 5.f, 7.f).ToString());
+  EXPECT_EQ(BoxF(0.f, 0.f, 0.f, 0.f, 0.f, 0.f).ToString(),
+            BoxF(-3.f, -5.f, -7.f).ToString());
+
+  EXPECT_EQ(BoxF(2.f, 4.f, 6.f, 3.f, 5.f, 7.f).ToString(),
+            BoxF(Point3F(2.f, 4.f, 6.f), 3.f, 5.f, 7.f).ToString());
+  EXPECT_EQ(BoxF(2.f, 4.f, 6.f, 0.f, 0.f, 0.f).ToString(),
+            BoxF(Point3F(2.f, 4.f, 6.f), -3.f, -5.f, -7.f).ToString());
+}
+
+TEST(BoxTest, IsEmpty) {
+  EXPECT_TRUE(BoxF(0.f, 0.f, 0.f, 0.f, 0.f, 0.f).IsEmpty());
+  EXPECT_TRUE(BoxF(1.f, 2.f, 3.f, 0.f, 0.f, 0.f).IsEmpty());
+
+  EXPECT_TRUE(BoxF(0.f, 0.f, 0.f, 2.f, 0.f, 0.f).IsEmpty());
+  EXPECT_TRUE(BoxF(1.f, 2.f, 3.f, 2.f, 0.f, 0.f).IsEmpty());
+  EXPECT_TRUE(BoxF(0.f, 0.f, 0.f, 0.f, 2.f, 0.f).IsEmpty());
+  EXPECT_TRUE(BoxF(1.f, 2.f, 3.f, 0.f, 2.f, 0.f).IsEmpty());
+  EXPECT_TRUE(BoxF(0.f, 0.f, 0.f, 0.f, 0.f, 2.f).IsEmpty());
+  EXPECT_TRUE(BoxF(1.f, 2.f, 3.f, 0.f, 0.f, 2.f).IsEmpty());
+
+  EXPECT_FALSE(BoxF(0.f, 0.f, 0.f, 0.f, 2.f, 2.f).IsEmpty());
+  EXPECT_FALSE(BoxF(1.f, 2.f, 3.f, 0.f, 2.f, 2.f).IsEmpty());
+  EXPECT_FALSE(BoxF(0.f, 0.f, 0.f, 2.f, 0.f, 2.f).IsEmpty());
+  EXPECT_FALSE(BoxF(1.f, 2.f, 3.f, 2.f, 0.f, 2.f).IsEmpty());
+  EXPECT_FALSE(BoxF(0.f, 0.f, 0.f, 2.f, 2.f, 0.f).IsEmpty());
+  EXPECT_FALSE(BoxF(1.f, 2.f, 3.f, 2.f, 2.f, 0.f).IsEmpty());
+
+  EXPECT_FALSE(BoxF(0.f, 0.f, 0.f, 2.f, 2.f, 2.f).IsEmpty());
+  EXPECT_FALSE(BoxF(1.f, 2.f, 3.f, 2.f, 2.f, 2.f).IsEmpty());
+}
+
+TEST(BoxTest, Union) {
+  BoxF empty_box;
+  BoxF box1(0.f, 0.f, 0.f, 1.f, 1.f, 1.f);
+  BoxF box2(0.f, 0.f, 0.f, 4.f, 6.f, 8.f);
+  BoxF box3(3.f, 4.f, 5.f, 6.f, 4.f, 0.f);
+
+  EXPECT_EQ(empty_box.ToString(), UnionBoxes(empty_box, empty_box).ToString());
+  EXPECT_EQ(box1.ToString(), UnionBoxes(empty_box, box1).ToString());
+  EXPECT_EQ(box1.ToString(), UnionBoxes(box1, empty_box).ToString());
+  EXPECT_EQ(box2.ToString(), UnionBoxes(empty_box, box2).ToString());
+  EXPECT_EQ(box2.ToString(), UnionBoxes(box2, empty_box).ToString());
+  EXPECT_EQ(box3.ToString(), UnionBoxes(empty_box, box3).ToString());
+  EXPECT_EQ(box3.ToString(), UnionBoxes(box3, empty_box).ToString());
+
+  // box_1 is contained in box_2
+  EXPECT_EQ(box2.ToString(), UnionBoxes(box1, box2).ToString());
+  EXPECT_EQ(box2.ToString(), UnionBoxes(box2, box1).ToString());
+
+  // box_1 and box_3 are disjoint
+  EXPECT_EQ(BoxF(0.f, 0.f, 0.f, 9.f, 8.f, 5.f).ToString(),
+            UnionBoxes(box1, box3).ToString());
+  EXPECT_EQ(BoxF(0.f, 0.f, 0.f, 9.f, 8.f, 5.f).ToString(),
+            UnionBoxes(box3, box1).ToString());
+
+  // box_2 and box_3 intersect, but neither contains the other
+  EXPECT_EQ(BoxF(0.f, 0.f, 0.f, 9.f, 8.f, 8.f).ToString(),
+            UnionBoxes(box2, box3).ToString());
+  EXPECT_EQ(BoxF(0.f, 0.f, 0.f, 9.f, 8.f, 8.f).ToString(),
+            UnionBoxes(box3, box2).ToString());
+}
+
+TEST(BoxTest, Scale) {
+  BoxF box1(2.f, 3.f, 4.f, 5.f, 6.f, 7.f);
+
+  EXPECT_EQ(BoxF().ToString(), ScaleBox(box1, 0.f).ToString());
+  EXPECT_EQ(box1.ToString(), ScaleBox(box1, 1.f).ToString());
+  EXPECT_EQ(BoxF(4.f, 12.f, 24.f, 10.f, 24.f, 42.f).ToString(),
+            ScaleBox(box1, 2.f, 4.f, 6.f).ToString());
+
+  BoxF box2 = box1;
+  box2.Scale(0.f);
+  EXPECT_EQ(BoxF().ToString(), box2.ToString());
+
+  box2 = box1;
+  box2.Scale(1.f);
+  EXPECT_EQ(box1.ToString(), box2.ToString());
+
+  box2.Scale(2.f, 4.f, 6.f);
+  EXPECT_EQ(BoxF(4.f, 12.f, 24.f, 10.f, 24.f, 42.f).ToString(),
+            box2.ToString());
+}
+
+TEST(BoxTest, Equals) {
+  EXPECT_TRUE(BoxF() == BoxF());
+  EXPECT_TRUE(BoxF(2.f, 3.f, 4.f, 6.f, 8.f, 10.f) ==
+              BoxF(2.f, 3.f, 4.f, 6.f, 8.f, 10.f));
+  EXPECT_FALSE(BoxF() == BoxF(0.f, 0.f, 0.f, 0.f, 0.f, 1.f));
+  EXPECT_FALSE(BoxF() == BoxF(0.f, 0.f, 0.f, 0.f, 1.f, 0.f));
+  EXPECT_FALSE(BoxF() == BoxF(0.f, 0.f, 0.f, 1.f, 0.f, 0.f));
+  EXPECT_FALSE(BoxF() == BoxF(0.f, 0.f, 1.f, 0.f, 0.f, 0.f));
+  EXPECT_FALSE(BoxF() == BoxF(0.f, 1.f, 0.f, 0.f, 0.f, 0.f));
+  EXPECT_FALSE(BoxF() == BoxF(1.f, 0.f, 0.f, 0.f, 0.f, 0.f));
+}
+
+TEST(BoxTest, NotEquals) {
+  EXPECT_FALSE(BoxF() != BoxF());
+  EXPECT_FALSE(BoxF(2.f, 3.f, 4.f, 6.f, 8.f, 10.f) !=
+               BoxF(2.f, 3.f, 4.f, 6.f, 8.f, 10.f));
+  EXPECT_TRUE(BoxF() != BoxF(0.f, 0.f, 0.f, 0.f, 0.f, 1.f));
+  EXPECT_TRUE(BoxF() != BoxF(0.f, 0.f, 0.f, 0.f, 1.f, 0.f));
+  EXPECT_TRUE(BoxF() != BoxF(0.f, 0.f, 0.f, 1.f, 0.f, 0.f));
+  EXPECT_TRUE(BoxF() != BoxF(0.f, 0.f, 1.f, 0.f, 0.f, 0.f));
+  EXPECT_TRUE(BoxF() != BoxF(0.f, 1.f, 0.f, 0.f, 0.f, 0.f));
+  EXPECT_TRUE(BoxF() != BoxF(1.f, 0.f, 0.f, 0.f, 0.f, 0.f));
+}
+
+
+TEST(BoxTest, Offset) {
+  BoxF box1(2.f, 3.f, 4.f, 5.f, 6.f, 7.f);
+
+  EXPECT_EQ(box1.ToString(), (box1 + Vector3dF(0.f, 0.f, 0.f)).ToString());
+  EXPECT_EQ(BoxF(3.f, 1.f, 0.f, 5.f, 6.f, 7.f).ToString(),
+            (box1 + Vector3dF(1.f, -2.f, -4.f)).ToString());
+
+  BoxF box2 = box1;
+  box2 += Vector3dF(0.f, 0.f, 0.f);
+  EXPECT_EQ(box1.ToString(), box2.ToString());
+
+  box2 += Vector3dF(1.f, -2.f, -4.f);
+  EXPECT_EQ(BoxF(3.f, 1.f, 0.f, 5.f, 6.f, 7.f).ToString(),
+            box2.ToString());
+}
+
+}  // namespace gfx
diff --git a/ui/gfx/font_list.cc b/ui/gfx/font_list.cc
index cb6cc97..e01483a 100644
--- a/ui/gfx/font_list.cc
+++ b/ui/gfx/font_list.cc
@@ -70,37 +70,60 @@
 
 namespace gfx {
 
-FontList::FontList() : common_height_(-1), common_baseline_(-1) {
+FontList::FontList()
+    : common_height_(-1),
+      common_baseline_(-1),
+      font_style_(-1),
+      font_size_(-1) {
   fonts_.push_back(Font());
 }
 
 FontList::FontList(const std::string& font_description_string)
     : font_description_string_(font_description_string),
       common_height_(-1),
-      common_baseline_(-1) {
+      common_baseline_(-1),
+      font_style_(-1),
+      font_size_(-1) {
   DCHECK(!font_description_string.empty());
   // DCHECK description string ends with "px" for size in pixel.
   DCHECK(EndsWith(font_description_string, "px", true));
 }
 
+FontList::FontList(const std::vector<std::string>& font_names,
+                   int font_style,
+                   int font_size)
+    : font_description_string_(BuildFontDescription(font_names, font_style,
+                                                    font_size)),
+      common_height_(-1),
+      common_baseline_(-1),
+      font_style_(font_style),
+      font_size_(font_size) {
+  DCHECK(!font_names.empty());
+  DCHECK(!font_names[0].empty());
+}
+
 FontList::FontList(const std::vector<Font>& fonts)
     : fonts_(fonts),
       common_height_(-1),
-      common_baseline_(-1) {
+      common_baseline_(-1),
+      font_style_(-1),
+      font_size_(-1) {
   DCHECK(!fonts.empty());
+  font_style_ = fonts[0].GetStyle();
+  font_size_ = fonts[0].GetFontSize();
   if (DCHECK_IS_ON()) {
-    int style = fonts[0].GetStyle();
-    int size = fonts[0].GetFontSize();
     for (size_t i = 1; i < fonts.size(); ++i) {
-      DCHECK_EQ(fonts[i].GetStyle(), style);
-      DCHECK_EQ(fonts[i].GetFontSize(), size);
+      DCHECK_EQ(fonts[i].GetStyle(), font_style_);
+      DCHECK_EQ(fonts[i].GetFontSize(), font_size_);
     }
   }
 }
 
 FontList::FontList(const Font& font)
     : common_height_(-1),
-      common_baseline_(-1) {
+      common_baseline_(-1),
+      font_style_(-1),
+      font_size_(-1) {
   fonts_.push_back(font);
 }
 
@@ -108,89 +131,74 @@
 }
 
 FontList FontList::DeriveFontList(int font_style) const {
-  // If there is a font vector, derive from that.
-  if (!fonts_.empty()) {
-    std::vector<Font> fonts = fonts_;
-    for (size_t i = 0; i < fonts.size(); ++i)
-      fonts[i] = fonts[i].DeriveFont(0, font_style);
-    return FontList(fonts);
-  }
-
-  // Otherwise, parse the font description string to derive from it.
-  std::vector<std::string> font_names;
-  int old_style;
-  int font_size;
-  ParseFontDescriptionString(font_description_string_, &font_names,
-                             &old_style, &font_size);
-  return FontList(BuildFontDescription(font_names, font_style, font_size));
+  return DeriveFontListWithSizeDeltaAndStyle(0, font_style);
 }
 
 FontList FontList::DeriveFontListWithSize(int size) const {
   DCHECK_GT(size, 0);
+  return DeriveFontListWithSizeDeltaAndStyle(size - GetFontSize(),
+                                             GetFontStyle());
+}
 
+FontList FontList::DeriveFontListWithSizeDelta(int size_delta) const {
+  return DeriveFontListWithSizeDeltaAndStyle(size_delta, GetFontStyle());
+}
+
+FontList FontList::DeriveFontListWithSizeDeltaAndStyle(int size_delta,
+                                                       int style) const {
   // If there is a font vector, derive from that.
-  int old_size = 0;
   if (!fonts_.empty()) {
-    old_size = fonts_[0].GetFontSize();
-    if (old_size == size)
-      return FontList(fonts_);
-
     std::vector<Font> fonts = fonts_;
     for (size_t i = 0; i < fonts.size(); ++i)
-      fonts[i] = fonts[i].DeriveFont(size - old_size);
+      fonts[i] = fonts[i].DeriveFont(size_delta, style);
     return FontList(fonts);
   }
 
   // Otherwise, parse the font description string to derive from it.
   std::vector<std::string> font_names;
-  int font_style = 0;
+  int old_size;
+  int old_style;
   ParseFontDescriptionString(font_description_string_, &font_names,
-                             &font_style, &old_size);
-
-  if (old_size == size)
-    return FontList(font_description_string_);
-
-  return FontList(BuildFontDescription(font_names, font_style, size));
+                             &old_style, &old_size);
+  int size = old_size + size_delta;
+  DCHECK_GT(size, 0);
+  return FontList(font_names, style, size);
 }
 
 int FontList::GetHeight() const {
-  if (common_height_ < 0) {
-    int ascent = 0;
-    int descent = 0;
-    const std::vector<Font>& fonts = GetFonts();
-    for (std::vector<Font>::const_iterator i = fonts.begin();
-         i != fonts.end(); ++i) {
-      ascent = std::max(ascent, i->GetBaseline());
-      descent = std::max(descent, i->GetHeight() - i->GetBaseline());
-    }
-    common_height_ = ascent + descent;
-  }
+  if (common_height_ == -1)
+    CacheCommonFontHeightAndBaseline();
   return common_height_;
 }
 
 int FontList::GetBaseline() const {
-  if (common_baseline_ < 0) {
-    int baseline = 0;
-    const std::vector<Font>& fonts = GetFonts();
-    for (std::vector<Font>::const_iterator i = fonts.begin();
-         i != fonts.end(); ++i) {
-      baseline = std::max(baseline, i->GetBaseline());
-    }
-    common_baseline_ = baseline;
-  }
+  if (common_baseline_ == -1)
+    CacheCommonFontHeightAndBaseline();
   return common_baseline_;
 }
 
-int FontList::GetFontStyle() const {
-  if (!fonts_.empty())
-    return fonts_[0].GetStyle();
+int FontList::GetStringWidth(const base::string16& text) const {
+  // Rely on the primary font metrics for the time being.
+  // TODO(yukishiino): Not only the first font, all the fonts in the list should
+  // be taken into account to compute the pixels needed to display |text|.
+  // Also this method, including one in Font class, should be deprecated and
+  // client code should call Canvas::GetStringWidth(text, font_list) directly.
+  // Our plan is as follows:
+  //   1. Introduce the FontList version of Canvas::GetStringWidth().
+  //   2. Make client code call Canvas::GetStringWidth().
+  //   3. Retire {Font,FontList}::GetStringWidth().
+  return GetPrimaryFont().GetStringWidth(text);
+}
 
-  std::vector<std::string> font_names;
-  int font_style;
-  int font_size;
-  ParseFontDescriptionString(font_description_string_, &font_names,
-                             &font_style, &font_size);
-  return font_style;
+int FontList::GetExpectedTextWidth(int length) const {
+  // Rely on the primary font metrics for the time being.
+  return GetPrimaryFont().GetExpectedTextWidth(length);
+}
+
+int FontList::GetFontStyle() const {
+  if (font_style_ == -1)
+    CacheFontStyleAndSize();
+  return font_style_;
 }
 
 const std::string& FontList::GetFontDescriptionString() const {
@@ -209,15 +217,9 @@
 }
 
 int FontList::GetFontSize() const {
-  if (!fonts_.empty())
-    return fonts_[0].GetFontSize();
-
-  std::vector<std::string> font_names;
-  int font_style;
-  int font_size;
-  ParseFontDescriptionString(font_description_string_, &font_names,
-                             &font_style, &font_size);
-  return font_size;
+  if (font_size_ == -1)
+    CacheFontStyleAndSize();
+  return font_size_;
 }
 
 const std::vector<Font>& FontList::GetFonts() const {
@@ -225,18 +227,16 @@
     DCHECK(!font_description_string_.empty());
 
     std::vector<std::string> font_names;
-    int font_style;
-    int font_size;
     ParseFontDescriptionString(font_description_string_, &font_names,
-                               &font_style, &font_size);
+                               &font_style_, &font_size_);
     for (size_t i = 0; i < font_names.size(); ++i) {
       DCHECK(!font_names[i].empty());
 
-      Font font(font_names[i], font_size);
-      if (font_style == Font::NORMAL)
+      Font font(font_names[i], font_size_);
+      if (font_style_ == Font::NORMAL)
         fonts_.push_back(font);
       else
-        fonts_.push_back(font.DeriveFont(0, font_style));
+        fonts_.push_back(font.DeriveFont(0, font_style_));
     }
   }
   return fonts_;
@@ -246,4 +246,28 @@
   return GetFonts()[0];
 }
 
+void FontList::CacheCommonFontHeightAndBaseline() const {
+  int ascent = 0;
+  int descent = 0;
+  const std::vector<Font>& fonts = GetFonts();
+  for (std::vector<Font>::const_iterator i = fonts.begin();
+       i != fonts.end(); ++i) {
+    ascent = std::max(ascent, i->GetBaseline());
+    descent = std::max(descent, i->GetHeight() - i->GetBaseline());
+  }
+  common_height_ = ascent + descent;
+  common_baseline_ = ascent;
+}
+
+void FontList::CacheFontStyleAndSize() const {
+  if (!fonts_.empty()) {
+    font_style_ = fonts_[0].GetStyle();
+    font_size_ = fonts_[0].GetFontSize();
+  } else {
+    std::vector<std::string> font_names;
+    ParseFontDescriptionString(font_description_string_, &font_names,
+                               &font_style_, &font_size_);
+  }
+}
+
 }  // namespace gfx
diff --git a/ui/gfx/font_list.h b/ui/gfx/font_list.h
index 8c1d0f3..22be912 100644
--- a/ui/gfx/font_list.h
+++ b/ui/gfx/font_list.h
@@ -41,6 +41,11 @@
   // size.
   explicit FontList(const std::string& font_description_string);
 
+  // Creates a font list from font names, styles and size.
+  FontList(const std::vector<std::string>& font_names,
+           int font_style,
+           int font_size);
+
   // Creates a font list from a Font vector.
   // All fonts in this vector should have the same style and size.
   explicit FontList(const std::vector<Font>& fonts);
@@ -57,6 +62,17 @@
   // given font |size| in pixels.
   FontList DeriveFontListWithSize(int size) const;
 
+  // Returns a new FontList with the same font names and style but resized.
+  // |size_delta| is the size in pixels to add to the current font size.
+  FontList DeriveFontListWithSizeDelta(int size_delta) const;
+
+  // Returns a new FontList with the same font names but resized and the given
+  // style. |size_delta| is the size in pixels to add to the current font size.
+  // |font_style| specifies the new style, which is a bitmask of the values:
+  // Font::BOLD, Font::ITALIC and Font::UNDERLINE.
+  FontList DeriveFontListWithSizeDeltaAndStyle(int size_delta,
+                                               int font_style) const;
+
   // Returns the height of this font list, which is max(ascent) + max(descent)
   // for all the fonts in the font list.
   int GetHeight() const;
@@ -65,6 +81,14 @@
   // fonts in the font list.
   int GetBaseline() const;
 
+  // Returns the number of horizontal pixels needed to display |text|.
+  int GetStringWidth(const base::string16& text) const;
+
+  // Returns the expected number of horizontal pixels needed to display the
+  // specified length of characters. Call GetStringWidth() to retrieve the
+  // actual number.
+  int GetExpectedTextWidth(int length) const;
+
   // Returns the |gfx::Font::FontStyle| style flags for this font list.
   int GetFontStyle() const;
 
@@ -83,6 +107,13 @@
   const Font& GetPrimaryFont() const;
 
  private:
+  // Extracts common font height and baseline into |common_height_| and
+  // |common_baseline_|.
+  void CacheCommonFontHeightAndBaseline() const;
+
+  // Extracts font style and size into |font_style_| and |font_size_|.
+  void CacheFontStyleAndSize() const;
+
   // A vector of Font. If FontList is constructed with font description string,
   // |fonts_| is not initialized during construction. Instead, it is computed
   // lazily when user asked to get the font vector.
@@ -99,6 +130,10 @@
   // The cached common height and baseline of the fonts in the font list.
   mutable int common_height_;
   mutable int common_baseline_;
+
+  // Cached font style and size.
+  mutable int font_style_;
+  mutable int font_size_;
 };
 
 }  // namespace gfx
diff --git a/ui/gfx/font_list_unittest.cc b/ui/gfx/font_list_unittest.cc
index 170f6e8..a62a13d 100644
--- a/ui/gfx/font_list_unittest.cc
+++ b/ui/gfx/font_list_unittest.cc
@@ -33,16 +33,27 @@
 TEST(FontListTest, FontDescString_FromDescString) {
   // Test init from font name style size string.
   FontList font_list = FontList("Droid Sans serif, Sans serif, 10px");
-  const std::string& font_str = font_list.GetFontDescriptionString();
-  EXPECT_EQ("Droid Sans serif, Sans serif, 10px", font_str);
+  EXPECT_EQ("Droid Sans serif, Sans serif, 10px",
+            font_list.GetFontDescriptionString());
+}
+
+TEST(FontListTest, FontDescString_FromFontNamesStyleAndSize) {
+  // Test init from font names, style and size.
+  std::vector<std::string> font_names;
+  font_names.push_back("Arial");
+  font_names.push_back("Droid Sans serif");
+  int font_style = Font::BOLD | Font::ITALIC;
+  int font_size = 11;
+  FontList font_list = FontList(font_names, font_style, font_size);
+  EXPECT_EQ("Arial,Droid Sans serif,Bold Italic 11px",
+            font_list.GetFontDescriptionString());
 }
 
 TEST(FontListTest, FontDescString_FromFont) {
   // Test init from Font.
   Font font("Arial", 8);
   FontList font_list = FontList(font);
-  const std::string& font_str = font_list.GetFontDescriptionString();
-  EXPECT_EQ("Arial,8px", font_str);
+  EXPECT_EQ("Arial,8px", font_list.GetFontDescriptionString());
 }
 
 TEST(FontListTest, FontDescString_FromFontWithNonNormalStyle) {
@@ -63,8 +74,7 @@
   fonts.push_back(font.DeriveFont(0, Font::BOLD));
   fonts.push_back(font_1.DeriveFont(-2, Font::BOLD));
   FontList font_list = FontList(fonts);
-  const std::string& font_str = font_list.GetFontDescriptionString();
-  EXPECT_EQ("Arial,Sans serif,Bold 8px", font_str);
+  EXPECT_EQ("Arial,Sans serif,Bold 8px", font_list.GetFontDescriptionString());
 }
 
 TEST(FontListTest, Fonts_FromDescString) {
@@ -233,6 +243,52 @@
   EXPECT_EQ("Sans serif|5", FontToString(derived_fonts[1]));
 }
 
+TEST(FontListTest, FontDescString_DeriveFontListWithSizeDelta) {
+  FontList font_list = FontList("Arial,Sans serif,Bold 18px");
+
+  FontList derived = font_list.DeriveFontListWithSizeDelta(-8);
+  EXPECT_EQ("Arial,Sans serif,Bold 10px",
+            derived.GetFontDescriptionString());
+}
+
+TEST(FontListTest, Fonts_DeriveFontListWithSizeDelta) {
+  std::vector<Font> fonts;
+  fonts.push_back(gfx::Font("Arial", 18).DeriveFont(0, Font::ITALIC));
+  fonts.push_back(gfx::Font("Sans serif", 18).DeriveFont(0, Font::ITALIC));
+  FontList font_list = FontList(fonts);
+
+  FontList derived = font_list.DeriveFontListWithSizeDelta(-5);
+  const std::vector<Font>& derived_fonts = derived.GetFonts();
+
+  EXPECT_EQ(2U, derived_fonts.size());
+  EXPECT_EQ("Arial|13|italic", FontToString(derived_fonts[0]));
+  EXPECT_EQ("Sans serif|13|italic", FontToString(derived_fonts[1]));
+}
+
+TEST(FontListTest, FontDescString_DeriveFontListWithSizeDeltaAndStyle) {
+  FontList font_list = FontList("Arial,Sans serif,Bold Italic  8px");
+
+  FontList derived =
+      font_list.DeriveFontListWithSizeDeltaAndStyle(10, Font::ITALIC);
+  EXPECT_EQ("Arial,Sans serif,Italic 18px",
+            derived.GetFontDescriptionString());
+}
+
+TEST(FontListTest, Fonts_DeriveFontListWithSizeDeltaAndStyle) {
+  std::vector<Font> fonts;
+  fonts.push_back(gfx::Font("Arial", 8));
+  fonts.push_back(gfx::Font("Sans serif", 8));
+  FontList font_list = FontList(fonts);
+
+  FontList derived =
+      font_list.DeriveFontListWithSizeDeltaAndStyle(5, Font::BOLD);
+  const std::vector<Font>& derived_fonts = derived.GetFonts();
+
+  EXPECT_EQ(2U, derived_fonts.size());
+  EXPECT_EQ("Arial|13|bold", FontToString(derived_fonts[0]));
+  EXPECT_EQ("Sans serif|13|bold", FontToString(derived_fonts[1]));
+}
+
 TEST(FontListTest, Fonts_GetHeight_GetBaseline) {
   // If a font list has only one font, the height and baseline must be the same.
   Font font1("Arial", 16);
diff --git a/ui/gfx/point3_f.h b/ui/gfx/point3_f.h
index 6c45a7d..8c700df 100644
--- a/ui/gfx/point3_f.h
+++ b/ui/gfx/point3_f.h
@@ -24,6 +24,14 @@
 
   ~Point3F() {}
 
+  void Scale(float scale) {
+    Scale(scale, scale, scale);
+  }
+
+  void Scale(float x_scale, float y_scale, float z_scale) {
+    SetPoint(x() * x_scale, y() * y_scale, z() * z_scale);
+  }
+
   float x() const { return x_; }
   float y() const { return y_; }
   float z() const { return z_; }
@@ -38,6 +46,20 @@
     z_ = z;
   }
 
+  // Offset the point by the given vector.
+  void operator+=(const Vector3dF& v) {
+    x_ += v.x();
+    y_ += v.y();
+    z_ += v.z();
+  }
+
+  // Offset the point by the given vector's inverse.
+  void operator-=(const Vector3dF& v) {
+    x_ -= v.x();
+    y_ -= v.y();
+    z_ -= v.z();
+  }
+
   // Returns the squared euclidean distance between two points.
   float SquaredDistanceTo(const Point3F& other) const {
     float dx = x_ - other.x_;
@@ -82,6 +104,17 @@
   return Point3F(offset.x(), offset.y(), offset.z());
 }
 
+inline Point3F ScalePoint(const Point3F& p,
+                          float x_scale,
+                          float y_scale,
+                          float z_scale) {
+  return Point3F(p.x() * x_scale, p.y() * y_scale, p.z() * z_scale);
+}
+
+inline Point3F ScalePoint(const Point3F& p, float scale) {
+  return ScalePoint(p, scale, scale, scale);
+}
+
 }  // namespace gfx
 
 #endif  // UI_GFX_POINT3_F_H_
diff --git a/ui/gfx/point3_unittest.cc b/ui/gfx/point3_unittest.cc
index 3de4f12..735ffd5 100644
--- a/ui/gfx/point3_unittest.cc
+++ b/ui/gfx/point3_unittest.cc
@@ -30,6 +30,12 @@
   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i)
     EXPECT_EQ(tests[i].expected.ToString(),
               tests[i].actual.ToString());
+
+  a += v1;
+  EXPECT_EQ(Point3F(4.7f, 1.9f, 12.5f).ToString(), a.ToString());
+
+  a -= v2;
+  EXPECT_EQ(Point3F(12.8f, 0.7f, 9.2f).ToString(), a.ToString());
 }
 
 TEST(Point3Test, VectorFromPoints) {
@@ -40,4 +46,25 @@
   EXPECT_EQ((b - a).ToString(), v1.ToString());
 }
 
+TEST(Point3Test, Scale) {
+  EXPECT_EQ(Point3F().ToString(), ScalePoint(Point3F(), 2.f).ToString());
+  EXPECT_EQ(Point3F().ToString(),
+            ScalePoint(Point3F(), 2.f, 2.f, 2.f).ToString());
+
+  EXPECT_EQ(Point3F(2.f, -2.f, 4.f).ToString(),
+            ScalePoint(Point3F(1.f, -1.f, 2.f), 2.f).ToString());
+  EXPECT_EQ(Point3F(2.f, -3.f, 8.f).ToString(),
+            ScalePoint(Point3F(1.f, -1.f, 2.f), 2.f, 3.f, 4.f).ToString());
+
+  Point3F zero;
+  zero.Scale(2.f);
+  zero.Scale(6.f, 3.f, 1.5f);
+  EXPECT_EQ(Point3F().ToString(), zero.ToString());
+
+  Point3F point(1.f, -1.f, 2.f);
+  point.Scale(2.f);
+  point.Scale(6.f, 3.f, 1.5f);
+  EXPECT_EQ(Point3F(12.f, -6.f, 6.f).ToString(), point.ToString());
+}
+
 }  // namespace gfx
diff --git a/ui/gfx/render_text.cc b/ui/gfx/render_text.cc
index 39d3eed..1fcf18c 100644
--- a/ui/gfx/render_text.cc
+++ b/ui/gfx/render_text.cc
@@ -661,15 +661,27 @@
   canvas->FillRect(GetCursorBounds(position, true), cursor_color_);
 }
 
-void RenderText::DrawSelectedText(Canvas* canvas) {
+void RenderText::DrawSelectedTextForDrag(Canvas* canvas) {
   EnsureLayout();
   const std::vector<Rect> sel = GetSubstringBounds(selection());
+
+  // Override the selection color with black, and force the background to be
+  // transparent so that it's rendered without subpixel antialiasing.
+  const bool saved_background_is_transparent = background_is_transparent();
+  const SkColor saved_selection_color = selection_color();
+  set_background_is_transparent(true);
+  set_selection_color(SK_ColorBLACK);
+
   for (size_t i = 0; i < sel.size(); ++i) {
     canvas->Save();
     canvas->ClipRect(sel[i]);
     DrawVisualText(canvas);
     canvas->Restore();
   }
+
+  // Restore saved transparency and selection color.
+  set_selection_color(saved_selection_color);
+  set_background_is_transparent(saved_background_is_transparent);
 }
 
 Rect RenderText::GetCursorBounds(const SelectionModel& caret,
diff --git a/ui/gfx/render_text.h b/ui/gfx/render_text.h
index 8a25d13..3427740 100644
--- a/ui/gfx/render_text.h
+++ b/ui/gfx/render_text.h
@@ -300,8 +300,9 @@
   // Draws a cursor at |position|.
   void DrawCursor(Canvas* canvas, const SelectionModel& position);
 
-  // Draw the selected text without a cursor or selection highlight.
-  void DrawSelectedText(Canvas* canvas);
+  // Draw the selected text without a cursor or selection highlight. Subpixel
+  // antialiasing is disabled and foreground color is forced to black.
+  void DrawSelectedTextForDrag(Canvas* canvas);
 
   // Gets the SelectionModel from a visual point in local coordinates.
   virtual SelectionModel FindCursorPosition(const Point& point) = 0;
diff --git a/ui/gl/gl.target.darwin-arm.mk b/ui/gl/gl.target.darwin-arm.mk
index 3433b8a..a0c95dd 100644
--- a/ui/gl/gl.target.darwin-arm.mk
+++ b/ui/gl/gl.target.darwin-arm.mk
@@ -195,6 +195,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-DPOSIX_AVOID_MMAP' \
 	'-DU_USING_ICU_NAMESPACE=0' \
@@ -311,6 +312,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-DPOSIX_AVOID_MMAP' \
 	'-DU_USING_ICU_NAMESPACE=0' \
diff --git a/ui/gl/gl.target.darwin-mips.mk b/ui/gl/gl.target.darwin-mips.mk
index 3869ca8..67cc9ee 100644
--- a/ui/gl/gl.target.darwin-mips.mk
+++ b/ui/gl/gl.target.darwin-mips.mk
@@ -194,6 +194,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-DPOSIX_AVOID_MMAP' \
 	'-DU_USING_ICU_NAMESPACE=0' \
@@ -309,6 +310,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-DPOSIX_AVOID_MMAP' \
 	'-DU_USING_ICU_NAMESPACE=0' \
diff --git a/ui/gl/gl.target.darwin-x86.mk b/ui/gl/gl.target.darwin-x86.mk
index 9baa74a..01f345e 100644
--- a/ui/gl/gl.target.darwin-x86.mk
+++ b/ui/gl/gl.target.darwin-x86.mk
@@ -197,6 +197,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-D__STDC_CONSTANT_MACROS' \
@@ -315,6 +316,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-D__STDC_CONSTANT_MACROS' \
diff --git a/ui/gl/gl.target.linux-arm.mk b/ui/gl/gl.target.linux-arm.mk
index 3433b8a..a0c95dd 100644
--- a/ui/gl/gl.target.linux-arm.mk
+++ b/ui/gl/gl.target.linux-arm.mk
@@ -195,6 +195,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-DPOSIX_AVOID_MMAP' \
 	'-DU_USING_ICU_NAMESPACE=0' \
@@ -311,6 +312,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-DPOSIX_AVOID_MMAP' \
 	'-DU_USING_ICU_NAMESPACE=0' \
diff --git a/ui/gl/gl.target.linux-mips.mk b/ui/gl/gl.target.linux-mips.mk
index 3869ca8..67cc9ee 100644
--- a/ui/gl/gl.target.linux-mips.mk
+++ b/ui/gl/gl.target.linux-mips.mk
@@ -194,6 +194,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-DPOSIX_AVOID_MMAP' \
 	'-DU_USING_ICU_NAMESPACE=0' \
@@ -309,6 +310,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-DPOSIX_AVOID_MMAP' \
 	'-DU_USING_ICU_NAMESPACE=0' \
diff --git a/ui/gl/gl.target.linux-x86.mk b/ui/gl/gl.target.linux-x86.mk
index 9baa74a..01f345e 100644
--- a/ui/gl/gl.target.linux-x86.mk
+++ b/ui/gl/gl.target.linux-x86.mk
@@ -197,6 +197,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-D__STDC_CONSTANT_MACROS' \
@@ -315,6 +316,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-D__STDC_CONSTANT_MACROS' \
diff --git a/ui/gl/vsync_provider.h b/ui/gl/vsync_provider.h
index f76cacc..b9cef7a 100644
--- a/ui/gl/vsync_provider.h
+++ b/ui/gl/vsync_provider.h
@@ -10,10 +10,11 @@
 #include "base/basictypes.h"
 #include "base/callback.h"
 #include "base/time/time.h"
+#include "ui/gl/gl_export.h"
 
 namespace gfx {
 
-class VSyncProvider {
+class GL_EXPORT VSyncProvider {
  public:
   VSyncProvider();
   virtual ~VSyncProvider();
diff --git a/ui/keyboard/keyboard_controller_unittest.cc b/ui/keyboard/keyboard_controller_unittest.cc
index b0b4001..49c695a 100644
--- a/ui/keyboard/keyboard_controller_unittest.cc
+++ b/ui/keyboard/keyboard_controller_unittest.cc
@@ -123,6 +123,9 @@
   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() OVERRIDE { return gfx::Rect(); }
 
@@ -170,6 +173,7 @@
   }
 
   virtual void TearDown() OVERRIDE {
+    focus_controller_.reset();
     aura_test_helper_->TearDown();
   }
 
diff --git a/ui/keyboard/keyboard_util.cc b/ui/keyboard/keyboard_util.cc
index 076eacf..1579068 100644
--- a/ui/keyboard/keyboard_util.cc
+++ b/ui/keyboard/keyboard_util.cc
@@ -64,6 +64,45 @@
   return true;
 }
 
+// TODO(varunjain): It would be cleaner to have something in the
+// ui::TextInputClient interface, say MoveCaretInDirection(). The code in
+// here would get the ui::InputMethod from the root_window, and the
+// ui::TextInputClient from that (see above in InsertText()).
+bool MoveCursor(int swipe_direction,
+                int modifier_flags,
+                aura::RootWindow* root_window) {
+  if (!root_window)
+    return false;
+  ui::KeyboardCode codex = ui::VKEY_UNKNOWN;
+  ui::KeyboardCode codey = ui::VKEY_UNKNOWN;
+  if (swipe_direction & kCursorMoveRight)
+    codex = ui::VKEY_RIGHT;
+  else if (swipe_direction & kCursorMoveLeft)
+    codex = ui::VKEY_LEFT;
+
+  if (swipe_direction & kCursorMoveUp)
+    codey = ui::VKEY_UP;
+  else if (swipe_direction & kCursorMoveDown)
+    codey = ui::VKEY_DOWN;
+
+  // First deal with the x movement.
+  if (codex != ui::VKEY_UNKNOWN) {
+    ui::KeyEvent press_event(ui::ET_KEY_PRESSED, codex, modifier_flags, 0);
+    root_window->AsRootWindowHostDelegate()->OnHostKeyEvent(&press_event);
+    ui::KeyEvent release_event(ui::ET_KEY_RELEASED, codex, modifier_flags, 0);
+    root_window->AsRootWindowHostDelegate()->OnHostKeyEvent(&release_event);
+  }
+
+  // Then deal with the y movement.
+  if (codey != ui::VKEY_UNKNOWN) {
+    ui::KeyEvent press_event(ui::ET_KEY_PRESSED, codey, modifier_flags, 0);
+    root_window->AsRootWindowHostDelegate()->OnHostKeyEvent(&press_event);
+    ui::KeyEvent release_event(ui::ET_KEY_RELEASED, codey, modifier_flags, 0);
+    root_window->AsRootWindowHostDelegate()->OnHostKeyEvent(&release_event);
+  }
+  return true;
+}
+
 const GritResourceMap* GetKeyboardExtensionResources(size_t* size) {
   // This looks a lot like the contents of a resource map; however it is
   // necessary to have a custom path for the extension path, so the resource
diff --git a/ui/keyboard/keyboard_util.h b/ui/keyboard/keyboard_util.h
index 0fc60ff..7d46433 100644
--- a/ui/keyboard/keyboard_util.h
+++ b/ui/keyboard/keyboard_util.h
@@ -17,6 +17,14 @@
 
 namespace keyboard {
 
+// Enumeration of swipe directions.
+enum CursorMoveDirection {
+  kCursorMoveRight = 0x01,
+  kCursorMoveLeft = 0x02,
+  kCursorMoveUp = 0x04,
+  kCursorMoveDown = 0x08
+};
+
 // Returns true if the virtual keyboard is enabled.
 KEYBOARD_EXPORT bool IsKeyboardEnabled();
 
@@ -27,6 +35,12 @@
 KEYBOARD_EXPORT bool InsertText(const base::string16& text,
                                 aura::RootWindow* root_window);
 
+// Move cursor when swipe on the virtualkeyboard. Returns true if cursor was
+// successfully moved according to |swipe_direction|.
+KEYBOARD_EXPORT bool MoveCursor(int swipe_direction,
+                                int modifier_flags,
+                                aura::RootWindow* root_window);
+
 // Get the list of keyboard resources.  |size| is populated with the number of
 // resources in the returned array.
 KEYBOARD_EXPORT const GritResourceMap* GetKeyboardExtensionResources(
diff --git a/ui/keyboard/resources/api_adapter.js b/ui/keyboard/resources/api_adapter.js
index cd64f57..eb95e35 100644
--- a/ui/keyboard/resources/api_adapter.js
+++ b/ui/keyboard/resources/api_adapter.js
@@ -11,3 +11,8 @@
 function insertText(text) {
   chrome.experimental.input.virtualKeyboard.insertText(text, logIfError);
 }
+
+function MoveCursor(swipe_direction, swipe_flags) {
+  chrome.experimental.input.virtualKeyboard.moveCursor(swipe_direction,
+                                                       swipe_flags);
+}
diff --git a/ui/keyboard/resources/elements/kb-key.html b/ui/keyboard/resources/elements/kb-key.html
index b8bbd4d..fc366bb 100644
--- a/ui/keyboard/resources/elements/kb-key.html
+++ b/ui/keyboard/resources/elements/kb-key.html
@@ -40,6 +40,7 @@
           detail.nextKeyset = this.keysetRules.dbl[NEXT_KEYSET - OFFSET];
         }
         this.fire('enable-dbl', detail);
+        this.fire('enable-sel');
       }
     });
   </script>
diff --git a/ui/keyboard/resources/elements/kb-keyboard.html b/ui/keyboard/resources/elements/kb-keyboard.html
index d21edf0..f4efb31 100644
--- a/ui/keyboard/resources/elements/kb-keyboard.html
+++ b/ui/keyboard/resources/elements/kb-keyboard.html
@@ -6,6 +6,7 @@
 
 <polymer-element name="kb-keyboard" on-key-over="keyOver" on-key-up="keyUp"
     on-key-down="keyDown" on-key-longpress="keyLongpress" on-pointerup="up"
+    on-pointerdown="down" on-enable-sel="enableSel"
     on-enable-dbl="enableDbl" attributes="keyset layout rows">
   <template>
     <style>
@@ -60,6 +61,7 @@
      * 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}
@@ -90,14 +92,97 @@
       }
     };
 
+    /**
+     * The minimum movement interval needed to trigger cursor move on
+     * horizontal and vertical way.
+     * @const
+     * @type {number}
+     */
+    var MIN_SWIPE_DIST = 30;
+
+    /**
+     * The flags constants when shift is on. It is according to the EventFlags
+     * in event_constants.h in chromium c++ code.
+     * @const
+     * @type {number}
+     * TODO(zyaozhujun): Might add more flags here according to the defination
+     * in EventFlags.
+     */
+    var SHIFT = 2;
+
+    /**
+     * The boolean to decide if it is swipe in process or finished.
+     * @const
+     * @type {boolean}
+     */
+    var swipeInProgress = false;
+
+    /**
+     * The enumeration of swipe directions.
+     * @const
+     * @type {Enum}
+     */
+    var SWIPE_DIRECTION = {
+      RIGHT: 0x1,
+      LEFT: 0x2,
+      UP: 0x4,
+      DOWN: 0x8
+    };
+
+    /**
+     * A structure to track the current swipe status.
+     */
+    var swipeStatus = {
+
+      /**
+       * 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 flag of current modifier key.
+       * @type {number}
+       */
+      swipeFlags : 0,
+
+      /**
+       * Current swipe direction.
+       * @type {number}
+       */
+      swipeDirection : 0,
+
+      /**
+       * 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;
+      }
+    };
+
     Polymer('kb-keyboard', {
       lastPressedKey: null,
       voiceInput_: null,
       dblDetail_: null,
       dblTimer_: null,
+      swipeHandler: null,
 
       ready: function() {
         this.voiceInput_ = new VoiceInput(this);
+        this.swipeHandler = this.onSwipeUpdate.bind(this);
       },
 
       /**
@@ -121,6 +206,48 @@
       },
 
       /**
+       * This function is bound to swipeHandler. And swipeHandler handle
+       * the pointermove event after pointerdown event happened.
+       * @para {PointerEvent} event.
+       */
+      onSwipeUpdate: function(event) {
+	swipeStatus.offset_x += event.screenX - swipeStatus.pre_x;
+	swipeStatus.offset_y += event.screenY - swipeStatus.pre_y;
+        if (Math.abs(swipeStatus.offset_x) > MIN_SWIPE_DIST ||
+            Math.abs(swipeStatus.offset_y) > MIN_SWIPE_DIST) {
+          swipeInProgress = true;
+          this.lastPressedKey.classList.remove('active');
+        }
+        if (swipeStatus.offset_x > MIN_SWIPE_DIST) {
+	  swipeStatus.swipeDirection |= SWIPE_DIRECTION.RIGHT;
+          swipeStatus.offset_x = 0;
+        }
+        else if (swipeStatus.offset_x < -MIN_SWIPE_DIST) {
+	  swipeStatus.swipeDirection |= SWIPE_DIRECTION.LEFT;
+	  swipeStatus.offset_x = 0;
+	}
+        // Swipe vertically only when the swipe reaches the gradient of 45
+        // degree. This can also be larger.
+	if (Math.abs(event.screenY - swipeStatus.pre_y) >
+            Math.abs(event.screenX - swipeStatus.pre_x)) {
+          if (swipeStatus.offset_y > MIN_SWIPE_DIST) {
+            swipeStatus.swipeDirection |= SWIPE_DIRECTION.DOWN;
+	    swipeStatus.offset_y = 0;
+	  }
+          else if (swipeStatus.offset_y < -MIN_SWIPE_DIST) {
+	    swipeStatus.swipeDirection |= SWIPE_DIRECTION.UP;
+            swipeStatus.offset_y = 0;
+	  }
+        }
+       if (swipeStatus.swipeDirection) {
+	  MoveCursor(swipeStatus.swipeDirection, swipeStatus.swipeFlags);
+          swipeStatus.swipeDirection = 0;
+        }
+	swipeStatus.pre_x = event.screenX;
+	swipeStatus.pre_y = event.screenY;
+      },
+
+      /**
        * Handles key-down event that is sent by kb-key-base.
        * @param {CustomEvent} event The key-down event dispatched by
        *     kb-key-base.
@@ -173,12 +300,34 @@
       },
 
       /**
+       * Enable the selection while swipe.
+       * @param {CustomEvent} event The enable-dbl event dispatched by
+       *    kb-shift-key.
+       */
+      enableSel: function(event) {
+        swipeStatus.swipeFlags = SHIFT;
+      },
+
+      /**
+       * 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) {
+        swipeStatus.pre_x = event.screenX;
+        swipeStatus.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) {
-        if(this.dblDetail_) {
+        if (this.dblDetail_) {
           this.dblDetail_.clickCount++;
           if (this.dblDetail_.clickCount == 2) {
             this.keyset = this.dblDetail_.toKeyset;
@@ -188,6 +337,18 @@
             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 (swipeInProgress) {
+          swipeInProgress = false;
+          swipeStatus.resetAll();
+        }
+        // Remove the pointermove event hander here.
+        this.removeEventListener('pointermove', this.swipeHandler, false);
       },
 
       /**
@@ -198,7 +359,8 @@
       keyUp: function(event, detail) {
         if (this.skipEvent(detail))
           return;
-
+        if (swipeInProgress)
+          return;
         this.lastPressedKey.classList.remove('active');
         if (this.lastPressedKey != event.target)
           return;
@@ -226,6 +388,7 @@
         switch(char) {
           case 'Invalid':
           case 'Shift':
+            swipeStatus.swipeFlags = 0;
             return;
           case 'Microphone':
             this.voiceInput_.onDown();
@@ -273,7 +436,7 @@
             this.selectDefaultKeyset();
           } else {
             console.error('Unable to find layout ' + this.layout);
-          }
+         }
         }
       },
 
diff --git a/ui/message_center/cocoa/notification_controller.mm b/ui/message_center/cocoa/notification_controller.mm
index 4a36ee6..965ba42 100644
--- a/ui/message_center/cocoa/notification_controller.mm
+++ b/ui/message_center/cocoa/notification_controller.mm
@@ -459,6 +459,18 @@
   listFrame.origin.y += NSHeight(frame);
   progressBarFrame.origin.y += NSHeight(frame);
 
+  // Make sure that there is a minimum amount of spacing below the icon and
+  // the edge of the frame.
+  CGFloat bottomDelta = NSHeight(rootFrame) - NSHeight([icon_ frame]);
+  if (bottomDelta > 0 && bottomDelta < message_center::kIconBottomPadding) {
+    CGFloat bottomAdjust = message_center::kIconBottomPadding - bottomDelta;
+    rootFrame.size.height += bottomAdjust;
+    titleFrame.origin.y += bottomAdjust;
+    messageFrame.origin.y += bottomAdjust;
+    listFrame.origin.y += bottomAdjust;
+    progressBarFrame.origin.y += bottomAdjust;
+  }
+
   [[self view] setFrame:rootFrame];
   [title_ setFrame:titleFrame];
   [message_ setFrame:messageFrame];
diff --git a/ui/message_center/cocoa/settings_controller.h b/ui/message_center/cocoa/settings_controller.h
index 380ae14..7bce5ab 100644
--- a/ui/message_center/cocoa/settings_controller.h
+++ b/ui/message_center/cocoa/settings_controller.h
@@ -13,6 +13,7 @@
 #include "ui/message_center/notifier_settings.h"
 
 @class MCSettingsController;
+@class MCTrayViewController;
 
 namespace message_center {
 
@@ -43,6 +44,7 @@
  @private
   scoped_ptr<message_center::NotifierSettingsObserverMac> observer_;
   message_center::NotifierSettingsProvider* provider_;
+  MCTrayViewController* trayViewController_;  // Weak. Owns us.
 
   // The "Settings" text at the top.
   base::scoped_nsobject<NSTextField> settingsText_;
@@ -50,6 +52,9 @@
   // The smaller text below the "Settings" text.
   base::scoped_nsobject<NSTextField> detailsText_;
 
+  // The profile switcher.
+  base::scoped_nsobject<NSPopUpButton> groupDropDownButton_;
+
   // Container for all the checkboxes.
   base::scoped_nsobject<NSScrollView> scrollView_;
 
@@ -57,13 +62,15 @@
 }
 
 // Designated initializer.
-- (id)initWithProvider:(message_center::NotifierSettingsProvider*)provider;
+- (id)initWithProvider:(message_center::NotifierSettingsProvider*)provider
+    trayViewController:(MCTrayViewController*)trayViewController;
 
 @end
 
 // Testing API /////////////////////////////////////////////////////////////////
 
 @interface MCSettingsController (TestingAPI)
+- (NSPopUpButton*)groupDropDownButton;
 - (NSScrollView*)scrollView;
 @end
 
diff --git a/ui/message_center/cocoa/settings_controller.mm b/ui/message_center/cocoa/settings_controller.mm
index f34f9f0..8865dd9 100644
--- a/ui/message_center/cocoa/settings_controller.mm
+++ b/ui/message_center/cocoa/settings_controller.mm
@@ -99,6 +99,12 @@
 
 // Returns the NSButton corresponding to the checkbox for |notifiers_[index]|.
 - (NSButton*)buttonForNotifierAtIndex:(size_t)index;
+
+// Update the contents view.
+- (void)updateView;
+
+// Handler for the notifier group dropdown menu.
+- (void)notifierGroupSelectionChanged:(id)sender;
 @end
 
 namespace message_center {
@@ -110,16 +116,20 @@
   [settings_controller_ setIcon:icon.AsNSImage() forNotifierId:notifier_id];
 }
 
-void NotifierSettingsObserverMac::NotifierGroupChanged() {}
+void NotifierSettingsObserverMac::NotifierGroupChanged() {
+  [settings_controller_ updateView];
+}
 
 }  // namespace message_center
 
 @implementation MCSettingsController
 
-- (id)initWithProvider:(message_center::NotifierSettingsProvider*)provider {
+- (id)initWithProvider:(message_center::NotifierSettingsProvider*)provider
+    trayViewController:(MCTrayViewController*)trayViewController {
   if ((self = [super initWithNibName:nil bundle:nil])) {
     observer_.reset(new message_center::NotifierSettingsObserverMac(self));
     provider_ = provider;
+    trayViewController_ = trayViewController;
     provider_->AddObserver(observer_.get());
   }
   return self;
@@ -142,6 +152,11 @@
   return label;
 }
 
+- (void)updateView {
+  notifiers_.clear();
+  [trayViewController_ updateSettings];
+}
+
 - (void)loadView {
   DCHECK(notifiers_.empty());
   provider_->GetNotifierList(&notifiers_);
@@ -187,8 +202,10 @@
   [detailsText_ setFont:
       [NSFont messageFontOfSize:message_center::kMessageFontSize]];
 
+  size_t groupCount = provider_->GetNotifierGroupCount();
   [detailsText_ setStringValue:l10n_util::GetNSString(
-      IDS_MESSAGE_CENTER_SETTINGS_DIALOG_DESCRIPTION)];
+      groupCount > 1 ? IDS_MESSAGE_CENTER_SETTINGS_DESCRIPTION_MULTIUSER
+                     : IDS_MESSAGE_CENTER_SETTINGS_DIALOG_DESCRIPTION)];
   [detailsText_ sizeToFit];
   subheaderFrame = [detailsText_ frame];
   subheaderFrame.origin.y =
@@ -196,6 +213,39 @@
       NSHeight(subheaderFrame);
   [[self view] addSubview:detailsText_];
 
+  // Profile switcher is only needed for more than one profile.
+  NSRect dropDownButtonFrame = subheaderFrame;
+  if (groupCount > 1) {
+    dropDownButtonFrame = NSMakeRect(
+        kMarginWidth, kMarginWidth, NSWidth(fullFrame), NSHeight(fullFrame));
+    groupDropDownButton_.reset(
+        [[NSPopUpButton alloc] initWithFrame:dropDownButtonFrame
+                                   pullsDown:YES]);
+    [groupDropDownButton_ setAction:@selector(notifierGroupSelectionChanged:)];
+    [groupDropDownButton_ setTarget:self];
+    // Add a dummy item for pull-down.
+    [groupDropDownButton_ addItemWithTitle:@""];
+    string16 title;
+    for (size_t i = 0; i < groupCount; ++i) {
+      const message_center::NotifierGroup& group =
+          provider_->GetNotifierGroupAt(i);
+      string16 item = group.login_info.empty() ? group.name : group.login_info;
+      [groupDropDownButton_ addItemWithTitle:base::SysUTF16ToNSString(item)];
+      if (provider_->IsNotifierGroupActiveAt(i)) {
+        title = item;
+        [[groupDropDownButton_ lastItem] setState:NSOnState];
+      }
+    }
+    [groupDropDownButton_ setTitle:base::SysUTF16ToNSString(title)];
+    [groupDropDownButton_ sizeToFit];
+    dropDownButtonFrame = [groupDropDownButton_ frame];
+    dropDownButtonFrame.origin.y =
+        NSMinY(subheaderFrame) - message_center::kTextTopPadding -
+        NSHeight(dropDownButtonFrame);
+    dropDownButtonFrame.size.width = NSWidth(fullFrame) - 2 * kMarginWidth;
+    [[self view] addSubview:groupDropDownButton_];
+  }
+
   // Document view for the notifier settings.
   CGFloat y = 0;
   NSRect documentFrame = NSMakeRect(0, 0, NSWidth(fullFrame), 0);
@@ -233,7 +283,7 @@
   NSRect scrollFrame = documentFrame;
   scrollFrame.origin.y = kMarginWidth;
   CGFloat remainingHeight =
-      NSMinY(subheaderFrame) - message_center::kTextTopPadding -
+      NSMinY(dropDownButtonFrame) - message_center::kTextTopPadding -
       NSMinY(scrollFrame);
 
   if (NSHeight(documentFrame) < remainingHeight) {
@@ -241,6 +291,7 @@
     CGFloat delta = remainingHeight - NSHeight(documentFrame);
     headerFrame.origin.y -= delta;
     subheaderFrame.origin.y -= delta;
+    dropDownButtonFrame.origin.y -= delta;
     fullFrame.size.height -= delta;
   } else {
     scrollFrame.size.height = remainingHeight;
@@ -266,6 +317,7 @@
   [[self view] addSubview:scrollView_];
   [settingsText_ setFrame:headerFrame];
   [detailsText_ setFrame:subheaderFrame];
+  [groupDropDownButton_ setFrame:dropDownButtonFrame];
 }
 
 - (void)checkboxClicked:(id)sender {
@@ -275,6 +327,10 @@
 
 // Testing API /////////////////////////////////////////////////////////////////
 
+- (NSPopUpButton*)groupDropDownButton {
+  return groupDropDownButton_;
+}
+
 - (NSScrollView*)scrollView {
   return scrollView_;
 }
@@ -305,4 +361,11 @@
   return base::mac::ObjCCastStrict<NSButton>(view);
 }
 
+- (void)notifierGroupSelectionChanged:(id)sender {
+  DCHECK_EQ(groupDropDownButton_.get(), sender);
+  NSPopUpButton* button = static_cast<NSPopUpButton*>(sender);
+  // The first item is a dummy item.
+  provider_->SwitchToNotifierGroup([button indexOfSelectedItem] - 1);
+}
+
 @end
diff --git a/ui/message_center/cocoa/settings_controller_unittest.mm b/ui/message_center/cocoa/settings_controller_unittest.mm
index d317c31..2e4a491 100644
--- a/ui/message_center/cocoa/settings_controller_unittest.mm
+++ b/ui/message_center/cocoa/settings_controller_unittest.mm
@@ -9,6 +9,12 @@
 #include "ui/message_center/fake_notifier_settings_provider.h"
 
 @implementation MCSettingsController (TestingInterface)
+- (NSInteger)profileSwitcherListCount {
+  // Subtract the dummy item.
+  return [self groupDropDownButton] ?
+      [[self groupDropDownButton] numberOfItems] - 1 : 0;
+}
+
 - (NSUInteger)scrollViewItemCount {
   return [[[[self scrollView] documentView] subviews] count];
 }
@@ -26,6 +32,14 @@
 
 namespace {
 
+NotifierGroup* NewGroup(const std::string& name,
+                        const std::string& login_info) {
+  return new NotifierGroup(gfx::Image(),
+                           base::UTF8ToUTF16(name),
+                           base::UTF8ToUTF16(login_info),
+                           true);
+}
+
 Notifier* NewNotifier(const std::string& id,
                       const std::string& title,
                       bool enabled) {
@@ -44,7 +58,8 @@
   FakeNotifierSettingsProvider provider(notifiers);
 
   base::scoped_nsobject<MCSettingsController> controller(
-      [[MCSettingsController alloc] initWithProvider:&provider]);
+      [[MCSettingsController alloc] initWithProvider:&provider
+                                  trayViewController:nil]);
   [controller view];
 
   EXPECT_EQ(notifiers.size(), [controller scrollViewItemCount]);
@@ -59,7 +74,8 @@
   FakeNotifierSettingsProvider provider(notifiers);
 
   base::scoped_nsobject<MCSettingsController> controller(
-      [[MCSettingsController alloc] initWithProvider:&provider]);
+      [[MCSettingsController alloc] initWithProvider:&provider
+                                  trayViewController:nil]);
   [controller view];
 
   NSButton* toggleSecond = [controller bottomMostButton];
@@ -75,4 +91,40 @@
   EXPECT_EQ(1, provider.closed_called_count());
 }
 
+TEST_F(CocoaTest, SingleProfile) {
+  // Notifiers are owned by settings controller.
+  std::vector<Notifier*> notifiers;
+  notifiers.push_back(NewNotifier("id", "title", /*enabled=*/true));
+  notifiers.push_back(NewNotifier("id2", "other title", /*enabled=*/false));
+
+  FakeNotifierSettingsProvider provider(notifiers);
+
+  base::scoped_nsobject<MCSettingsController> controller(
+      [[MCSettingsController alloc] initWithProvider:&provider
+                                  trayViewController:nil]);
+  [controller view];
+
+  EXPECT_EQ(0, [controller profileSwitcherListCount]);
+}
+
+TEST_F(CocoaTest, MultiProfile) {
+  FakeNotifierSettingsProvider provider;
+  std::vector<Notifier*> group1_notifiers;
+  group1_notifiers.push_back(NewNotifier("id", "title", /*enabled=*/true));
+  group1_notifiers.push_back(NewNotifier("id2", "title2", /*enabled=*/false));
+  provider.AddGroup(NewGroup("Group1", "GroupId1"), group1_notifiers);
+  std::vector<Notifier*> group2_notifiers;
+  group2_notifiers.push_back(NewNotifier("id3", "title3", /*enabled=*/true));
+  group2_notifiers.push_back(NewNotifier("id4", "title4", /*enabled=*/false));
+  group2_notifiers.push_back(NewNotifier("id5", "title5", /*enabled=*/false));
+  provider.AddGroup(NewGroup("Group2", "GroupId2"), group2_notifiers);
+
+  base::scoped_nsobject<MCSettingsController> controller(
+      [[MCSettingsController alloc] initWithProvider:&provider
+                                  trayViewController:nil]);
+  [controller view];
+
+  EXPECT_EQ(2, [controller profileSwitcherListCount]);
+}
+
 }  // namespace message_center
diff --git a/ui/message_center/cocoa/tray_view_controller.h b/ui/message_center/cocoa/tray_view_controller.h
index 76ce518..e1e9ca2 100644
--- a/ui/message_center/cocoa/tray_view_controller.h
+++ b/ui/message_center/cocoa/tray_view_controller.h
@@ -125,6 +125,10 @@
 // Action for the settings button.
 - (void)showSettings:(id)sender;
 
+// Updates the settings dialog in response to contents change due to something
+// like selecting a different profile.
+- (void)updateSettings;
+
 // Hides the settings dialog if it's open.
 - (void)hideSettings:(id)sender;
 
diff --git a/ui/message_center/cocoa/tray_view_controller.mm b/ui/message_center/cocoa/tray_view_controller.mm
index 45cb1a4..cf49a95 100644
--- a/ui/message_center/cocoa/tray_view_controller.mm
+++ b/ui/message_center/cocoa/tray_view_controller.mm
@@ -273,7 +273,8 @@
   message_center::NotifierSettingsProvider* provider =
       messageCenter_->GetNotifierSettingsProvider();
   settingsController_.reset(
-      [[MCSettingsController alloc] initWithProvider:provider]);
+      [[MCSettingsController alloc] initWithProvider:provider
+                                  trayViewController:self]);
 
   [[self view] addSubview:[settingsController_ view]];
 
@@ -291,6 +292,17 @@
   [self updateTrayViewAndWindow];
 }
 
+- (void)updateSettings {
+  // TODO(jianli): This class should not be calling -loadView, but instead
+  // should just observe a resize notification.
+  // (http://crbug.com/270251)
+  [[settingsController_ view] removeFromSuperview];
+  [settingsController_ loadView];
+  [[self view] addSubview:[settingsController_ view]];
+
+  [self updateTrayViewAndWindow];
+}
+
 - (void)hideSettings:(id)sender {
   [scrollView_ setHidden:NO];
 
diff --git a/ui/message_center/fake_notifier_settings_provider.cc b/ui/message_center/fake_notifier_settings_provider.cc
index 66b193b..d8054ca 100644
--- a/ui/message_center/fake_notifier_settings_provider.cc
+++ b/ui/message_center/fake_notifier_settings_provider.cc
@@ -9,36 +9,62 @@
 
 namespace message_center {
 
+FakeNotifierSettingsProvider::NotifierGroupItem::NotifierGroupItem() {
+}
+
+FakeNotifierSettingsProvider::NotifierGroupItem::~NotifierGroupItem() {
+}
+
+FakeNotifierSettingsProvider::FakeNotifierSettingsProvider() {
+}
+
 FakeNotifierSettingsProvider::FakeNotifierSettingsProvider(
     const std::vector<Notifier*>& notifiers)
-    : notifiers_(notifiers),
-      notifier_group_(gfx::Image(),
-                      UTF8ToUTF16("Fake name"),
-                      UTF8ToUTF16("fake@email.com"),
-                      true),
-      closed_called_count_(0) {}
+    : closed_called_count_(0),
+      active_item_index_(0) {
+  NotifierGroupItem item;
+  item.group = new NotifierGroup(gfx::Image(),
+                                 UTF8ToUTF16("Fake name"),
+                                 UTF8ToUTF16("fake@email.com"),
+                                 true);
+  item.notifiers = notifiers;
+  items_.push_back(item);
+}
 
-FakeNotifierSettingsProvider::~FakeNotifierSettingsProvider() {}
+FakeNotifierSettingsProvider::~FakeNotifierSettingsProvider() {
+  for (size_t i = 0; i < items_.size(); ++i) {
+    delete items_[i].group;
+  }
+}
 
-size_t FakeNotifierSettingsProvider::GetNotifierGroupCount() const { return 1; }
+size_t FakeNotifierSettingsProvider::GetNotifierGroupCount() const {
+  return items_.size();
+}
 
 const message_center::NotifierGroup&
 FakeNotifierSettingsProvider::GetNotifierGroupAt(size_t index) const {
-  return notifier_group_;
+  return *(items_[index].group);
 }
 
-void FakeNotifierSettingsProvider::SwitchToNotifierGroup(size_t index) {}
+bool FakeNotifierSettingsProvider::IsNotifierGroupActiveAt(
+    size_t index) const {
+  return active_item_index_ == index;
+}
+
+void FakeNotifierSettingsProvider::SwitchToNotifierGroup(size_t index) {
+  active_item_index_ = index;
+}
 
 const message_center::NotifierGroup&
 FakeNotifierSettingsProvider::GetActiveNotifierGroup() const {
-  return notifier_group_;
+  return *(items_[active_item_index_].group);
 }
 
 void FakeNotifierSettingsProvider::GetNotifierList(
     std::vector<Notifier*>* notifiers) {
   notifiers->clear();
-  for (size_t i = 0; i < notifiers_.size(); ++i)
-    notifiers->push_back(notifiers_[i]);
+  for (size_t i = 0; i < items_[active_item_index_].notifiers.size(); ++i)
+    notifiers->push_back(items_[active_item_index_].notifiers[i]);
 }
 
 void FakeNotifierSettingsProvider::SetNotifierEnabled(const Notifier& notifier,
@@ -62,6 +88,14 @@
   return enabled_[&notifier];
 }
 
+void FakeNotifierSettingsProvider::AddGroup(
+    NotifierGroup* group, const std::vector<Notifier*>& notifiers) {
+  NotifierGroupItem item;
+  item.group = group;
+  item.notifiers = notifiers;
+  items_.push_back(item);
+}
+
 int FakeNotifierSettingsProvider::closed_called_count() {
   return closed_called_count_;
 }
diff --git a/ui/message_center/fake_notifier_settings_provider.h b/ui/message_center/fake_notifier_settings_provider.h
index f2c5cd7..85348f7 100644
--- a/ui/message_center/fake_notifier_settings_provider.h
+++ b/ui/message_center/fake_notifier_settings_provider.h
@@ -13,12 +13,14 @@
 // notifiers and records which callbacks were called. For use in tests.
 class FakeNotifierSettingsProvider : public NotifierSettingsProvider {
  public:
+  FakeNotifierSettingsProvider();
   FakeNotifierSettingsProvider(const std::vector<Notifier*>& notifiers);
   virtual ~FakeNotifierSettingsProvider();
 
   virtual size_t GetNotifierGroupCount() const OVERRIDE;
   virtual const message_center::NotifierGroup& GetNotifierGroupAt(
       size_t index) const OVERRIDE;
+  virtual bool IsNotifierGroupActiveAt(size_t index) const OVERRIDE;
   virtual void SwitchToNotifierGroup(size_t index) OVERRIDE;
   virtual const message_center::NotifierGroup& GetActiveNotifierGroup() const
       OVERRIDE;
@@ -35,11 +37,21 @@
   bool WasEnabled(const Notifier& notifier);
   int closed_called_count();
 
+  void AddGroup(NotifierGroup* group, const std::vector<Notifier*>& notifiers);
+
  private:
-  std::vector<Notifier*> notifiers_;
+  struct NotifierGroupItem {
+    NotifierGroup* group;
+    std::vector<Notifier*> notifiers;
+
+    NotifierGroupItem();
+    ~NotifierGroupItem();
+  };
+
   std::map<const Notifier*, bool> enabled_;
-  const NotifierGroup notifier_group_;
+  std::vector<NotifierGroupItem> items_;
   int closed_called_count_;
+  size_t active_item_index_;
 };
 
 }  // namespace message_center
diff --git a/ui/message_center/message_center_impl.cc b/ui/message_center/message_center_impl.cc
index 9d73327..c1d0179 100644
--- a/ui/message_center/message_center_impl.cc
+++ b/ui/message_center/message_center_impl.cc
@@ -313,6 +313,11 @@
   if (!HasNotification(id))
     return;
 
+  NotificationDelegate* delegate =
+      notification_list_->GetNotificationDelegate(id);
+  if (delegate)
+    delegate->Close(by_user);
+
   // In many cases |id| is a reference to an existing notification instance
   // but the instance can be destructed in RemoveNotification(). Hence
   // copies the id explicitly here.
diff --git a/ui/message_center/message_center_style.cc b/ui/message_center/message_center_style.cc
index 5c8d066..0289a96 100644
--- a/ui/message_center/message_center_style.cc
+++ b/ui/message_center/message_center_style.cc
@@ -31,6 +31,7 @@
 const int kNotificationWidth = 360;
 const int kIconToTextPadding = 16;
 const int kTextTopPadding = 12;
+const int kIconBottomPadding = 16;
 
 // Text sizes.
 const int kTitleFontSize = 14;
diff --git a/ui/message_center/message_center_style.h b/ui/message_center/message_center_style.h
index 222a61d..1235363 100644
--- a/ui/message_center/message_center_style.h
+++ b/ui/message_center/message_center_style.h
@@ -39,6 +39,8 @@
 extern const int kControlButtonSize;  // Square size of close & expand buttons.
 extern const int kIconToTextPadding;  // H space between icon & title/message.
 extern const int kTextTopPadding;     // V space between text elements.
+extern const int kIconBottomPadding;  // Minimum non-zero V space between icon
+                                      // and frame.
 
 // Text sizes.
 extern const int kTitleFontSize;      // For title only.
diff --git a/ui/message_center/notifier_settings.h b/ui/message_center/notifier_settings.h
index 05fc7fe..b8771a3 100644
--- a/ui/message_center/notifier_settings.h
+++ b/ui/message_center/notifier_settings.h
@@ -142,6 +142,9 @@
   virtual const message_center::NotifierGroup& GetNotifierGroupAt(
       size_t index) const = 0;
 
+  // Returns true if the notifier group at |index| is active.
+  virtual bool IsNotifierGroupActiveAt(size_t index) const = 0;
+
   // Informs the settings provider that further requests to GetNotifierList
   // should return notifiers for the specified notifier group.
   virtual void SwitchToNotifierGroup(size_t index) = 0;
diff --git a/ui/message_center/views/message_center_button_bar.cc b/ui/message_center/views/message_center_button_bar.cc
index b436bf3..b6ebd81 100644
--- a/ui/message_center/views/message_center_button_bar.cc
+++ b/ui/message_center/views/message_center_button_bar.cc
@@ -29,8 +29,8 @@
 
 namespace {
 const int kButtonSize = 40;
-const int kChevronMargin = 4;
-const int kFooterLeftMargin = 17;
+const int kChevronWidth = 8;
+const int kFooterLeftMargin = 20;
 const int kFooterRightMargin = 14;
 }  // namespace
 
@@ -43,6 +43,7 @@
                            int hover_id,
                            int pressed_id,
                            int text_id);
+  void set_size(gfx::Size size) { size_ = size; }
 
  protected:
   // Overridden from views::View:
@@ -50,6 +51,8 @@
   virtual void OnPaintFocusBorder(gfx::Canvas* canvas) OVERRIDE;
 
  private:
+  gfx::Size size_;
+
   DISALLOW_COPY_AND_ASSIGN(NotificationCenterButton);
 };
 
@@ -59,21 +62,21 @@
     int hover_id,
     int pressed_id,
     int text_id)
-    : views::ToggleImageButton(listener) {
+    : views::ToggleImageButton(listener), size_(kButtonSize, kButtonSize) {
   ui::ResourceBundle& resource_bundle = ui::ResourceBundle::GetSharedInstance();
   SetImage(STATE_NORMAL, resource_bundle.GetImageSkiaNamed(normal_id));
   SetImage(STATE_HOVERED, resource_bundle.GetImageSkiaNamed(hover_id));
   SetImage(STATE_PRESSED, resource_bundle.GetImageSkiaNamed(pressed_id));
   SetImageAlignment(views::ImageButton::ALIGN_CENTER,
                     views::ImageButton::ALIGN_MIDDLE);
-  SetTooltipText(resource_bundle.GetLocalizedString(text_id));
+  if (text_id)
+    SetTooltipText(resource_bundle.GetLocalizedString(text_id));
+
   set_focusable(true);
   set_request_focus_on_press(false);
 }
 
-gfx::Size NotificationCenterButton::GetPreferredSize() {
-  return gfx::Size(kButtonSize, kButtonSize);
-}
+gfx::Size NotificationCenterButton::GetPreferredSize() { return size_; }
 
 void NotificationCenterButton::OnPaintFocusBorder(gfx::Canvas* canvas) {
   if (HasFocus() && (focusable() || IsAccessibilityFocusable())) {
@@ -91,22 +94,42 @@
     bool settings_initially_visible)
     : message_center_view_(message_center_view),
       message_center_(message_center),
+      title_arrow_(NULL),
+      notification_label_(NULL),
+      button_container_(NULL),
       close_all_button_(NULL),
+      settings_button_(NULL),
       quiet_mode_button_(NULL) {
   if (get_use_acceleration_when_possible())
     SetPaintToLayer(true);
   set_background(
       views::Background::CreateSolidBackground(kMessageCenterBackgroundColor));
 
-  views::Label* notification_label = new views::Label(
-      l10n_util::GetStringUTF16(IDS_MESSAGE_CENTER_FOOTER_TITLE));
-  notification_label->SetAutoColorReadabilityEnabled(false);
-  notification_label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
-  notification_label->SetEnabledColor(kRegularTextColor);
-  AddChildView(notification_label);
+  ui::ResourceBundle& resource_bundle = ui::ResourceBundle::GetSharedInstance();
 
-  views::View* button_container = new views::View;
-  button_container->SetLayoutManager(
+  title_arrow_ = new NotificationCenterButton(this,
+                                              IDR_NOTIFICATION_ARROW,
+                                              IDR_NOTIFICATION_ARROW_HOVER,
+                                              IDR_NOTIFICATION_ARROW_PRESSED,
+                                              0);
+  title_arrow_->set_size(gfx::Size(kChevronWidth, kButtonSize));
+
+  // Keyboardists can use the gear button to switch modes.
+  title_arrow_->set_focusable(false);
+  AddChildView(title_arrow_);
+
+  gfx::Font notification_label_font =
+      ResourceBundle::GetSharedInstance().GetFont(ResourceBundle::BaseFont);
+  notification_label_ = new views::Label(
+      l10n_util::GetStringUTF16(IDS_MESSAGE_CENTER_FOOTER_TITLE),
+      notification_label_font);
+  notification_label_->SetAutoColorReadabilityEnabled(false);
+  notification_label_->SetHorizontalAlignment(gfx::ALIGN_LEFT);
+  notification_label_->SetEnabledColor(kRegularTextColor);
+  AddChildView(notification_label_);
+
+  button_container_ = new views::View;
+  button_container_->SetLayoutManager(
       new views::BoxLayout(views::BoxLayout::kHorizontal, 0, 0, 0));
   quiet_mode_button_ = new NotificationCenterButton(
       this,
@@ -114,7 +137,6 @@
       IDR_NOTIFICATION_DO_NOT_DISTURB_HOVER,
       IDR_NOTIFICATION_DO_NOT_DISTURB_PRESSED,
       IDS_MESSAGE_CENTER_QUIET_MODE_BUTTON_TOOLTIP);
-  ui::ResourceBundle& resource_bundle = ui::ResourceBundle::GetSharedInstance();
   quiet_mode_button_->SetToggledImage(
       views::Button::STATE_NORMAL,
       resource_bundle.GetImageSkiaNamed(
@@ -128,7 +150,7 @@
       resource_bundle.GetImageSkiaNamed(
           IDR_NOTIFICATION_DO_NOT_DISTURB_PRESSED));
   quiet_mode_button_->SetToggled(message_center->IsQuietMode());
-  button_container->AddChildView(quiet_mode_button_);
+  button_container_->AddChildView(quiet_mode_button_);
 
   close_all_button_ =
       new NotificationCenterButton(this,
@@ -136,15 +158,21 @@
                                    IDR_NOTIFICATION_CLEAR_ALL_HOVER,
                                    IDR_NOTIFICATION_CLEAR_ALL_PRESSED,
                                    IDS_MESSAGE_CENTER_CLEAR_ALL);
-  button_container->AddChildView(close_all_button_);
+  button_container_->AddChildView(close_all_button_);
   settings_button_ =
       new NotificationCenterButton(this,
                                    IDR_NOTIFICATION_SETTINGS,
                                    IDR_NOTIFICATION_SETTINGS_HOVER,
                                    IDR_NOTIFICATION_SETTINGS_PRESSED,
                                    IDS_MESSAGE_CENTER_SETTINGS_BUTTON_LABEL);
-  button_container->AddChildView(settings_button_);
+  button_container_->AddChildView(settings_button_);
 
+  SetCloseAllButtonEnabled(!settings_initially_visible);
+  SetBackArrowVisible(settings_initially_visible);
+  ViewVisibilityChanged();
+}
+
+void MessageCenterButtonBar::ViewVisibilityChanged() {
   gfx::ImageSkia* settings_image =
       ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed(
           IDR_NOTIFICATION_SETTINGS);
@@ -154,21 +182,42 @@
   layout->SetInsets(
       0, kFooterLeftMargin, 0, std::max(0, kFooterRightMargin - image_margin));
   views::ColumnSet* column = layout->AddColumnSet(0);
-  column->AddColumn(views::GridLayout::FILL,
-                    views::GridLayout::FILL,
-                    1.0f,
-                    views::GridLayout::USE_PREF,
-                    0,
-                    0);
+  if (title_arrow_->visible()) {
+    // Column for the left-arrow used to back out of settings.
+    column->AddColumn(views::GridLayout::LEADING,
+                      views::GridLayout::CENTER,
+                      0.0f,
+                      views::GridLayout::USE_PREF,
+                      0,
+                      0);
+
+    column->AddPaddingColumn(0.0f, 10);
+  }
+
+  // Column for the label "Notifications".
   column->AddColumn(views::GridLayout::LEADING,
-                    views::GridLayout::FILL,
-                    0,
+                    views::GridLayout::CENTER,
+                    0.0f,
                     views::GridLayout::USE_PREF,
                     0,
                     0);
+
+  // Fills in the remaining space between "Notifications" and buttons.
+  column->AddPaddingColumn(1.0f, image_margin);
+
+  // The button area column.
+  column->AddColumn(views::GridLayout::LEADING,
+                    views::GridLayout::CENTER,
+                    0.0f,
+                    views::GridLayout::USE_PREF,
+                    0,
+                    0);
+
   layout->StartRow(0, 0);
-  layout->AddView(notification_label);
-  layout->AddView(button_container);
+  if (title_arrow_->visible())
+    layout->AddView(title_arrow_);
+  layout->AddView(notification_label_);
+  layout->AddView(button_container_);
 }
 
 MessageCenterButtonBar::~MessageCenterButtonBar() {}
@@ -180,9 +229,16 @@
   quiet_mode_button_->SetEnabled(enabled);
 }
 
-void MessageCenterButtonBar::SetCloseAllButtonVisible(bool visible) {
+void MessageCenterButtonBar::SetCloseAllButtonEnabled(bool enabled) {
   if (close_all_button_)
-    close_all_button_->SetVisible(visible);
+    close_all_button_->SetEnabled(enabled);
+}
+
+void MessageCenterButtonBar::SetBackArrowVisible(bool visible) {
+  if (title_arrow_)
+    title_arrow_->SetVisible(visible);
+  ViewVisibilityChanged();
+  Layout();
 }
 
 void MessageCenterButtonBar::ChildVisibilityChanged(views::View* child) {
@@ -193,7 +249,7 @@
                                            const ui::Event& event) {
   if (sender == close_all_button_) {
     message_center_view()->ClearAllNotifications();
-  } else if (sender == settings_button_) {
+  } else if (sender == settings_button_ || sender == title_arrow_) {
     MessageCenterView* center_view = message_center_view();
     center_view->SetSettingsVisible(!center_view->settings_visible());
   } else if (sender == quiet_mode_button_) {
diff --git a/ui/message_center/views/message_center_button_bar.h b/ui/message_center/views/message_center_button_bar.h
index 72b30c9..950e25e 100644
--- a/ui/message_center/views/message_center_button_bar.h
+++ b/ui/message_center/views/message_center_button_bar.h
@@ -6,6 +6,7 @@
 #define UI_MESSAGE_CENTER_VIEWS_MESSAGE_CENTER_BUTTON_BAR_H_
 
 #include "ui/views/controls/button/button.h"
+#include "ui/views/controls/button/image_button.h"
 #include "ui/views/view.h"
 
 namespace views {
@@ -37,9 +38,16 @@
   virtual void SetAllButtonsEnabled(bool enabled);
 
   // Sometimes we shouldn't see the close-all button.
-  void SetCloseAllButtonVisible(bool visible);
+  void SetCloseAllButtonEnabled(bool enabled);
+
+  // Sometimes we shouldn't see the back arrow (not in settings).
+  void SetBackArrowVisible(bool visible);
 
  private:
+  // Updates the layout manager which can have differing configuration
+  // depending on the visibilty of different parts of the button bar.
+  void ViewVisibilityChanged();
+
   // Overridden from views::View:
   virtual void ChildVisibilityChanged(views::View* child) OVERRIDE;
 
@@ -56,6 +64,9 @@
   MessageCenter* message_center_;           // Weak reference.
 
   // Sub-views of the button bar.
+  NotificationCenterButton* title_arrow_;
+  views::Label* notification_label_;
+  views::View* button_container_;
   views::Button* close_all_button_;
   NotificationCenterButton* settings_button_;
   NotificationCenterButton* quiet_mode_button_;
diff --git a/ui/message_center/views/message_center_view.cc b/ui/message_center/views/message_center_view.cc
index 9f0d2fd..95c2cc3 100644
--- a/ui/message_center/views/message_center_view.cc
+++ b/ui/message_center/views/message_center_view.cc
@@ -611,12 +611,6 @@
                                            initially_settings_visible);
 
   const int button_height = button_bar_->GetPreferredSize().height();
-  button_bar_->set_border(views::Border::CreateSolidSidedBorder(
-      top_down_ ? 0 : kButtonBarBorderThickness,
-      0,
-      top_down_ ? kButtonBarBorderThickness : 0,
-      0,
-      kFooterDelimiterColor));
 
   scroller_ =
       new BoundedScrollView(kMinScrollViewHeight, max_height - button_height);
@@ -715,8 +709,9 @@
   settings_transition_animation_->set_delegate(this);
   settings_transition_animation_->set_continuous(false);
   settings_transition_animation_->Start();
-}
 
+  button_bar_->SetBackArrowVisible(visible);
+}
 
 void MessageCenterView::ClearAllNotifications() {
   if (is_closing_)
@@ -730,6 +725,7 @@
 void MessageCenterView::OnAllNotificationsCleared() {
   scroller_->SetEnabled(true);
   button_bar_->SetAllButtonsEnabled(true);
+  button_bar_->SetCloseAllButtonEnabled(false);
   message_center_->RemoveAllNotifications(true);  // Action by user.
 }
 
@@ -776,6 +772,26 @@
                             width(),
                             height() - button_height);
 
+  bool is_scrollable = false;
+  if (scroller_->visible())
+    is_scrollable = scroller_->height() < message_list_view_->height();
+  else
+    is_scrollable = settings_view_->IsScrollable();
+
+  if (is_scrollable && !button_bar_->border()) {
+    // Draw separator line on the top of the button bar if it is on the bottom
+    // or draw it at the bottom if the bar is on the top.
+    button_bar_->set_border(views::Border::CreateSolidSidedBorder(
+        top_down_ ? 0 : 1,
+        0,
+        top_down_ ? 1 : 0,
+        0,
+        kFooterDelimiterColor));
+    button_bar_->SchedulePaint();
+  } else if (!is_scrollable && button_bar_->border()) {
+    button_bar_->set_border(NULL);
+    button_bar_->SchedulePaint();
+  }
   button_bar_->SetBounds(0,
                          top_down_ ? 0 : height() - button_height,
                          width(),
@@ -971,7 +987,7 @@
   bool no_message_views = message_views_.empty();
 
   no_notifications_message_view_->SetVisible(no_message_views);
-  button_bar_->SetCloseAllButtonVisible(!no_message_views);
+  button_bar_->SetCloseAllButtonEnabled(!no_message_views);
   scroller_->set_focusable(!no_message_views);
 
   scroller_->InvalidateLayout();
diff --git a/ui/message_center/views/notification_view.cc b/ui/message_center/views/notification_view.cc
index e829bee..abfc1ef 100644
--- a/ui/message_center/views/notification_view.cc
+++ b/ui/message_center/views/notification_view.cc
@@ -35,7 +35,6 @@
 // Dimensions.
 const int kIconSize = message_center::kNotificationIconSize;
 const int kLegacyIconSize = 40;
-const int kIconBottomPadding = 16;
 const int kTextLeftPadding = kIconSize + message_center::kIconToTextPadding;
 const int kTextBottomPadding = 12;
 const int kTextRightPadding = 23;
@@ -607,7 +606,8 @@
   // Adjust the height to make sure there is at least 16px of space below the
   // icon if there is any space there (<http://crbug.com/232966>).
   if (content_height > kIconSize)
-    content_height = std::max(content_height, kIconSize + kIconBottomPadding);
+    content_height = std::max(content_height,
+                              kIconSize + message_center::kIconBottomPadding);
 
   return content_height + GetInsets().height();
 }
diff --git a/ui/message_center/views/notifier_settings_view.cc b/ui/message_center/views/notifier_settings_view.cc
index b97bc84..b4e1884 100644
--- a/ui/message_center/views/notifier_settings_view.cc
+++ b/ui/message_center/views/notifier_settings_view.cc
@@ -19,7 +19,6 @@
 #include "ui/base/resource/resource_bundle.h"
 #include "ui/gfx/canvas.h"
 #include "ui/gfx/image/image.h"
-#include "ui/gfx/image/image_skia_operations.h"
 #include "ui/gfx/size.h"
 #include "ui/message_center/message_center_style.h"
 #include "ui/message_center/views/message_center_view.h"
@@ -27,6 +26,7 @@
 #include "ui/views/border.h"
 #include "ui/views/controls/button/checkbox.h"
 #include "ui/views/controls/button/custom_button.h"
+#include "ui/views/controls/button/label_button_border.h"
 #include "ui/views/controls/button/menu_button.h"
 #include "ui/views/controls/image_view.h"
 #include "ui/views/controls/label.h"
@@ -34,6 +34,7 @@
 #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/layout/grid_layout.h"
 #include "ui/views/widget/widget.h"
 
@@ -43,11 +44,28 @@
 
 namespace message_center {
 namespace {
-
-const int kSpaceInButtonComponents = 16;
-const int kMarginWidth = 16;
-const int kMinimumWindowWidth = 320;
+const int kButtonPainterInsets = 5;
+// We really want the margin to be 20px, but various views are padded by
+// whitespace.
+const int kDesiredMargin = 20;
+// The MenuButton has 2px whitespace built-in.
+const int kMenuButtonInnateMargin = 2;
+const int kMinimumHorizontalMargin = kDesiredMargin - kMenuButtonInnateMargin;
+// The EntryViews' leftmost view is a checkbox with 1px whitespace built in, so
+// the margin for entry views should be one less than the target margin.
+const int kCheckboxInnateMargin = 1;
+const int kEntryMargin = kDesiredMargin - kCheckboxInnateMargin;
+const int kMenuButtonLeftPadding = 12;
+const int kMenuButtonRightPadding = 13;
+const int kMenuButtonVerticalPadding = 9;
+const int kMenuWhitespaceOffset = 2;
 const int kMinimumWindowHeight = 480;
+const int kMinimumWindowWidth = 320;
+const int kSettingsTitleBottomMargin = 12;
+const int kSettingsTitleTopMargin = 15;
+const int kSpaceInButtonComponents = 16;
+const int kTitleVerticalMargin = 1;
+const int kTitleElementSpacing = 10;
 const int kEntryHeight = kMinimumWindowHeight / 10;
 
 // The view to guarantee the 48px height and place the contents at the
@@ -80,10 +98,10 @@
 void EntryView::Layout() {
   DCHECK_EQ(1, child_count());
   views::View* content = child_at(0);
-  int content_width = width() - kMarginWidth * 2;
+  int content_width = width() - kEntryMargin * 2;
   int content_height = content->GetHeightForWidth(content_width);
   int y = std::max((height() - content_height) / 2, 0);
-  content->SetBounds(kMarginWidth, y, content_width, content_height);
+  content->SetBounds(kEntryMargin, y, content_width, content_height);
 }
 
 gfx::Size EntryView::GetPreferredSize() {
@@ -120,6 +138,40 @@
 
 }  // namespace
 
+// NotifierGroupMenuButtonBorder ///////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
+class NotifierGroupMenuButtonBorder : public views::TextButtonDefaultBorder {
+ public:
+  NotifierGroupMenuButtonBorder();
+
+ private:
+  virtual ~NotifierGroupMenuButtonBorder();
+};
+
+NotifierGroupMenuButtonBorder::NotifierGroupMenuButtonBorder()
+    : views::TextButtonDefaultBorder() {
+  ui::ResourceBundle& rb = ResourceBundle::GetSharedInstance();
+
+  gfx::Insets insets(kButtonPainterInsets,
+                     kButtonPainterInsets,
+                     kButtonPainterInsets,
+                     kButtonPainterInsets);
+
+  set_normal_painter(views::Painter::CreateImagePainter(
+      *rb.GetImageSkiaNamed(IDR_BUTTON_NORMAL), insets));
+  set_hot_painter(views::Painter::CreateImagePainter(
+      *rb.GetImageSkiaNamed(IDR_BUTTON_HOVER), insets));
+  set_pushed_painter(views::Painter::CreateImagePainter(
+      *rb.GetImageSkiaNamed(IDR_BUTTON_PRESSED), insets));
+
+  SetInsets(gfx::Insets(kMenuButtonVerticalPadding,
+                        kMenuButtonLeftPadding,
+                        kMenuButtonVerticalPadding,
+                        kMenuButtonRightPadding));
+}
+
+NotifierGroupMenuButtonBorder::~NotifierGroupMenuButtonBorder() {}
+
 // NotifierGroupMenuModel //////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////////////////
 class NotifierGroupMenuModel : public ui::SimpleMenuModel,
@@ -152,21 +204,18 @@
     const NotifierGroup& group =
         notifier_settings_provider_->GetNotifierGroupAt(i);
 
-    AddItem(i, group.login_info.empty() ? group.name : group.login_info);
-
-    gfx::ImageSkia resized_icon = gfx::ImageSkiaOperations::CreateResizedImage(
-        *group.icon.ToImageSkia(),
-        skia::ImageOperations::RESIZE_BETTER,
-        gfx::Size(kSettingsIconSize, kSettingsIconSize));
-
-    SetIcon(i, gfx::Image(resized_icon));
+    AddCheckItem(i, group.login_info.empty() ? group.name : group.login_info);
   }
 }
 
 NotifierGroupMenuModel::~NotifierGroupMenuModel() {}
 
 bool NotifierGroupMenuModel::IsCommandIdChecked(int command_id) const {
-  return false;
+  // If there's no provider, assume only one notifier group - the active one.
+  if (!notifier_settings_provider_)
+    return true;
+
+  return notifier_settings_provider_->IsNotifierGroupActiveAt(command_id);
 }
 
 bool NotifierGroupMenuModel::IsCommandIdEnabled(int command_id) const {
@@ -268,7 +317,11 @@
 };
 
 NotifierSettingsView::NotifierSettingsView(NotifierSettingsProvider* provider)
-    : provider_(provider) {
+    : title_arrow_(NULL),
+      title_label_(NULL),
+      notifier_group_selector_(NULL),
+      scroller_(NULL),
+      provider_(provider) {
   // |provider_| may be NULL in tests.
   if (provider_)
     provider_->AddObserver(this);
@@ -280,39 +333,20 @@
   if (get_use_acceleration_when_possible())
     SetPaintToLayer(true);
 
-  ResourceBundle& bundle = ResourceBundle::GetSharedInstance();
-
-  views::View* title_container = new views::View;
-  // The title_arrow and title_label aren't aligned well in Windows for the
-  // horizontal BoxLayout. That's why GridLayout with vertical alignment is
-  // used here.
-  views::GridLayout* title_layout = new views::GridLayout(title_container);
-  title_container->SetLayoutManager(title_layout);
-  views::ColumnSet* columns = title_layout->AddColumnSet(0);
-  columns->AddColumn(views::GridLayout::FILL, views::GridLayout::CENTER,
-                     0, views::GridLayout::USE_PREF, 0, 0);
-  columns->AddPaddingColumn(0, kMarginWidth);
-  columns->AddColumn(views::GridLayout::FILL, views::GridLayout::CENTER,
-                     1, views::GridLayout::USE_PREF, 0, 0);
-  title_arrow_ = new views::ImageButton(this);
-  title_arrow_->SetImage(views::Button::STATE_NORMAL, bundle.GetImageSkiaNamed(
-      IDR_NOTIFICATION_ARROW));
-  title_arrow_->SetImage(views::Button::STATE_HOVERED, bundle.GetImageSkiaNamed(
-      IDR_NOTIFICATION_ARROW_HOVER));
-  title_arrow_->SetImage(views::Button::STATE_PRESSED, bundle.GetImageSkiaNamed(
-      IDR_NOTIFICATION_ARROW_PRESSED));
   gfx::Font title_font =
       ResourceBundle::GetSharedInstance().GetFont(ResourceBundle::MediumFont);
-  views::Label* title_label = new views::Label(
+  title_label_ = new views::Label(
       l10n_util::GetStringUTF16(IDS_MESSAGE_CENTER_SETTINGS_BUTTON_LABEL),
       title_font);
-  title_label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
-  title_label->SetMultiLine(true);
-  title_layout->StartRow(0, 0);
-  title_layout->AddView(title_arrow_);
-  title_layout->AddView(title_label);
-  title_entry_ = new EntryView(title_container);
-  AddChildView(title_entry_);
+  title_label_->SetHorizontalAlignment(gfx::ALIGN_LEFT);
+  title_label_->SetMultiLine(true);
+  title_label_->set_border(
+      views::Border::CreateEmptyBorder(kSettingsTitleTopMargin,
+                                       kDesiredMargin,
+                                       kSettingsTitleBottomMargin,
+                                       kDesiredMargin));
+
+  AddChildView(title_label_);
 
   scroller_ = new views::ScrollView();
   scroller_->SetVerticalScrollBar(new views::OverlayScrollBar(false));
@@ -364,11 +398,24 @@
 
   views::View* contents_title_view = new views::View();
   contents_title_view->SetLayoutManager(
-      new views::BoxLayout(views::BoxLayout::kVertical, 0, 0, 5));
-  views::Label* top_label = new views::Label(l10n_util::GetStringUTF16(
-      IDS_MESSAGE_CENTER_SETTINGS_DIALOG_DESCRIPTION));
+      new views::BoxLayout(views::BoxLayout::kVertical,
+                           kMinimumHorizontalMargin,
+                           kTitleVerticalMargin,
+                           kTitleElementSpacing));
+
+  bool need_account_switcher =
+      provider_ && provider_->GetNotifierGroupCount() > 1;
+  int top_label_resource_id =
+      need_account_switcher ? IDS_MESSAGE_CENTER_SETTINGS_DESCRIPTION_MULTIUSER
+                            : IDS_MESSAGE_CENTER_SETTINGS_DIALOG_DESCRIPTION;
+
+  views::Label* top_label =
+      new views::Label(l10n_util::GetStringUTF16(top_label_resource_id));
+
   top_label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
   top_label->SetMultiLine(true);
+  top_label->set_border(views::Border::CreateEmptyBorder(
+      0, kMenuButtonInnateMargin, 0, kMenuButtonInnateMargin));
   contents_title_view->AddChildView(top_label);
 
   string16 notifier_group_text;
@@ -379,10 +426,17 @@
                               : active_group.login_info;
   }
 
-  views::View* notifier_group_selector =
-      new views::MenuButton(NULL, notifier_group_text, this, true);
-  contents_title_view->AddChildView(notifier_group_selector);
-  contents_view->AddChildView(new EntryView(contents_title_view));
+  if (need_account_switcher) {
+    notifier_group_selector_ =
+        new views::MenuButton(NULL, notifier_group_text, this, true);
+    notifier_group_selector_->set_border(new NotifierGroupMenuButtonBorder);
+    notifier_group_selector_->set_focus_border(NULL);
+    notifier_group_selector_->set_animate_on_state_change(false);
+    notifier_group_selector_->set_focusable(true);
+    contents_title_view->AddChildView(notifier_group_selector_);
+  }
+
+  contents_view->AddChildView(contents_title_view);
 
   for (size_t i = 0; i < notifiers.size(); ++i) {
     NotifierButton* button = new NotifierButton(notifiers[i], this);
@@ -391,6 +445,7 @@
     contents_view->AddChildView(entry);
     buttons_.insert(button);
   }
+
   scroller_->SetContents(contents_view);
 
   contents_view->SetBoundsRect(gfx::Rect(contents_view->GetPreferredSize()));
@@ -398,8 +453,8 @@
 }
 
 void NotifierSettingsView::Layout() {
-  int title_height = title_entry_->GetHeightForWidth(width());
-  title_entry_->SetBounds(0, 0, width(), title_height);
+  int title_height = title_label_->GetHeightForWidth(width());
+  title_label_->SetBounds(0, 0, width(), title_height);
 
   views::View* contents_view = scroller_->contents();
   int content_width = width();
@@ -414,8 +469,8 @@
 
 gfx::Size NotifierSettingsView::GetMinimumSize() {
   gfx::Size size(kMinimumWindowWidth, kMinimumWindowHeight);
-  int total_height = title_entry_->GetPreferredSize().height() +
-      scroller_->contents()->GetPreferredSize().height();
+  int total_height = title_label_->GetPreferredSize().height() +
+                     scroller_->contents()->GetPreferredSize().height();
   if (total_height > kMinimumWindowHeight)
     size.Enlarge(scroller_->GetScrollBarWidth(), 0);
   return size;
@@ -424,7 +479,7 @@
 gfx::Size NotifierSettingsView::GetPreferredSize() {
   gfx::Size preferred_size;
   std::vector<gfx::Size> child_sizes;
-  gfx::Size title_size = title_entry_->GetPreferredSize();
+  gfx::Size title_size = title_label_->GetPreferredSize();
   gfx::Size content_size = scroller_->contents()->GetPreferredSize();
   return gfx::Size(std::max(title_size.width(), content_size.width()),
                    title_size.height() + content_size.height());
@@ -467,10 +522,13 @@
   notifier_group_menu_model_.reset(new NotifierGroupMenuModel(provider_));
   notifier_group_menu_runner_.reset(
       new views::MenuRunner(notifier_group_menu_model_.get()));
+  gfx::Rect menu_anchor = source->GetBoundsInScreen();
+  menu_anchor.Inset(
+      gfx::Insets(0, kMenuWhitespaceOffset, 0, kMenuWhitespaceOffset));
   if (views::MenuRunner::MENU_DELETED ==
       notifier_group_menu_runner_->RunMenuAt(GetWidget(),
-                                             NULL,
-                                             source->GetBoundsInScreen(),
+                                             notifier_group_selector_,
+                                             menu_anchor,
                                              views::MenuItemView::BUBBLE_ABOVE,
                                              ui::MENU_SOURCE_MOUSE,
                                              views::MenuRunner::CONTEXT_MENU))
diff --git a/ui/message_center/views/notifier_settings_view.h b/ui/message_center/views/notifier_settings_view.h
index 6fc5b58..5e64ab9 100644
--- a/ui/message_center/views/notifier_settings_view.h
+++ b/ui/message_center/views/notifier_settings_view.h
@@ -16,6 +16,8 @@
 #include "ui/views/view.h"
 
 namespace views {
+class Label;
+class MenuButton;
 class MenuRunner;
 }
 
@@ -64,7 +66,8 @@
                                    const gfx::Point& point) OVERRIDE;
 
   views::ImageButton* title_arrow_;
-  views::View* title_entry_;
+  views::Label* title_label_;
+  views::MenuButton* notifier_group_selector_;
   views::ScrollView* scroller_;
   NotifierSettingsProvider* provider_;
   std::set<NotifierButton*> buttons_;
diff --git a/ui/message_center/views/toast_contents_view.cc b/ui/message_center/views/toast_contents_view.cc
index bb4b7d8..b7dae98 100644
--- a/ui/message_center/views/toast_contents_view.cc
+++ b/ui/message_center/views/toast_contents_view.cc
@@ -84,10 +84,15 @@
 }
 
 void ToastContentsView::SetContents(MessageView* view) {
+  bool already_has_contents = child_count() > 0;
   RemoveAllChildViews(true);
   AddChildView(view);
   preferred_size_ = GetToastSizeForView(view);
   Layout();
+  // If it has the contents already, this invocation means an update of the
+  // popup toast, and the new contents should be read through a11y feature.
+  if (already_has_contents)
+    NotifyAccessibilityEvent(ui::AccessibilityTypes::EVENT_FOCUS, false);
 }
 
 void ToastContentsView::RevealWithAnimation(gfx::Point origin) {
diff --git a/ui/native_theme/native_theme.target.darwin-arm.mk b/ui/native_theme/native_theme.target.darwin-arm.mk
index 167c94e..74f5245 100644
--- a/ui/native_theme/native_theme.target.darwin-arm.mk
+++ b/ui/native_theme/native_theme.target.darwin-arm.mk
@@ -88,6 +88,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DPOSIX_AVOID_MMAP' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-D__STDC_CONSTANT_MACROS' \
@@ -196,6 +197,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DPOSIX_AVOID_MMAP' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-D__STDC_CONSTANT_MACROS' \
diff --git a/ui/native_theme/native_theme.target.darwin-mips.mk b/ui/native_theme/native_theme.target.darwin-mips.mk
index 5e7b61c..8594dde 100644
--- a/ui/native_theme/native_theme.target.darwin-mips.mk
+++ b/ui/native_theme/native_theme.target.darwin-mips.mk
@@ -87,6 +87,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DPOSIX_AVOID_MMAP' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-D__STDC_CONSTANT_MACROS' \
@@ -194,6 +195,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DPOSIX_AVOID_MMAP' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-D__STDC_CONSTANT_MACROS' \
diff --git a/ui/native_theme/native_theme.target.darwin-x86.mk b/ui/native_theme/native_theme.target.darwin-x86.mk
index a0fc1ae..48d6d7a 100644
--- a/ui/native_theme/native_theme.target.darwin-x86.mk
+++ b/ui/native_theme/native_theme.target.darwin-x86.mk
@@ -90,6 +90,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
@@ -200,6 +201,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
diff --git a/ui/native_theme/native_theme.target.linux-arm.mk b/ui/native_theme/native_theme.target.linux-arm.mk
index 167c94e..74f5245 100644
--- a/ui/native_theme/native_theme.target.linux-arm.mk
+++ b/ui/native_theme/native_theme.target.linux-arm.mk
@@ -88,6 +88,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DPOSIX_AVOID_MMAP' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-D__STDC_CONSTANT_MACROS' \
@@ -196,6 +197,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DPOSIX_AVOID_MMAP' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-D__STDC_CONSTANT_MACROS' \
diff --git a/ui/native_theme/native_theme.target.linux-mips.mk b/ui/native_theme/native_theme.target.linux-mips.mk
index 5e7b61c..8594dde 100644
--- a/ui/native_theme/native_theme.target.linux-mips.mk
+++ b/ui/native_theme/native_theme.target.linux-mips.mk
@@ -87,6 +87,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DPOSIX_AVOID_MMAP' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-D__STDC_CONSTANT_MACROS' \
@@ -194,6 +195,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DPOSIX_AVOID_MMAP' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-D__STDC_CONSTANT_MACROS' \
diff --git a/ui/native_theme/native_theme.target.linux-x86.mk b/ui/native_theme/native_theme.target.linux-x86.mk
index a0fc1ae..48d6d7a 100644
--- a/ui/native_theme/native_theme.target.linux-x86.mk
+++ b/ui/native_theme/native_theme.target.linux-x86.mk
@@ -90,6 +90,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
@@ -200,6 +201,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
diff --git a/ui/resources/default_100_percent/common/app_list_tools_hover.png b/ui/resources/default_100_percent/common/app_list_tools_hover.png
index 8a230fa..984b603 100644
--- a/ui/resources/default_100_percent/common/app_list_tools_hover.png
+++ b/ui/resources/default_100_percent/common/app_list_tools_hover.png
Binary files differ
diff --git a/ui/resources/default_100_percent/common/app_list_tools_normal.png b/ui/resources/default_100_percent/common/app_list_tools_normal.png
index 99b300e..53653d0 100644
--- a/ui/resources/default_100_percent/common/app_list_tools_normal.png
+++ b/ui/resources/default_100_percent/common/app_list_tools_normal.png
Binary files differ
diff --git a/ui/resources/default_100_percent/common/app_list_tools_pressed.png b/ui/resources/default_100_percent/common/app_list_tools_pressed.png
index f439821..6a460a5 100644
--- a/ui/resources/default_100_percent/common/app_list_tools_pressed.png
+++ b/ui/resources/default_100_percent/common/app_list_tools_pressed.png
Binary files differ
diff --git a/ui/resources/default_200_percent/common/app_list_tools_hover.png b/ui/resources/default_200_percent/common/app_list_tools_hover.png
index fdff0e2..3db04e8 100644
--- a/ui/resources/default_200_percent/common/app_list_tools_hover.png
+++ b/ui/resources/default_200_percent/common/app_list_tools_hover.png
Binary files differ
diff --git a/ui/resources/default_200_percent/common/app_list_tools_normal.png b/ui/resources/default_200_percent/common/app_list_tools_normal.png
index 5200f2a..9a8c506 100644
--- a/ui/resources/default_200_percent/common/app_list_tools_normal.png
+++ b/ui/resources/default_200_percent/common/app_list_tools_normal.png
Binary files differ
diff --git a/ui/resources/default_200_percent/common/app_list_tools_pressed.png b/ui/resources/default_200_percent/common/app_list_tools_pressed.png
index ec107e8..089cdba 100644
--- a/ui/resources/default_200_percent/common/app_list_tools_pressed.png
+++ b/ui/resources/default_200_percent/common/app_list_tools_pressed.png
Binary files differ
diff --git a/ui/shell_dialogs.target.darwin-arm.mk b/ui/shell_dialogs.target.darwin-arm.mk
index ba77732..b6c6e59 100644
--- a/ui/shell_dialogs.target.darwin-arm.mk
+++ b/ui/shell_dialogs.target.darwin-arm.mk
@@ -92,6 +92,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DPOSIX_AVOID_MMAP' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-D__STDC_CONSTANT_MACROS' \
@@ -203,6 +204,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DPOSIX_AVOID_MMAP' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-D__STDC_CONSTANT_MACROS' \
diff --git a/ui/shell_dialogs.target.darwin-mips.mk b/ui/shell_dialogs.target.darwin-mips.mk
index 9aa7cde..271b265 100644
--- a/ui/shell_dialogs.target.darwin-mips.mk
+++ b/ui/shell_dialogs.target.darwin-mips.mk
@@ -91,6 +91,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DPOSIX_AVOID_MMAP' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-D__STDC_CONSTANT_MACROS' \
@@ -201,6 +202,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DPOSIX_AVOID_MMAP' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-D__STDC_CONSTANT_MACROS' \
diff --git a/ui/shell_dialogs.target.darwin-x86.mk b/ui/shell_dialogs.target.darwin-x86.mk
index a16792b..5159909 100644
--- a/ui/shell_dialogs.target.darwin-x86.mk
+++ b/ui/shell_dialogs.target.darwin-x86.mk
@@ -94,6 +94,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
@@ -207,6 +208,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
diff --git a/ui/shell_dialogs.target.linux-arm.mk b/ui/shell_dialogs.target.linux-arm.mk
index ba77732..b6c6e59 100644
--- a/ui/shell_dialogs.target.linux-arm.mk
+++ b/ui/shell_dialogs.target.linux-arm.mk
@@ -92,6 +92,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DPOSIX_AVOID_MMAP' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-D__STDC_CONSTANT_MACROS' \
@@ -203,6 +204,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DPOSIX_AVOID_MMAP' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-D__STDC_CONSTANT_MACROS' \
diff --git a/ui/shell_dialogs.target.linux-mips.mk b/ui/shell_dialogs.target.linux-mips.mk
index 9aa7cde..271b265 100644
--- a/ui/shell_dialogs.target.linux-mips.mk
+++ b/ui/shell_dialogs.target.linux-mips.mk
@@ -91,6 +91,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DPOSIX_AVOID_MMAP' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-D__STDC_CONSTANT_MACROS' \
@@ -201,6 +202,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DPOSIX_AVOID_MMAP' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-D__STDC_CONSTANT_MACROS' \
diff --git a/ui/shell_dialogs.target.linux-x86.mk b/ui/shell_dialogs.target.linux-x86.mk
index a16792b..5159909 100644
--- a/ui/shell_dialogs.target.linux-x86.mk
+++ b/ui/shell_dialogs.target.linux-x86.mk
@@ -94,6 +94,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
@@ -207,6 +208,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
diff --git a/ui/snapshot/snapshot.target.darwin-arm.mk b/ui/snapshot/snapshot.target.darwin-arm.mk
index 2d904ea..eeea992 100644
--- a/ui/snapshot/snapshot.target.darwin-arm.mk
+++ b/ui/snapshot/snapshot.target.darwin-arm.mk
@@ -83,6 +83,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DPOSIX_AVOID_MMAP' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-D__STDC_CONSTANT_MACROS' \
@@ -191,6 +192,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DPOSIX_AVOID_MMAP' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-D__STDC_CONSTANT_MACROS' \
diff --git a/ui/snapshot/snapshot.target.darwin-mips.mk b/ui/snapshot/snapshot.target.darwin-mips.mk
index 0b4e165..9334e6a 100644
--- a/ui/snapshot/snapshot.target.darwin-mips.mk
+++ b/ui/snapshot/snapshot.target.darwin-mips.mk
@@ -82,6 +82,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DPOSIX_AVOID_MMAP' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-D__STDC_CONSTANT_MACROS' \
@@ -189,6 +190,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DPOSIX_AVOID_MMAP' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-D__STDC_CONSTANT_MACROS' \
diff --git a/ui/snapshot/snapshot.target.darwin-x86.mk b/ui/snapshot/snapshot.target.darwin-x86.mk
index cb10e9a..6796eb7 100644
--- a/ui/snapshot/snapshot.target.darwin-x86.mk
+++ b/ui/snapshot/snapshot.target.darwin-x86.mk
@@ -85,6 +85,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
@@ -195,6 +196,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
diff --git a/ui/snapshot/snapshot.target.linux-arm.mk b/ui/snapshot/snapshot.target.linux-arm.mk
index 2d904ea..eeea992 100644
--- a/ui/snapshot/snapshot.target.linux-arm.mk
+++ b/ui/snapshot/snapshot.target.linux-arm.mk
@@ -83,6 +83,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DPOSIX_AVOID_MMAP' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-D__STDC_CONSTANT_MACROS' \
@@ -191,6 +192,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DPOSIX_AVOID_MMAP' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-D__STDC_CONSTANT_MACROS' \
diff --git a/ui/snapshot/snapshot.target.linux-mips.mk b/ui/snapshot/snapshot.target.linux-mips.mk
index 0b4e165..9334e6a 100644
--- a/ui/snapshot/snapshot.target.linux-mips.mk
+++ b/ui/snapshot/snapshot.target.linux-mips.mk
@@ -82,6 +82,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DPOSIX_AVOID_MMAP' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-D__STDC_CONSTANT_MACROS' \
@@ -189,6 +190,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DPOSIX_AVOID_MMAP' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-D__STDC_CONSTANT_MACROS' \
diff --git a/ui/snapshot/snapshot.target.linux-x86.mk b/ui/snapshot/snapshot.target.linux-x86.mk
index cb10e9a..6796eb7 100644
--- a/ui/snapshot/snapshot.target.linux-x86.mk
+++ b/ui/snapshot/snapshot.target.linux-x86.mk
@@ -85,6 +85,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
@@ -195,6 +196,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
diff --git a/ui/surface/surface.target.darwin-arm.mk b/ui/surface/surface.target.darwin-arm.mk
index 3f569ec..597a400 100644
--- a/ui/surface/surface.target.darwin-arm.mk
+++ b/ui/surface/surface.target.darwin-arm.mk
@@ -88,6 +88,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-DPOSIX_AVOID_MMAP' \
 	'-DU_USING_ICU_NAMESPACE=0' \
@@ -202,6 +203,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-DPOSIX_AVOID_MMAP' \
 	'-DU_USING_ICU_NAMESPACE=0' \
diff --git a/ui/surface/surface.target.darwin-mips.mk b/ui/surface/surface.target.darwin-mips.mk
index 821abeb..50836ab 100644
--- a/ui/surface/surface.target.darwin-mips.mk
+++ b/ui/surface/surface.target.darwin-mips.mk
@@ -87,6 +87,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-DPOSIX_AVOID_MMAP' \
 	'-DU_USING_ICU_NAMESPACE=0' \
@@ -200,6 +201,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-DPOSIX_AVOID_MMAP' \
 	'-DU_USING_ICU_NAMESPACE=0' \
diff --git a/ui/surface/surface.target.darwin-x86.mk b/ui/surface/surface.target.darwin-x86.mk
index bab9f0a..e0f8727 100644
--- a/ui/surface/surface.target.darwin-x86.mk
+++ b/ui/surface/surface.target.darwin-x86.mk
@@ -90,6 +90,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-D__STDC_CONSTANT_MACROS' \
@@ -206,6 +207,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-D__STDC_CONSTANT_MACROS' \
diff --git a/ui/surface/surface.target.linux-arm.mk b/ui/surface/surface.target.linux-arm.mk
index 3f569ec..597a400 100644
--- a/ui/surface/surface.target.linux-arm.mk
+++ b/ui/surface/surface.target.linux-arm.mk
@@ -88,6 +88,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-DPOSIX_AVOID_MMAP' \
 	'-DU_USING_ICU_NAMESPACE=0' \
@@ -202,6 +203,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-DPOSIX_AVOID_MMAP' \
 	'-DU_USING_ICU_NAMESPACE=0' \
diff --git a/ui/surface/surface.target.linux-mips.mk b/ui/surface/surface.target.linux-mips.mk
index 821abeb..50836ab 100644
--- a/ui/surface/surface.target.linux-mips.mk
+++ b/ui/surface/surface.target.linux-mips.mk
@@ -87,6 +87,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-DPOSIX_AVOID_MMAP' \
 	'-DU_USING_ICU_NAMESPACE=0' \
@@ -200,6 +201,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-DPOSIX_AVOID_MMAP' \
 	'-DU_USING_ICU_NAMESPACE=0' \
diff --git a/ui/surface/surface.target.linux-x86.mk b/ui/surface/surface.target.linux-x86.mk
index bab9f0a..e0f8727 100644
--- a/ui/surface/surface.target.linux-x86.mk
+++ b/ui/surface/surface.target.linux-x86.mk
@@ -90,6 +90,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-D__STDC_CONSTANT_MACROS' \
@@ -206,6 +207,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-D__STDC_CONSTANT_MACROS' \
diff --git a/ui/ui.gyp b/ui/ui.gyp
index e17d242..2aa50d4 100644
--- a/ui/ui.gyp
+++ b/ui/ui.gyp
@@ -412,6 +412,8 @@
         'gfx/android/java_bitmap.h',
         'gfx/blit.cc',
         'gfx/blit.h',
+        'gfx/box_f.cc',
+        'gfx/box_f.h',
         'gfx/break_list.h',
         'gfx/canvas.cc',
         'gfx/canvas.h',
diff --git a/ui/ui.target.darwin-arm.mk b/ui/ui.target.darwin-arm.mk
index f3e940a..dfe1e1a 100644
--- a/ui/ui.target.darwin-arm.mk
+++ b/ui/ui.target.darwin-arm.mk
@@ -89,6 +89,7 @@
 	ui/gfx/android/device_display_info.cc \
 	ui/gfx/android/java_bitmap.cc \
 	ui/gfx/blit.cc \
+	ui/gfx/box_f.cc \
 	ui/gfx/canvas.cc \
 	ui/gfx/canvas_android.cc \
 	ui/gfx/codec/jpeg_codec.cc \
@@ -207,6 +208,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DCHROME_PNG_WRITE_SUPPORT' \
 	'-DPNG_USER_CONFIG' \
@@ -324,6 +326,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DCHROME_PNG_WRITE_SUPPORT' \
 	'-DPNG_USER_CONFIG' \
diff --git a/ui/ui.target.darwin-mips.mk b/ui/ui.target.darwin-mips.mk
index 7a521ee..01a6fa8 100644
--- a/ui/ui.target.darwin-mips.mk
+++ b/ui/ui.target.darwin-mips.mk
@@ -89,6 +89,7 @@
 	ui/gfx/android/device_display_info.cc \
 	ui/gfx/android/java_bitmap.cc \
 	ui/gfx/blit.cc \
+	ui/gfx/box_f.cc \
 	ui/gfx/canvas.cc \
 	ui/gfx/canvas_android.cc \
 	ui/gfx/codec/jpeg_codec.cc \
@@ -206,6 +207,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DCHROME_PNG_WRITE_SUPPORT' \
 	'-DPNG_USER_CONFIG' \
@@ -322,6 +324,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DCHROME_PNG_WRITE_SUPPORT' \
 	'-DPNG_USER_CONFIG' \
diff --git a/ui/ui.target.darwin-x86.mk b/ui/ui.target.darwin-x86.mk
index 9c93235..0eba80b 100644
--- a/ui/ui.target.darwin-x86.mk
+++ b/ui/ui.target.darwin-x86.mk
@@ -89,6 +89,7 @@
 	ui/gfx/android/device_display_info.cc \
 	ui/gfx/android/java_bitmap.cc \
 	ui/gfx/blit.cc \
+	ui/gfx/box_f.cc \
 	ui/gfx/canvas.cc \
 	ui/gfx/canvas_android.cc \
 	ui/gfx/codec/jpeg_codec.cc \
@@ -208,6 +209,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DCHROME_PNG_WRITE_SUPPORT' \
 	'-DPNG_USER_CONFIG' \
@@ -327,6 +329,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DCHROME_PNG_WRITE_SUPPORT' \
 	'-DPNG_USER_CONFIG' \
diff --git a/ui/ui.target.linux-arm.mk b/ui/ui.target.linux-arm.mk
index f3e940a..dfe1e1a 100644
--- a/ui/ui.target.linux-arm.mk
+++ b/ui/ui.target.linux-arm.mk
@@ -89,6 +89,7 @@
 	ui/gfx/android/device_display_info.cc \
 	ui/gfx/android/java_bitmap.cc \
 	ui/gfx/blit.cc \
+	ui/gfx/box_f.cc \
 	ui/gfx/canvas.cc \
 	ui/gfx/canvas_android.cc \
 	ui/gfx/codec/jpeg_codec.cc \
@@ -207,6 +208,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DCHROME_PNG_WRITE_SUPPORT' \
 	'-DPNG_USER_CONFIG' \
@@ -324,6 +326,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DCHROME_PNG_WRITE_SUPPORT' \
 	'-DPNG_USER_CONFIG' \
diff --git a/ui/ui.target.linux-mips.mk b/ui/ui.target.linux-mips.mk
index 7a521ee..01a6fa8 100644
--- a/ui/ui.target.linux-mips.mk
+++ b/ui/ui.target.linux-mips.mk
@@ -89,6 +89,7 @@
 	ui/gfx/android/device_display_info.cc \
 	ui/gfx/android/java_bitmap.cc \
 	ui/gfx/blit.cc \
+	ui/gfx/box_f.cc \
 	ui/gfx/canvas.cc \
 	ui/gfx/canvas_android.cc \
 	ui/gfx/codec/jpeg_codec.cc \
@@ -206,6 +207,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DCHROME_PNG_WRITE_SUPPORT' \
 	'-DPNG_USER_CONFIG' \
@@ -322,6 +324,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DCHROME_PNG_WRITE_SUPPORT' \
 	'-DPNG_USER_CONFIG' \
diff --git a/ui/ui.target.linux-x86.mk b/ui/ui.target.linux-x86.mk
index 9c93235..0eba80b 100644
--- a/ui/ui.target.linux-x86.mk
+++ b/ui/ui.target.linux-x86.mk
@@ -89,6 +89,7 @@
 	ui/gfx/android/device_display_info.cc \
 	ui/gfx/android/java_bitmap.cc \
 	ui/gfx/blit.cc \
+	ui/gfx/box_f.cc \
 	ui/gfx/canvas.cc \
 	ui/gfx/canvas_android.cc \
 	ui/gfx/codec/jpeg_codec.cc \
@@ -208,6 +209,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DCHROME_PNG_WRITE_SUPPORT' \
 	'-DPNG_USER_CONFIG' \
@@ -327,6 +329,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DCHROME_PNG_WRITE_SUPPORT' \
 	'-DPNG_USER_CONFIG' \
diff --git a/ui/ui_unittests.gypi b/ui/ui_unittests.gypi
index dc46a55..e62af93 100644
--- a/ui/ui_unittests.gypi
+++ b/ui/ui_unittests.gypi
@@ -108,6 +108,7 @@
         'base/resource/data_pack_unittest.cc',
         'base/resource/resource_bundle_unittest.cc',
         'base/text/text_elider_unittest.cc',
+        'gfx/box_unittest.cc',
         'gfx/codec/png_codec_unittest.cc',
         'gfx/color_utils_unittest.cc',
         'gfx/display_unittest.cc',
diff --git a/ui/views/bubble/bubble_border.cc b/ui/views/bubble/bubble_border.cc
index 8b9a612..3c9a320 100644
--- a/ui/views/bubble/bubble_border.cc
+++ b/ui/views/bubble/bubble_border.cc
@@ -157,12 +157,13 @@
   const int min_with_arrow_thickness = images_->border_thickness +
       std::max(images_->arrow_thickness + images_->border_interior_thickness,
                images_->border_thickness);
-  if (is_arrow_on_horizontal(arrow_))
-    size.SetToMax(gfx::Size(min_with_arrow_width, min_with_arrow_thickness));
-  else if (has_arrow(arrow_))
-    size.SetToMax(gfx::Size(min_with_arrow_thickness, min_with_arrow_width));
-  else
+  // Only take arrow image sizes into account when the bubble tip is shown.
+  if (arrow_paint_type_ == PAINT_TRANSPARENT || !has_arrow(arrow_))
     size.SetToMax(gfx::Size(min, min));
+  else if (is_arrow_on_horizontal(arrow_))
+    size.SetToMax(gfx::Size(min_with_arrow_width, min_with_arrow_thickness));
+  else
+    size.SetToMax(gfx::Size(min_with_arrow_thickness, min_with_arrow_width));
 
   int x = anchor_rect.x();
   int y = anchor_rect.y();
diff --git a/ui/views/bubble/bubble_border_unittest.cc b/ui/views/bubble/bubble_border_unittest.cc
index cb49030..b8838f6 100644
--- a/ui/views/bubble/bubble_border_unittest.cc
+++ b/ui/views/bubble/bubble_border_unittest.cc
@@ -202,4 +202,39 @@
   EXPECT_FALSE(BubbleBorder::is_arrow_at_center(BubbleBorder::FLOAT));
 }
 
+TEST_F(BubbleBorderTest, TestMinimalSize) {
+  gfx::Rect anchor = gfx::Rect(100, 100, 20, 20);
+  gfx::Size contents = gfx::Size(10, 10);
+  BubbleBorder b1(BubbleBorder::RIGHT_TOP, BubbleBorder::NO_SHADOW, 0);
+
+  // The height should be much bigger then the requested size + border and
+  // padding since it needs to be able to include the tip bitmap.
+  gfx::Rect visible_tip_1 = b1.GetBounds(anchor, contents);
+  EXPECT_GE(visible_tip_1.height(), 30);
+  EXPECT_LE(visible_tip_1.width(), 30);
+
+  // With the tip being invisible the height should now be much smaller.
+  b1.set_paint_arrow(BubbleBorder::PAINT_TRANSPARENT);
+  gfx::Rect invisible_tip_1 = b1.GetBounds(anchor, contents);
+  EXPECT_LE(invisible_tip_1.height(), 30);
+  EXPECT_LE(invisible_tip_1.width(), 30);
+
+  // When the orientation of the tip changes, the above mentioned tests need to
+  // be reverse for width and height.
+  BubbleBorder b2(BubbleBorder::TOP_RIGHT, BubbleBorder::NO_SHADOW, 0);
+
+  // The width should be much bigger then the requested size + border and
+  // padding since it needs to be able to include the tip bitmap.
+  gfx::Rect visible_tip_2 = b2.GetBounds(anchor, contents);
+  EXPECT_GE(visible_tip_2.width(), 30);
+  EXPECT_LE(visible_tip_2.height(), 30);
+
+  // With the tip being invisible the width should now be much smaller.
+  b2.set_paint_arrow(BubbleBorder::PAINT_TRANSPARENT);
+  gfx::Rect invisible_tip_2 = b2.GetBounds(anchor, contents);
+  EXPECT_LE(invisible_tip_2.width(), 30);
+  EXPECT_LE(invisible_tip_2.height(), 30);
+}
+
+
 }  // namespace views
diff --git a/ui/views/bubble/bubble_frame_view.cc b/ui/views/bubble/bubble_frame_view.cc
index 94d99d2..2bd579d 100644
--- a/ui/views/bubble/bubble_frame_view.cc
+++ b/ui/views/bubble/bubble_frame_view.cc
@@ -54,6 +54,11 @@
 // static
 const char BubbleFrameView::kViewClassName[] = "BubbleFrameView";
 
+// static
+gfx::Insets BubbleFrameView::GetTitleInsets() {
+  return gfx::Insets(kTitleTopInset, kTitleLeftInset, kTitleBottomInset, 0);
+}
+
 BubbleFrameView::BubbleFrameView(const gfx::Insets& content_margins)
     : bubble_border_(NULL),
       content_margins_(content_margins),
diff --git a/ui/views/bubble/bubble_frame_view.h b/ui/views/bubble/bubble_frame_view.h
index e39b538..7dc4596 100644
--- a/ui/views/bubble/bubble_frame_view.h
+++ b/ui/views/bubble/bubble_frame_view.h
@@ -25,6 +25,10 @@
   // Internal class name.
   static const char kViewClassName[];
 
+  // Insets to make bubble contents align horizontal with the bubble title.
+  // NOTE: this does not take into account whether a title actually exists.
+  static gfx::Insets GetTitleInsets();
+
   explicit BubbleFrameView(const gfx::Insets& content_margins);
   virtual ~BubbleFrameView();
 
diff --git a/ui/views/bubble/tray_bubble_view.cc b/ui/views/bubble/tray_bubble_view.cc
index 76a2d42..0d8accd 100644
--- a/ui/views/bubble/tray_bubble_view.cc
+++ b/ui/views/bubble/tray_bubble_view.cc
@@ -33,10 +33,10 @@
 
 // The new theme adjusts the menus / bubbles to be flush with the shelf when
 // there is no bubble. These are the offsets which need to be applied.
-const int kArrowOffsetTopBottom = 5;
+const int kArrowOffsetTopBottom = 4;
 const int kArrowOffsetLeft = 9;
 const int kArrowOffsetRight = -5;
-const int kOffsetLeftRightForTopBottomOrientation = 2;
+const int kOffsetLeftRightForTopBottomOrientation = 5;
 
 }  // namespace
 
@@ -86,8 +86,6 @@
       return rect;
     }
 
-    // TODO(skuhne): With shelf LR alignment, arrow-less messages get
-    // automatically offsetted from an open status menu which needs addressing.
     gfx::Size border_size(contents_size);
     gfx::Insets insets = GetInsets();
     border_size.Enlarge(insets.width(), insets.height());
diff --git a/ui/views/controls/button/button_dropdown.cc b/ui/views/controls/button/button_dropdown.cc
index 32ee4f4..9a699ea 100644
--- a/ui/views/controls/button/button_dropdown.cc
+++ b/ui/views/controls/button/button_dropdown.cc
@@ -12,6 +12,8 @@
 #include "ui/base/accessibility/accessible_view_state.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/base/models/menu_model.h"
+#include "ui/gfx/display.h"
+#include "ui/gfx/screen.h"
 #include "ui/views/controls/menu/menu_item_view.h"
 #include "ui/views/controls/menu/menu_model_adapter.h"
 #include "ui/views/controls/menu/menu_runner.h"
@@ -172,6 +174,14 @@
 
 #if defined(OS_WIN)
   int left_bound = GetSystemMetrics(SM_XVIRTUALSCREEN);
+#elif defined(OS_CHROMEOS)
+  // A window won't overlap between displays on ChromeOS.
+  // Use the left bound of the display on which
+  // the menu button exists.
+  gfx::NativeView view = GetWidget()->GetNativeView();
+  gfx::Display display = gfx::Screen::GetScreenFor(
+      view)->GetDisplayNearestWindow(view);
+  int left_bound = display.bounds().x();
 #else
   int left_bound = 0;
   NOTIMPLEMENTED();
diff --git a/ui/views/controls/button/text_button.cc b/ui/views/controls/button/text_button.cc
index aba3941..a02d6b2 100644
--- a/ui/views/controls/button/text_button.cc
+++ b/ui/views/controls/button/text_button.cc
@@ -481,7 +481,7 @@
 #if defined(OS_WIN)
       // TODO(erg): Either port DrawStringWithHalo to linux or find an
       // alternative here.
-      canvas->DrawStringWithHalo(text_, font_, text_color, color_highlight_,
+      canvas->DrawStringWithHalo(text_, font_, SK_ColorBLACK, SK_ColorWHITE,
           text_bounds.x(), text_bounds.y(), text_bounds.width(),
           text_bounds.height(), draw_string_flags);
 #else
diff --git a/ui/views/controls/prefix_selector.cc b/ui/views/controls/prefix_selector.cc
index 12208c0..6d6e080 100644
--- a/ui/views/controls/prefix_selector.cc
+++ b/ui/views/controls/prefix_selector.cc
@@ -63,6 +63,10 @@
   return ui::TEXT_INPUT_TYPE_TEXT;
 }
 
+ui::TextInputMode PrefixSelector::GetTextInputMode() const {
+  return ui::TEXT_INPUT_MODE_DEFAULT;
+}
+
 bool PrefixSelector::CanComposeInline() const {
   return false;
 }
diff --git a/ui/views/controls/prefix_selector.h b/ui/views/controls/prefix_selector.h
index b587f77..629c306 100644
--- a/ui/views/controls/prefix_selector.h
+++ b/ui/views/controls/prefix_selector.h
@@ -33,6 +33,7 @@
   virtual void InsertChar(char16 ch, int flags) OVERRIDE;
   virtual gfx::NativeWindow GetAttachedWindow() const OVERRIDE;
   virtual ui::TextInputType GetTextInputType() const OVERRIDE;
+  virtual ui::TextInputMode GetTextInputMode() const OVERRIDE;
   virtual bool CanComposeInline() const OVERRIDE;
   virtual gfx::Rect GetCaretBounds() OVERRIDE;
   virtual bool GetCompositionCharacterBounds(uint32 index,
diff --git a/ui/views/controls/textfield/native_textfield_views.cc b/ui/views/controls/textfield/native_textfield_views.cc
index 2ac35aa..14831ba 100644
--- a/ui/views/controls/textfield/native_textfield_views.cc
+++ b/ui/views/controls/textfield/native_textfield_views.cc
@@ -457,7 +457,7 @@
   data->SetString(GetSelectedText());
   scoped_ptr<gfx::Canvas> canvas(
       views::GetCanvasForDragImage(textfield_->GetWidget(), size()));
-  GetRenderText()->DrawSelectedText(canvas.get());
+  GetRenderText()->DrawSelectedTextForDrag(canvas.get());
   drag_utils::SetDragImageOnDataObject(*canvas, size(),
                                        press_pt.OffsetFromOrigin(),
                                        data);
@@ -959,6 +959,10 @@
   return textfield_->GetTextInputType();
 }
 
+ui::TextInputMode NativeTextfieldViews::GetTextInputMode() const {
+  return ui::TEXT_INPUT_MODE_DEFAULT;
+}
+
 bool NativeTextfieldViews::CanComposeInline() const {
   return true;
 }
@@ -1409,7 +1413,10 @@
     base::TimeDelta time_delta = event.time_stamp() - last_click_time_;
     if (time_delta.InMilliseconds() <= GetDoubleClickInterval() &&
         !ExceededDragThresholdFromLastClickLocation(event)) {
-      aggregated_clicks_ = (aggregated_clicks_ + 1) % 3;
+      // Upon clicking after a triple click, the count should go back to double
+      // click and alternate between double and triple. This assignment maps
+      // 0 to 1, 1 to 2, 2 to 1.
+      aggregated_clicks_ = (aggregated_clicks_ % 2) + 1;
     } else {
       aggregated_clicks_ = 0;
     }
diff --git a/ui/views/controls/textfield/native_textfield_views.h b/ui/views/controls/textfield/native_textfield_views.h
index 98ca71e..3230fb4 100644
--- a/ui/views/controls/textfield/native_textfield_views.h
+++ b/ui/views/controls/textfield/native_textfield_views.h
@@ -185,6 +185,7 @@
   virtual void InsertChar(char16 ch, int flags) OVERRIDE;
   virtual gfx::NativeWindow GetAttachedWindow() const OVERRIDE;
   virtual ui::TextInputType GetTextInputType() const OVERRIDE;
+  virtual ui::TextInputMode GetTextInputMode() const OVERRIDE;
   virtual bool CanComposeInline() const OVERRIDE;
   virtual gfx::Rect GetCaretBounds() OVERRIDE;
   virtual bool GetCompositionCharacterBounds(uint32 index,
diff --git a/ui/views/controls/textfield/native_textfield_views_unittest.cc b/ui/views/controls/textfield/native_textfield_views_unittest.cc
index a56905c..adaac20 100644
--- a/ui/views/controls/textfield/native_textfield_views_unittest.cc
+++ b/ui/views/controls/textfield/native_textfield_views_unittest.cc
@@ -816,10 +816,10 @@
   textfield_view_->OnMouseReleased(release);
   EXPECT_STR_EQ("hello world", textfield_->GetSelectedText());
 
-  // Another click should reset back to single click.
+  // Another click should reset back to double click.
   textfield_view_->OnMousePressed(click);
   textfield_view_->OnMouseReleased(release);
-  EXPECT_TRUE(textfield_->GetSelectedText().empty());
+  EXPECT_STR_EQ("hello", textfield_->GetSelectedText());
 }
 
 TEST_F(NativeTextfieldViewsTest, DragToSelect) {
diff --git a/ui/views/ime/input_method_bridge.cc b/ui/views/ime/input_method_bridge.cc
index 34f6e1b..5507647 100644
--- a/ui/views/ime/input_method_bridge.cc
+++ b/ui/views/ime/input_method_bridge.cc
@@ -147,6 +147,11 @@
   return client ? client->GetTextInputType() : ui::TEXT_INPUT_TYPE_NONE;
 }
 
+ui::TextInputMode InputMethodBridge::GetTextInputMode() const {
+  TextInputClient* client = GetTextInputClient();
+  return client ? client->GetTextInputMode() : ui::TEXT_INPUT_MODE_DEFAULT;
+}
+
 bool InputMethodBridge::CanComposeInline() const {
   TextInputClient* client = GetTextInputClient();
   return client ? client->CanComposeInline() : true;
diff --git a/ui/views/ime/input_method_bridge.h b/ui/views/ime/input_method_bridge.h
index 9eace28..03ea567 100644
--- a/ui/views/ime/input_method_bridge.h
+++ b/ui/views/ime/input_method_bridge.h
@@ -58,6 +58,7 @@
   virtual void InsertChar(char16 ch, int flags) OVERRIDE;
   virtual gfx::NativeWindow GetAttachedWindow() const OVERRIDE;
   virtual ui::TextInputType GetTextInputType() const OVERRIDE;
+  virtual ui::TextInputMode GetTextInputMode() const OVERRIDE;
   virtual bool CanComposeInline() const OVERRIDE;
   virtual gfx::Rect GetCaretBounds() OVERRIDE;
   virtual bool GetCompositionCharacterBounds(uint32 index,
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 0df5cf4..1870e11 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
@@ -19,7 +19,6 @@
 #include "ui/base/x/selection_utils.h"
 #include "ui/base/x/x11_util.h"
 #include "ui/views/widget/desktop_aura/desktop_native_cursor_manager.h"
-#include "ui/views/widget/desktop_aura/desktop_root_window_host_x11.h"
 
 using aura::client::DragDropDelegate;
 using ui::OSExchangeData;
@@ -367,13 +366,11 @@
 ///////////////////////////////////////////////////////////////////////////////
 
 DesktopDragDropClientAuraX11::DesktopDragDropClientAuraX11(
-    views::DesktopRootWindowHostX11* root_window_host,
     aura::RootWindow* root_window,
     views::DesktopNativeCursorManager* cursor_manager,
     Display* xdisplay,
     ::Window xwindow)
     : move_loop_(this),
-      root_window_host_(root_window_host),
       root_window_(root_window),
       xdisplay_(xdisplay),
       xwindow_(xwindow),
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 b473a98..2dee730 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
@@ -45,7 +45,6 @@
 
 namespace views {
 class DesktopNativeCursorManager;
-class DesktopRootWindowHostX11;
 
 // Implements drag and drop on X11 for aura. On one side, this class takes raw
 // X11 events forwarded from DesktopRootWindowHostLinux, while on the other, it
@@ -56,7 +55,6 @@
       public X11WholeScreenMoveLoopDelegate {
  public:
   DesktopDragDropClientAuraX11(
-      views::DesktopRootWindowHostX11* root_window_host,
       aura::RootWindow* root_window,
       views::DesktopNativeCursorManager* cursor_manager,
       Display* xdisplay,
@@ -156,7 +154,6 @@
   // X11WholeScreenMoveLoopDelegate interface.
   X11WholeScreenMoveLoop move_loop_;
 
-  views::DesktopRootWindowHostX11* root_window_host_;
   aura::RootWindow* root_window_;
 
   Display* xdisplay_;
diff --git a/ui/views/widget/desktop_aura/desktop_root_window_host_win.cc b/ui/views/widget/desktop_aura/desktop_root_window_host_win.cc
index ee83e26..159ffc1 100644
--- a/ui/views/widget/desktop_aura/desktop_root_window_host_win.cc
+++ b/ui/views/widget/desktop_aura/desktop_root_window_host_win.cc
@@ -390,14 +390,9 @@
 
 void DesktopRootWindowHostWin::SetInactiveRenderingDisabled(
     bool disable_inactive) {
-  // We call DefWindowProc of WM_NCACTIVATE to paint the caption as active or
-  // inactive. This is safe with the only sideeffect being the
-  // WM_GETTEXT message which is sent by DefWindowProc to get the text to be
-  // displayed on the caption.
-  ::DefWindowProc(message_handler_->hwnd(),
-                  WM_NCACTIVATE,
-                  !!disable_inactive,
-                  0);
+  // Force the non-client area (most notably the title bar) to paint as either
+  // active or inactive, depending on the input.
+  SendMessage(message_handler_->hwnd(), WM_NCACTIVATE, !!disable_inactive, 0);
 }
 
 ////////////////////////////////////////////////////////////////////////////////
diff --git a/ui/views/widget/desktop_aura/desktop_root_window_host_x11.cc b/ui/views/widget/desktop_aura/desktop_root_window_host_x11.cc
index b9656a6..8c4ba7c 100644
--- a/ui/views/widget/desktop_aura/desktop_root_window_host_x11.cc
+++ b/ui/views/widget/desktop_aura/desktop_root_window_host_x11.cc
@@ -159,7 +159,23 @@
 
 void DesktopRootWindowHostX11::HandleNativeWidgetActivationChanged(
     bool active) {
+  if (active)
+    root_window_host_delegate_->OnHostActivated();
   native_widget_delegate_->OnNativeWidgetActivationChanged(active);
+  // If we're not active we need to deactivate the corresponding aura::Window.
+  // This way if a child widget is active it gets correctly deactivated (child
+  // widgets don't get native desktop activation changes, only aura activation
+  // changes).
+  if (!active) {
+    aura::client::ActivationClient* activation_client =
+        aura::client::GetActivationClient(root_window_);
+    if (activation_client) {
+      aura::Window* active_window = activation_client->GetActiveWindow();
+      if (active_window)
+        activation_client->DeactivateWindow(active_window);
+    }
+  }
+
   native_widget_delegate_->AsWidget()->GetRootView()->SchedulePaint();
 }
 
@@ -930,7 +946,7 @@
   desktop_native_widget_aura_->InstallInputMethodEventFilter(root_window_);
 
   drag_drop_client_.reset(new DesktopDragDropClientAuraX11(
-      this, root_window_, desktop_native_cursor_manager, xdisplay_, xwindow_));
+      root_window_, desktop_native_cursor_manager, xdisplay_, xwindow_));
   aura::client::SetDragDropClient(root_window_, drag_drop_client_.get());
 
   // TODO(erg): Unify this code once the other consumer goes away.
diff --git a/ui/views/widget/native_widget_aura.cc b/ui/views/widget/native_widget_aura.cc
index 9e14f20..8c9ad02 100644
--- a/ui/views/widget/native_widget_aura.cc
+++ b/ui/views/widget/native_widget_aura.cc
@@ -443,8 +443,8 @@
 
 void NativeWidgetAura::ShowMaximizedWithBounds(
     const gfx::Rect& restored_bounds) {
-  ShowWithWindowState(ui::SHOW_STATE_MAXIMIZED);
   SetRestoreBounds(window_, restored_bounds);
+  ShowWithWindowState(ui::SHOW_STATE_MAXIMIZED);
 }
 
 void NativeWidgetAura::ShowWithWindowState(ui::WindowShowState state) {
diff --git a/ui/views/window/non_client_view.h b/ui/views/window/non_client_view.h
index e5be44e..d430578 100644
--- a/ui/views/window/non_client_view.h
+++ b/ui/views/window/non_client_view.h
@@ -107,7 +107,7 @@
 //  +- views::Widget ------------------------------------+
 //  | +- views::RootView ------------------------------+ |
 //  | | +- views::NonClientView ---------------------+ | |
-//  | | | +- views::NonClientFrameView subclas  ---+ | | |
+//  | | | +- views::NonClientFrameView subclass ---+ | | |
 //  | | | |                                        | | | |
 //  | | | | << all painting and event receiving >> | | | |
 //  | | | | << of the non-client areas of a     >> | | | |
diff --git a/ui/webui/resources/css/overlay.css b/ui/webui/resources/css/overlay.css
index 7086d54..af47453 100644
--- a/ui/webui/resources/css/overlay.css
+++ b/ui/webui/resources/css/overlay.css
@@ -167,3 +167,13 @@
   background-color: rgba(0, 0, 0, 0.5);
 }
 </if>
+
+.gray-bottom-bar {
+  background-color: #f5f5f5;
+  border-color: #e7e7e7;
+  border-top-style: solid;
+  border-width: 1px;
+  color: #888;
+  display: -webkit-box;
+  padding: 14px 17px;
+}
diff --git a/ui/webui/resources/js/cr/ui/focus_outline_manager.js b/ui/webui/resources/js/cr/ui/focus_outline_manager.js
index fd106c2..5fdbb5d 100644
--- a/ui/webui/resources/js/cr/ui/focus_outline_manager.js
+++ b/ui/webui/resources/js/cr/ui/focus_outline_manager.js
@@ -45,19 +45,13 @@
     }, true);
   }
 
-  /**
-   * The class name to set on the document element.
-   * @const
-   */
-  FocusOutlineManager.CLASS_NAME = CLASS_NAME;
-
   FocusOutlineManager.prototype = {
     /**
      * Whether focus change is triggered by TAB key.
      * @type {boolean}
      * @private
      */
-    focusByKeyboard_: false,
+    focusByKeyboard_: true,
 
     /**
      * Whether the focus outline should be visible.
diff --git a/ui/webui/resources/js/cr/ui/list.js b/ui/webui/resources/js/cr/ui/list.js
index 2f7ced9..52f2896 100644
--- a/ui/webui/resources/js/cr/ui/list.js
+++ b/ui/webui/resources/js/cr/ui/list.js
@@ -515,13 +515,15 @@
       // When the blur event happens we do not know who is getting focus so we
       // delay this a bit until we know if the new focus node is outside the
       // list.
+      // We need 51 msec delay because InlineEditableList sets focus after
+      // 50 msec.
       var list = this;
       var doc = e.target.ownerDocument;
       window.setTimeout(function() {
         var activeElement = doc.activeElement;
-        if (activeElement != doc.body && !list.contains(activeElement))
+        if (!list.contains(activeElement))
           list.hasElementFocus = false;
-      });
+      }, 51);
     },
 
     /**
diff --git a/url/third_party/mozilla/LICENSE.txt b/url/third_party/mozilla/LICENSE.txt
new file mode 100644
index 0000000..ac40837
--- /dev/null
+++ b/url/third_party/mozilla/LICENSE.txt
@@ -0,0 +1,65 @@
+Copyright 2007, 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.
+
+-------------------------------------------------------------------------------
+
+The file url_parse.cc is based on nsURLParsers.cc from Mozilla. This file is
+licensed separately as follows:
+
+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 mozilla.org code.
+
+The Initial Developer of the Original Code is
+Netscape Communications Corporation.
+Portions created by the Initial Developer are Copyright (C) 1998
+the Initial Developer. All Rights Reserved.
+
+Contributor(s):
+  Darin Fisher (original author)
+
+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.
diff --git a/url/third_party/mozilla/README.chromium b/url/third_party/mozilla/README.chromium
new file mode 100644
index 0000000..ef396d3
--- /dev/null
+++ b/url/third_party/mozilla/README.chromium
@@ -0,0 +1,8 @@
+Name: url_parse
+URL: http://mxr.mozilla.org/comm-central/source/mozilla/netwerk/base/src/nsURLParsers.cpp
+License: BSD and MPL 1.1/GPL 2.0/LGPL 2.1
+License File: LICENSE.txt
+
+Description:
+
+The file url_parse.cc is based on nsURLParsers.cc from Mozilla.
diff --git a/url/url_parse.cc b/url/third_party/mozilla/url_parse.cc
similarity index 99%
rename from url/url_parse.cc
rename to url/third_party/mozilla/url_parse.cc
index 0d9c6dd..52c6196 100644
--- a/url/url_parse.cc
+++ b/url/third_party/mozilla/url_parse.cc
@@ -34,7 +34,7 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
-#include "url/url_parse.h"
+#include "url/third_party/mozilla/url_parse.h"
 
 #include <stdlib.h>
 
diff --git a/url/third_party/mozilla/url_parse.h b/url/third_party/mozilla/url_parse.h
new file mode 100644
index 0000000..fd974f8
--- /dev/null
+++ b/url/third_party/mozilla/url_parse.h
@@ -0,0 +1,361 @@
+// 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 URL_THIRD_PARTY_MOZILLA_URL_PARSE_H_
+#define URL_THIRD_PARTY_MOZILLA_URL_PARSE_H_
+
+#include <string>
+
+#include "base/basictypes.h"
+#include "base/strings/string16.h"
+#include "url/url_export.h"
+
+namespace url_parse {
+
+// Deprecated, but WebKit/WebCore/platform/KURLGooglePrivate.h and
+// KURLGoogle.cpp still rely on this type.
+typedef base::char16 UTF16Char;
+
+// Component ------------------------------------------------------------------
+
+// Represents a substring for URL parsing.
+struct Component {
+  Component() : begin(0), len(-1) {}
+
+  // Normal constructor: takes an offset and a length.
+  Component(int b, int l) : begin(b), len(l) {}
+
+  int end() const {
+    return begin + len;
+  }
+
+  // Returns true if this component is valid, meaning the length is given. Even
+  // valid components may be empty to record the fact that they exist.
+  bool is_valid() const {
+    return (len != -1);
+  }
+
+  // Returns true if the given component is specified on false, the component
+  // is either empty or invalid.
+  bool is_nonempty() const {
+    return (len > 0);
+  }
+
+  void reset() {
+    begin = 0;
+    len = -1;
+  }
+
+  bool operator==(const Component& other) const {
+    return begin == other.begin && len == other.len;
+  }
+
+  int begin;  // Byte offset in the string of this component.
+  int len;    // Will be -1 if the component is unspecified.
+};
+
+// Helper that returns a component created with the given begin and ending
+// points. The ending point is non-inclusive.
+inline Component MakeRange(int begin, int end) {
+  return Component(begin, end - begin);
+}
+
+// Parsed ---------------------------------------------------------------------
+
+// A structure that holds the identified parts of an input URL. This structure
+// does NOT store the URL itself. The caller will have to store the URL text
+// and its corresponding Parsed structure separately.
+//
+// Typical usage would be:
+//
+//    url_parse::Parsed parsed;
+//    url_parse::Component scheme;
+//    if (!url_parse::ExtractScheme(url, url_len, &scheme))
+//      return I_CAN_NOT_FIND_THE_SCHEME_DUDE;
+//
+//    if (IsStandardScheme(url, scheme))  // Not provided by this component
+//      url_parseParseStandardURL(url, url_len, &parsed);
+//    else if (IsFileURL(url, scheme))    // Not provided by this component
+//      url_parse::ParseFileURL(url, url_len, &parsed);
+//    else
+//      url_parse::ParsePathURL(url, url_len, &parsed);
+//
+struct URL_EXPORT Parsed {
+  // Identifies different components.
+  enum ComponentType {
+    SCHEME,
+    USERNAME,
+    PASSWORD,
+    HOST,
+    PORT,
+    PATH,
+    QUERY,
+    REF,
+  };
+
+  // The default constructor is sufficient for the components, but inner_parsed_
+  // requires special handling.
+  Parsed();
+  Parsed(const Parsed&);
+  Parsed& operator=(const Parsed&);
+  ~Parsed();
+
+  // Returns the length of the URL (the end of the last component).
+  //
+  // Note that for some invalid, non-canonical URLs, this may not be the length
+  // of the string. For example "http://": the parsed structure will only
+  // contain an entry for the four-character scheme, and it doesn't know about
+  // the "://". For all other last-components, it will return the real length.
+  int Length() const;
+
+  // Returns the number of characters before the given component if it exists,
+  // or where the component would be if it did exist. This will return the
+  // string length if the component would be appended to the end.
+  //
+  // Note that this can get a little funny for the port, query, and ref
+  // components which have a delimiter that is not counted as part of the
+  // component. The |include_delimiter| flag controls if you want this counted
+  // as part of the component or not when the component exists.
+  //
+  // This example shows the difference between the two flags for two of these
+  // delimited components that is present (the port and query) and one that
+  // isn't (the reference). The components that this flag affects are marked
+  // with a *.
+  //                 0         1         2
+  //                 012345678901234567890
+  // Example input:  http://foo:80/?query
+  //              include_delim=true,  ...=false  ("<-" indicates different)
+  //      SCHEME: 0                    0
+  //    USERNAME: 5                    5
+  //    PASSWORD: 5                    5
+  //        HOST: 7                    7
+  //       *PORT: 10                   11 <-
+  //        PATH: 13                   13
+  //      *QUERY: 14                   15 <-
+  //        *REF: 20                   20
+  //
+  int CountCharactersBefore(ComponentType type, bool include_delimiter) const;
+
+  // Scheme without the colon: "http://foo"/ would have a scheme of "http".
+  // The length will be -1 if no scheme is specified ("foo.com"), or 0 if there
+  // is a colon but no scheme (":foo"). Note that the scheme is not guaranteed
+  // to start at the beginning of the string if there are preceeding whitespace
+  // or control characters.
+  Component scheme;
+
+  // Username. Specified in URLs with an @ sign before the host. See |password|
+  Component username;
+
+  // Password. The length will be -1 if unspecified, 0 if specified but empty.
+  // Not all URLs with a username have a password, as in "http://me@host/".
+  // The password is separated form the username with a colon, as in
+  // "http://me:secret@host/"
+  Component password;
+
+  // Host name.
+  Component host;
+
+  // Port number.
+  Component port;
+
+  // Path, this is everything following the host name. Length will be -1 if
+  // unspecified. This includes the preceeding slash, so the path on
+  // http://www.google.com/asdf" is "/asdf". As a result, it is impossible to
+  // have a 0 length path, it will be -1 in cases like "http://host?foo".
+  // Note that we treat backslashes the same as slashes.
+  Component path;
+
+  // Stuff between the ? and the # after the path. This does not include the
+  // preceeding ? character. Length will be -1 if unspecified, 0 if there is
+  // a question mark but no query string.
+  Component query;
+
+  // Indicated by a #, this is everything following the hash sign (not
+  // including it). If there are multiple hash signs, we'll use the last one.
+  // Length will be -1 if there is no hash sign, or 0 if there is one but
+  // nothing follows it.
+  Component ref;
+
+  // This is used for nested URL types, currently only filesystem.  If you
+  // parse a filesystem URL, the resulting Parsed will have a nested
+  // inner_parsed_ to hold the parsed inner URL's component information.
+  // For all other url types [including the inner URL], it will be NULL.
+  Parsed* inner_parsed() const {
+    return inner_parsed_;
+  }
+
+  void set_inner_parsed(const Parsed& inner_parsed) {
+    if (!inner_parsed_)
+      inner_parsed_ = new Parsed(inner_parsed);
+    else
+      *inner_parsed_ = inner_parsed;
+  }
+
+  void clear_inner_parsed() {
+    if (inner_parsed_) {
+      delete inner_parsed_;
+      inner_parsed_ = NULL;
+    }
+  }
+
+ private:
+  Parsed* inner_parsed_;  // This object is owned and managed by this struct.
+};
+
+// Initialization functions ---------------------------------------------------
+//
+// These functions parse the given URL, filling in all of the structure's
+// components. These functions can not fail, they will always do their best
+// at interpreting the input given.
+//
+// The string length of the URL MUST be specified, we do not check for NULLs
+// at any point in the process, and will actually handle embedded NULLs.
+//
+// IMPORTANT: These functions do NOT hang on to the given pointer or copy it
+// in any way. See the comment above the struct.
+//
+// The 8-bit versions require UTF-8 encoding.
+
+// StandardURL is for when the scheme is known to be one that has an
+// authority (host) like "http". This function will not handle weird ones
+// like "about:" and "javascript:", or do the right thing for "file:" URLs.
+URL_EXPORT void ParseStandardURL(const char* url,
+                                 int url_len,
+                                 Parsed* parsed);
+URL_EXPORT void ParseStandardURL(const base::char16* url,
+                                 int url_len,
+                                 Parsed* parsed);
+
+// PathURL is for when the scheme is known not to have an authority (host)
+// section but that aren't file URLs either. The scheme is parsed, and
+// everything after the scheme is considered as the path. This is used for
+// things like "about:" and "javascript:"
+URL_EXPORT void ParsePathURL(const char* url, int url_len, Parsed* parsed);
+URL_EXPORT void ParsePathURL(const base::char16* url,
+                             int url_len,
+                             Parsed* parsed);
+
+// FileURL is for file URLs. There are some special rules for interpreting
+// these.
+URL_EXPORT void ParseFileURL(const char* url, int url_len, Parsed* parsed);
+URL_EXPORT void ParseFileURL(const base::char16* url,
+                             int url_len,
+                             Parsed* parsed);
+
+// Filesystem URLs are structured differently than other URLs.
+URL_EXPORT void ParseFileSystemURL(const char* url,
+                                   int url_len,
+                                   Parsed* parsed);
+URL_EXPORT void ParseFileSystemURL(const base::char16* url,
+                                   int url_len,
+                                   Parsed* parsed);
+
+// MailtoURL is for mailto: urls. They are made up scheme,path,query
+URL_EXPORT void ParseMailtoURL(const char* url, int url_len, Parsed* parsed);
+URL_EXPORT void ParseMailtoURL(const base::char16* url,
+                               int url_len,
+                               Parsed* parsed);
+
+// Helper functions -----------------------------------------------------------
+
+// Locates the scheme according to the URL  parser's rules. This function is
+// designed so the caller can find the scheme and call the correct Init*
+// function according to their known scheme types.
+//
+// It also does not perform any validation on the scheme.
+//
+// This function will return true if the scheme is found and will put the
+// scheme's range into *scheme. False means no scheme could be found. Note
+// that a URL beginning with a colon has a scheme, but it is empty, so this
+// function will return true but *scheme will = (0,0).
+//
+// The scheme is found by skipping spaces and control characters at the
+// beginning, and taking everything from there to the first colon to be the
+// scheme. The character at scheme.end() will be the colon (we may enhance
+// this to handle full width colons or something, so don't count on the
+// actual character value). The character at scheme.end()+1 will be the
+// beginning of the rest of the URL, be it the authority or the path (or the
+// end of the string).
+//
+// The 8-bit version requires UTF-8 encoding.
+URL_EXPORT bool ExtractScheme(const char* url,
+                              int url_len,
+                              Component* scheme);
+URL_EXPORT bool ExtractScheme(const base::char16* url,
+                              int url_len,
+                              Component* scheme);
+
+// Returns true if ch is a character that terminates the authority segment
+// of a URL.
+URL_EXPORT bool IsAuthorityTerminator(base::char16 ch);
+
+// Does a best effort parse of input |spec|, in range |auth|. If a particular
+// component is not found, it will be set to invalid.
+URL_EXPORT void ParseAuthority(const char* spec,
+                               const Component& auth,
+                               Component* username,
+                               Component* password,
+                               Component* hostname,
+                               Component* port_num);
+URL_EXPORT void ParseAuthority(const base::char16* spec,
+                               const Component& auth,
+                               Component* username,
+                               Component* password,
+                               Component* hostname,
+                               Component* port_num);
+
+// Computes the integer port value from the given port component. The port
+// component should have been identified by one of the init functions on
+// |Parsed| for the given input url.
+//
+// The return value will be a positive integer between 0 and 64K, or one of
+// the two special values below.
+enum SpecialPort { PORT_UNSPECIFIED = -1, PORT_INVALID = -2 };
+URL_EXPORT int ParsePort(const char* url, const Component& port);
+URL_EXPORT int ParsePort(const base::char16* url, const Component& port);
+
+// Extracts the range of the file name in the given url. The path must
+// already have been computed by the parse function, and the matching URL
+// and extracted path are provided to this function. The filename is
+// defined as being everything from the last slash/backslash of the path
+// to the end of the path.
+//
+// The file name will be empty if the path is empty or there is nothing
+// following the last slash.
+//
+// The 8-bit version requires UTF-8 encoding.
+URL_EXPORT void ExtractFileName(const char* url,
+                                const Component& path,
+                                Component* file_name);
+URL_EXPORT void ExtractFileName(const base::char16* url,
+                                const Component& path,
+                                Component* file_name);
+
+// Extract the first key/value from the range defined by |*query|. Updates
+// |*query| to start at the end of the extracted key/value pair. This is
+// designed for use in a loop: you can keep calling it with the same query
+// object and it will iterate over all items in the query.
+//
+// Some key/value pairs may have the key, the value, or both be empty (for
+// example, the query string "?&"). These will be returned. Note that an empty
+// last parameter "foo.com?" or foo.com?a&" will not be returned, this case
+// is the same as "done."
+//
+// The initial query component should not include the '?' (this is the default
+// for parsed URLs).
+//
+// If no key/value are found |*key| and |*value| will be unchanged and it will
+// return false.
+URL_EXPORT bool ExtractQueryKeyValue(const char* url,
+                                     Component* query,
+                                     Component* key,
+                                     Component* value);
+URL_EXPORT bool ExtractQueryKeyValue(const base::char16* url,
+                                     Component* query,
+                                     Component* key,
+                                     Component* value);
+
+}  // namespace url_parse
+
+#endif  // URL_THIRD_PARTY_MOZILLA_URL_PARSE_H_
diff --git a/url/url.gyp b/url/url.gyp
index a9a1a19..fe4d5fd 100644
--- a/url/url.gyp
+++ b/url/url.gyp
@@ -22,6 +22,8 @@
       'sources': [
         'gurl.cc',
         'gurl.h',
+        'third_party/mozilla/url_parse.cc',
+        'third_party/mozilla/url_parse.h',
         'url_canon.h',
         'url_canon_etc.cc',
         'url_canon_filesystemurl.cc',
@@ -42,8 +44,6 @@
         'url_canon_stdstring.h',
         'url_canon_stdurl.cc',
         'url_file.h',
-        'url_parse.cc',
-        'url_parse.h',
         'url_parse_file.cc',
         'url_parse_internal.h',
         'url_util.cc',
diff --git a/url/url_lib.target.darwin-arm.mk b/url/url_lib.target.darwin-arm.mk
index 0f359f5..30e0c4b 100644
--- a/url/url_lib.target.darwin-arm.mk
+++ b/url/url_lib.target.darwin-arm.mk
@@ -27,6 +27,7 @@
 
 LOCAL_SRC_FILES := \
 	url/gurl.cc \
+	url/third_party/mozilla/url_parse.cc \
 	url/url_canon_etc.cc \
 	url/url_canon_filesystemurl.cc \
 	url/url_canon_fileurl.cc \
@@ -40,7 +41,6 @@
 	url/url_canon_query.cc \
 	url/url_canon_relative.cc \
 	url/url_canon_stdurl.cc \
-	url/url_parse.cc \
 	url/url_parse_file.cc \
 	url/url_util.cc
 
diff --git a/url/url_lib.target.darwin-mips.mk b/url/url_lib.target.darwin-mips.mk
index 7801c4f..2e0a4b0 100644
--- a/url/url_lib.target.darwin-mips.mk
+++ b/url/url_lib.target.darwin-mips.mk
@@ -27,6 +27,7 @@
 
 LOCAL_SRC_FILES := \
 	url/gurl.cc \
+	url/third_party/mozilla/url_parse.cc \
 	url/url_canon_etc.cc \
 	url/url_canon_filesystemurl.cc \
 	url/url_canon_fileurl.cc \
@@ -40,7 +41,6 @@
 	url/url_canon_query.cc \
 	url/url_canon_relative.cc \
 	url/url_canon_stdurl.cc \
-	url/url_parse.cc \
 	url/url_parse_file.cc \
 	url/url_util.cc
 
diff --git a/url/url_lib.target.darwin-x86.mk b/url/url_lib.target.darwin-x86.mk
index b530406..c864096 100644
--- a/url/url_lib.target.darwin-x86.mk
+++ b/url/url_lib.target.darwin-x86.mk
@@ -27,6 +27,7 @@
 
 LOCAL_SRC_FILES := \
 	url/gurl.cc \
+	url/third_party/mozilla/url_parse.cc \
 	url/url_canon_etc.cc \
 	url/url_canon_filesystemurl.cc \
 	url/url_canon_fileurl.cc \
@@ -40,7 +41,6 @@
 	url/url_canon_query.cc \
 	url/url_canon_relative.cc \
 	url/url_canon_stdurl.cc \
-	url/url_parse.cc \
 	url/url_parse_file.cc \
 	url/url_util.cc
 
diff --git a/url/url_lib.target.linux-arm.mk b/url/url_lib.target.linux-arm.mk
index 0f359f5..30e0c4b 100644
--- a/url/url_lib.target.linux-arm.mk
+++ b/url/url_lib.target.linux-arm.mk
@@ -27,6 +27,7 @@
 
 LOCAL_SRC_FILES := \
 	url/gurl.cc \
+	url/third_party/mozilla/url_parse.cc \
 	url/url_canon_etc.cc \
 	url/url_canon_filesystemurl.cc \
 	url/url_canon_fileurl.cc \
@@ -40,7 +41,6 @@
 	url/url_canon_query.cc \
 	url/url_canon_relative.cc \
 	url/url_canon_stdurl.cc \
-	url/url_parse.cc \
 	url/url_parse_file.cc \
 	url/url_util.cc
 
diff --git a/url/url_lib.target.linux-mips.mk b/url/url_lib.target.linux-mips.mk
index 7801c4f..2e0a4b0 100644
--- a/url/url_lib.target.linux-mips.mk
+++ b/url/url_lib.target.linux-mips.mk
@@ -27,6 +27,7 @@
 
 LOCAL_SRC_FILES := \
 	url/gurl.cc \
+	url/third_party/mozilla/url_parse.cc \
 	url/url_canon_etc.cc \
 	url/url_canon_filesystemurl.cc \
 	url/url_canon_fileurl.cc \
@@ -40,7 +41,6 @@
 	url/url_canon_query.cc \
 	url/url_canon_relative.cc \
 	url/url_canon_stdurl.cc \
-	url/url_parse.cc \
 	url/url_parse_file.cc \
 	url/url_util.cc
 
diff --git a/url/url_lib.target.linux-x86.mk b/url/url_lib.target.linux-x86.mk
index b530406..c864096 100644
--- a/url/url_lib.target.linux-x86.mk
+++ b/url/url_lib.target.linux-x86.mk
@@ -27,6 +27,7 @@
 
 LOCAL_SRC_FILES := \
 	url/gurl.cc \
+	url/third_party/mozilla/url_parse.cc \
 	url/url_canon_etc.cc \
 	url/url_canon_filesystemurl.cc \
 	url/url_canon_fileurl.cc \
@@ -40,7 +41,6 @@
 	url/url_canon_query.cc \
 	url/url_canon_relative.cc \
 	url/url_canon_stdurl.cc \
-	url/url_parse.cc \
 	url/url_parse_file.cc \
 	url/url_util.cc
 
diff --git a/url/url_parse.h b/url/url_parse.h
index 21033dd..3b9c546 100644
--- a/url/url_parse.h
+++ b/url/url_parse.h
@@ -5,357 +5,7 @@
 #ifndef URL_URL_PARSE_H_
 #define URL_URL_PARSE_H_
 
-#include <string>
-
-#include "base/basictypes.h"
-#include "base/strings/string16.h"
-#include "url/url_export.h"
-
-namespace url_parse {
-
-// Deprecated, but WebKit/WebCore/platform/KURLGooglePrivate.h and
-// KURLGoogle.cpp still rely on this type.
-typedef base::char16 UTF16Char;
-
-// Component ------------------------------------------------------------------
-
-// Represents a substring for URL parsing.
-struct Component {
-  Component() : begin(0), len(-1) {}
-
-  // Normal constructor: takes an offset and a length.
-  Component(int b, int l) : begin(b), len(l) {}
-
-  int end() const {
-    return begin + len;
-  }
-
-  // Returns true if this component is valid, meaning the length is given. Even
-  // valid components may be empty to record the fact that they exist.
-  bool is_valid() const {
-    return (len != -1);
-  }
-
-  // Returns true if the given component is specified on false, the component
-  // is either empty or invalid.
-  bool is_nonempty() const {
-    return (len > 0);
-  }
-
-  void reset() {
-    begin = 0;
-    len = -1;
-  }
-
-  bool operator==(const Component& other) const {
-    return begin == other.begin && len == other.len;
-  }
-
-  int begin;  // Byte offset in the string of this component.
-  int len;    // Will be -1 if the component is unspecified.
-};
-
-// Helper that returns a component created with the given begin and ending
-// points. The ending point is non-inclusive.
-inline Component MakeRange(int begin, int end) {
-  return Component(begin, end - begin);
-}
-
-// Parsed ---------------------------------------------------------------------
-
-// A structure that holds the identified parts of an input URL. This structure
-// does NOT store the URL itself. The caller will have to store the URL text
-// and its corresponding Parsed structure separately.
-//
-// Typical usage would be:
-//
-//    url_parse::Parsed parsed;
-//    url_parse::Component scheme;
-//    if (!url_parse::ExtractScheme(url, url_len, &scheme))
-//      return I_CAN_NOT_FIND_THE_SCHEME_DUDE;
-//
-//    if (IsStandardScheme(url, scheme))  // Not provided by this component
-//      url_parseParseStandardURL(url, url_len, &parsed);
-//    else if (IsFileURL(url, scheme))    // Not provided by this component
-//      url_parse::ParseFileURL(url, url_len, &parsed);
-//    else
-//      url_parse::ParsePathURL(url, url_len, &parsed);
-//
-struct URL_EXPORT Parsed {
-  // Identifies different components.
-  enum ComponentType {
-    SCHEME,
-    USERNAME,
-    PASSWORD,
-    HOST,
-    PORT,
-    PATH,
-    QUERY,
-    REF,
-  };
-
-  // The default constructor is sufficient for the components, but inner_parsed_
-  // requires special handling.
-  Parsed();
-  Parsed(const Parsed&);
-  Parsed& operator=(const Parsed&);
-  ~Parsed();
-
-  // Returns the length of the URL (the end of the last component).
-  //
-  // Note that for some invalid, non-canonical URLs, this may not be the length
-  // of the string. For example "http://": the parsed structure will only
-  // contain an entry for the four-character scheme, and it doesn't know about
-  // the "://". For all other last-components, it will return the real length.
-  int Length() const;
-
-  // Returns the number of characters before the given component if it exists,
-  // or where the component would be if it did exist. This will return the
-  // string length if the component would be appended to the end.
-  //
-  // Note that this can get a little funny for the port, query, and ref
-  // components which have a delimiter that is not counted as part of the
-  // component. The |include_delimiter| flag controls if you want this counted
-  // as part of the component or not when the component exists.
-  //
-  // This example shows the difference between the two flags for two of these
-  // delimited components that is present (the port and query) and one that
-  // isn't (the reference). The components that this flag affects are marked
-  // with a *.
-  //                 0         1         2
-  //                 012345678901234567890
-  // Example input:  http://foo:80/?query
-  //              include_delim=true,  ...=false  ("<-" indicates different)
-  //      SCHEME: 0                    0
-  //    USERNAME: 5                    5
-  //    PASSWORD: 5                    5
-  //        HOST: 7                    7
-  //       *PORT: 10                   11 <-
-  //        PATH: 13                   13
-  //      *QUERY: 14                   15 <-
-  //        *REF: 20                   20
-  //
-  int CountCharactersBefore(ComponentType type, bool include_delimiter) const;
-
-  // Scheme without the colon: "http://foo"/ would have a scheme of "http".
-  // The length will be -1 if no scheme is specified ("foo.com"), or 0 if there
-  // is a colon but no scheme (":foo"). Note that the scheme is not guaranteed
-  // to start at the beginning of the string if there are preceeding whitespace
-  // or control characters.
-  Component scheme;
-
-  // Username. Specified in URLs with an @ sign before the host. See |password|
-  Component username;
-
-  // Password. The length will be -1 if unspecified, 0 if specified but empty.
-  // Not all URLs with a username have a password, as in "http://me@host/".
-  // The password is separated form the username with a colon, as in
-  // "http://me:secret@host/"
-  Component password;
-
-  // Host name.
-  Component host;
-
-  // Port number.
-  Component port;
-
-  // Path, this is everything following the host name. Length will be -1 if
-  // unspecified. This includes the preceeding slash, so the path on
-  // http://www.google.com/asdf" is "/asdf". As a result, it is impossible to
-  // have a 0 length path, it will be -1 in cases like "http://host?foo".
-  // Note that we treat backslashes the same as slashes.
-  Component path;
-
-  // Stuff between the ? and the # after the path. This does not include the
-  // preceeding ? character. Length will be -1 if unspecified, 0 if there is
-  // a question mark but no query string.
-  Component query;
-
-  // Indicated by a #, this is everything following the hash sign (not
-  // including it). If there are multiple hash signs, we'll use the last one.
-  // Length will be -1 if there is no hash sign, or 0 if there is one but
-  // nothing follows it.
-  Component ref;
-
-  // This is used for nested URL types, currently only filesystem.  If you
-  // parse a filesystem URL, the resulting Parsed will have a nested
-  // inner_parsed_ to hold the parsed inner URL's component information.
-  // For all other url types [including the inner URL], it will be NULL.
-  Parsed* inner_parsed() const {
-    return inner_parsed_;
-  }
-
-  void set_inner_parsed(const Parsed& inner_parsed) {
-    if (!inner_parsed_)
-      inner_parsed_ = new Parsed(inner_parsed);
-    else
-      *inner_parsed_ = inner_parsed;
-  }
-
-  void clear_inner_parsed() {
-    if (inner_parsed_) {
-      delete inner_parsed_;
-      inner_parsed_ = NULL;
-    }
-  }
-
- private:
-  Parsed* inner_parsed_;  // This object is owned and managed by this struct.
-};
-
-// Initialization functions ---------------------------------------------------
-//
-// These functions parse the given URL, filling in all of the structure's
-// components. These functions can not fail, they will always do their best
-// at interpreting the input given.
-//
-// The string length of the URL MUST be specified, we do not check for NULLs
-// at any point in the process, and will actually handle embedded NULLs.
-//
-// IMPORTANT: These functions do NOT hang on to the given pointer or copy it
-// in any way. See the comment above the struct.
-//
-// The 8-bit versions require UTF-8 encoding.
-
-// StandardURL is for when the scheme is known to be one that has an
-// authority (host) like "http". This function will not handle weird ones
-// like "about:" and "javascript:", or do the right thing for "file:" URLs.
-URL_EXPORT void ParseStandardURL(const char* url,
-                                 int url_len,
-                                 Parsed* parsed);
-URL_EXPORT void ParseStandardURL(const base::char16* url,
-                                 int url_len,
-                                 Parsed* parsed);
-
-// PathURL is for when the scheme is known not to have an authority (host)
-// section but that aren't file URLs either. The scheme is parsed, and
-// everything after the scheme is considered as the path. This is used for
-// things like "about:" and "javascript:"
-URL_EXPORT void ParsePathURL(const char* url, int url_len, Parsed* parsed);
-URL_EXPORT void ParsePathURL(const base::char16* url,
-                             int url_len,
-                             Parsed* parsed);
-
-// FileURL is for file URLs. There are some special rules for interpreting
-// these.
-URL_EXPORT void ParseFileURL(const char* url, int url_len, Parsed* parsed);
-URL_EXPORT void ParseFileURL(const base::char16* url,
-                             int url_len,
-                             Parsed* parsed);
-
-// Filesystem URLs are structured differently than other URLs.
-URL_EXPORT void ParseFileSystemURL(const char* url,
-                                   int url_len,
-                                   Parsed* parsed);
-URL_EXPORT void ParseFileSystemURL(const base::char16* url,
-                                   int url_len,
-                                   Parsed* parsed);
-
-// MailtoURL is for mailto: urls. They are made up scheme,path,query
-URL_EXPORT void ParseMailtoURL(const char* url, int url_len, Parsed* parsed);
-URL_EXPORT void ParseMailtoURL(const base::char16* url,
-                               int url_len,
-                               Parsed* parsed);
-
-// Helper functions -----------------------------------------------------------
-
-// Locates the scheme according to the URL  parser's rules. This function is
-// designed so the caller can find the scheme and call the correct Init*
-// function according to their known scheme types.
-//
-// It also does not perform any validation on the scheme.
-//
-// This function will return true if the scheme is found and will put the
-// scheme's range into *scheme. False means no scheme could be found. Note
-// that a URL beginning with a colon has a scheme, but it is empty, so this
-// function will return true but *scheme will = (0,0).
-//
-// The scheme is found by skipping spaces and control characters at the
-// beginning, and taking everything from there to the first colon to be the
-// scheme. The character at scheme.end() will be the colon (we may enhance
-// this to handle full width colons or something, so don't count on the
-// actual character value). The character at scheme.end()+1 will be the
-// beginning of the rest of the URL, be it the authority or the path (or the
-// end of the string).
-//
-// The 8-bit version requires UTF-8 encoding.
-URL_EXPORT bool ExtractScheme(const char* url,
-                              int url_len,
-                              Component* scheme);
-URL_EXPORT bool ExtractScheme(const base::char16* url,
-                              int url_len,
-                              Component* scheme);
-
-// Returns true if ch is a character that terminates the authority segment
-// of a URL.
-URL_EXPORT bool IsAuthorityTerminator(base::char16 ch);
-
-// Does a best effort parse of input |spec|, in range |auth|. If a particular
-// component is not found, it will be set to invalid.
-URL_EXPORT void ParseAuthority(const char* spec,
-                               const Component& auth,
-                               Component* username,
-                               Component* password,
-                               Component* hostname,
-                               Component* port_num);
-URL_EXPORT void ParseAuthority(const base::char16* spec,
-                               const Component& auth,
-                               Component* username,
-                               Component* password,
-                               Component* hostname,
-                               Component* port_num);
-
-// Computes the integer port value from the given port component. The port
-// component should have been identified by one of the init functions on
-// |Parsed| for the given input url.
-//
-// The return value will be a positive integer between 0 and 64K, or one of
-// the two special values below.
-enum SpecialPort { PORT_UNSPECIFIED = -1, PORT_INVALID = -2 };
-URL_EXPORT int ParsePort(const char* url, const Component& port);
-URL_EXPORT int ParsePort(const base::char16* url, const Component& port);
-
-// Extracts the range of the file name in the given url. The path must
-// already have been computed by the parse function, and the matching URL
-// and extracted path are provided to this function. The filename is
-// defined as being everything from the last slash/backslash of the path
-// to the end of the path.
-//
-// The file name will be empty if the path is empty or there is nothing
-// following the last slash.
-//
-// The 8-bit version requires UTF-8 encoding.
-URL_EXPORT void ExtractFileName(const char* url,
-                                const Component& path,
-                                Component* file_name);
-URL_EXPORT void ExtractFileName(const base::char16* url,
-                                const Component& path,
-                                Component* file_name);
-
-// Extract the first key/value from the range defined by |*query|. Updates
-// |*query| to start at the end of the extracted key/value pair. This is
-// designed for use in a loop: you can keep calling it with the same query
-// object and it will iterate over all items in the query.
-//
-// Some key/value pairs may have the key, the value, or both be empty (for
-// example, the query string "?&"). These will be returned. Note that an empty
-// last parameter "foo.com?" or foo.com?a&" will not be returned, this case
-// is the same as "done."
-//
-// The initial query component should not include the '?' (this is the default
-// for parsed URLs).
-//
-// If no key/value are found |*key| and |*value| will be unchanged and it will
-// return false.
-URL_EXPORT bool ExtractQueryKeyValue(const char* url,
-                                     Component* query,
-                                     Component* key,
-                                     Component* value);
-URL_EXPORT bool ExtractQueryKeyValue(const base::char16* url,
-                                     Component* query,
-                                     Component* key,
-                                     Component* value);
-
-}  // namespace url_parse
+// TODO(tfarina): Remove this file when the callers are updated.
+#include "url/third_party/mozilla/url_parse.h"
 
 #endif  // URL_URL_PARSE_H_
diff --git a/webkit/DEPS b/webkit/DEPS
index fb09b7c..4571d4c 100644
--- a/webkit/DEPS
+++ b/webkit/DEPS
@@ -37,7 +37,6 @@
   "+ui/base/keycodes",
 
   # TODO(brettw) - review these; move up if it's ok, or remove the dependency
-  "+crypto",
   "+net",
   "+third_party/npapi/bindings",
 
diff --git a/webkit/browser/fileapi/copy_or_move_operation_delegate.cc b/webkit/browser/fileapi/copy_or_move_operation_delegate.cc
index 15e222d..da1ef97 100644
--- a/webkit/browser/fileapi/copy_or_move_operation_delegate.cc
+++ b/webkit/browser/fileapi/copy_or_move_operation_delegate.cc
@@ -26,7 +26,8 @@
       src_root_(src_root),
       dest_root_(dest_root),
       operation_type_(operation_type),
-      callback_(callback) {
+      callback_(callback),
+      weak_factory_(this) {
   same_file_system_ = src_root_.IsInSameFileSystem(dest_root_);
 }
 
@@ -56,7 +57,7 @@
   // First try to copy/move it as a file.
   CopyOrMoveFile(URLPair(src_root_, dest_root_),
                  base::Bind(&CopyOrMoveOperationDelegate::DidTryCopyOrMoveFile,
-                            AsWeakPtr()));
+                            weak_factory_.GetWeakPtr()));
 }
 
 void CopyOrMoveOperationDelegate::ProcessFile(const FileSystemURL& src_url,
@@ -90,7 +91,7 @@
   operation_runner()->RemoveDirectory(
       dest_root_,
       base::Bind(&CopyOrMoveOperationDelegate::DidTryRemoveDestRoot,
-                 AsWeakPtr()));
+                 weak_factory_.GetWeakPtr()));
 }
 
 void CopyOrMoveOperationDelegate::DidTryRemoveDestRoot(
@@ -112,7 +113,7 @@
   StartRecursiveOperation(
       src_root_,
       base::Bind(&CopyOrMoveOperationDelegate::DidFinishRecursiveCopyDir,
-                 AsWeakPtr(), src_root_, callback_));
+                 weak_factory_.GetWeakPtr(), src_root_, callback_));
 }
 
 void CopyOrMoveOperationDelegate::CopyOrMoveFile(
@@ -132,12 +133,12 @@
   // Perform CreateSnapshotFile, CopyInForeignFile and then calls
   // copy_callback which removes the source file if operation_type == MOVE.
   StatusCallback copy_callback =
-      base::Bind(&CopyOrMoveOperationDelegate::DidFinishCopy, AsWeakPtr(),
-                 url_pair, callback);
+      base::Bind(&CopyOrMoveOperationDelegate::DidFinishCopy,
+                 weak_factory_.GetWeakPtr(), url_pair, callback);
   operation_runner()->CreateSnapshotFile(
       url_pair.src,
-      base::Bind(&CopyOrMoveOperationDelegate::DidCreateSnapshot, AsWeakPtr(),
-                 url_pair, copy_callback));
+      base::Bind(&CopyOrMoveOperationDelegate::DidCreateSnapshot,
+                 weak_factory_.GetWeakPtr(), url_pair, copy_callback));
 }
 
 void CopyOrMoveOperationDelegate::DidCreateSnapshot(
@@ -172,7 +173,8 @@
   validator_.reset(
       factory->CreateCopyOrMoveFileValidator(url_pair.src, platform_path));
   validator_->StartPreWriteValidation(
-      base::Bind(&CopyOrMoveOperationDelegate::DidValidateFile, AsWeakPtr(),
+      base::Bind(&CopyOrMoveOperationDelegate::DidValidateFile,
+                 weak_factory_.GetWeakPtr(),
                  url_pair.dest, callback, file_info, platform_path));
 }
 
@@ -206,7 +208,7 @@
   operation_runner()->Remove(
       src, true /* recursive */,
       base::Bind(&CopyOrMoveOperationDelegate::DidRemoveSourceForMove,
-                 AsWeakPtr(), callback));
+                 weak_factory_.GetWeakPtr(), callback));
 }
 
 void CopyOrMoveOperationDelegate::DidFinishCopy(
@@ -231,7 +233,7 @@
   operation_runner()->CreateSnapshotFile(
       url_pair.dest,
       base::Bind(&CopyOrMoveOperationDelegate::DoPostWriteValidation,
-                 AsWeakPtr(), url_pair, callback));
+                 weak_factory_.GetWeakPtr(), url_pair, callback));
 }
 
 void CopyOrMoveOperationDelegate::DoPostWriteValidation(
@@ -245,7 +247,7 @@
     operation_runner()->Remove(
         url_pair.dest, true,
         base::Bind(&CopyOrMoveOperationDelegate::DidRemoveDestForError,
-                   AsWeakPtr(), error, callback));
+                   weak_factory_.GetWeakPtr(), error, callback));
     return;
   }
 
@@ -255,7 +257,7 @@
   validator_->StartPostWriteValidation(
       platform_path,
       base::Bind(&CopyOrMoveOperationDelegate::DidPostWriteValidation,
-                 AsWeakPtr(), url_pair, callback, file_ref));
+                 weak_factory_.GetWeakPtr(), url_pair, callback, file_ref));
 }
 
 // |file_ref| is unused; it is passed here to make sure the reference is
@@ -269,7 +271,7 @@
     operation_runner()->Remove(
         url_pair.dest, true,
         base::Bind(&CopyOrMoveOperationDelegate::DidRemoveDestForError,
-                   AsWeakPtr(), error, callback));
+                   weak_factory_.GetWeakPtr(), error, callback));
     return;
   }
 
@@ -284,7 +286,7 @@
   operation_runner()->Remove(
       url_pair.src, true /* recursive */,
       base::Bind(&CopyOrMoveOperationDelegate::DidRemoveSourceForMove,
-                 AsWeakPtr(), callback));
+                 weak_factory_.GetWeakPtr(), callback));
 }
 
 void CopyOrMoveOperationDelegate::DidRemoveSourceForMove(
diff --git a/webkit/browser/fileapi/copy_or_move_operation_delegate.h b/webkit/browser/fileapi/copy_or_move_operation_delegate.h
index 3c40cae..ceceb97 100644
--- a/webkit/browser/fileapi/copy_or_move_operation_delegate.h
+++ b/webkit/browser/fileapi/copy_or_move_operation_delegate.h
@@ -21,8 +21,7 @@
 
 // A delegate class for recursive copy or move operations.
 class CopyOrMoveOperationDelegate
-    : public RecursiveOperationDelegate,
-      public base::SupportsWeakPtr<CopyOrMoveOperationDelegate> {
+    : public RecursiveOperationDelegate {
  public:
   enum OperationType {
     OPERATION_COPY,
@@ -45,8 +44,6 @@
   virtual void ProcessDirectory(const FileSystemURL& url,
                                 const StatusCallback& callback) OVERRIDE;
 
-  using base::SupportsWeakPtr<CopyOrMoveOperationDelegate>::AsWeakPtr;
-
  private:
   struct URLPair {
     URLPair(const FileSystemURL& src, const FileSystemURL& dest)
@@ -115,6 +112,8 @@
 
   scoped_ptr<CopyOrMoveFileValidator> validator_;
 
+  base::WeakPtrFactory<CopyOrMoveOperationDelegate> weak_factory_;
+
   DISALLOW_COPY_AND_ASSIGN(CopyOrMoveOperationDelegate);
 };
 
diff --git a/webkit/browser/fileapi/file_system_operation_impl_unittest.cc b/webkit/browser/fileapi/file_system_operation_impl_unittest.cc
index 846335c..083fdeb 100644
--- a/webkit/browser/fileapi/file_system_operation_impl_unittest.cc
+++ b/webkit/browser/fileapi/file_system_operation_impl_unittest.cc
@@ -47,11 +47,11 @@
 
 // Test class for FileSystemOperationImpl.
 class FileSystemOperationImplTest
-    : public testing::Test,
-      public base::SupportsWeakPtr<FileSystemOperationImplTest> {
+    : public testing::Test {
  public:
   FileSystemOperationImplTest()
-      : status_(kFileOperationStatusNotSet) {}
+      : status_(kFileOperationStatusNotSet),
+        weak_factory_(this) {}
 
  protected:
   virtual void SetUp() OVERRIDE {
@@ -165,23 +165,24 @@
 
   // Callbacks for recording test results.
   FileSystemOperation::StatusCallback RecordStatusCallback() {
-    return base::Bind(&FileSystemOperationImplTest::DidFinish, AsWeakPtr());
+    return base::Bind(&FileSystemOperationImplTest::DidFinish,
+                      weak_factory_.GetWeakPtr());
   }
 
   FileSystemOperation::ReadDirectoryCallback
   RecordReadDirectoryCallback() {
     return base::Bind(&FileSystemOperationImplTest::DidReadDirectory,
-                      AsWeakPtr());
+                      weak_factory_.GetWeakPtr());
   }
 
   FileSystemOperation::GetMetadataCallback RecordMetadataCallback() {
     return base::Bind(&FileSystemOperationImplTest::DidGetMetadata,
-                      AsWeakPtr());
+                      weak_factory_.GetWeakPtr());
   }
 
   FileSystemOperation::SnapshotFileCallback RecordSnapshotFileCallback() {
     return base::Bind(&FileSystemOperationImplTest::DidCreateSnapshotFile,
-                      AsWeakPtr());
+                      weak_factory_.GetWeakPtr());
   }
 
   void DidFinish(base::PlatformFileError status) {
@@ -287,6 +288,8 @@
   MockFileChangeObserver change_observer_;
   ChangeObserverList change_observers_;
 
+  base::WeakPtrFactory<FileSystemOperationImplTest> weak_factory_;
+
   DISALLOW_COPY_AND_ASSIGN(FileSystemOperationImplTest);
 };
 
diff --git a/webkit/browser/fileapi/file_system_operation_impl_write_unittest.cc b/webkit/browser/fileapi/file_system_operation_impl_write_unittest.cc
index 88a48d8..d8ecc28 100644
--- a/webkit/browser/fileapi/file_system_operation_impl_write_unittest.cc
+++ b/webkit/browser/fileapi/file_system_operation_impl_write_unittest.cc
@@ -48,15 +48,15 @@
 }  // namespace
 
 class FileSystemOperationImplWriteTest
-    : public testing::Test,
-      public base::SupportsWeakPtr<FileSystemOperationImplWriteTest> {
+    : public testing::Test {
  public:
   FileSystemOperationImplWriteTest()
       : loop_(base::MessageLoop::TYPE_IO),
         status_(base::PLATFORM_FILE_OK),
         cancel_status_(base::PLATFORM_FILE_ERROR_FAILED),
         bytes_written_(0),
-        complete_(false) {
+        complete_(false),
+        weak_factory_(this) {
     change_observers_ = MockFileChangeObserver::CreateList(&change_observer_);
   }
 
@@ -118,12 +118,12 @@
   // Callback function for recording test results.
   FileSystemOperation::WriteCallback RecordWriteCallback() {
     return base::Bind(&FileSystemOperationImplWriteTest::DidWrite,
-                      AsWeakPtr());
+                      weak_factory_.GetWeakPtr());
   }
 
   FileSystemOperation::StatusCallback RecordCancelCallback() {
     return base::Bind(&FileSystemOperationImplWriteTest::DidCancel,
-                      AsWeakPtr());
+                      weak_factory_.GetWeakPtr());
   }
 
   void DidWrite(base::PlatformFileError status, int64 bytes, bool complete) {
@@ -168,6 +168,8 @@
   MockFileChangeObserver change_observer_;
   ChangeObserverList change_observers_;
 
+  base::WeakPtrFactory<FileSystemOperationImplWriteTest> weak_factory_;
+
   DISALLOW_COPY_AND_ASSIGN(FileSystemOperationImplWriteTest);
 };
 
diff --git a/webkit/browser/fileapi/file_writer_delegate.cc b/webkit/browser/fileapi/file_writer_delegate.cc
index 48f1770..7a0094e 100644
--- a/webkit/browser/fileapi/file_writer_delegate.cc
+++ b/webkit/browser/fileapi/file_writer_delegate.cc
@@ -46,7 +46,8 @@
       bytes_written_backlog_(0),
       bytes_written_(0),
       bytes_read_(0),
-      io_buffer_(new net::IOBufferWithSize(kReadBufSize)) {
+      io_buffer_(new net::IOBufferWithSize(kReadBufSize)),
+      weak_factory_(this) {
 }
 
 FileWriterDelegate::~FileWriterDelegate() {
@@ -67,7 +68,8 @@
   }
 
   const int status = file_stream_writer_->Cancel(
-      base::Bind(&FileWriterDelegate::OnWriteCancelled, AsWeakPtr()));
+      base::Bind(&FileWriterDelegate::OnWriteCancelled,
+                 weak_factory_.GetWeakPtr()));
   // Return true to finish immediately if we have no pending writes.
   // Otherwise we'll do the final cleanup in the Cancel callback.
   if (status != net::ERR_IO_PENDING) {
@@ -129,7 +131,7 @@
     base::MessageLoop::current()->PostTask(
         FROM_HERE,
         base::Bind(&FileWriterDelegate::OnDataReceived,
-                   AsWeakPtr(), bytes_read_));
+                   weak_factory_.GetWeakPtr(), bytes_read_));
   } else if (!request_->status().is_io_pending()) {
     OnError(base::PLATFORM_FILE_ERROR_FAILED);
   }
@@ -155,12 +157,12 @@
       file_stream_writer_->Write(cursor_.get(),
                                  static_cast<int>(bytes_to_write),
                                  base::Bind(&FileWriterDelegate::OnDataWritten,
-                                            AsWeakPtr()));
+                                            weak_factory_.GetWeakPtr()));
   if (write_response > 0) {
     base::MessageLoop::current()->PostTask(
         FROM_HERE,
         base::Bind(&FileWriterDelegate::OnDataWritten,
-                   AsWeakPtr(), write_response));
+                   weak_factory_.GetWeakPtr(), write_response));
   } else if (net::ERR_IO_PENDING != write_response) {
     OnError(NetErrorToPlatformFileError(write_response));
   }
@@ -230,7 +232,7 @@
     int bytes_written,
     WriteProgressStatus progress_status) {
   int flush_error = file_stream_writer_->Flush(
-      base::Bind(&FileWriterDelegate::OnFlushed, AsWeakPtr(),
+      base::Bind(&FileWriterDelegate::OnFlushed, weak_factory_.GetWeakPtr(),
                  error, bytes_written, progress_status));
   if (flush_error != net::ERR_IO_PENDING)
     OnFlushed(error, bytes_written, progress_status, flush_error);
diff --git a/webkit/browser/fileapi/file_writer_delegate.h b/webkit/browser/fileapi/file_writer_delegate.h
index e6e53cf..ae63e7f 100644
--- a/webkit/browser/fileapi/file_writer_delegate.h
+++ b/webkit/browser/fileapi/file_writer_delegate.h
@@ -20,8 +20,7 @@
 class FileStreamWriter;
 
 class WEBKIT_STORAGE_BROWSER_EXPORT_PRIVATE FileWriterDelegate
-    : public net::URLRequest::Delegate,
-      public base::SupportsWeakPtr<FileWriterDelegate> {
+    : public net::URLRequest::Delegate {
  public:
   enum WriteProgressStatus {
     SUCCESS_IO_PENDING,
@@ -93,6 +92,10 @@
   scoped_refptr<net::IOBufferWithSize> io_buffer_;
   scoped_refptr<net::DrainableIOBuffer> cursor_;
   scoped_ptr<net::URLRequest> request_;
+
+  base::WeakPtrFactory<FileWriterDelegate> weak_factory_;
+
+  DISALLOW_COPY_AND_ASSIGN(FileWriterDelegate);
 };
 
 }  // namespace fileapi
diff --git a/webkit/browser/fileapi/remove_operation_delegate.cc b/webkit/browser/fileapi/remove_operation_delegate.cc
index a639e98..fcd9ba9 100644
--- a/webkit/browser/fileapi/remove_operation_delegate.cc
+++ b/webkit/browser/fileapi/remove_operation_delegate.cc
@@ -16,20 +16,22 @@
     const StatusCallback& callback)
     : RecursiveOperationDelegate(file_system_context),
       url_(url),
-      callback_(callback) {
+      callback_(callback),
+      weak_factory_(this) {
 }
 
 RemoveOperationDelegate::~RemoveOperationDelegate() {}
 
 void RemoveOperationDelegate::Run() {
   operation_runner()->RemoveFile(url_, base::Bind(
-      &RemoveOperationDelegate::DidTryRemoveFile, AsWeakPtr()));
+      &RemoveOperationDelegate::DidTryRemoveFile, weak_factory_.GetWeakPtr()));
 }
 
 void RemoveOperationDelegate::RunRecursively() {
   StartRecursiveOperation(
       url_,
-      base::Bind(&RemoveOperationDelegate::RemoveNextDirectory, AsWeakPtr()));
+      base::Bind(&RemoveOperationDelegate::RemoveNextDirectory,
+                 weak_factory_.GetWeakPtr()));
 }
 
 void RemoveOperationDelegate::ProcessFile(const FileSystemURL& url,
@@ -40,7 +42,8 @@
     to_remove_directories_.pop();
   }
   operation_runner()->RemoveFile(url, base::Bind(
-      &RemoveOperationDelegate::DidRemoveFile, AsWeakPtr(), callback));
+      &RemoveOperationDelegate::DidRemoveFile,
+      weak_factory_.GetWeakPtr(), callback));
 }
 
 void RemoveOperationDelegate::ProcessDirectory(const FileSystemURL& url,
@@ -79,7 +82,7 @@
   to_remove_directories_.pop();
   operation_runner()->RemoveDirectory(url, base::Bind(
       &RemoveOperationDelegate::RemoveNextDirectory,
-      AsWeakPtr()));
+      weak_factory_.GetWeakPtr()));
 }
 
 }  // namespace fileapi
diff --git a/webkit/browser/fileapi/remove_operation_delegate.h b/webkit/browser/fileapi/remove_operation_delegate.h
index 4657cff..ef9e1a0 100644
--- a/webkit/browser/fileapi/remove_operation_delegate.h
+++ b/webkit/browser/fileapi/remove_operation_delegate.h
@@ -12,8 +12,7 @@
 namespace fileapi {
 
 class RemoveOperationDelegate
-    : public RecursiveOperationDelegate,
-      public base::SupportsWeakPtr<RemoveOperationDelegate> {
+    : public RecursiveOperationDelegate {
  public:
   RemoveOperationDelegate(FileSystemContext* file_system_context,
                           const FileSystemURL& url,
@@ -28,8 +27,6 @@
   virtual void ProcessDirectory(const FileSystemURL& url,
                                 const StatusCallback& callback) OVERRIDE;
 
-  using base::SupportsWeakPtr<RemoveOperationDelegate>::AsWeakPtr;
-
  private:
   void DidTryRemoveFile(base::PlatformFileError error);
   void DidRemoveFile(const StatusCallback& callback,
@@ -41,6 +38,8 @@
 
   std::stack<FileSystemURL> to_remove_directories_;
 
+  base::WeakPtrFactory<RemoveOperationDelegate> weak_factory_;
+
   DISALLOW_COPY_AND_ASSIGN(RemoveOperationDelegate);
 };
 
diff --git a/webkit/common/gpu/webkit_gpu.target.darwin-arm.mk b/webkit/common/gpu/webkit_gpu.target.darwin-arm.mk
index c560512..822ad0c 100644
--- a/webkit/common/gpu/webkit_gpu.target.darwin-arm.mk
+++ b/webkit/common/gpu/webkit_gpu.target.darwin-arm.mk
@@ -94,6 +94,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-DPOSIX_AVOID_MMAP' \
 	'-DU_USING_ICU_NAMESPACE=0' \
@@ -210,6 +211,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-DPOSIX_AVOID_MMAP' \
 	'-DU_USING_ICU_NAMESPACE=0' \
diff --git a/webkit/common/gpu/webkit_gpu.target.darwin-mips.mk b/webkit/common/gpu/webkit_gpu.target.darwin-mips.mk
index 9ca7067..93fc07b 100644
--- a/webkit/common/gpu/webkit_gpu.target.darwin-mips.mk
+++ b/webkit/common/gpu/webkit_gpu.target.darwin-mips.mk
@@ -94,6 +94,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-DPOSIX_AVOID_MMAP' \
 	'-DU_USING_ICU_NAMESPACE=0' \
@@ -210,6 +211,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-DPOSIX_AVOID_MMAP' \
 	'-DU_USING_ICU_NAMESPACE=0' \
diff --git a/webkit/common/gpu/webkit_gpu.target.darwin-x86.mk b/webkit/common/gpu/webkit_gpu.target.darwin-x86.mk
index 227272c..cf7e31c 100644
--- a/webkit/common/gpu/webkit_gpu.target.darwin-x86.mk
+++ b/webkit/common/gpu/webkit_gpu.target.darwin-x86.mk
@@ -96,6 +96,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DANDROID' \
@@ -214,6 +215,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DANDROID' \
diff --git a/webkit/common/gpu/webkit_gpu.target.linux-arm.mk b/webkit/common/gpu/webkit_gpu.target.linux-arm.mk
index c560512..822ad0c 100644
--- a/webkit/common/gpu/webkit_gpu.target.linux-arm.mk
+++ b/webkit/common/gpu/webkit_gpu.target.linux-arm.mk
@@ -94,6 +94,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-DPOSIX_AVOID_MMAP' \
 	'-DU_USING_ICU_NAMESPACE=0' \
@@ -210,6 +211,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-DPOSIX_AVOID_MMAP' \
 	'-DU_USING_ICU_NAMESPACE=0' \
diff --git a/webkit/common/gpu/webkit_gpu.target.linux-mips.mk b/webkit/common/gpu/webkit_gpu.target.linux-mips.mk
index 9ca7067..93fc07b 100644
--- a/webkit/common/gpu/webkit_gpu.target.linux-mips.mk
+++ b/webkit/common/gpu/webkit_gpu.target.linux-mips.mk
@@ -94,6 +94,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-DPOSIX_AVOID_MMAP' \
 	'-DU_USING_ICU_NAMESPACE=0' \
@@ -210,6 +211,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-DPOSIX_AVOID_MMAP' \
 	'-DU_USING_ICU_NAMESPACE=0' \
diff --git a/webkit/common/gpu/webkit_gpu.target.linux-x86.mk b/webkit/common/gpu/webkit_gpu.target.linux-x86.mk
index 227272c..cf7e31c 100644
--- a/webkit/common/gpu/webkit_gpu.target.linux-x86.mk
+++ b/webkit/common/gpu/webkit_gpu.target.linux-x86.mk
@@ -96,6 +96,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DANDROID' \
@@ -214,6 +215,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DANDROID' \
diff --git a/webkit/common/plugins/ppapi/OWNERS b/webkit/common/plugins/ppapi/OWNERS
deleted file mode 100644
index d24c4ea..0000000
--- a/webkit/common/plugins/ppapi/OWNERS
+++ /dev/null
@@ -1,6 +0,0 @@
-brettw@chromium.org
-bbudge@chromium.org
-dmichael@chromium.org
-piman@chromium.org
-raymes@chromium.org
-yzshen@chromium.org
diff --git a/webkit/common/plugins/ppapi/ppapi_utils.h b/webkit/common/plugins/ppapi/ppapi_utils.h
deleted file mode 100644
index 849bac9..0000000
--- a/webkit/common/plugins/ppapi/ppapi_utils.h
+++ /dev/null
@@ -1,20 +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 WEBKIT_COMMON_PLUGINS_PPAPI_PPAPI_UTILS_H_
-#define WEBKIT_COMMON_PLUGINS_PPAPI_PPAPI_UTILS_H_
-
-namespace webkit {
-namespace ppapi {
-
-// Returns true if the interface name passed in is supported by the
-// browser.
-bool IsSupportedPepperInterface(const char* name);
-
-}  // namespace ppapi
-}  // namespace webkit
-
-#endif  // WEBKIT_COMMON_PLUGINS_PPAPI_PPAPI_UTILS_H_
-
-
diff --git a/webkit/common/webkit_common.target.darwin-arm.mk b/webkit/common/webkit_common.target.darwin-arm.mk
index 7ceb7ad..67e9a0f 100644
--- a/webkit/common/webkit_common.target.darwin-arm.mk
+++ b/webkit/common/webkit_common.target.darwin-arm.mk
@@ -93,6 +93,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
@@ -204,6 +205,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
diff --git a/webkit/common/webkit_common.target.darwin-mips.mk b/webkit/common/webkit_common.target.darwin-mips.mk
index 46c3b0d..2c22851 100644
--- a/webkit/common/webkit_common.target.darwin-mips.mk
+++ b/webkit/common/webkit_common.target.darwin-mips.mk
@@ -92,6 +92,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
@@ -202,6 +203,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
diff --git a/webkit/common/webkit_common.target.darwin-x86.mk b/webkit/common/webkit_common.target.darwin-x86.mk
index a199c81..25c463a 100644
--- a/webkit/common/webkit_common.target.darwin-x86.mk
+++ b/webkit/common/webkit_common.target.darwin-x86.mk
@@ -94,6 +94,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
@@ -207,6 +208,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
diff --git a/webkit/common/webkit_common.target.linux-arm.mk b/webkit/common/webkit_common.target.linux-arm.mk
index 7ceb7ad..67e9a0f 100644
--- a/webkit/common/webkit_common.target.linux-arm.mk
+++ b/webkit/common/webkit_common.target.linux-arm.mk
@@ -93,6 +93,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
@@ -204,6 +205,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
diff --git a/webkit/common/webkit_common.target.linux-mips.mk b/webkit/common/webkit_common.target.linux-mips.mk
index 46c3b0d..2c22851 100644
--- a/webkit/common/webkit_common.target.linux-mips.mk
+++ b/webkit/common/webkit_common.target.linux-mips.mk
@@ -92,6 +92,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
@@ -202,6 +203,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
diff --git a/webkit/common/webkit_common.target.linux-x86.mk b/webkit/common/webkit_common.target.linux-x86.mk
index a199c81..25c463a 100644
--- a/webkit/common/webkit_common.target.linux-x86.mk
+++ b/webkit/common/webkit_common.target.linux-x86.mk
@@ -94,6 +94,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
@@ -207,6 +208,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
diff --git a/webkit/glue/webkit_glue.gypi b/webkit/glue/webkit_glue.gypi
index 3400cea..adbd54d 100644
--- a/webkit/glue/webkit_glue.gypi
+++ b/webkit/glue/webkit_glue.gypi
@@ -31,7 +31,6 @@
         '<(DEPTH)/v8/tools/gyp/v8.gyp:v8',
         '<(DEPTH)/webkit/common/user_agent/webkit_user_agent.gyp:user_agent',
         '<(DEPTH)/webkit/common/webkit_common.gyp:webkit_common',
-        '<(DEPTH)/webkit/plugins/webkit_plugins.gyp:plugins_common',
       ],
 
       'include_dirs': [
@@ -123,6 +122,7 @@
         'WEBKIT_GLUE_IMPLEMENTATION',
       ],
       'dependencies': [
+        '<(DEPTH)/base/base.gyp:base',
         '<(DEPTH)/base/base.gyp:base_i18n',
         '<(DEPTH)/base/base.gyp:base_static',
         '<(DEPTH)/base/third_party/dynamic_annotations/dynamic_annotations.gyp:dynamic_annotations',
@@ -141,13 +141,11 @@
         '<(DEPTH)/v8/tools/gyp/v8.gyp:v8',
         '<(DEPTH)/webkit/common/user_agent/webkit_user_agent.gyp:user_agent',
         '<(DEPTH)/webkit/common/webkit_common.gyp:webkit_common',
-        '<(DEPTH)/webkit/plugins/webkit_plugins.gyp:plugins_common',
         '<(DEPTH)/webkit/renderer/compositor_bindings/compositor_bindings.gyp:webkit_compositor_support',
         '<(DEPTH)/webkit/storage_browser.gyp:webkit_storage_browser',
         '<(DEPTH)/webkit/storage_common.gyp:webkit_storage_common',
         '<(DEPTH)/webkit/webkit_resources.gyp:webkit_resources',
         '<(DEPTH)/webkit/webkit_resources.gyp:webkit_strings',
-        'plugins',
       ],
       'include_dirs': [
         '<(INTERMEDIATE_DIR)',
diff --git a/webkit/plugins/OWNERS b/webkit/plugins/OWNERS
deleted file mode 100644
index b47b3b2..0000000
--- a/webkit/plugins/OWNERS
+++ /dev/null
@@ -1 +0,0 @@
-jam@chromium.org
diff --git a/webkit/plugins/plugin_constants.cc b/webkit/plugins/plugin_constants.cc
deleted file mode 100644
index 52d5aa2..0000000
--- a/webkit/plugins/plugin_constants.cc
+++ /dev/null
@@ -1,17 +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/plugins/plugin_constants.h"
-
-const char kFlashPluginName[] = "Shockwave Flash";
-const char kFlashPluginSwfMimeType[] = "application/x-shockwave-flash";
-const char kFlashPluginSwfExtension[] = "swf";
-const char kFlashPluginSwfDescription[] = "Shockwave Flash";
-const char kFlashPluginSplMimeType[] = "application/futuresplash";
-const char kFlashPluginSplExtension[] = "spl";
-const char kFlashPluginSplDescription[] = "FutureSplash Player";
-
-const uint16 kMaxPluginSideLength = 1 << 15;
-// 8m pixels.
-const uint32 kMaxPluginSize = 8 << 20;
diff --git a/webkit/plugins/plugin_constants.h b/webkit/plugins/plugin_constants.h
deleted file mode 100644
index 6792fb3..0000000
--- a/webkit/plugins/plugin_constants.h
+++ /dev/null
@@ -1,24 +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_PLUGINS_PLUGIN_CONSTANTS_H_
-#define WEBKIT_PLUGINS_PLUGIN_CONSTANTS_H_
-
-#include "base/basictypes.h"
-
-extern const char kFlashPluginName[];
-extern const char kFlashPluginSwfMimeType[];
-extern const char kFlashPluginSwfExtension[];
-extern const char kFlashPluginSwfDescription[];
-extern const char kFlashPluginSplMimeType[];
-extern const char kFlashPluginSplExtension[];
-extern const char kFlashPluginSplDescription[];
-
-// The maximum plugin width and height.
-extern const uint16 kMaxPluginSideLength;
-// The maximum plugin size, defined as the number of pixels occupied by the
-// plugin.
-extern const uint32 kMaxPluginSize;
-
-#endif  // WEBKIT_PLUGINS_PLUGIN_CONSTANTS_H_
diff --git a/webkit/plugins/plugin_switches.cc b/webkit/plugins/plugin_switches.cc
deleted file mode 100644
index 563b844..0000000
--- a/webkit/plugins/plugin_switches.cc
+++ /dev/null
@@ -1,18 +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 "webkit/plugins/plugin_switches.h"
-
-namespace switches {
-
-// Dumps extra logging about plugin loading to the log file.
-const char kDebugPluginLoading[] = "debug-plugin-loading";
-
-// Disable Pepper3D.
-const char kDisablePepper3d[] = "disable-pepper-3d";
-
-// "Command-line" arguments for the PPAPI Flash; used for debugging options.
-const char kPpapiFlashArgs[] = "ppapi-flash-args";
-
-}  // namespace switches
diff --git a/webkit/plugins/plugin_switches.h b/webkit/plugins/plugin_switches.h
deleted file mode 100644
index 6ba76cd..0000000
--- a/webkit/plugins/plugin_switches.h
+++ /dev/null
@@ -1,18 +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 WEBKIT_PLUGINS_PLUGIN_SWITCHES_H_
-#define WEBKIT_PLUGINS_PLUGIN_SWITCHES_H_
-
-#include "build/build_config.h"
-
-namespace switches {
-
-extern const char kDebugPluginLoading[];
-extern const char kDisablePepper3d[];
-extern const char kPpapiFlashArgs[];
-
-}  // namespace switches
-
-#endif  // WEBKIT_PLUGINS_PLUGIN_SWITCHES_H_
diff --git a/webkit/plugins/plugins_common.target.darwin-arm.mk b/webkit/plugins/plugins_common.target.darwin-arm.mk
deleted file mode 100644
index 9b324e9..0000000
--- a/webkit/plugins/plugins_common.target.darwin-arm.mk
+++ /dev/null
@@ -1,276 +0,0 @@
-# This file is generated by gyp; do not edit.
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_CLASS := STATIC_LIBRARIES
-LOCAL_MODULE := webkit_plugins_plugins_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_ui_gyp)/ui_ui_gyp.a \
-	$(call intermediates-dir-for,GYP,ui_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 := \
-	webkit/plugins/plugin_constants.cc \
-	webkit/plugins/plugin_switches.cc \
-	webkit/common/plugins/ppapi/ppapi_utils.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-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-address \
-	-Wno-format-security \
-	-Wno-return-type \
-	-Wno-sequence-point \
-	-Os \
-	-g \
-	-fomit-frame-pointer \
-	-fdata-sections \
-	-ffunction-sections
-
-MY_DEFS_Debug := \
-	'-DANGLE_DX11' \
-	'-D_FILE_OFFSET_BITS=64' \
-	'-DNO_TCMALLOC' \
-	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
-	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
-	'-DDISABLE_NACL' \
-	'-DCHROMIUM_BUILD' \
-	'-DUSE_LIBJPEG_TURBO=1' \
-	'-DUSE_PROPRIETARY_CODECS' \
-	'-DENABLE_CONFIGURATION_POLICY' \
-	'-DENABLE_GPU=1' \
-	'-DUSE_OPENSSL=1' \
-	'-DENABLE_EGLIMAGE=1' \
-	'-DWEBKIT_PLUGINS_IMPLEMENTATION' \
-	'-DPOSIX_AVOID_MMAP' \
-	'-DU_USING_ICU_NAMESPACE=0' \
-	'-DANDROID' \
-	'-D__GNU_SOURCE=1' \
-	'-DUSE_STLPORT=1' \
-	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
-	'-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 \
-	$(LOCAL_PATH) \
-	$(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 \
-	-Wno-deprecated \
-	-Wno-abi \
-	-Wno-error=c++0x-compat \
-	-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-address \
-	-Wno-format-security \
-	-Wno-return-type \
-	-Wno-sequence-point \
-	-Os \
-	-fno-ident \
-	-fdata-sections \
-	-ffunction-sections \
-	-fomit-frame-pointer
-
-MY_DEFS_Release := \
-	'-DANGLE_DX11' \
-	'-D_FILE_OFFSET_BITS=64' \
-	'-DNO_TCMALLOC' \
-	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
-	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
-	'-DDISABLE_NACL' \
-	'-DCHROMIUM_BUILD' \
-	'-DUSE_LIBJPEG_TURBO=1' \
-	'-DUSE_PROPRIETARY_CODECS' \
-	'-DENABLE_CONFIGURATION_POLICY' \
-	'-DENABLE_GPU=1' \
-	'-DUSE_OPENSSL=1' \
-	'-DENABLE_EGLIMAGE=1' \
-	'-DWEBKIT_PLUGINS_IMPLEMENTATION' \
-	'-DPOSIX_AVOID_MMAP' \
-	'-DU_USING_ICU_NAMESPACE=0' \
-	'-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 \
-	$(gyp_intermediate_dir) \
-	$(gyp_shared_intermediate_dir)/ui \
-	$(LOCAL_PATH) \
-	$(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 \
-	-Wno-deprecated \
-	-Wno-abi \
-	-Wno-error=c++0x-compat \
-	-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))
-### Rules for final target.
-
-LOCAL_LDFLAGS_Debug := \
-	-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,-O1 \
-	-Wl,--as-needed
-
-
-LOCAL_LDFLAGS_Release := \
-	-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
-
-
-LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
-
-LOCAL_STATIC_LIBRARIES := \
-	ui_ui_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_plugins_plugins_common_gyp
-
-# Alias gyp target name.
-.PHONY: plugins_common
-plugins_common: webkit_plugins_plugins_common_gyp
-
-include $(BUILD_STATIC_LIBRARY)
diff --git a/webkit/plugins/plugins_common.target.darwin-mips.mk b/webkit/plugins/plugins_common.target.darwin-mips.mk
deleted file mode 100644
index aee20e4..0000000
--- a/webkit/plugins/plugins_common.target.darwin-mips.mk
+++ /dev/null
@@ -1,272 +0,0 @@
-# This file is generated by gyp; do not edit.
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_CLASS := STATIC_LIBRARIES
-LOCAL_MODULE := webkit_plugins_plugins_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_ui_gyp)/ui_ui_gyp.a \
-	$(call intermediates-dir-for,GYP,ui_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 := \
-	webkit/plugins/plugin_constants.cc \
-	webkit/plugins/plugin_switches.cc \
-	webkit/common/plugins/ppapi/ppapi_utils.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-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-address \
-	-Wno-format-security \
-	-Wno-return-type \
-	-Wno-sequence-point \
-	-Os \
-	-g \
-	-fomit-frame-pointer \
-	-fdata-sections \
-	-ffunction-sections
-
-MY_DEFS_Debug := \
-	'-DANGLE_DX11' \
-	'-D_FILE_OFFSET_BITS=64' \
-	'-DNO_TCMALLOC' \
-	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
-	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
-	'-DDISABLE_NACL' \
-	'-DCHROMIUM_BUILD' \
-	'-DUSE_LIBJPEG_TURBO=1' \
-	'-DUSE_PROPRIETARY_CODECS' \
-	'-DENABLE_CONFIGURATION_POLICY' \
-	'-DENABLE_GPU=1' \
-	'-DUSE_OPENSSL=1' \
-	'-DENABLE_EGLIMAGE=1' \
-	'-DWEBKIT_PLUGINS_IMPLEMENTATION' \
-	'-DPOSIX_AVOID_MMAP' \
-	'-DU_USING_ICU_NAMESPACE=0' \
-	'-DANDROID' \
-	'-D__GNU_SOURCE=1' \
-	'-DUSE_STLPORT=1' \
-	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
-	'-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 \
-	$(LOCAL_PATH) \
-	$(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 \
-	-Wno-deprecated \
-	-Wno-uninitialized \
-	-Wno-error=c++0x-compat \
-	-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-address \
-	-Wno-format-security \
-	-Wno-return-type \
-	-Wno-sequence-point \
-	-Os \
-	-fno-ident \
-	-fdata-sections \
-	-ffunction-sections \
-	-fomit-frame-pointer
-
-MY_DEFS_Release := \
-	'-DANGLE_DX11' \
-	'-D_FILE_OFFSET_BITS=64' \
-	'-DNO_TCMALLOC' \
-	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
-	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
-	'-DDISABLE_NACL' \
-	'-DCHROMIUM_BUILD' \
-	'-DUSE_LIBJPEG_TURBO=1' \
-	'-DUSE_PROPRIETARY_CODECS' \
-	'-DENABLE_CONFIGURATION_POLICY' \
-	'-DENABLE_GPU=1' \
-	'-DUSE_OPENSSL=1' \
-	'-DENABLE_EGLIMAGE=1' \
-	'-DWEBKIT_PLUGINS_IMPLEMENTATION' \
-	'-DPOSIX_AVOID_MMAP' \
-	'-DU_USING_ICU_NAMESPACE=0' \
-	'-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 \
-	$(gyp_intermediate_dir) \
-	$(gyp_shared_intermediate_dir)/ui \
-	$(LOCAL_PATH) \
-	$(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 \
-	-Wno-deprecated \
-	-Wno-uninitialized \
-	-Wno-error=c++0x-compat \
-	-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))
-### Rules for final target.
-
-LOCAL_LDFLAGS_Debug := \
-	-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,-O1 \
-	-Wl,--as-needed
-
-
-LOCAL_LDFLAGS_Release := \
-	-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
-
-
-LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
-
-LOCAL_STATIC_LIBRARIES := \
-	ui_ui_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_plugins_plugins_common_gyp
-
-# Alias gyp target name.
-.PHONY: plugins_common
-plugins_common: webkit_plugins_plugins_common_gyp
-
-include $(BUILD_STATIC_LIBRARY)
diff --git a/webkit/plugins/plugins_common.target.darwin-x86.mk b/webkit/plugins/plugins_common.target.darwin-x86.mk
deleted file mode 100644
index 580ac45..0000000
--- a/webkit/plugins/plugins_common.target.darwin-x86.mk
+++ /dev/null
@@ -1,274 +0,0 @@
-# This file is generated by gyp; do not edit.
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_CLASS := STATIC_LIBRARIES
-LOCAL_MODULE := webkit_plugins_plugins_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_ui_gyp)/ui_ui_gyp.a \
-	$(call intermediates-dir-for,GYP,ui_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 := \
-	webkit/plugins/plugin_constants.cc \
-	webkit/plugins/plugin_switches.cc \
-	webkit/common/plugins/ppapi/ppapi_utils.cc
-
-
-# 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 \
-	-m32 \
-	-mmmx \
-	-march=pentium4 \
-	-msse2 \
-	-mfpmath=sse \
-	-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-address \
-	-Wno-format-security \
-	-Wno-return-type \
-	-Wno-sequence-point \
-	-fno-stack-protector \
-	-Os \
-	-g \
-	-fomit-frame-pointer \
-	-fdata-sections \
-	-ffunction-sections
-
-MY_DEFS_Debug := \
-	'-DANGLE_DX11' \
-	'-D_FILE_OFFSET_BITS=64' \
-	'-DNO_TCMALLOC' \
-	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
-	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
-	'-DDISABLE_NACL' \
-	'-DCHROMIUM_BUILD' \
-	'-DUSE_LIBJPEG_TURBO=1' \
-	'-DUSE_PROPRIETARY_CODECS' \
-	'-DENABLE_CONFIGURATION_POLICY' \
-	'-DENABLE_GPU=1' \
-	'-DUSE_OPENSSL=1' \
-	'-DENABLE_EGLIMAGE=1' \
-	'-DWEBKIT_PLUGINS_IMPLEMENTATION' \
-	'-DU_USING_ICU_NAMESPACE=0' \
-	'-DANDROID' \
-	'-D__GNU_SOURCE=1' \
-	'-DUSE_STLPORT=1' \
-	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
-	'-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 \
-	$(LOCAL_PATH) \
-	$(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 \
-	-Wno-deprecated \
-	-Wno-error=c++0x-compat \
-	-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 \
-	-m32 \
-	-mmmx \
-	-march=pentium4 \
-	-msse2 \
-	-mfpmath=sse \
-	-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-address \
-	-Wno-format-security \
-	-Wno-return-type \
-	-Wno-sequence-point \
-	-fno-stack-protector \
-	-Os \
-	-fno-ident \
-	-fdata-sections \
-	-ffunction-sections \
-	-fomit-frame-pointer \
-	-fno-unwind-tables \
-	-fno-asynchronous-unwind-tables
-
-MY_DEFS_Release := \
-	'-DANGLE_DX11' \
-	'-D_FILE_OFFSET_BITS=64' \
-	'-DNO_TCMALLOC' \
-	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
-	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
-	'-DDISABLE_NACL' \
-	'-DCHROMIUM_BUILD' \
-	'-DUSE_LIBJPEG_TURBO=1' \
-	'-DUSE_PROPRIETARY_CODECS' \
-	'-DENABLE_CONFIGURATION_POLICY' \
-	'-DENABLE_GPU=1' \
-	'-DUSE_OPENSSL=1' \
-	'-DENABLE_EGLIMAGE=1' \
-	'-DWEBKIT_PLUGINS_IMPLEMENTATION' \
-	'-DU_USING_ICU_NAMESPACE=0' \
-	'-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 \
-	$(gyp_intermediate_dir) \
-	$(gyp_shared_intermediate_dir)/ui \
-	$(LOCAL_PATH) \
-	$(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 \
-	-Wno-deprecated \
-	-Wno-error=c++0x-compat \
-	-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))
-### Rules for final target.
-
-LOCAL_LDFLAGS_Debug := \
-	-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,-O1 \
-	-Wl,--as-needed
-
-
-LOCAL_LDFLAGS_Release := \
-	-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
-
-
-LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
-
-LOCAL_STATIC_LIBRARIES := \
-	ui_ui_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_plugins_plugins_common_gyp
-
-# Alias gyp target name.
-.PHONY: plugins_common
-plugins_common: webkit_plugins_plugins_common_gyp
-
-include $(BUILD_STATIC_LIBRARY)
diff --git a/webkit/plugins/plugins_common.target.linux-arm.mk b/webkit/plugins/plugins_common.target.linux-arm.mk
deleted file mode 100644
index 9b324e9..0000000
--- a/webkit/plugins/plugins_common.target.linux-arm.mk
+++ /dev/null
@@ -1,276 +0,0 @@
-# This file is generated by gyp; do not edit.
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_CLASS := STATIC_LIBRARIES
-LOCAL_MODULE := webkit_plugins_plugins_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_ui_gyp)/ui_ui_gyp.a \
-	$(call intermediates-dir-for,GYP,ui_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 := \
-	webkit/plugins/plugin_constants.cc \
-	webkit/plugins/plugin_switches.cc \
-	webkit/common/plugins/ppapi/ppapi_utils.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-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-address \
-	-Wno-format-security \
-	-Wno-return-type \
-	-Wno-sequence-point \
-	-Os \
-	-g \
-	-fomit-frame-pointer \
-	-fdata-sections \
-	-ffunction-sections
-
-MY_DEFS_Debug := \
-	'-DANGLE_DX11' \
-	'-D_FILE_OFFSET_BITS=64' \
-	'-DNO_TCMALLOC' \
-	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
-	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
-	'-DDISABLE_NACL' \
-	'-DCHROMIUM_BUILD' \
-	'-DUSE_LIBJPEG_TURBO=1' \
-	'-DUSE_PROPRIETARY_CODECS' \
-	'-DENABLE_CONFIGURATION_POLICY' \
-	'-DENABLE_GPU=1' \
-	'-DUSE_OPENSSL=1' \
-	'-DENABLE_EGLIMAGE=1' \
-	'-DWEBKIT_PLUGINS_IMPLEMENTATION' \
-	'-DPOSIX_AVOID_MMAP' \
-	'-DU_USING_ICU_NAMESPACE=0' \
-	'-DANDROID' \
-	'-D__GNU_SOURCE=1' \
-	'-DUSE_STLPORT=1' \
-	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
-	'-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 \
-	$(LOCAL_PATH) \
-	$(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 \
-	-Wno-deprecated \
-	-Wno-abi \
-	-Wno-error=c++0x-compat \
-	-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-address \
-	-Wno-format-security \
-	-Wno-return-type \
-	-Wno-sequence-point \
-	-Os \
-	-fno-ident \
-	-fdata-sections \
-	-ffunction-sections \
-	-fomit-frame-pointer
-
-MY_DEFS_Release := \
-	'-DANGLE_DX11' \
-	'-D_FILE_OFFSET_BITS=64' \
-	'-DNO_TCMALLOC' \
-	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
-	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
-	'-DDISABLE_NACL' \
-	'-DCHROMIUM_BUILD' \
-	'-DUSE_LIBJPEG_TURBO=1' \
-	'-DUSE_PROPRIETARY_CODECS' \
-	'-DENABLE_CONFIGURATION_POLICY' \
-	'-DENABLE_GPU=1' \
-	'-DUSE_OPENSSL=1' \
-	'-DENABLE_EGLIMAGE=1' \
-	'-DWEBKIT_PLUGINS_IMPLEMENTATION' \
-	'-DPOSIX_AVOID_MMAP' \
-	'-DU_USING_ICU_NAMESPACE=0' \
-	'-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 \
-	$(gyp_intermediate_dir) \
-	$(gyp_shared_intermediate_dir)/ui \
-	$(LOCAL_PATH) \
-	$(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 \
-	-Wno-deprecated \
-	-Wno-abi \
-	-Wno-error=c++0x-compat \
-	-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))
-### Rules for final target.
-
-LOCAL_LDFLAGS_Debug := \
-	-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,-O1 \
-	-Wl,--as-needed
-
-
-LOCAL_LDFLAGS_Release := \
-	-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
-
-
-LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
-
-LOCAL_STATIC_LIBRARIES := \
-	ui_ui_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_plugins_plugins_common_gyp
-
-# Alias gyp target name.
-.PHONY: plugins_common
-plugins_common: webkit_plugins_plugins_common_gyp
-
-include $(BUILD_STATIC_LIBRARY)
diff --git a/webkit/plugins/plugins_common.target.linux-mips.mk b/webkit/plugins/plugins_common.target.linux-mips.mk
deleted file mode 100644
index aee20e4..0000000
--- a/webkit/plugins/plugins_common.target.linux-mips.mk
+++ /dev/null
@@ -1,272 +0,0 @@
-# This file is generated by gyp; do not edit.
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_CLASS := STATIC_LIBRARIES
-LOCAL_MODULE := webkit_plugins_plugins_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_ui_gyp)/ui_ui_gyp.a \
-	$(call intermediates-dir-for,GYP,ui_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 := \
-	webkit/plugins/plugin_constants.cc \
-	webkit/plugins/plugin_switches.cc \
-	webkit/common/plugins/ppapi/ppapi_utils.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-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-address \
-	-Wno-format-security \
-	-Wno-return-type \
-	-Wno-sequence-point \
-	-Os \
-	-g \
-	-fomit-frame-pointer \
-	-fdata-sections \
-	-ffunction-sections
-
-MY_DEFS_Debug := \
-	'-DANGLE_DX11' \
-	'-D_FILE_OFFSET_BITS=64' \
-	'-DNO_TCMALLOC' \
-	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
-	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
-	'-DDISABLE_NACL' \
-	'-DCHROMIUM_BUILD' \
-	'-DUSE_LIBJPEG_TURBO=1' \
-	'-DUSE_PROPRIETARY_CODECS' \
-	'-DENABLE_CONFIGURATION_POLICY' \
-	'-DENABLE_GPU=1' \
-	'-DUSE_OPENSSL=1' \
-	'-DENABLE_EGLIMAGE=1' \
-	'-DWEBKIT_PLUGINS_IMPLEMENTATION' \
-	'-DPOSIX_AVOID_MMAP' \
-	'-DU_USING_ICU_NAMESPACE=0' \
-	'-DANDROID' \
-	'-D__GNU_SOURCE=1' \
-	'-DUSE_STLPORT=1' \
-	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
-	'-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 \
-	$(LOCAL_PATH) \
-	$(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 \
-	-Wno-deprecated \
-	-Wno-uninitialized \
-	-Wno-error=c++0x-compat \
-	-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-address \
-	-Wno-format-security \
-	-Wno-return-type \
-	-Wno-sequence-point \
-	-Os \
-	-fno-ident \
-	-fdata-sections \
-	-ffunction-sections \
-	-fomit-frame-pointer
-
-MY_DEFS_Release := \
-	'-DANGLE_DX11' \
-	'-D_FILE_OFFSET_BITS=64' \
-	'-DNO_TCMALLOC' \
-	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
-	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
-	'-DDISABLE_NACL' \
-	'-DCHROMIUM_BUILD' \
-	'-DUSE_LIBJPEG_TURBO=1' \
-	'-DUSE_PROPRIETARY_CODECS' \
-	'-DENABLE_CONFIGURATION_POLICY' \
-	'-DENABLE_GPU=1' \
-	'-DUSE_OPENSSL=1' \
-	'-DENABLE_EGLIMAGE=1' \
-	'-DWEBKIT_PLUGINS_IMPLEMENTATION' \
-	'-DPOSIX_AVOID_MMAP' \
-	'-DU_USING_ICU_NAMESPACE=0' \
-	'-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 \
-	$(gyp_intermediate_dir) \
-	$(gyp_shared_intermediate_dir)/ui \
-	$(LOCAL_PATH) \
-	$(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 \
-	-Wno-deprecated \
-	-Wno-uninitialized \
-	-Wno-error=c++0x-compat \
-	-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))
-### Rules for final target.
-
-LOCAL_LDFLAGS_Debug := \
-	-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,-O1 \
-	-Wl,--as-needed
-
-
-LOCAL_LDFLAGS_Release := \
-	-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
-
-
-LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
-
-LOCAL_STATIC_LIBRARIES := \
-	ui_ui_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_plugins_plugins_common_gyp
-
-# Alias gyp target name.
-.PHONY: plugins_common
-plugins_common: webkit_plugins_plugins_common_gyp
-
-include $(BUILD_STATIC_LIBRARY)
diff --git a/webkit/plugins/plugins_common.target.linux-x86.mk b/webkit/plugins/plugins_common.target.linux-x86.mk
deleted file mode 100644
index 580ac45..0000000
--- a/webkit/plugins/plugins_common.target.linux-x86.mk
+++ /dev/null
@@ -1,274 +0,0 @@
-# This file is generated by gyp; do not edit.
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_CLASS := STATIC_LIBRARIES
-LOCAL_MODULE := webkit_plugins_plugins_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_ui_gyp)/ui_ui_gyp.a \
-	$(call intermediates-dir-for,GYP,ui_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 := \
-	webkit/plugins/plugin_constants.cc \
-	webkit/plugins/plugin_switches.cc \
-	webkit/common/plugins/ppapi/ppapi_utils.cc
-
-
-# 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 \
-	-m32 \
-	-mmmx \
-	-march=pentium4 \
-	-msse2 \
-	-mfpmath=sse \
-	-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-address \
-	-Wno-format-security \
-	-Wno-return-type \
-	-Wno-sequence-point \
-	-fno-stack-protector \
-	-Os \
-	-g \
-	-fomit-frame-pointer \
-	-fdata-sections \
-	-ffunction-sections
-
-MY_DEFS_Debug := \
-	'-DANGLE_DX11' \
-	'-D_FILE_OFFSET_BITS=64' \
-	'-DNO_TCMALLOC' \
-	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
-	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
-	'-DDISABLE_NACL' \
-	'-DCHROMIUM_BUILD' \
-	'-DUSE_LIBJPEG_TURBO=1' \
-	'-DUSE_PROPRIETARY_CODECS' \
-	'-DENABLE_CONFIGURATION_POLICY' \
-	'-DENABLE_GPU=1' \
-	'-DUSE_OPENSSL=1' \
-	'-DENABLE_EGLIMAGE=1' \
-	'-DWEBKIT_PLUGINS_IMPLEMENTATION' \
-	'-DU_USING_ICU_NAMESPACE=0' \
-	'-DANDROID' \
-	'-D__GNU_SOURCE=1' \
-	'-DUSE_STLPORT=1' \
-	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
-	'-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 \
-	$(LOCAL_PATH) \
-	$(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 \
-	-Wno-deprecated \
-	-Wno-error=c++0x-compat \
-	-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 \
-	-m32 \
-	-mmmx \
-	-march=pentium4 \
-	-msse2 \
-	-mfpmath=sse \
-	-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-address \
-	-Wno-format-security \
-	-Wno-return-type \
-	-Wno-sequence-point \
-	-fno-stack-protector \
-	-Os \
-	-fno-ident \
-	-fdata-sections \
-	-ffunction-sections \
-	-fomit-frame-pointer \
-	-fno-unwind-tables \
-	-fno-asynchronous-unwind-tables
-
-MY_DEFS_Release := \
-	'-DANGLE_DX11' \
-	'-D_FILE_OFFSET_BITS=64' \
-	'-DNO_TCMALLOC' \
-	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
-	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
-	'-DDISABLE_NACL' \
-	'-DCHROMIUM_BUILD' \
-	'-DUSE_LIBJPEG_TURBO=1' \
-	'-DUSE_PROPRIETARY_CODECS' \
-	'-DENABLE_CONFIGURATION_POLICY' \
-	'-DENABLE_GPU=1' \
-	'-DUSE_OPENSSL=1' \
-	'-DENABLE_EGLIMAGE=1' \
-	'-DWEBKIT_PLUGINS_IMPLEMENTATION' \
-	'-DU_USING_ICU_NAMESPACE=0' \
-	'-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 \
-	$(gyp_intermediate_dir) \
-	$(gyp_shared_intermediate_dir)/ui \
-	$(LOCAL_PATH) \
-	$(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 \
-	-Wno-deprecated \
-	-Wno-error=c++0x-compat \
-	-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))
-### Rules for final target.
-
-LOCAL_LDFLAGS_Debug := \
-	-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,-O1 \
-	-Wl,--as-needed
-
-
-LOCAL_LDFLAGS_Release := \
-	-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
-
-
-LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
-
-LOCAL_STATIC_LIBRARIES := \
-	ui_ui_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_plugins_plugins_common_gyp
-
-# Alias gyp target name.
-.PHONY: plugins_common
-plugins_common: webkit_plugins_plugins_common_gyp
-
-include $(BUILD_STATIC_LIBRARY)
diff --git a/webkit/plugins/sad_plugin.h b/webkit/plugins/sad_plugin.h
deleted file mode 100644
index d4ae546..0000000
--- a/webkit/plugins/sad_plugin.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 WEBKIT_PLUGINS_SAD_PLUGIN_H_
-#define WEBKIT_PLUGINS_SAD_PLUGIN_H_
-
-#include "third_party/WebKit/public/platform/WebCanvas.h"
-#include "webkit/plugins/webkit_plugins_export.h"
-
-class SkBitmap;
-
-namespace gfx {
-class Rect;
-}
-
-namespace webkit {
-
-// Paints the sad plugin to the given canvas for the given plugin bounds. This
-// is used by both the NPAPI and the PPAPI out-of-process plugin impls.
-WEBKIT_PLUGINS_EXPORT void PaintSadPlugin(WebKit::WebCanvas* canvas,
-                                          const gfx::Rect& plugin_rect,
-                                          const SkBitmap& sad_plugin_bitmap);
-
-}  // namespace
-
-#endif  // WEBKIT_PLUGINS_SAD_PLUGIN_H_
diff --git a/webkit/plugins/webkit_plugins.gyp b/webkit/plugins/webkit_plugins.gyp
deleted file mode 100644
index 18fb10d..0000000
--- a/webkit/plugins/webkit_plugins.gyp
+++ /dev/null
@@ -1,55 +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.
-
-{
-  'targets': [
-    {
-      'target_name': 'plugins_common',
-      'type': 'static_library',
-      'defines': [
-        'WEBKIT_PLUGINS_IMPLEMENTATION',
-      ],
-      'include_dirs': [
-        '<(INTERMEDIATE_DIR)',
-        '<(SHARED_INTERMEDIATE_DIR)/ui',
-      ],
-      'dependencies': [
-        '<(DEPTH)/base/base.gyp:base_i18n',
-        '<(DEPTH)/base/base.gyp:base',
-        '<(DEPTH)/base/base.gyp:base_static',
-        '<(DEPTH)/base/third_party/dynamic_annotations/dynamic_annotations.gyp:dynamic_annotations',
-        '<(DEPTH)/net/net.gyp:net',
-        '<(DEPTH)/ui/ui.gyp:ui',
-        '<(DEPTH)/ui/ui.gyp:ui_resources',
-      ],
-      'sources': [
-        '../plugins/plugin_constants.cc',
-        '../plugins/plugin_constants.h',
-        '../plugins/plugin_switches.cc',
-        '../plugins/plugin_switches.h',
-        '../common/plugins/ppapi/ppapi_utils.cc',
-        '../common/plugins/ppapi/ppapi_utils.h',
-      ],
-      'conditions': [
-        ['toolkit_uses_gtk == 1', {
-          'dependencies': [
-            '<(DEPTH)/build/linux/system.gyp:gtk',
-          ],
-          'sources/': [['exclude', '_x11\\.cc$']],
-        }],
-        ['OS!="win"', {
-          'sources/': [['exclude', '_win\\.cc$']],
-        }, {  # else: OS=="win"
-          # TODO(jschuh): crbug.com/167187 fix size_t to int truncations.
-          'msvs_disabled_warnings': [ 4800, 4267 ],
-          'sources/': [['exclude', '_posix\\.cc$']],
-          'include_dirs': [
-            '<(DEPTH)/third_party/wtl/include',
-          ],
-        }],
-      ],
-    },
-  ],
-}
-
diff --git a/webkit/plugins/webkit_plugins.gypi b/webkit/plugins/webkit_plugins.gypi
deleted file mode 100644
index 8cc2648..0000000
--- a/webkit/plugins/webkit_plugins.gypi
+++ /dev/null
@@ -1,55 +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.
-
-{
-  'targets': [
-    {
-      'target_name': 'plugins',
-      'type': '<(component)',
-      'defines': [
-        'WEBKIT_PLUGINS_IMPLEMENTATION',
-      ],
-      'include_dirs': [
-        '<(INTERMEDIATE_DIR)',
-        '<(SHARED_INTERMEDIATE_DIR)/webkit',
-        '<(SHARED_INTERMEDIATE_DIR)/ui',
-      ],
-      'dependencies': [
-        '<(DEPTH)/base/base.gyp:base',
-        '<(DEPTH)/base/base.gyp:base_i18n',
-        '<(DEPTH)/base/third_party/dynamic_annotations/dynamic_annotations.gyp:dynamic_annotations',
-        '<(DEPTH)/gpu/gpu.gyp:command_buffer_common',
-        '<(DEPTH)/gpu/gpu.gyp:gles2_c_lib',
-        '<(DEPTH)/gpu/gpu.gyp:gles2_implementation',
-        '<(DEPTH)/media/media.gyp:media',
-        '<(DEPTH)/media/media.gyp:shared_memory_support',
-        '<(DEPTH)/net/net.gyp:net',
-        '<(DEPTH)/ppapi/ppapi.gyp:ppapi_c',
-        '<(DEPTH)/ppapi/ppapi_internal.gyp:ppapi_shared',
-        '<(DEPTH)/printing/printing.gyp:printing',
-        '<(DEPTH)/skia/skia.gyp:skia',
-        '<(DEPTH)/third_party/WebKit/public/blink.gyp:blink',
-        '<(DEPTH)/ui/gl/gl.gyp:gl',
-        '<(DEPTH)/ui/ui.gyp:ui',
-        '<(DEPTH)/ui/ui.gyp:ui_resources',
-        '<(DEPTH)/url/url.gyp:url_lib',
-        '<(DEPTH)/v8/tools/gyp/v8.gyp:v8',
-        '<(DEPTH)/webkit/common/user_agent/webkit_user_agent.gyp:user_agent',
-        '<(DEPTH)/webkit/common/webkit_common.gyp:webkit_common',
-        '<(DEPTH)/webkit/plugins/webkit_plugins.gyp:plugins_common',
-        '<(DEPTH)/webkit/renderer/compositor_bindings/compositor_bindings.gyp:webkit_compositor_support',
-        '<(DEPTH)/webkit/storage_common.gyp:webkit_storage_common',
-        'glue_child',
-      ],
-      'sources': [
-        # This list contains all .h, .cc, and .mm files in glue except for
-        # those in the test subdirectory and those with unittest in in their
-        # names.
-        '../plugins/sad_plugin.cc',
-        '../plugins/sad_plugin.h',
-        '../plugins/webkit_plugins_export.h',
-      ],
-    },
-  ]
-}
diff --git a/webkit/plugins/webkit_plugins_export.h b/webkit/plugins/webkit_plugins_export.h
deleted file mode 100644
index 387d5e4..0000000
--- a/webkit/plugins/webkit_plugins_export.h
+++ /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.
-
-#ifndef WEBKIT_PLUGINS_WEBKIT_PLUGINS_EXPORT_H_
-#define WEBKIT_PLUGINS_WEBKIT_PLUGINS_EXPORT_H_
-
-#if defined(COMPONENT_BUILD)
-#if defined(WIN32)
-
-#if defined(WEBKIT_PLUGINS_IMPLEMENTATION)
-#define WEBKIT_PLUGINS_EXPORT __declspec(dllexport)
-#else
-#define WEBKIT_PLUGINS_EXPORT __declspec(dllimport)
-#endif  // defined(WEBKIT_PLUGINS_IMPLEMENTATION)
-
-#else // defined(WIN32)
-#if defined(WEBKIT_PLUGINS_IMPLEMENTATION)
-#define WEBKIT_PLUGINS_EXPORT __attribute__((visibility("default")))
-#else
-#define WEBKIT_PLUGINS_EXPORT
-#endif
-#endif
-
-#else // defined(COMPONENT_BUILD)
-#define WEBKIT_PLUGINS_EXPORT
-#endif
-
-#endif  // WEBKIT_PLUGINS_WEBKIT_PLUGINS_EXPORT_H_
diff --git a/webkit/renderer/appcache/appcache_frontend_impl.h b/webkit/renderer/appcache/appcache_frontend_impl.h
deleted file mode 100644
index 42ba745..0000000
--- a/webkit/renderer/appcache/appcache_frontend_impl.h
+++ /dev/null
@@ -1,37 +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 WEBKIT_RENDERER_APPCACHE_APPCACHE_FRONTEND_IMPL_H_
-#define WEBKIT_RENDERER_APPCACHE_APPCACHE_FRONTEND_IMPL_H_
-
-#include <string>
-#include <vector>
-
-#include "webkit/common/appcache/appcache_interfaces.h"
-#include "webkit/renderer/webkit_storage_renderer_export.h"
-
-namespace appcache {
-
-class WEBKIT_STORAGE_RENDERER_EXPORT AppCacheFrontendImpl
-    : public AppCacheFrontend {
- public:
-  virtual void OnCacheSelected(
-      int host_id, const appcache::AppCacheInfo& info) OVERRIDE;
-  virtual void OnStatusChanged(const std::vector<int>& host_ids,
-                               Status status) OVERRIDE;
-  virtual void OnEventRaised(const std::vector<int>& host_ids,
-                             EventID event_id) OVERRIDE;
-  virtual void OnProgressEventRaised(const std::vector<int>& host_ids,
-                                     const GURL& url,
-                                     int num_total, int num_complete) OVERRIDE;
-  virtual void OnErrorEventRaised(const std::vector<int>& host_ids,
-                                  const std::string& message) OVERRIDE;
-  virtual void OnLogMessage(int host_id, LogLevel log_level,
-                            const std::string& message) OVERRIDE;
-  virtual void OnContentBlocked(int host_id, const GURL& manifest_url) OVERRIDE;
-};
-
-}  // namespace
-
-#endif  // WEBKIT_RENDERER_APPCACHE_APPCACHE_FRONTEND_IMPL_H_
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 c4663a0..f9398e9 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
@@ -102,6 +102,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DPOSIX_AVOID_MMAP' \
 	'-D__STDC_CONSTANT_MACROS' \
@@ -216,6 +217,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DPOSIX_AVOID_MMAP' \
 	'-D__STDC_CONSTANT_MACROS' \
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 2d5eb70..9362b4c 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
@@ -101,6 +101,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DPOSIX_AVOID_MMAP' \
 	'-D__STDC_CONSTANT_MACROS' \
@@ -214,6 +215,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DPOSIX_AVOID_MMAP' \
 	'-D__STDC_CONSTANT_MACROS' \
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 9fe67e9..3ffef57 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
@@ -104,6 +104,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
@@ -220,6 +221,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
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 c4663a0..f9398e9 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
@@ -102,6 +102,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DPOSIX_AVOID_MMAP' \
 	'-D__STDC_CONSTANT_MACROS' \
@@ -216,6 +217,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DPOSIX_AVOID_MMAP' \
 	'-D__STDC_CONSTANT_MACROS' \
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 2d5eb70..9362b4c 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
@@ -101,6 +101,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DPOSIX_AVOID_MMAP' \
 	'-D__STDC_CONSTANT_MACROS' \
@@ -214,6 +215,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DPOSIX_AVOID_MMAP' \
 	'-D__STDC_CONSTANT_MACROS' \
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 9fe67e9..3ffef57 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
@@ -104,6 +104,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
@@ -220,6 +221,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
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 b031ec9..07c01dd 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
@@ -81,6 +81,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -187,6 +188,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=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 1dfda10..35d8f22 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
@@ -80,6 +80,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -185,6 +186,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=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 3515dbb..068afeb 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
@@ -83,6 +83,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -192,6 +193,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
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 b031ec9..07c01dd 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
@@ -81,6 +81,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -187,6 +188,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=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 1dfda10..35d8f22 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
@@ -80,6 +80,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -185,6 +186,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=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 3515dbb..068afeb 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
@@ -83,6 +83,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -192,6 +193,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/webkit/renderer/media/DEPS b/webkit/renderer/media/DEPS
deleted file mode 100644
index c3a5b96..0000000
--- a/webkit/renderer/media/DEPS
+++ /dev/null
@@ -1,3 +0,0 @@
-include_rules = [
-  "+media",
-]
diff --git a/webkit/renderer/media/OWNERS b/webkit/renderer/media/OWNERS
deleted file mode 100644
index 679494d..0000000
--- a/webkit/renderer/media/OWNERS
+++ /dev/null
@@ -1,9 +0,0 @@
-acolwell@chromium.org
-dalecurtis@chromium.org
-ddorwin@chromium.org
-fischman@chromium.org
-scherkus@chromium.org
-shadi@chromium.org
-vrk@chromium.org
-xhwang@chromium.org
-wjia@chromium.org
diff --git a/webkit/renderer/media/crypto/ppapi/DEPS b/webkit/renderer/media/crypto/ppapi/DEPS
deleted file mode 100644
index 00317f1..0000000
--- a/webkit/renderer/media/crypto/ppapi/DEPS
+++ /dev/null
@@ -1,4 +0,0 @@
-include_rules = [
-  "+ppapi",
-  "+third_party/libvpx",
-]
diff --git a/webkit/renderer/webkit_renderer.target.darwin-arm.mk b/webkit/renderer/webkit_renderer.target.darwin-arm.mk
index 2f627be..6239808 100644
--- a/webkit/renderer/webkit_renderer.target.darwin-arm.mk
+++ b/webkit/renderer/webkit_renderer.target.darwin-arm.mk
@@ -92,6 +92,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
@@ -207,6 +208,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
diff --git a/webkit/renderer/webkit_renderer.target.darwin-mips.mk b/webkit/renderer/webkit_renderer.target.darwin-mips.mk
index edae01d..cb0a2f7 100644
--- a/webkit/renderer/webkit_renderer.target.darwin-mips.mk
+++ b/webkit/renderer/webkit_renderer.target.darwin-mips.mk
@@ -92,6 +92,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
@@ -207,6 +208,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
diff --git a/webkit/renderer/webkit_renderer.target.darwin-x86.mk b/webkit/renderer/webkit_renderer.target.darwin-x86.mk
index 0b06f75..f07b99d 100644
--- a/webkit/renderer/webkit_renderer.target.darwin-x86.mk
+++ b/webkit/renderer/webkit_renderer.target.darwin-x86.mk
@@ -93,6 +93,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
@@ -210,6 +211,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
diff --git a/webkit/renderer/webkit_renderer.target.linux-arm.mk b/webkit/renderer/webkit_renderer.target.linux-arm.mk
index 2f627be..6239808 100644
--- a/webkit/renderer/webkit_renderer.target.linux-arm.mk
+++ b/webkit/renderer/webkit_renderer.target.linux-arm.mk
@@ -92,6 +92,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
@@ -207,6 +208,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
diff --git a/webkit/renderer/webkit_renderer.target.linux-mips.mk b/webkit/renderer/webkit_renderer.target.linux-mips.mk
index edae01d..cb0a2f7 100644
--- a/webkit/renderer/webkit_renderer.target.linux-mips.mk
+++ b/webkit/renderer/webkit_renderer.target.linux-mips.mk
@@ -92,6 +92,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
@@ -207,6 +208,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
diff --git a/webkit/renderer/webkit_renderer.target.linux-x86.mk b/webkit/renderer/webkit_renderer.target.linux-x86.mk
index 0b06f75..f07b99d 100644
--- a/webkit/renderer/webkit_renderer.target.linux-x86.mk
+++ b/webkit/renderer/webkit_renderer.target.linux-x86.mk
@@ -93,6 +93,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
@@ -210,6 +211,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
diff --git a/webkit/storage_renderer.gyp b/webkit/storage_renderer.gyp
index b2a17aa..dc406e2 100644
--- a/webkit/storage_renderer.gyp
+++ b/webkit/storage_renderer.gyp
@@ -19,10 +19,6 @@
       'defines': ['WEBKIT_STORAGE_RENDERER_IMPLEMENTATION'],
       'sources': [
         'renderer/webkit_storage_renderer_export.h',
-        'renderer/appcache/appcache_frontend_impl.cc',
-        'renderer/appcache/appcache_frontend_impl.h',
-        'renderer/appcache/web_application_cache_host_impl.cc',
-        'renderer/appcache/web_application_cache_host_impl.h',
         'renderer/fileapi/webfilewriter_base.cc',
         'renderer/fileapi/webfilewriter_base.h',
       ],
diff --git a/webkit/support/glue.target.darwin-arm.mk b/webkit/support/glue.target.darwin-arm.mk
index e2f96a0..503fc46 100644
--- a/webkit/support/glue.target.darwin-arm.mk
+++ b/webkit/support/glue.target.darwin-arm.mk
@@ -102,6 +102,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-D__STDC_CONSTANT_MACROS' \
@@ -231,6 +232,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-D__STDC_CONSTANT_MACROS' \
diff --git a/webkit/support/glue.target.darwin-mips.mk b/webkit/support/glue.target.darwin-mips.mk
index 47c264d..af15923 100644
--- a/webkit/support/glue.target.darwin-mips.mk
+++ b/webkit/support/glue.target.darwin-mips.mk
@@ -101,6 +101,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-D__STDC_CONSTANT_MACROS' \
@@ -229,6 +230,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-D__STDC_CONSTANT_MACROS' \
diff --git a/webkit/support/glue.target.darwin-x86.mk b/webkit/support/glue.target.darwin-x86.mk
index 5cc61e1..ba3135c 100644
--- a/webkit/support/glue.target.darwin-x86.mk
+++ b/webkit/support/glue.target.darwin-x86.mk
@@ -103,6 +103,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-D__STDC_CONSTANT_MACROS' \
@@ -234,6 +235,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-D__STDC_CONSTANT_MACROS' \
diff --git a/webkit/support/glue.target.linux-arm.mk b/webkit/support/glue.target.linux-arm.mk
index e2f96a0..503fc46 100644
--- a/webkit/support/glue.target.linux-arm.mk
+++ b/webkit/support/glue.target.linux-arm.mk
@@ -102,6 +102,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-D__STDC_CONSTANT_MACROS' \
@@ -231,6 +232,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-D__STDC_CONSTANT_MACROS' \
diff --git a/webkit/support/glue.target.linux-mips.mk b/webkit/support/glue.target.linux-mips.mk
index 47c264d..af15923 100644
--- a/webkit/support/glue.target.linux-mips.mk
+++ b/webkit/support/glue.target.linux-mips.mk
@@ -101,6 +101,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-D__STDC_CONSTANT_MACROS' \
@@ -229,6 +230,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-D__STDC_CONSTANT_MACROS' \
diff --git a/webkit/support/glue.target.linux-x86.mk b/webkit/support/glue.target.linux-x86.mk
index 5cc61e1..ba3135c 100644
--- a/webkit/support/glue.target.linux-x86.mk
+++ b/webkit/support/glue.target.linux-x86.mk
@@ -103,6 +103,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-D__STDC_CONSTANT_MACROS' \
@@ -234,6 +235,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-D__STDC_CONSTANT_MACROS' \
diff --git a/webkit/support/glue_child.target.darwin-arm.mk b/webkit/support/glue_child.target.darwin-arm.mk
index 896b6b8..35dbc20 100644
--- a/webkit/support/glue_child.target.darwin-arm.mk
+++ b/webkit/support/glue_child.target.darwin-arm.mk
@@ -109,6 +109,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
@@ -230,6 +231,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
diff --git a/webkit/support/glue_child.target.darwin-mips.mk b/webkit/support/glue_child.target.darwin-mips.mk
index 7fdefb2..a0f2206 100644
--- a/webkit/support/glue_child.target.darwin-mips.mk
+++ b/webkit/support/glue_child.target.darwin-mips.mk
@@ -108,6 +108,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
@@ -228,6 +229,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
diff --git a/webkit/support/glue_child.target.darwin-x86.mk b/webkit/support/glue_child.target.darwin-x86.mk
index bd57c82..d836937 100644
--- a/webkit/support/glue_child.target.darwin-x86.mk
+++ b/webkit/support/glue_child.target.darwin-x86.mk
@@ -110,6 +110,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
@@ -233,6 +234,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
diff --git a/webkit/support/glue_child.target.linux-arm.mk b/webkit/support/glue_child.target.linux-arm.mk
index 896b6b8..35dbc20 100644
--- a/webkit/support/glue_child.target.linux-arm.mk
+++ b/webkit/support/glue_child.target.linux-arm.mk
@@ -109,6 +109,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
@@ -230,6 +231,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
diff --git a/webkit/support/glue_child.target.linux-mips.mk b/webkit/support/glue_child.target.linux-mips.mk
index 7fdefb2..a0f2206 100644
--- a/webkit/support/glue_child.target.linux-mips.mk
+++ b/webkit/support/glue_child.target.linux-mips.mk
@@ -108,6 +108,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
@@ -228,6 +229,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
diff --git a/webkit/support/glue_child.target.linux-x86.mk b/webkit/support/glue_child.target.linux-x86.mk
index bd57c82..d836937 100644
--- a/webkit/support/glue_child.target.linux-x86.mk
+++ b/webkit/support/glue_child.target.linux-x86.mk
@@ -110,6 +110,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
@@ -233,6 +234,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
diff --git a/webkit/support/plugins.target.darwin-arm.mk b/webkit/support/plugins.target.darwin-arm.mk
deleted file mode 100644
index a75476b..0000000
--- a/webkit/support/plugins.target.darwin-arm.mk
+++ /dev/null
@@ -1,359 +0,0 @@
-# This file is generated by gyp; do not edit.
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_CLASS := STATIC_LIBRARIES
-LOCAL_MODULE := webkit_support_plugins_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,ppapi_ppapi_c_gyp)/ppapi_c.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,STATIC_LIBRARIES,ui_gl_gl_gyp)/ui_gl_gl_gyp.a \
-	$(call intermediates-dir-for,STATIC_LIBRARIES,ui_ui_gyp)/ui_ui_gyp.a \
-	$(call intermediates-dir-for,GYP,ui_ui_resources_gyp)/ui_resources.stamp \
-	$(call intermediates-dir-for,GYP,v8_tools_gyp_v8_gyp)/v8.stamp \
-	$(call intermediates-dir-for,STATIC_LIBRARIES,webkit_support_glue_child_gyp)/webkit_support_glue_child_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/plugins/sad_plugin.cc
-
-
-# Flags passed to both C and C++ files.
-MY_CFLAGS_Debug := \
-	-Wno-narrowing \
-	-fstack-protector \
-	--param=ssp-buffer-size=4 \
-	-Werror \
-	-fno-exceptions \
-	-fno-strict-aliasing \
-	-Wall \
-	-Wno-unused-parameter \
-	-Wno-missing-field-initializers \
-	-fvisibility=hidden \
-	-pipe \
-	-fPIC \
-	-Wno-unknown-pragmas \
-	-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-address \
-	-Wno-format-security \
-	-Wno-return-type \
-	-Wno-sequence-point \
-	-Os \
-	-g \
-	-fomit-frame-pointer \
-	-fdata-sections \
-	-ffunction-sections
-
-MY_DEFS_Debug := \
-	'-DANGLE_DX11' \
-	'-D_FILE_OFFSET_BITS=64' \
-	'-DNO_TCMALLOC' \
-	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
-	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
-	'-DDISABLE_NACL' \
-	'-DCHROMIUM_BUILD' \
-	'-DUSE_LIBJPEG_TURBO=1' \
-	'-DUSE_PROPRIETARY_CODECS' \
-	'-DENABLE_CONFIGURATION_POLICY' \
-	'-DENABLE_GPU=1' \
-	'-DUSE_OPENSSL=1' \
-	'-DENABLE_EGLIMAGE=1' \
-	'-DWEBKIT_PLUGINS_IMPLEMENTATION' \
-	'-DMEDIA_DISABLE_LIBVPX' \
-	'-DPOSIX_AVOID_MMAP' \
-	'-DSK_ENABLE_INST_COUNT=0' \
-	'-DSK_SUPPORT_GPU=1' \
-	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
-	'-DSK_BUILD_FOR_ANDROID' \
-	'-DUSE_CHROMIUM_SKIA' \
-	'-DSK_USE_POSIX_THREADS' \
-	'-DU_USING_ICU_NAMESPACE=0' \
-	'-DMESA_EGL_NO_X11_HEADERS' \
-	'-D__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)/webkit \
-	$(gyp_shared_intermediate_dir)/ui \
-	$(LOCAL_PATH)/third_party/khronos \
-	$(LOCAL_PATH)/gpu \
-	$(LOCAL_PATH) \
-	$(LOCAL_PATH)/third_party/skia/src/core \
-	$(LOCAL_PATH)/skia/config \
-	$(LOCAL_PATH)/third_party/skia/include/config \
-	$(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/gpu/gl \
-	$(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 \
-	$(gyp_shared_intermediate_dir)/ui/gl \
-	$(LOCAL_PATH)/third_party/mesa/src/include \
-	$(gyp_shared_intermediate_dir)/ui/ui_resources \
-	$(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 := \
-	-Wno-narrowing \
-	-fno-rtti \
-	-fno-threadsafe-statics \
-	-fvisibility-inlines-hidden \
-	-Wsign-compare \
-	-Wno-abi \
-	-Wno-error=c++0x-compat \
-	-Wno-non-virtual-dtor \
-	-Wno-sign-promo \
-	-Wno-non-virtual-dtor
-
-
-# Flags passed to both C and C++ files.
-MY_CFLAGS_Release := \
-	-Wno-narrowing \
-	-fstack-protector \
-	--param=ssp-buffer-size=4 \
-	-Werror \
-	-fno-exceptions \
-	-fno-strict-aliasing \
-	-Wall \
-	-Wno-unused-parameter \
-	-Wno-missing-field-initializers \
-	-fvisibility=hidden \
-	-pipe \
-	-fPIC \
-	-Wno-unknown-pragmas \
-	-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-address \
-	-Wno-format-security \
-	-Wno-return-type \
-	-Wno-sequence-point \
-	-Os \
-	-fno-ident \
-	-fdata-sections \
-	-ffunction-sections \
-	-fomit-frame-pointer
-
-MY_DEFS_Release := \
-	'-DANGLE_DX11' \
-	'-D_FILE_OFFSET_BITS=64' \
-	'-DNO_TCMALLOC' \
-	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
-	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
-	'-DDISABLE_NACL' \
-	'-DCHROMIUM_BUILD' \
-	'-DUSE_LIBJPEG_TURBO=1' \
-	'-DUSE_PROPRIETARY_CODECS' \
-	'-DENABLE_CONFIGURATION_POLICY' \
-	'-DENABLE_GPU=1' \
-	'-DUSE_OPENSSL=1' \
-	'-DENABLE_EGLIMAGE=1' \
-	'-DWEBKIT_PLUGINS_IMPLEMENTATION' \
-	'-DMEDIA_DISABLE_LIBVPX' \
-	'-DPOSIX_AVOID_MMAP' \
-	'-DSK_ENABLE_INST_COUNT=0' \
-	'-DSK_SUPPORT_GPU=1' \
-	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
-	'-DSK_BUILD_FOR_ANDROID' \
-	'-DUSE_CHROMIUM_SKIA' \
-	'-DSK_USE_POSIX_THREADS' \
-	'-DU_USING_ICU_NAMESPACE=0' \
-	'-DMESA_EGL_NO_X11_HEADERS' \
-	'-D__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)/webkit \
-	$(gyp_shared_intermediate_dir)/ui \
-	$(LOCAL_PATH)/third_party/khronos \
-	$(LOCAL_PATH)/gpu \
-	$(LOCAL_PATH) \
-	$(LOCAL_PATH)/third_party/skia/src/core \
-	$(LOCAL_PATH)/skia/config \
-	$(LOCAL_PATH)/third_party/skia/include/config \
-	$(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/gpu/gl \
-	$(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 \
-	$(gyp_shared_intermediate_dir)/ui/gl \
-	$(LOCAL_PATH)/third_party/mesa/src/include \
-	$(gyp_shared_intermediate_dir)/ui/ui_resources \
-	$(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 := \
-	-Wno-narrowing \
-	-fno-rtti \
-	-fno-threadsafe-statics \
-	-fvisibility-inlines-hidden \
-	-Wsign-compare \
-	-Wno-abi \
-	-Wno-error=c++0x-compat \
-	-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))
-### Rules for final target.
-
-LOCAL_LDFLAGS_Debug := \
-	-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,-O1 \
-	-Wl,--as-needed
-
-
-LOCAL_LDFLAGS_Release := \
-	-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
-
-
-LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
-
-LOCAL_STATIC_LIBRARIES := \
-	skia_skia_library_gyp \
-	ui_gl_gl_gyp \
-	ui_ui_gyp \
-	webkit_support_glue_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: webkit_support_plugins_gyp
-
-# Alias gyp target name.
-.PHONY: plugins
-plugins: webkit_support_plugins_gyp
-
-include $(BUILD_STATIC_LIBRARY)
diff --git a/webkit/support/plugins.target.darwin-mips.mk b/webkit/support/plugins.target.darwin-mips.mk
deleted file mode 100644
index 7761ce3..0000000
--- a/webkit/support/plugins.target.darwin-mips.mk
+++ /dev/null
@@ -1,353 +0,0 @@
-# This file is generated by gyp; do not edit.
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_CLASS := STATIC_LIBRARIES
-LOCAL_MODULE := webkit_support_plugins_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,ppapi_ppapi_c_gyp)/ppapi_c.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,STATIC_LIBRARIES,ui_gl_gl_gyp)/ui_gl_gl_gyp.a \
-	$(call intermediates-dir-for,STATIC_LIBRARIES,ui_ui_gyp)/ui_ui_gyp.a \
-	$(call intermediates-dir-for,GYP,ui_ui_resources_gyp)/ui_resources.stamp \
-	$(call intermediates-dir-for,GYP,v8_tools_gyp_v8_gyp)/v8.stamp \
-	$(call intermediates-dir-for,STATIC_LIBRARIES,webkit_support_glue_child_gyp)/webkit_support_glue_child_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/plugins/sad_plugin.cc
-
-
-# Flags passed to both C and C++ files.
-MY_CFLAGS_Debug := \
-	-Wno-narrowing \
-	-fstack-protector \
-	--param=ssp-buffer-size=4 \
-	 \
-	-fno-exceptions \
-	-fno-strict-aliasing \
-	-Wall \
-	-Wno-unused-parameter \
-	-Wno-missing-field-initializers \
-	-fvisibility=hidden \
-	-pipe \
-	-fPIC \
-	-Wno-unknown-pragmas \
-	-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-address \
-	-Wno-format-security \
-	-Wno-return-type \
-	-Wno-sequence-point \
-	-Os \
-	-g \
-	-fomit-frame-pointer \
-	-fdata-sections \
-	-ffunction-sections
-
-MY_DEFS_Debug := \
-	'-DANGLE_DX11' \
-	'-D_FILE_OFFSET_BITS=64' \
-	'-DNO_TCMALLOC' \
-	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
-	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
-	'-DDISABLE_NACL' \
-	'-DCHROMIUM_BUILD' \
-	'-DUSE_LIBJPEG_TURBO=1' \
-	'-DUSE_PROPRIETARY_CODECS' \
-	'-DENABLE_CONFIGURATION_POLICY' \
-	'-DENABLE_GPU=1' \
-	'-DUSE_OPENSSL=1' \
-	'-DENABLE_EGLIMAGE=1' \
-	'-DWEBKIT_PLUGINS_IMPLEMENTATION' \
-	'-DMEDIA_DISABLE_LIBVPX' \
-	'-DPOSIX_AVOID_MMAP' \
-	'-DSK_ENABLE_INST_COUNT=0' \
-	'-DSK_SUPPORT_GPU=1' \
-	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
-	'-DSK_BUILD_FOR_ANDROID' \
-	'-DUSE_CHROMIUM_SKIA' \
-	'-DSK_USE_POSIX_THREADS' \
-	'-DU_USING_ICU_NAMESPACE=0' \
-	'-DMESA_EGL_NO_X11_HEADERS' \
-	'-D__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)/webkit \
-	$(gyp_shared_intermediate_dir)/ui \
-	$(LOCAL_PATH)/third_party/khronos \
-	$(LOCAL_PATH)/gpu \
-	$(LOCAL_PATH) \
-	$(LOCAL_PATH)/third_party/skia/src/core \
-	$(LOCAL_PATH)/skia/config \
-	$(LOCAL_PATH)/third_party/skia/include/config \
-	$(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/gpu/gl \
-	$(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 \
-	$(gyp_shared_intermediate_dir)/ui/gl \
-	$(LOCAL_PATH)/third_party/mesa/src/include \
-	$(gyp_shared_intermediate_dir)/ui/ui_resources \
-	$(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 := \
-	-Wno-narrowing \
-	-fno-rtti \
-	-fno-threadsafe-statics \
-	-fvisibility-inlines-hidden \
-	-Wsign-compare \
-	-Wno-uninitialized \
-	-Wno-error=c++0x-compat \
-	-Wno-non-virtual-dtor \
-	-Wno-sign-promo \
-	-Wno-non-virtual-dtor
-
-
-# Flags passed to both C and C++ files.
-MY_CFLAGS_Release := \
-	-Wno-narrowing \
-	-fstack-protector \
-	--param=ssp-buffer-size=4 \
-	 \
-	-fno-exceptions \
-	-fno-strict-aliasing \
-	-Wall \
-	-Wno-unused-parameter \
-	-Wno-missing-field-initializers \
-	-fvisibility=hidden \
-	-pipe \
-	-fPIC \
-	-Wno-unknown-pragmas \
-	-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-address \
-	-Wno-format-security \
-	-Wno-return-type \
-	-Wno-sequence-point \
-	-Os \
-	-fno-ident \
-	-fdata-sections \
-	-ffunction-sections \
-	-fomit-frame-pointer
-
-MY_DEFS_Release := \
-	'-DANGLE_DX11' \
-	'-D_FILE_OFFSET_BITS=64' \
-	'-DNO_TCMALLOC' \
-	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
-	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
-	'-DDISABLE_NACL' \
-	'-DCHROMIUM_BUILD' \
-	'-DUSE_LIBJPEG_TURBO=1' \
-	'-DUSE_PROPRIETARY_CODECS' \
-	'-DENABLE_CONFIGURATION_POLICY' \
-	'-DENABLE_GPU=1' \
-	'-DUSE_OPENSSL=1' \
-	'-DENABLE_EGLIMAGE=1' \
-	'-DWEBKIT_PLUGINS_IMPLEMENTATION' \
-	'-DMEDIA_DISABLE_LIBVPX' \
-	'-DPOSIX_AVOID_MMAP' \
-	'-DSK_ENABLE_INST_COUNT=0' \
-	'-DSK_SUPPORT_GPU=1' \
-	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
-	'-DSK_BUILD_FOR_ANDROID' \
-	'-DUSE_CHROMIUM_SKIA' \
-	'-DSK_USE_POSIX_THREADS' \
-	'-DU_USING_ICU_NAMESPACE=0' \
-	'-DMESA_EGL_NO_X11_HEADERS' \
-	'-D__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)/webkit \
-	$(gyp_shared_intermediate_dir)/ui \
-	$(LOCAL_PATH)/third_party/khronos \
-	$(LOCAL_PATH)/gpu \
-	$(LOCAL_PATH) \
-	$(LOCAL_PATH)/third_party/skia/src/core \
-	$(LOCAL_PATH)/skia/config \
-	$(LOCAL_PATH)/third_party/skia/include/config \
-	$(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/gpu/gl \
-	$(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 \
-	$(gyp_shared_intermediate_dir)/ui/gl \
-	$(LOCAL_PATH)/third_party/mesa/src/include \
-	$(gyp_shared_intermediate_dir)/ui/ui_resources \
-	$(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 := \
-	-Wno-narrowing \
-	-fno-rtti \
-	-fno-threadsafe-statics \
-	-fvisibility-inlines-hidden \
-	-Wsign-compare \
-	-Wno-uninitialized \
-	-Wno-error=c++0x-compat \
-	-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))
-### Rules for final target.
-
-LOCAL_LDFLAGS_Debug := \
-	-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,-O1 \
-	-Wl,--as-needed
-
-
-LOCAL_LDFLAGS_Release := \
-	-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
-
-
-LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
-
-LOCAL_STATIC_LIBRARIES := \
-	skia_skia_library_gyp \
-	ui_gl_gl_gyp \
-	ui_ui_gyp \
-	webkit_support_glue_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: webkit_support_plugins_gyp
-
-# Alias gyp target name.
-.PHONY: plugins
-plugins: webkit_support_plugins_gyp
-
-include $(BUILD_STATIC_LIBRARY)
diff --git a/webkit/support/plugins.target.darwin-x86.mk b/webkit/support/plugins.target.darwin-x86.mk
deleted file mode 100644
index 00061ee..0000000
--- a/webkit/support/plugins.target.darwin-x86.mk
+++ /dev/null
@@ -1,357 +0,0 @@
-# This file is generated by gyp; do not edit.
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_CLASS := STATIC_LIBRARIES
-LOCAL_MODULE := webkit_support_plugins_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,ppapi_ppapi_c_gyp)/ppapi_c.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,STATIC_LIBRARIES,ui_gl_gl_gyp)/ui_gl_gl_gyp.a \
-	$(call intermediates-dir-for,STATIC_LIBRARIES,ui_ui_gyp)/ui_ui_gyp.a \
-	$(call intermediates-dir-for,GYP,ui_ui_resources_gyp)/ui_resources.stamp \
-	$(call intermediates-dir-for,GYP,v8_tools_gyp_v8_gyp)/v8.stamp \
-	$(call intermediates-dir-for,STATIC_LIBRARIES,webkit_support_glue_child_gyp)/webkit_support_glue_child_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/plugins/sad_plugin.cc
-
-
-# Flags passed to both C and C++ files.
-MY_CFLAGS_Debug := \
-	-Wno-narrowing \
-	--param=ssp-buffer-size=4 \
-	-Werror \
-	-fno-exceptions \
-	-fno-strict-aliasing \
-	-Wall \
-	-Wno-unused-parameter \
-	-Wno-missing-field-initializers \
-	-fvisibility=hidden \
-	-pipe \
-	-fPIC \
-	-Wno-unknown-pragmas \
-	-m32 \
-	-mmmx \
-	-march=pentium4 \
-	-msse2 \
-	-mfpmath=sse \
-	-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-address \
-	-Wno-format-security \
-	-Wno-return-type \
-	-Wno-sequence-point \
-	-fno-stack-protector \
-	-Os \
-	-g \
-	-fomit-frame-pointer \
-	-fdata-sections \
-	-ffunction-sections
-
-MY_DEFS_Debug := \
-	'-DANGLE_DX11' \
-	'-D_FILE_OFFSET_BITS=64' \
-	'-DNO_TCMALLOC' \
-	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
-	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
-	'-DDISABLE_NACL' \
-	'-DCHROMIUM_BUILD' \
-	'-DUSE_LIBJPEG_TURBO=1' \
-	'-DUSE_PROPRIETARY_CODECS' \
-	'-DENABLE_CONFIGURATION_POLICY' \
-	'-DENABLE_GPU=1' \
-	'-DUSE_OPENSSL=1' \
-	'-DENABLE_EGLIMAGE=1' \
-	'-DWEBKIT_PLUGINS_IMPLEMENTATION' \
-	'-DMEDIA_DISABLE_LIBVPX' \
-	'-DSK_ENABLE_INST_COUNT=0' \
-	'-DSK_SUPPORT_GPU=1' \
-	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
-	'-DSK_BUILD_FOR_ANDROID' \
-	'-DUSE_CHROMIUM_SKIA' \
-	'-DSK_USE_POSIX_THREADS' \
-	'-DU_USING_ICU_NAMESPACE=0' \
-	'-DMESA_EGL_NO_X11_HEADERS' \
-	'-D__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)/webkit \
-	$(gyp_shared_intermediate_dir)/ui \
-	$(LOCAL_PATH)/third_party/khronos \
-	$(LOCAL_PATH)/gpu \
-	$(LOCAL_PATH) \
-	$(LOCAL_PATH)/third_party/skia/src/core \
-	$(LOCAL_PATH)/skia/config \
-	$(LOCAL_PATH)/third_party/skia/include/config \
-	$(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/gpu/gl \
-	$(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 \
-	$(gyp_shared_intermediate_dir)/ui/gl \
-	$(LOCAL_PATH)/third_party/mesa/src/include \
-	$(gyp_shared_intermediate_dir)/ui/ui_resources \
-	$(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 := \
-	-Wno-narrowing \
-	-fno-rtti \
-	-fno-threadsafe-statics \
-	-fvisibility-inlines-hidden \
-	-Wsign-compare \
-	-Wno-error=c++0x-compat \
-	-Wno-non-virtual-dtor \
-	-Wno-sign-promo \
-	-Wno-non-virtual-dtor
-
-
-# Flags passed to both C and C++ files.
-MY_CFLAGS_Release := \
-	-Wno-narrowing \
-	--param=ssp-buffer-size=4 \
-	-Werror \
-	-fno-exceptions \
-	-fno-strict-aliasing \
-	-Wall \
-	-Wno-unused-parameter \
-	-Wno-missing-field-initializers \
-	-fvisibility=hidden \
-	-pipe \
-	-fPIC \
-	-Wno-unknown-pragmas \
-	-m32 \
-	-mmmx \
-	-march=pentium4 \
-	-msse2 \
-	-mfpmath=sse \
-	-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-address \
-	-Wno-format-security \
-	-Wno-return-type \
-	-Wno-sequence-point \
-	-fno-stack-protector \
-	-Os \
-	-fno-ident \
-	-fdata-sections \
-	-ffunction-sections \
-	-fomit-frame-pointer \
-	-fno-unwind-tables \
-	-fno-asynchronous-unwind-tables
-
-MY_DEFS_Release := \
-	'-DANGLE_DX11' \
-	'-D_FILE_OFFSET_BITS=64' \
-	'-DNO_TCMALLOC' \
-	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
-	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
-	'-DDISABLE_NACL' \
-	'-DCHROMIUM_BUILD' \
-	'-DUSE_LIBJPEG_TURBO=1' \
-	'-DUSE_PROPRIETARY_CODECS' \
-	'-DENABLE_CONFIGURATION_POLICY' \
-	'-DENABLE_GPU=1' \
-	'-DUSE_OPENSSL=1' \
-	'-DENABLE_EGLIMAGE=1' \
-	'-DWEBKIT_PLUGINS_IMPLEMENTATION' \
-	'-DMEDIA_DISABLE_LIBVPX' \
-	'-DSK_ENABLE_INST_COUNT=0' \
-	'-DSK_SUPPORT_GPU=1' \
-	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
-	'-DSK_BUILD_FOR_ANDROID' \
-	'-DUSE_CHROMIUM_SKIA' \
-	'-DSK_USE_POSIX_THREADS' \
-	'-DU_USING_ICU_NAMESPACE=0' \
-	'-DMESA_EGL_NO_X11_HEADERS' \
-	'-D__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)/webkit \
-	$(gyp_shared_intermediate_dir)/ui \
-	$(LOCAL_PATH)/third_party/khronos \
-	$(LOCAL_PATH)/gpu \
-	$(LOCAL_PATH) \
-	$(LOCAL_PATH)/third_party/skia/src/core \
-	$(LOCAL_PATH)/skia/config \
-	$(LOCAL_PATH)/third_party/skia/include/config \
-	$(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/gpu/gl \
-	$(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 \
-	$(gyp_shared_intermediate_dir)/ui/gl \
-	$(LOCAL_PATH)/third_party/mesa/src/include \
-	$(gyp_shared_intermediate_dir)/ui/ui_resources \
-	$(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 := \
-	-Wno-narrowing \
-	-fno-rtti \
-	-fno-threadsafe-statics \
-	-fvisibility-inlines-hidden \
-	-Wsign-compare \
-	-Wno-error=c++0x-compat \
-	-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))
-### Rules for final target.
-
-LOCAL_LDFLAGS_Debug := \
-	-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,-O1 \
-	-Wl,--as-needed
-
-
-LOCAL_LDFLAGS_Release := \
-	-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
-
-
-LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
-
-LOCAL_STATIC_LIBRARIES := \
-	skia_skia_library_gyp \
-	ui_gl_gl_gyp \
-	ui_ui_gyp \
-	webkit_support_glue_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: webkit_support_plugins_gyp
-
-# Alias gyp target name.
-.PHONY: plugins
-plugins: webkit_support_plugins_gyp
-
-include $(BUILD_STATIC_LIBRARY)
diff --git a/webkit/support/plugins.target.linux-arm.mk b/webkit/support/plugins.target.linux-arm.mk
deleted file mode 100644
index a75476b..0000000
--- a/webkit/support/plugins.target.linux-arm.mk
+++ /dev/null
@@ -1,359 +0,0 @@
-# This file is generated by gyp; do not edit.
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_CLASS := STATIC_LIBRARIES
-LOCAL_MODULE := webkit_support_plugins_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,ppapi_ppapi_c_gyp)/ppapi_c.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,STATIC_LIBRARIES,ui_gl_gl_gyp)/ui_gl_gl_gyp.a \
-	$(call intermediates-dir-for,STATIC_LIBRARIES,ui_ui_gyp)/ui_ui_gyp.a \
-	$(call intermediates-dir-for,GYP,ui_ui_resources_gyp)/ui_resources.stamp \
-	$(call intermediates-dir-for,GYP,v8_tools_gyp_v8_gyp)/v8.stamp \
-	$(call intermediates-dir-for,STATIC_LIBRARIES,webkit_support_glue_child_gyp)/webkit_support_glue_child_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/plugins/sad_plugin.cc
-
-
-# Flags passed to both C and C++ files.
-MY_CFLAGS_Debug := \
-	-Wno-narrowing \
-	-fstack-protector \
-	--param=ssp-buffer-size=4 \
-	-Werror \
-	-fno-exceptions \
-	-fno-strict-aliasing \
-	-Wall \
-	-Wno-unused-parameter \
-	-Wno-missing-field-initializers \
-	-fvisibility=hidden \
-	-pipe \
-	-fPIC \
-	-Wno-unknown-pragmas \
-	-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-address \
-	-Wno-format-security \
-	-Wno-return-type \
-	-Wno-sequence-point \
-	-Os \
-	-g \
-	-fomit-frame-pointer \
-	-fdata-sections \
-	-ffunction-sections
-
-MY_DEFS_Debug := \
-	'-DANGLE_DX11' \
-	'-D_FILE_OFFSET_BITS=64' \
-	'-DNO_TCMALLOC' \
-	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
-	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
-	'-DDISABLE_NACL' \
-	'-DCHROMIUM_BUILD' \
-	'-DUSE_LIBJPEG_TURBO=1' \
-	'-DUSE_PROPRIETARY_CODECS' \
-	'-DENABLE_CONFIGURATION_POLICY' \
-	'-DENABLE_GPU=1' \
-	'-DUSE_OPENSSL=1' \
-	'-DENABLE_EGLIMAGE=1' \
-	'-DWEBKIT_PLUGINS_IMPLEMENTATION' \
-	'-DMEDIA_DISABLE_LIBVPX' \
-	'-DPOSIX_AVOID_MMAP' \
-	'-DSK_ENABLE_INST_COUNT=0' \
-	'-DSK_SUPPORT_GPU=1' \
-	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
-	'-DSK_BUILD_FOR_ANDROID' \
-	'-DUSE_CHROMIUM_SKIA' \
-	'-DSK_USE_POSIX_THREADS' \
-	'-DU_USING_ICU_NAMESPACE=0' \
-	'-DMESA_EGL_NO_X11_HEADERS' \
-	'-D__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)/webkit \
-	$(gyp_shared_intermediate_dir)/ui \
-	$(LOCAL_PATH)/third_party/khronos \
-	$(LOCAL_PATH)/gpu \
-	$(LOCAL_PATH) \
-	$(LOCAL_PATH)/third_party/skia/src/core \
-	$(LOCAL_PATH)/skia/config \
-	$(LOCAL_PATH)/third_party/skia/include/config \
-	$(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/gpu/gl \
-	$(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 \
-	$(gyp_shared_intermediate_dir)/ui/gl \
-	$(LOCAL_PATH)/third_party/mesa/src/include \
-	$(gyp_shared_intermediate_dir)/ui/ui_resources \
-	$(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 := \
-	-Wno-narrowing \
-	-fno-rtti \
-	-fno-threadsafe-statics \
-	-fvisibility-inlines-hidden \
-	-Wsign-compare \
-	-Wno-abi \
-	-Wno-error=c++0x-compat \
-	-Wno-non-virtual-dtor \
-	-Wno-sign-promo \
-	-Wno-non-virtual-dtor
-
-
-# Flags passed to both C and C++ files.
-MY_CFLAGS_Release := \
-	-Wno-narrowing \
-	-fstack-protector \
-	--param=ssp-buffer-size=4 \
-	-Werror \
-	-fno-exceptions \
-	-fno-strict-aliasing \
-	-Wall \
-	-Wno-unused-parameter \
-	-Wno-missing-field-initializers \
-	-fvisibility=hidden \
-	-pipe \
-	-fPIC \
-	-Wno-unknown-pragmas \
-	-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-address \
-	-Wno-format-security \
-	-Wno-return-type \
-	-Wno-sequence-point \
-	-Os \
-	-fno-ident \
-	-fdata-sections \
-	-ffunction-sections \
-	-fomit-frame-pointer
-
-MY_DEFS_Release := \
-	'-DANGLE_DX11' \
-	'-D_FILE_OFFSET_BITS=64' \
-	'-DNO_TCMALLOC' \
-	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
-	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
-	'-DDISABLE_NACL' \
-	'-DCHROMIUM_BUILD' \
-	'-DUSE_LIBJPEG_TURBO=1' \
-	'-DUSE_PROPRIETARY_CODECS' \
-	'-DENABLE_CONFIGURATION_POLICY' \
-	'-DENABLE_GPU=1' \
-	'-DUSE_OPENSSL=1' \
-	'-DENABLE_EGLIMAGE=1' \
-	'-DWEBKIT_PLUGINS_IMPLEMENTATION' \
-	'-DMEDIA_DISABLE_LIBVPX' \
-	'-DPOSIX_AVOID_MMAP' \
-	'-DSK_ENABLE_INST_COUNT=0' \
-	'-DSK_SUPPORT_GPU=1' \
-	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
-	'-DSK_BUILD_FOR_ANDROID' \
-	'-DUSE_CHROMIUM_SKIA' \
-	'-DSK_USE_POSIX_THREADS' \
-	'-DU_USING_ICU_NAMESPACE=0' \
-	'-DMESA_EGL_NO_X11_HEADERS' \
-	'-D__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)/webkit \
-	$(gyp_shared_intermediate_dir)/ui \
-	$(LOCAL_PATH)/third_party/khronos \
-	$(LOCAL_PATH)/gpu \
-	$(LOCAL_PATH) \
-	$(LOCAL_PATH)/third_party/skia/src/core \
-	$(LOCAL_PATH)/skia/config \
-	$(LOCAL_PATH)/third_party/skia/include/config \
-	$(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/gpu/gl \
-	$(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 \
-	$(gyp_shared_intermediate_dir)/ui/gl \
-	$(LOCAL_PATH)/third_party/mesa/src/include \
-	$(gyp_shared_intermediate_dir)/ui/ui_resources \
-	$(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 := \
-	-Wno-narrowing \
-	-fno-rtti \
-	-fno-threadsafe-statics \
-	-fvisibility-inlines-hidden \
-	-Wsign-compare \
-	-Wno-abi \
-	-Wno-error=c++0x-compat \
-	-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))
-### Rules for final target.
-
-LOCAL_LDFLAGS_Debug := \
-	-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,-O1 \
-	-Wl,--as-needed
-
-
-LOCAL_LDFLAGS_Release := \
-	-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
-
-
-LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
-
-LOCAL_STATIC_LIBRARIES := \
-	skia_skia_library_gyp \
-	ui_gl_gl_gyp \
-	ui_ui_gyp \
-	webkit_support_glue_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: webkit_support_plugins_gyp
-
-# Alias gyp target name.
-.PHONY: plugins
-plugins: webkit_support_plugins_gyp
-
-include $(BUILD_STATIC_LIBRARY)
diff --git a/webkit/support/plugins.target.linux-mips.mk b/webkit/support/plugins.target.linux-mips.mk
deleted file mode 100644
index 7761ce3..0000000
--- a/webkit/support/plugins.target.linux-mips.mk
+++ /dev/null
@@ -1,353 +0,0 @@
-# This file is generated by gyp; do not edit.
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_CLASS := STATIC_LIBRARIES
-LOCAL_MODULE := webkit_support_plugins_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,ppapi_ppapi_c_gyp)/ppapi_c.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,STATIC_LIBRARIES,ui_gl_gl_gyp)/ui_gl_gl_gyp.a \
-	$(call intermediates-dir-for,STATIC_LIBRARIES,ui_ui_gyp)/ui_ui_gyp.a \
-	$(call intermediates-dir-for,GYP,ui_ui_resources_gyp)/ui_resources.stamp \
-	$(call intermediates-dir-for,GYP,v8_tools_gyp_v8_gyp)/v8.stamp \
-	$(call intermediates-dir-for,STATIC_LIBRARIES,webkit_support_glue_child_gyp)/webkit_support_glue_child_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/plugins/sad_plugin.cc
-
-
-# Flags passed to both C and C++ files.
-MY_CFLAGS_Debug := \
-	-Wno-narrowing \
-	-fstack-protector \
-	--param=ssp-buffer-size=4 \
-	 \
-	-fno-exceptions \
-	-fno-strict-aliasing \
-	-Wall \
-	-Wno-unused-parameter \
-	-Wno-missing-field-initializers \
-	-fvisibility=hidden \
-	-pipe \
-	-fPIC \
-	-Wno-unknown-pragmas \
-	-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-address \
-	-Wno-format-security \
-	-Wno-return-type \
-	-Wno-sequence-point \
-	-Os \
-	-g \
-	-fomit-frame-pointer \
-	-fdata-sections \
-	-ffunction-sections
-
-MY_DEFS_Debug := \
-	'-DANGLE_DX11' \
-	'-D_FILE_OFFSET_BITS=64' \
-	'-DNO_TCMALLOC' \
-	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
-	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
-	'-DDISABLE_NACL' \
-	'-DCHROMIUM_BUILD' \
-	'-DUSE_LIBJPEG_TURBO=1' \
-	'-DUSE_PROPRIETARY_CODECS' \
-	'-DENABLE_CONFIGURATION_POLICY' \
-	'-DENABLE_GPU=1' \
-	'-DUSE_OPENSSL=1' \
-	'-DENABLE_EGLIMAGE=1' \
-	'-DWEBKIT_PLUGINS_IMPLEMENTATION' \
-	'-DMEDIA_DISABLE_LIBVPX' \
-	'-DPOSIX_AVOID_MMAP' \
-	'-DSK_ENABLE_INST_COUNT=0' \
-	'-DSK_SUPPORT_GPU=1' \
-	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
-	'-DSK_BUILD_FOR_ANDROID' \
-	'-DUSE_CHROMIUM_SKIA' \
-	'-DSK_USE_POSIX_THREADS' \
-	'-DU_USING_ICU_NAMESPACE=0' \
-	'-DMESA_EGL_NO_X11_HEADERS' \
-	'-D__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)/webkit \
-	$(gyp_shared_intermediate_dir)/ui \
-	$(LOCAL_PATH)/third_party/khronos \
-	$(LOCAL_PATH)/gpu \
-	$(LOCAL_PATH) \
-	$(LOCAL_PATH)/third_party/skia/src/core \
-	$(LOCAL_PATH)/skia/config \
-	$(LOCAL_PATH)/third_party/skia/include/config \
-	$(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/gpu/gl \
-	$(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 \
-	$(gyp_shared_intermediate_dir)/ui/gl \
-	$(LOCAL_PATH)/third_party/mesa/src/include \
-	$(gyp_shared_intermediate_dir)/ui/ui_resources \
-	$(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 := \
-	-Wno-narrowing \
-	-fno-rtti \
-	-fno-threadsafe-statics \
-	-fvisibility-inlines-hidden \
-	-Wsign-compare \
-	-Wno-uninitialized \
-	-Wno-error=c++0x-compat \
-	-Wno-non-virtual-dtor \
-	-Wno-sign-promo \
-	-Wno-non-virtual-dtor
-
-
-# Flags passed to both C and C++ files.
-MY_CFLAGS_Release := \
-	-Wno-narrowing \
-	-fstack-protector \
-	--param=ssp-buffer-size=4 \
-	 \
-	-fno-exceptions \
-	-fno-strict-aliasing \
-	-Wall \
-	-Wno-unused-parameter \
-	-Wno-missing-field-initializers \
-	-fvisibility=hidden \
-	-pipe \
-	-fPIC \
-	-Wno-unknown-pragmas \
-	-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-address \
-	-Wno-format-security \
-	-Wno-return-type \
-	-Wno-sequence-point \
-	-Os \
-	-fno-ident \
-	-fdata-sections \
-	-ffunction-sections \
-	-fomit-frame-pointer
-
-MY_DEFS_Release := \
-	'-DANGLE_DX11' \
-	'-D_FILE_OFFSET_BITS=64' \
-	'-DNO_TCMALLOC' \
-	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
-	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
-	'-DDISABLE_NACL' \
-	'-DCHROMIUM_BUILD' \
-	'-DUSE_LIBJPEG_TURBO=1' \
-	'-DUSE_PROPRIETARY_CODECS' \
-	'-DENABLE_CONFIGURATION_POLICY' \
-	'-DENABLE_GPU=1' \
-	'-DUSE_OPENSSL=1' \
-	'-DENABLE_EGLIMAGE=1' \
-	'-DWEBKIT_PLUGINS_IMPLEMENTATION' \
-	'-DMEDIA_DISABLE_LIBVPX' \
-	'-DPOSIX_AVOID_MMAP' \
-	'-DSK_ENABLE_INST_COUNT=0' \
-	'-DSK_SUPPORT_GPU=1' \
-	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
-	'-DSK_BUILD_FOR_ANDROID' \
-	'-DUSE_CHROMIUM_SKIA' \
-	'-DSK_USE_POSIX_THREADS' \
-	'-DU_USING_ICU_NAMESPACE=0' \
-	'-DMESA_EGL_NO_X11_HEADERS' \
-	'-D__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)/webkit \
-	$(gyp_shared_intermediate_dir)/ui \
-	$(LOCAL_PATH)/third_party/khronos \
-	$(LOCAL_PATH)/gpu \
-	$(LOCAL_PATH) \
-	$(LOCAL_PATH)/third_party/skia/src/core \
-	$(LOCAL_PATH)/skia/config \
-	$(LOCAL_PATH)/third_party/skia/include/config \
-	$(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/gpu/gl \
-	$(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 \
-	$(gyp_shared_intermediate_dir)/ui/gl \
-	$(LOCAL_PATH)/third_party/mesa/src/include \
-	$(gyp_shared_intermediate_dir)/ui/ui_resources \
-	$(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 := \
-	-Wno-narrowing \
-	-fno-rtti \
-	-fno-threadsafe-statics \
-	-fvisibility-inlines-hidden \
-	-Wsign-compare \
-	-Wno-uninitialized \
-	-Wno-error=c++0x-compat \
-	-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))
-### Rules for final target.
-
-LOCAL_LDFLAGS_Debug := \
-	-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,-O1 \
-	-Wl,--as-needed
-
-
-LOCAL_LDFLAGS_Release := \
-	-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
-
-
-LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
-
-LOCAL_STATIC_LIBRARIES := \
-	skia_skia_library_gyp \
-	ui_gl_gl_gyp \
-	ui_ui_gyp \
-	webkit_support_glue_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: webkit_support_plugins_gyp
-
-# Alias gyp target name.
-.PHONY: plugins
-plugins: webkit_support_plugins_gyp
-
-include $(BUILD_STATIC_LIBRARY)
diff --git a/webkit/support/plugins.target.linux-x86.mk b/webkit/support/plugins.target.linux-x86.mk
deleted file mode 100644
index 00061ee..0000000
--- a/webkit/support/plugins.target.linux-x86.mk
+++ /dev/null
@@ -1,357 +0,0 @@
-# This file is generated by gyp; do not edit.
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_CLASS := STATIC_LIBRARIES
-LOCAL_MODULE := webkit_support_plugins_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,ppapi_ppapi_c_gyp)/ppapi_c.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,STATIC_LIBRARIES,ui_gl_gl_gyp)/ui_gl_gl_gyp.a \
-	$(call intermediates-dir-for,STATIC_LIBRARIES,ui_ui_gyp)/ui_ui_gyp.a \
-	$(call intermediates-dir-for,GYP,ui_ui_resources_gyp)/ui_resources.stamp \
-	$(call intermediates-dir-for,GYP,v8_tools_gyp_v8_gyp)/v8.stamp \
-	$(call intermediates-dir-for,STATIC_LIBRARIES,webkit_support_glue_child_gyp)/webkit_support_glue_child_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/plugins/sad_plugin.cc
-
-
-# Flags passed to both C and C++ files.
-MY_CFLAGS_Debug := \
-	-Wno-narrowing \
-	--param=ssp-buffer-size=4 \
-	-Werror \
-	-fno-exceptions \
-	-fno-strict-aliasing \
-	-Wall \
-	-Wno-unused-parameter \
-	-Wno-missing-field-initializers \
-	-fvisibility=hidden \
-	-pipe \
-	-fPIC \
-	-Wno-unknown-pragmas \
-	-m32 \
-	-mmmx \
-	-march=pentium4 \
-	-msse2 \
-	-mfpmath=sse \
-	-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-address \
-	-Wno-format-security \
-	-Wno-return-type \
-	-Wno-sequence-point \
-	-fno-stack-protector \
-	-Os \
-	-g \
-	-fomit-frame-pointer \
-	-fdata-sections \
-	-ffunction-sections
-
-MY_DEFS_Debug := \
-	'-DANGLE_DX11' \
-	'-D_FILE_OFFSET_BITS=64' \
-	'-DNO_TCMALLOC' \
-	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
-	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
-	'-DDISABLE_NACL' \
-	'-DCHROMIUM_BUILD' \
-	'-DUSE_LIBJPEG_TURBO=1' \
-	'-DUSE_PROPRIETARY_CODECS' \
-	'-DENABLE_CONFIGURATION_POLICY' \
-	'-DENABLE_GPU=1' \
-	'-DUSE_OPENSSL=1' \
-	'-DENABLE_EGLIMAGE=1' \
-	'-DWEBKIT_PLUGINS_IMPLEMENTATION' \
-	'-DMEDIA_DISABLE_LIBVPX' \
-	'-DSK_ENABLE_INST_COUNT=0' \
-	'-DSK_SUPPORT_GPU=1' \
-	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
-	'-DSK_BUILD_FOR_ANDROID' \
-	'-DUSE_CHROMIUM_SKIA' \
-	'-DSK_USE_POSIX_THREADS' \
-	'-DU_USING_ICU_NAMESPACE=0' \
-	'-DMESA_EGL_NO_X11_HEADERS' \
-	'-D__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)/webkit \
-	$(gyp_shared_intermediate_dir)/ui \
-	$(LOCAL_PATH)/third_party/khronos \
-	$(LOCAL_PATH)/gpu \
-	$(LOCAL_PATH) \
-	$(LOCAL_PATH)/third_party/skia/src/core \
-	$(LOCAL_PATH)/skia/config \
-	$(LOCAL_PATH)/third_party/skia/include/config \
-	$(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/gpu/gl \
-	$(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 \
-	$(gyp_shared_intermediate_dir)/ui/gl \
-	$(LOCAL_PATH)/third_party/mesa/src/include \
-	$(gyp_shared_intermediate_dir)/ui/ui_resources \
-	$(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 := \
-	-Wno-narrowing \
-	-fno-rtti \
-	-fno-threadsafe-statics \
-	-fvisibility-inlines-hidden \
-	-Wsign-compare \
-	-Wno-error=c++0x-compat \
-	-Wno-non-virtual-dtor \
-	-Wno-sign-promo \
-	-Wno-non-virtual-dtor
-
-
-# Flags passed to both C and C++ files.
-MY_CFLAGS_Release := \
-	-Wno-narrowing \
-	--param=ssp-buffer-size=4 \
-	-Werror \
-	-fno-exceptions \
-	-fno-strict-aliasing \
-	-Wall \
-	-Wno-unused-parameter \
-	-Wno-missing-field-initializers \
-	-fvisibility=hidden \
-	-pipe \
-	-fPIC \
-	-Wno-unknown-pragmas \
-	-m32 \
-	-mmmx \
-	-march=pentium4 \
-	-msse2 \
-	-mfpmath=sse \
-	-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-address \
-	-Wno-format-security \
-	-Wno-return-type \
-	-Wno-sequence-point \
-	-fno-stack-protector \
-	-Os \
-	-fno-ident \
-	-fdata-sections \
-	-ffunction-sections \
-	-fomit-frame-pointer \
-	-fno-unwind-tables \
-	-fno-asynchronous-unwind-tables
-
-MY_DEFS_Release := \
-	'-DANGLE_DX11' \
-	'-D_FILE_OFFSET_BITS=64' \
-	'-DNO_TCMALLOC' \
-	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
-	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
-	'-DDISABLE_NACL' \
-	'-DCHROMIUM_BUILD' \
-	'-DUSE_LIBJPEG_TURBO=1' \
-	'-DUSE_PROPRIETARY_CODECS' \
-	'-DENABLE_CONFIGURATION_POLICY' \
-	'-DENABLE_GPU=1' \
-	'-DUSE_OPENSSL=1' \
-	'-DENABLE_EGLIMAGE=1' \
-	'-DWEBKIT_PLUGINS_IMPLEMENTATION' \
-	'-DMEDIA_DISABLE_LIBVPX' \
-	'-DSK_ENABLE_INST_COUNT=0' \
-	'-DSK_SUPPORT_GPU=1' \
-	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
-	'-DSK_BUILD_FOR_ANDROID' \
-	'-DUSE_CHROMIUM_SKIA' \
-	'-DSK_USE_POSIX_THREADS' \
-	'-DU_USING_ICU_NAMESPACE=0' \
-	'-DMESA_EGL_NO_X11_HEADERS' \
-	'-D__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)/webkit \
-	$(gyp_shared_intermediate_dir)/ui \
-	$(LOCAL_PATH)/third_party/khronos \
-	$(LOCAL_PATH)/gpu \
-	$(LOCAL_PATH) \
-	$(LOCAL_PATH)/third_party/skia/src/core \
-	$(LOCAL_PATH)/skia/config \
-	$(LOCAL_PATH)/third_party/skia/include/config \
-	$(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/gpu/gl \
-	$(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 \
-	$(gyp_shared_intermediate_dir)/ui/gl \
-	$(LOCAL_PATH)/third_party/mesa/src/include \
-	$(gyp_shared_intermediate_dir)/ui/ui_resources \
-	$(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 := \
-	-Wno-narrowing \
-	-fno-rtti \
-	-fno-threadsafe-statics \
-	-fvisibility-inlines-hidden \
-	-Wsign-compare \
-	-Wno-error=c++0x-compat \
-	-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))
-### Rules for final target.
-
-LOCAL_LDFLAGS_Debug := \
-	-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,-O1 \
-	-Wl,--as-needed
-
-
-LOCAL_LDFLAGS_Release := \
-	-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
-
-
-LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
-
-LOCAL_STATIC_LIBRARIES := \
-	skia_skia_library_gyp \
-	ui_gl_gl_gyp \
-	ui_ui_gyp \
-	webkit_support_glue_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: webkit_support_plugins_gyp
-
-# Alias gyp target name.
-.PHONY: plugins
-plugins: webkit_support_plugins_gyp
-
-include $(BUILD_STATIC_LIBRARY)
diff --git a/webkit/support/test_webkit_platform_support.cc b/webkit/support/test_webkit_platform_support.cc
index 6eecfed..5156568 100644
--- a/webkit/support/test_webkit_platform_support.cc
+++ b/webkit/support/test_webkit_platform_support.cc
@@ -34,7 +34,6 @@
 #include "webkit/common/gpu/webgraphicscontext3d_provider_impl.h"
 #include "webkit/glue/simple_webmimeregistry_impl.h"
 #include "webkit/glue/webkit_glue.h"
-#include "webkit/renderer/appcache/web_application_cache_host_impl.h"
 #include "webkit/renderer/compositor_bindings/web_compositor_support_impl.h"
 #include "webkit/support/gc_extension.h"
 #include "webkit/support/mock_webclipboard_impl.h"
diff --git a/webkit/support/webkit_support.gyp b/webkit/support/webkit_support.gyp
index 7e39747..5bbf80a 100644
--- a/webkit/support/webkit_support.gyp
+++ b/webkit/support/webkit_support.gyp
@@ -11,8 +11,6 @@
       'includes': [
         '../../build/win_precompile.gypi',
         '../glue/webkit_glue.gypi',
-        '../plugins/webkit_plugins.gypi',
-        '../renderer/media/webkit_media.gypi',
         'webkit_support.gypi',
       ],
     }],
diff --git a/webkit/support/webkit_support.gypi b/webkit/support/webkit_support.gypi
index bf1a35e..25d9de1 100644
--- a/webkit/support/webkit_support.gypi
+++ b/webkit/support/webkit_support.gypi
@@ -34,7 +34,6 @@
         '<(DEPTH)/webkit/storage_renderer.gyp:webkit_storage_renderer',
         'glue',
         'glue_child',
-        'plugins',
         'webkit_support_common',
       ],
       'include_dirs': [
@@ -98,7 +97,6 @@
       'variables': { 'enable_wexit_time_destructors': 1, },
       'dependencies': [
         '<(DEPTH)/base/base.gyp:base',
-        '<(DEPTH)/crypto/crypto.gyp:crypto',
         '<(DEPTH)/net/net.gyp:net',
         '<(DEPTH)/skia/skia.gyp:skia',
         '<(DEPTH)/third_party/zlib/zlib.gyp:zlib',
diff --git a/webkit/webkit_storage_browser.target.darwin-arm.mk b/webkit/webkit_storage_browser.target.darwin-arm.mk
index 349d8bc..4ca2850 100644
--- a/webkit/webkit_storage_browser.target.darwin-arm.mk
+++ b/webkit/webkit_storage_browser.target.darwin-arm.mk
@@ -163,6 +163,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
@@ -282,6 +283,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
diff --git a/webkit/webkit_storage_browser.target.darwin-mips.mk b/webkit/webkit_storage_browser.target.darwin-mips.mk
index 223f22b..550f873 100644
--- a/webkit/webkit_storage_browser.target.darwin-mips.mk
+++ b/webkit/webkit_storage_browser.target.darwin-mips.mk
@@ -163,6 +163,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
@@ -282,6 +283,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
diff --git a/webkit/webkit_storage_browser.target.darwin-x86.mk b/webkit/webkit_storage_browser.target.darwin-x86.mk
index 9c2fe20..c38c105 100644
--- a/webkit/webkit_storage_browser.target.darwin-x86.mk
+++ b/webkit/webkit_storage_browser.target.darwin-x86.mk
@@ -164,6 +164,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
@@ -285,6 +286,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
diff --git a/webkit/webkit_storage_browser.target.linux-arm.mk b/webkit/webkit_storage_browser.target.linux-arm.mk
index 349d8bc..4ca2850 100644
--- a/webkit/webkit_storage_browser.target.linux-arm.mk
+++ b/webkit/webkit_storage_browser.target.linux-arm.mk
@@ -163,6 +163,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
@@ -282,6 +283,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
diff --git a/webkit/webkit_storage_browser.target.linux-mips.mk b/webkit/webkit_storage_browser.target.linux-mips.mk
index 223f22b..550f873 100644
--- a/webkit/webkit_storage_browser.target.linux-mips.mk
+++ b/webkit/webkit_storage_browser.target.linux-mips.mk
@@ -163,6 +163,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
@@ -282,6 +283,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
diff --git a/webkit/webkit_storage_browser.target.linux-x86.mk b/webkit/webkit_storage_browser.target.linux-x86.mk
index 9c2fe20..c38c105 100644
--- a/webkit/webkit_storage_browser.target.linux-x86.mk
+++ b/webkit/webkit_storage_browser.target.linux-x86.mk
@@ -164,6 +164,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
@@ -285,6 +286,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
diff --git a/webkit/webkit_storage_renderer.target.darwin-arm.mk b/webkit/webkit_storage_renderer.target.darwin-arm.mk
index cf6a55a..ccf4621 100644
--- a/webkit/webkit_storage_renderer.target.darwin-arm.mk
+++ b/webkit/webkit_storage_renderer.target.darwin-arm.mk
@@ -25,8 +25,6 @@
 GYP_COPIED_SOURCE_ORIGIN_DIRS :=
 
 LOCAL_SRC_FILES := \
-	webkit/renderer/appcache/appcache_frontend_impl.cc \
-	webkit/renderer/appcache/web_application_cache_host_impl.cc \
 	webkit/renderer/fileapi/webfilewriter_base.cc
 
 
@@ -87,6 +85,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
@@ -201,6 +200,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
diff --git a/webkit/webkit_storage_renderer.target.darwin-mips.mk b/webkit/webkit_storage_renderer.target.darwin-mips.mk
index 464a0dc..5680461 100644
--- a/webkit/webkit_storage_renderer.target.darwin-mips.mk
+++ b/webkit/webkit_storage_renderer.target.darwin-mips.mk
@@ -25,8 +25,6 @@
 GYP_COPIED_SOURCE_ORIGIN_DIRS :=
 
 LOCAL_SRC_FILES := \
-	webkit/renderer/appcache/appcache_frontend_impl.cc \
-	webkit/renderer/appcache/web_application_cache_host_impl.cc \
 	webkit/renderer/fileapi/webfilewriter_base.cc
 
 
@@ -87,6 +85,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
@@ -201,6 +200,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
diff --git a/webkit/webkit_storage_renderer.target.darwin-x86.mk b/webkit/webkit_storage_renderer.target.darwin-x86.mk
index e15e6ec..b37d229 100644
--- a/webkit/webkit_storage_renderer.target.darwin-x86.mk
+++ b/webkit/webkit_storage_renderer.target.darwin-x86.mk
@@ -25,8 +25,6 @@
 GYP_COPIED_SOURCE_ORIGIN_DIRS :=
 
 LOCAL_SRC_FILES := \
-	webkit/renderer/appcache/appcache_frontend_impl.cc \
-	webkit/renderer/appcache/web_application_cache_host_impl.cc \
 	webkit/renderer/fileapi/webfilewriter_base.cc
 
 
@@ -89,6 +87,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
@@ -206,6 +205,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
diff --git a/webkit/webkit_storage_renderer.target.linux-arm.mk b/webkit/webkit_storage_renderer.target.linux-arm.mk
index cf6a55a..ccf4621 100644
--- a/webkit/webkit_storage_renderer.target.linux-arm.mk
+++ b/webkit/webkit_storage_renderer.target.linux-arm.mk
@@ -25,8 +25,6 @@
 GYP_COPIED_SOURCE_ORIGIN_DIRS :=
 
 LOCAL_SRC_FILES := \
-	webkit/renderer/appcache/appcache_frontend_impl.cc \
-	webkit/renderer/appcache/web_application_cache_host_impl.cc \
 	webkit/renderer/fileapi/webfilewriter_base.cc
 
 
@@ -87,6 +85,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
@@ -201,6 +200,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
diff --git a/webkit/webkit_storage_renderer.target.linux-mips.mk b/webkit/webkit_storage_renderer.target.linux-mips.mk
index 464a0dc..5680461 100644
--- a/webkit/webkit_storage_renderer.target.linux-mips.mk
+++ b/webkit/webkit_storage_renderer.target.linux-mips.mk
@@ -25,8 +25,6 @@
 GYP_COPIED_SOURCE_ORIGIN_DIRS :=
 
 LOCAL_SRC_FILES := \
-	webkit/renderer/appcache/appcache_frontend_impl.cc \
-	webkit/renderer/appcache/web_application_cache_host_impl.cc \
 	webkit/renderer/fileapi/webfilewriter_base.cc
 
 
@@ -87,6 +85,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
@@ -201,6 +200,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
diff --git a/webkit/webkit_storage_renderer.target.linux-x86.mk b/webkit/webkit_storage_renderer.target.linux-x86.mk
index e15e6ec..b37d229 100644
--- a/webkit/webkit_storage_renderer.target.linux-x86.mk
+++ b/webkit/webkit_storage_renderer.target.linux-x86.mk
@@ -25,8 +25,6 @@
 GYP_COPIED_SOURCE_ORIGIN_DIRS :=
 
 LOCAL_SRC_FILES := \
-	webkit/renderer/appcache/appcache_frontend_impl.cc \
-	webkit/renderer/appcache/web_application_cache_host_impl.cc \
 	webkit/renderer/fileapi/webfilewriter_base.cc
 
 
@@ -89,6 +87,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
@@ -206,6 +205,7 @@
 	'-DSK_BUILD_FOR_ANDROID' \
 	'-DUSE_CHROMIUM_SKIA' \
 	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \